您的位置:首页 > 移动开发 > Cocos引擎

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

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

      我们先来实现墙壁的碰撞逻辑。大家可以先思考一下,如何判断勇士撞到墙了?相信你已经有了一些思路了:可以在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;
//获取当前坐标位置的图块ID
int 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);
//人物开始移动,设置标识为true
isHeroWalking = true;
}

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

                


最后附上前期阶段项目源码的下载地址:点此下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cocos2d-x 魔塔