cocos2d-x-3.16 实例开发之StickHero【4】游戏逻辑

一、开始游戏

在欢迎界面点击开始按钮后,进入游戏状态,平台和主角会移动到指定位置

void BackgroundLayer::Start(Ref* pSender)
{
	log("1\start");
	//移除按钮、标题
	this->removeChild(menu);
	this->removeChild(GameName);
	MoveTo* stageMove1 = MoveTo::create(0.2,Vec2(STAGE_SCALE,stage_sprite[0]->getContentSize().height/2));
	MoveTo* playerMove = MoveTo::create(0.2,Vec2(STAGE_SCALE+stage_sprite[NowStage]->getContentSize().width*stage_sprite[NowStage]->getScaleX()/2 - My_Player.getSprite()->getContentSize().width/2 - 5,stage_sprite[0]->getContentSize().height));
	stage_sprite[0]->runAction(stageMove1);
	My_Player.getSprite()->runAction(playerMove);
	isStart=true;
	initStick();
	addStage();
}

初始化棍子的位置并添加下一个平台

void BackgroundLayer::addStage()
{
	log("2\addStage");
	Size MyWinSize = Director::getInstance()->getVisibleSize();
	stage_sprite[stage_number]->setScaleX(10+CCRANDOM_0_1()*40);
	stage_sprite[stage_number]->setPosition(Vec2(MyWinSize.width + stage_sprite[stage_number]->getScaleX()*stage_sprite[stage_number]->getContentSize().width, stage_sprite[stage_number]->getContentSize().height/2));
	MoveTo* stageMove = MoveTo::create(0.2, Vec2(MyWinSize.width/2 + CCRANDOM_0_1()*MyWinSize.width/3, stage_sprite[stage_number]->getContentSize().height/2));
	stage_sprite[stage_number]->runAction(stageMove);
	log("stage_number=%d",stage_number);
	if(stage_number+1<=2)
	{
		stage_number+=1;
	}
	else
	{
		stage_number = 0;
	}
	//NowStage的编号是[0,2]对应stage_number的编号是[1,3]
	NowStage = stage_number  == 0 ? 2:stage_number-1;
	LastStage = NowStage ==0 ? 2:(NowStage-1);
	NextStage = NowStage == 2 ? 0:(NowStage+1);
}

二、游戏中

1、游戏是通过触摸屏幕进行交互的,所以在初始化时添加单点触摸事件

// 单点触摸事件
touch_listener = EventListenerTouchOneByOne::create();
touch_listener->setSwallowTouches(true);
touch_listener->onTouchBegan = CC_CALLBACK_2(BackgroundLayer::onTouchBegan,this);
touch_listener->onTouchMoved = CC_CALLBACK_2(BackgroundLayer::onTouchMoved,this);
touch_listener->onTouchEnded = CC_CALLBACK_2(BackgroundLayer::onTouchEnded,this);
touch_listener->onTouchCancelled = CC_CALLBACK_2(BackgroundLayer::onTouchCancelled, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touch_listener, this);

    触摸开始时,使棍子变长,触摸结束时停止

bool BackgroundLayer::onTouchBegan(Touch* pTouch, Event* pEvent)
{
	log("4\onTouchBegan");
	if(isStart){
		addStick();
	}else{
		return false;
	}
	isStart = false;
	return true;
}
void BackgroundLayer::onTouchEnded(Touch* pTouch, Event* pEvent)
{
	log("5\onTouchEnded");
	StopStick();
	RotateStickAndGo();
}

2、棍子变长使用了schedule定时器,触摸开始棍子一直变长直到触摸结束

void BackgroundLayer::addStick()
{
	log("6\addStick");
	// 棍子设置在平台的右上角那个点上
	stick->setPosition(StickPoint);
	this->schedule(schedule_selector(BackgroundLayer::StickLength));
}
void BackgroundLayer::StickLength(float)
{
	stick->setScaleY(stick->getScaleY()+5);
}

    当结束触摸时,记录下棍子的长度并结束定时器

void BackgroundLayer::StopStick()
{
	// 存储棍子的长度
	TouchLength = stick->getContentSize().height*stick->getScaleY();
	this->unschedule(schedule_selector(BackgroundLayer::StickLength));
}

3、判断是否成功到下一个平台还是掉落失败

只要棍子末端在下个平台之上则进入下个平台,否则游戏结束

void BackgroundLayer::RotateStickAndGo()
{
	log("7\RotateStickAndGo");
	// 算出棍子到下个平台的最小距离、最大距离
	DestLengthMin = abs(stage_sprite[LastStage]->getPositionX() - stage_sprite[NowStage]->getPositionX()) - stage_sprite[LastStage]->getContentSize().width*stage_sprite[LastStage]->getScaleX()/2 - stage_sprite[NowStage]->getContentSize().width*stage_sprite[NowStage]->getScaleX()/2;
	DestLengthMax = DestLengthMin + stage_sprite[NowStage]->getContentSize().width*stage_sprite[NowStage]->getScaleX();

	CallFunc* MoveToNext = CallFunc::create(CC_CALLBACK_0(BackgroundLayer::PlayerMoveToNextStage, this));
	RotateTo* Ro_Stick = RotateTo::create(0.5, 90); //旋转90度
	Sequence* GOGO = Sequence::create(Ro_Stick,MoveToNext, NULL);

	CallFunc* GoCallBack = CallFunc::create(CC_CALLBACK_0(BackgroundLayer::PlayerMove, this));
	Sequence* StickDown = Sequence::create(Ro_Stick,GoCallBack,NULL);
	log("TouchLength=%d,DestLengthMin=%d,DestLengthMax=%d", TouchLength,DestLengthMin,DestLengthMax);
	log("LastStage=%d,NowStage=%d", LastStage,NowStage);
	// 判断计算出的棍子长度是不是在我们最大距离和最小距离之间
	if(TouchLength<DestLengthMin || TouchLength > DestLengthMax)
	{
		stick->runAction(StickDown);
	}
	else if(TouchLength >= DestLengthMin && TouchLength <=DestLengthMax)
	{
		stick->runAction(GOGO);
	}

}

    安全到达下个平台,英雄动画变为行走状态移动到下个平台

void BackgroundLayer::StageAndPlayerMove()
{
	log("8\StageAndPlayerMove");
	Vec2 dest;
	dest.x = stage_sprite[NowStage]->getPosition().x + stage_sprite[NowStage]->getContentSize().width*stage_sprite[NowStage]->getScaleX()/2 - My_Player.getSprite()->getContentSize().width/2 - 5;
	dest.y = stage_sprite[NowStage]->getContentSize().height;
	float dist = dest.x - My_Player.getSprite()->getPosition().x;
	log("dist=%f", dist);
	MoveTo* playermove = MoveTo::create(dist / MOVE_SPEED, dest);
	My_Player.Stop();
	My_Player.Walk();
	CallFunc* moveCallBack = CallFunc::create(CC_CALLBACK_0(BackgroundLayer::stageMove, this));
	CallFunc* moveCallBack1 = CallFunc::create([&]{isStart = true;});
	CallFunc* moveCallBack2 = CallFunc::create([&]{
		My_Player.Stay();
	});
	Sequence* Move = Sequence::create(playermove,moveCallBack,moveCallBack1,moveCallBack2,NULL);
	My_Player.getSprite()->runAction(Move);

}

    如果失败,则执行掉落动作,进入游戏结束界面

void BackgroundLayer::PlayerDown()
{
	log("11\PlayerDown");

	MoveBy* Down = MoveBy::create(0.1,Vec2(0,-800));
	My_Player.getSprite()->runAction(Down);
	RotateTo* Ro_Stick = RotateTo::create(0.5, 180); //旋转180度
	Sequence* StickDown = Sequence::create(Ro_Stick, NULL);
	stick->runAction(StickDown);
	over = GameOverLayer::create();
	this->addChild(over,8);

}
void BackgroundLayer::PlayerMove()
{
	log("12\PlayerMove");
	MoveBy* GO = MoveBy::create((float)TouchLength/MOVE_SPEED,Vec2(TouchLength,0));
	CallFunc* DownCallBack = CallFunc::create(CC_CALLBACK_0(BackgroundLayer::PlayerDown, this));
	Sequence* Goon = Sequence::create(GO,DownCallBack,NULL);
	My_Player.getSprite()->runAction(Goon);
}


发表评论

(必填)

(必填)

(以便回访)

博客已稳定运行: 访问量:115,543 views 网站备案号:闽ICP备17026396号-1