接下来直接运行游戏,我们发现地图现在充实多了,有点真正游戏的样子了。
(2)我们希望勇士遇到地图上的物品时,头上会冒出一行文字说明,如“获取小血瓶,生命值+100”,然后将地图上的物品移除,并增加到勇士自己的背包当中。下面来看代码实现。
首先要在GameConstants.h中增加一种碰撞类型kItem,接着为GameMap类增加获取itemLayer的方法:
CC_PROPERTY_READONLY(CCTMXLayer*,itemLayer,ItemLayer);
itemLayer=this->layerNamed("item");
//获取物品层对应的图块ID tileGid=sGlobal->gameMap->getItemLayer()->tileGIDAt(targetTileCoord); //如果图块ID不为0,表示有物品 if(tileGid) { //拾取物品 pickUpItem(); return kItem; }
//拾取物品 void Hero::pickUpItem() { //显示提示消息 sGlobal->gameLayer->showTip("get an item, hp +100",this->getPosition()); //将物品从地图上移除 sGlobal->gameMap->getItemLayer()->removeTileAt(targetTileCoord); }
//调用checkCollision检测碰撞类型,如果是墙壁,则只需要设置勇士的朝向 CollisionType collisionType=checkCollision(targetPosition); if(collisionType==kWall||collisionType==kEnemy) { setFaceDirection((HeroDirection)direction); return; }
在地图上添加门的方法仍然与添加墙壁、怪物和物品的方法基本相同。不同之处是,勇士在执行打开门的操作后,门需要播放一段打开的动画。
还是一步一步来,在GameConstants.h中增加一种碰撞类型kDoor。在GameMap中增加doorLayer的相关代码,包括初始化get方法。这里就不再列出了。接下来修改Hero的checkCollision方法,增加门的碰撞检测:
//获取门对应的坐标图块ID tileGid=sGlobal->gameMap->getDoorLayer()->tileGIDAt(targetTileCoord); if(tileGid) { //打开门 openDoor(tileGid); return kDoor; }
//打开门 void Hero::openDoor(int gid) { //如果门正在被开启,则返回 if(isDoorOpening) return; //保存正在被开启的门的初始GID targetDoorGID=gid; isDoorOpening=true; //定时器更新门动画 schedule(schedule_selector(Hero::updteOpenDoorAnimation),0.1f); }
//更新开门动画 void Hero::updteOpenDoorAnimation(float dt) { //计算动画下一帧的图块ID,TileMap的图块编号方式是横向递增1, //所以每列相同的位置的图块ID相差了每行图块的个数 int nextGID=sGlobal->gameMap->getDoorLayer()->tileGIDAt(targetTileCoord)+4; //如果超过了第4帧动画,就将当前位置的图块删除,并取消定时器 if(nextGID-targetDoorGID>4*3){ sGlobal->gameMap->getDoorLayer()->removeTileAt(targetTileCoord); unschedule(schedule_selector(Hero::updteOpenDoorAnimation)); isDoorOpening=false; }else{ //更新动画至下一帧 sGlobal->gameMap->getDoorLayer()->setTileGID(nextGID,targetTileCoord); } }
//调用checkCollision检测碰撞类型,如果是墙壁、怪物、门,则只需要设置勇士的朝向 CollisionType collisionType=checkCollision(targetPosition); if(collisionType==kWall||collisionType==kEnemy||collisionType==kDoor) { setFaceDirection((HeroDirection)direction); return; }