改写《魔塔》前篇07:碰撞检测(附:前期阶段项目下载)

来源:互联网 发布:手机酷狗链接不到网络 编辑:程序博客网 时间:2024/05/22 12:56

       前面已经初步实现了勇士在地图内的移动。这一篇我们就 开始加入碰撞检测,让勇士在碰到墙壁之后无法行走,到地图边缘时也不会走出去。

      我们先来实现墙壁的碰撞逻辑。大家可以先思考一下,如何判断勇士撞到墙了?相信你已经有了一些思路了:可以在menuCallBackMove方法中判断目标地点的图块类型,如果是墙壁的话,就不让勇士移动。没错,这就是我们将要采用的方法。下面我们看一下如何用代码实现这个逻辑。

(1)先熟悉一下CCTMXLayer中的一个重要方法tileGIDAt(CCPoint tileCoordinate)。此方法可以根据传入的Tilemap坐标,返回坐标位置的图块编号,如果该位置没有图块,则返回0.有了这个方法,就可以方便地判断目标位置是否有墙壁了。现在只需要将勇士的cocos2d-x坐标转换为Tilemap坐标即可。转换方法如下,在计算y坐标时,用最大的y值减去当前y值即可。首先我们在HelloWorldScene.h文件里声明方法tileCoordForPosition,即把“CCPoint tileCoordForPosition(CCPoint position);”添加到声明方法里即可。然后在.cpp文件的最后添加下面代码。

CCPoint HelloWorld::tileCoordForPosition(CCPoint position){int x=position.x/map->getTileSize().width;int y=(((map->getMapSize().height-1)*map->getTileSize().height)-position.y)/map->getTileSize().height;return ccp(x,y);}

(2)在HelloWorldScene.h头文件里定义几个碰撞类型:

typedef enum

{

   kNone=1,//可以通行

   kWall,//墙

   kEnemy,//敌人

}CollisionType; //碰撞类型

(3)添加一个方法checkCollision(用于碰撞检测)。注意:在获取图块ID之前,先判断目标位置是否在地图范围内,如果超出了地图范围,则返回kWall类型,阻止勇士移动。首先在HelloWorldScene.h文件添加方法的声明,即“CollisionType checkCollision(CCPoint heroPosition);”。然后在.cpp文件里实现此方法,代码如下:

CollisionType HelloWorld::checkCollision(CCPoint heroPosition){//cocos2d-x坐标转换为Tilemap坐标CCPoint tileCoord=tileCoordForPosition(heroPosition);//如果勇士坐标超过地图边界,返回kWall类型,阻止其移动if(heroPosition.x<0||tileCoord.x>map->getMapSize().width-1||tileCoord.y<0||tileCoord.y>map->getMapSize().height-1)return kWall;//获取当前坐标位置的图块IDint tileGid=map->layerNamed("wall")->tileGIDAt(tileCoord);//如果图块ID不为0,表示有墙if(tileCoord){    return kWall;}//可以通行return kNone;}

(4)在menuCallBackMove这个回调方法中调用checkCollision,检测碰撞。如果碰撞类型为墙壁,只需要设置勇士的朝向;如果无障碍,则开始行走。修改menuCallBackMove()函数如下:

void HelloWorld::menuCallBackMove(CCObject* pSender){//正在移动中,不接受新的指令if (isHeroWalking)return;    CCNode *node = (CCNode *) pSender;//按钮的tag就是需要行走的方向int targetDirection = node->getTag();//移动的距离CCPoint moveByPosition;switch(targetDirection){case kDown:moveByPosition=ccp(0,-32);break;case kLeft:moveByPosition=ccp(-32,0);break;case kRight:moveByPosition=ccp(32,0);break;case kUp:moveByPosition=ccp(0,32);break;}//计算目标坐标,用当前勇士坐标加上移动距离CCPoint targetPosition = ccpAdd(heroSprite->getPosition(), moveByPosition);//调用checkCollision检测碰撞类型,如果是墙壁,则只需要设置勇士的朝向if (checkCollision(targetPosition) == kWall){setFaceDirection((HeroDirection)targetDirection);return;}//利用CCSpawn将行走动画和移动同时执行CCAction *action = CCSequence::create(CCSpawn::create(CCAnimate::create(walkAnimation[targetDirection]),CCMoveBy::create(0.28f,moveByPosition),NULL),        //把方向信息传递给onWalkDone方法CCCallFuncND::create(this, callfuncND_selector(HelloWorld::onWalkDone), (void*)targetDirection),NULL);//主角执行动作heroSprite->runAction(action);//人物开始移动,设置标识为trueisHeroWalking = true;}

现在编译运行程序,控制勇士在地图上行走,当遇到墙的时候,勇士不会再穿墙而过了,而是乖乖地站在原地不动。

                

最后附上前期阶段项目源码的下载地址:点此下载

原创粉丝点击