失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > cocos2d-x游戏开发系列教程-超级玛丽07-CMGameMap(四)-马里奥平移

cocos2d-x游戏开发系列教程-超级玛丽07-CMGameMap(四)-马里奥平移

时间:2021-07-17 14:29:27

相关推荐

cocos2d-x游戏开发系列教程-超级玛丽07-CMGameMap(四)-马里奥平移

上一篇博文提到,程序如何获取键盘输入,也就是D键按下,程序获取到前进指令,那么获取到前进指令之后,马里奥是如何前进的呢,这篇文章我们重点讨论这个问题。

马里奥的移动,依旧是在帧刷新函数中,这个调用过程上个博文说过,这里不再重复,简单来说就是CMGameScene::OnCallPerFrame调用CMGameMap::OnCallPerFrame,再调用CMGameMap::MarioMove函数,在MarioMove函数中,实现马里奥的移动。

void CMGameMap::MarioMove(float fT){do {CMMario* pMario = dynamic_cast<CMMario*>(getChildByTag(enTagMario));CC_BREAK_IF(pMario==NULL);CCPoint CurMarioPos = pMario->getPosition();//如果左键按下if(m_bIsLeftKeyDown){pMario->OnCtrlMove(fT,false);}//如果右键按下if (m_bIsRightKeyDown){CCPoint CurMarioPos = pMario->getPosition();pMario->OnCtrlMove(fT,true);//如果Mario的位置变化了,则地图才会卷动if (convertToWorldSpace(pMario->getPosition()).x>120 && abs(pMario->getPositionX()-CurMarioPos.x)>1 &&pMario->getPositionX() < (getContentSize().width - SCREEN_WIDTH + 100)){setPositionX(getPositionX()-100*fT);}}//如果跳跃键按下if (m_bIsJumpKeyDown){pMario->OnCtrlJump();}//如果没有键按下if (m_bIsLeftKeyDown==false && m_bIsRightKeyDown==false && m_bIsJumpKeyDown==false){pMario->OnCtrlNoAction();}

在MarioMove函数中,根据按键的情况,分别调用Mario对象的OnCtrlMove,OnCtrlJump,OnCtrlNoAction三个函数

我们依次来学习这么三个函数,这个文章里首先学习平移函数OnCtrlMove函数

void CMMario::OnCtrlMove(float fT,bool bToRight){if(m_pGameMap==NULL){CCAssert(false,"Error:No Map!");return;}//判断是否可以移动bool bCanMove = true;CCSprite* pTileSpriteTop = NULL;CCSprite* pTileSpriteMid = NULL;CCSprite* pTileSpriteBottom = NULL;CCPoint ptPosTop = bToRight?ccp(getPositionX()+boundingBox().size.width,getPositionY()+boundingBox().size.height):ccp(getPositionX(),getPositionY()+boundingBox().size.height);CCPoint ptPosMid = bToRight?ccp(getPositionX()+boundingBox().size.width,getPositionY()+boundingBox().size.height/2):ccp(getPositionX(),getPositionY()+boundingBox().size.height/2);CCPoint ptPosBottom = bToRight?ccp(getPositionX()+boundingBox().size.width,getPositionY()+5):ccp(getPositionX(),getPositionY()+5);//检查马里奥前进方向是否有障碍(检查 上 中 下 三个方向)pTileSpriteTop = m_pGameMap->TileMapLayerPosToTileSprite(ptPosTop);pTileSpriteMid = m_pGameMap->TileMapLayerPosToTileSprite(ptPosMid);pTileSpriteBottom = m_pGameMap->TileMapLayerPosToTileSprite(ptPosBottom);if (pTileSpriteTop!=NULL || pTileSpriteMid!=NULL || pTileSpriteBottom!=NULL){bCanMove = false;//若在前进方向找到了砖块 则 禁止移动}//判断马里奥是否移动出屏幕边界if(bToRight==false)//判断是否左出界{CCPoint ptMarioInWorld = m_pGameMap->convertToWorldSpace(getPosition());if(ptMarioInWorld.x<=0){bCanMove = false;}}else//判断是否右出界(假定,实际不应该出现这种情况){CCPoint ptMarioInWorld = m_pGameMap->convertToWorldSpace(getPosition());if(ptMarioInWorld.x>=SCREEN_WIDTH-boundingBox().size.width){bCanMove = false;}}//根据马里奥当前状态 来处理switch(m_eCurMarioStatus){case enMarioStatusStandLeft://如果是待机状态case enMarioStatusStandRight:{//根据状态播放动画switch(m_eCurMarioLevel){case enMarioLevelSmall:{m_pCcbReader->getAnimationManager()->runAnimationsForSequenceNamed(_CCB_MARIO_SMALL_RUN_);}break;case enMarioLevelBig:{m_pCcbReader->getAnimationManager()->runAnimationsForSequenceNamed(_CCB_MARIO_BIG_RUN_);}break;case enMarioLevelMax:{m_pCcbReader->getAnimationManager()->runAnimationsForSequenceNamed(_CCB_MARIO_MAX_RUN_);}break;}//变更位移if(bCanMove==true){float fCurPosX = getPositionX();if(bToRight){fCurPosX += _MARIO_BASIC_SPEED_PER_SEC_*fT;//向右移动m_bFaceToRight = true;}else{fCurPosX -= _MARIO_BASIC_SPEED_PER_SEC_*fT;//向左移动m_bFaceToRight = false;}setPositionX(fCurPosX);}//改变马里奥状态m_eCurMarioStatus = bToRight?enMarioStatusRunRight:enMarioStatusRunLeft;//设置马里奥面对方向MarioTurn(bToRight);}break;case enMarioStatusRunLeft://若马里奥正在向左移动case enMarioStatusRunRight://这里设计成允许直接变向,如果要增加额外动作效果,可在这里区分{//变更位移if(bCanMove==true){float fCurPosX = getPositionX();if(bToRight){fCurPosX += _MARIO_BASIC_SPEED_PER_SEC_*fT;//向右移动}else{fCurPosX -= _MARIO_BASIC_SPEED_PER_SEC_*fT;//向左移动}setPositionX(fCurPosX);}//改变马里奥状态m_eCurMarioStatus = bToRight?enMarioStatusRunRight:enMarioStatusRunLeft;//设置马里奥面对方向MarioTurn(bToRight);}break;case enMarioStatusOnAirLeft://同方向跳跃正常位移 反方向跳跃 不改变面对方向 且位移量减半case enMarioStatusOnAirRight://{if(bCanMove==true){//变更位移float fCurPosX = getPositionX();//计算位移量float fMoveDis = 0.f;if((m_eCurMarioStatus==enMarioStatusOnAirLeft&&bToRight==true)||(m_eCurMarioStatus==enMarioStatusOnAirRight&&bToRight==false)){fMoveDis = _MARIO_BASIC_SPEED_PER_SEC_*fT*0.5f;//若反向 则 位移量减半}else{fMoveDis = _MARIO_BASIC_SPEED_PER_SEC_*fT;//若同向 则 正常位移}if(bToRight){fCurPosX += fMoveDis;//向右移动}else{fCurPosX -= fMoveDis;//向左移动}setPositionX(fCurPosX);}}break;}}

这个函数代码比较多,我们一段段来分析,首先第一段代码

这段代码根据马里奥移动的方向,找到它移动的边界点ptPosTop,ptPosButton, ptPosMid,再查看这三个点上是否有障碍物,如果有,那么马里奥不能移动。

以上代码判断马里奥是否出了边界,判断出边界有很多办法,这里采用了转化成世界坐标来判断的方法。

这里要注意的是这段代码:

CCPoint ptMarioInWorld = m_pGameMap->convertToWorldSpace(getPosition());

首先getPosition是马里奥精灵调用的函数,它返回的坐标是它的父亲节点的坐标系,也就是地图的坐标系。

然后用m_pGameMap去调用convertToWorldSpace,又把这个坐标转化成窗口的坐标。

这个窗口的坐标,如何x<0或者x>窗口的宽度,那么我们认为出界了。

如果大家不怎么理解上面的话,那么建议好好学习cocos2dx的坐标系,在之前的博文中有。

接下来就是马里奥的移动,如果能移动的话,根据马里奥原来的状态,来控制马里奥的移动,这里选取一种case来说明,因为其他case是差不多的。

马里奥的状态有:向左站立,向右站立,向左移动,向右移动,向左飞行,向右飞行六种状态,我们看看在移动状态下的case是如何处理的

在这个case中,如果能移动,则根据ft时间计算移动长度,再累加到马里奥的x坐标,最后设置新的位置,这样完成了位置的移动

如果方向发生变化,那么马里奥的状态也要变,同时马里奥的方向也要变,这个是调用MarioTurn函数实现的。

如果觉得《cocos2d-x游戏开发系列教程-超级玛丽07-CMGameMap(四)-马里奥平移》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。