cocos2d-x游戏开发系列教程-坦克大战游戏之子弹和地图碰撞
上篇文章实现了坦克与地图碰撞的检测,
这篇我们继续完成子弹和地图的碰撞检测。
1.先设计一个子弹类Bullet,如下所示:
class Bullet : public CCSprite
{
public:
Bullet();
~Bullet(); static Bullet* createBulletWithTank(Tank* tank);
void initBulletWithTank(Tank* tank);
bool fire();
virtual void update(float delta);
void bulletBoom(); private:
bool isFlying;
Tank* mTank;
TileMapInfo* mTileMapInfo;
float stepX, stepY;
};
在上面
static Bullet* createBulletWithTank(Tank* tank);
void initBulletWithTank(Tank* tank);
分别是创建子弹的静态方法和初始化子弹的方法,他们都有一个共同参数tank,
用来表示他们所属的坦克。
fire()方法用来被坦克开火的时候调用,
然后在update方法中控制子弹移动以及碰撞检测。
在撞击后通过调用bulletBoom来引爆子弹,炸毁周围的砖块等。
2.在构造函数中初始化
Bullet::Bullet() :isFlying(false)
{
}
isFlying指示子弹是否在飞行中,初始为false表示没有飞行。
3.void Bullet::initBulletWithTank(Tank* tank)函数的实现:
void Bullet::initBulletWithTank(Tank* tank)
{
mTank = tank;
mTileMapInfo = mTank->getTileMapInfo(); initWithSpriteFrameName("bullet.png");
mTileMapInfo->getTileMap()->addChild(this);
setVisible(false);
}
在Bullet类中我们用mTank成员变量存储了他所属的坦克,
用mTIleMapInfo存储了他所属的地图。
用bullet.png精灵帧初始化了精灵。
然后把子弹加入了地图层中
然后把子弹设置为不可见。
4.继续实现静态方法Bullet* Bullet::createBulletWithTank(Tank* tank)
Bullet* Bullet::createBulletWithTank(Tank* tank)
{
Bullet* bullet = new Bullet();
bullet->initBulletWithTank(tank);
bullet->autorelease(); return bullet;
}
可以看到实现非常简单,创建一个Bullet类实例,然后用tank参数初始化,
最后加入自动释放列表,然后返回子弹类指针。
5.是先fire()函数,控制子弹运动方向等:
bool Bullet::fire()
{
if (!isFlying)
{
isFlying = true;
setVisible(true);
setPosition(mTank->getPosition());
//设置子弹运行方向
int Rotation = mTank->getRotation();
switch (Rotation)
{
case 0:
stepX = 0.0f, stepY = 2.0f;
break;
case 90:
stepX = 2.0f, stepY = 0.0f;
break;
case 180:
stepX = 0.0f, stepY = -2.0f;
break;
case 270:
stepX = -2.0f, stepY = 0.0f;
break;
default:
break;
}
scheduleUpdate();
} return isFlying;
}
可以看到,先判断子弹是否在飞行中,如果不在飞行中被调用了,
则先设置飞行状态isFlying为飞行中。
然后设置子弹初始位置为坦克所在的位置,
然后根据坦克旋转的方向,来设置子弹的运行方向分量——stepX和stepY。
最后调用scheduleUpdate()启动update定时器。这样显示每一帧动画的时候,
就会调用我们的update()函数。
6.下面看看怎么实现update()函数:
void Bullet::update(float delta)
{
CCSprite::update(delta);
//设置移动后的位置
setPosition(ccp(getPositionX() + stepX, getPositionY() + stepY)); //检测是否有碰撞
CCRect rect = boundingBox();
if (mTileMapInfo->collisionTest(rect))
{
unscheduleUpdate();
setVisible(false);
isFlying = false;
//引爆子弹
bulletBoom();
}
}
上面先设置了子弹根据分量stepX和stepY移动后的位置。
然后获取自己在地图上的CCRect,然后传入地图信息类中的碰撞检测函数。
如果碰撞了,就调用unscheduleUpdate()来取消update()定时器,
然后设置子弹为不可见,飞行状态设置为false,调用bulletBoom()来引爆子弹。
7.下面实现Bullet类中最后一个成员函数bulletBoom(),来看看它怎么引爆子弹的:
void Bullet::bulletBoom()
{
CCRect rect = boundingBox();
CCSize mapSize = mTileMapInfo->getTileMap()->getContentSize(); if (rect.getMinX() < 0 || rect.getMaxX() >= mapSize.width ||
rect.getMinY() < 0 || rect.getMaxY() >= mapSize.height)
return ; CCTMXLayer* tmxLayer = mTileMapInfo->getTileMap()->layerNamed("layer_0");
CCSize tileSize = tmxLayer->getMapTileSize(); //调整Y轴位tmx地图中的Y轴
float MinY = mapSize.height - rect.getMinY();
float MaxY = mapSize.height - rect.getMaxY(); //将与子弹碰撞的墙壁tileWall图块删除
CCPoint pt = ccp((int)rect.getMinX() / tileSize.width,(int)(MinY / tileSize.height));
if (gidToTileType[tmxLayer->tileGIDAt(pt)] == tileWall)
tmxLayer->setTileGID(gidToTileType[tileNone], pt); pt = ccp((int)rect.getMinX() / tileSize.width,(int)(MaxY / tileSize.height));
if (gidToTileType[tmxLayer->tileGIDAt(pt)] == tileWall)
tmxLayer->setTileGID(gidToTileType[tileNone], pt); pt = ccp((int)rect.getMaxX() / tileSize.width,(int)(MinY / tileSize.height));
if (gidToTileType[tmxLayer->tileGIDAt(pt)] == tileWall)
tmxLayer->setTileGID(gidToTileType[tileNone], pt); pt = ccp((int)rect.getMaxX() / tileSize.width,(int)(MaxY / tileSize.height));
if (gidToTileType[tmxLayer->tileGIDAt(pt)] == tileWall)
tmxLayer->setTileGID(gidToTileType[tileNone], pt);
}
先获取了自己的位置rect和地图的尺寸mapSIze。
首先判断了自己是否跑到了地图外边。如果在地图外边就直接返回。
然后获取了layer_0层的地图信息,将屏幕中的Y轴转换成tmx地图中的Y轴,
然后判断子弹四个角所接触的图块,如果图块是墙壁,那么获取墙壁的GID都设置成tileNone,这样就相当于炸毁墙壁图块。
8.最后我们需要在Tank类型初始化我们的子弹才能看到子弹运行效果,在坦克类中:
void Tank::initTankWithTankType(const char* tankTypeName, TileMapInfo* tileMapInfo)
{
initWithSpriteFrameName(tankTypeName);
mTileMapInfo = tileMapInfo; //将坦克放入地图层中
mTileMapInfo->getTileMap()->addChild(this); //缩放到合适大小
CCTMXTiledMap* tmxTileMap = mTileMapInfo->getTileMap();
CCSize tileSize = tmxTileMap->getTileSize();
CCSize tankSize = getContentSize();
//比地图上砖块小一点
setScale((tileSize.height * 2-4) / (tankSize.height)); //初始化坦克的子弹
mBullet = Bullet::createBulletWithTank(this);
}
可以看到很简单在最下面一行,给mBullet成员函数调用Bullet::createBulletWithTank(this)初始化了子弹。
然后我们还要在Tank类的命中响应函数中调用开火命令:
void Tank::command(enumOrder order)
{
float stepX = 0.0f;
float stepY = 0.0f;
static float fRotation = 0.0f; switch (order)
{
case cmdNothing:
break;
case cmdGoUP:
stepY = 1.0f;
fRotation = 0.0f;
break;
case cmdGoDown:
stepY = -1.0f;
fRotation = 180.0f;
break;
case cmdGoLeft:
stepX = -1.0f;
fRotation = 270.0f;
break;
case cmdGoRight:
stepX = 1.0f;
fRotation = 90.0f;
break;
case cmdFire:
//调用子弹开火
mBullet->fire();
break;
default:
break;
} //检测地图上的碰撞
CCRect rect = this->boundingBox();
if (!mTileMapInfo->collisionTest(CCRectMake(rect.getMinX() + stepX,
rect.getMinY() + stepY, rect.size.width, rect.size.height)))
{
setPositionX(getPositionX() + stepX);
setPositionY(getPositionY() + stepY);
} //根据运行方向旋转坦克
setRotation(fRotation);
}
case cmdFire:
//调用子弹开火
mBullet->fire();
break;
容易看到,只加上这一句就能实现开火效果了。
下面我们编译运行程序,看看效果:
完整实现的代码下载地址如下:
http://download.csdn.net/detail/yincheng01/6760931
cocos2d-x游戏开发系列教程-坦克大战游戏之子弹和地图碰撞的更多相关文章
- cocos2d-x游戏开发系列教程-坦克大战游戏启动界面的编写
用前面介绍的方法,创建一个cocos2d-x项目,可以看到新项目内容如下图:
- cocos2d-x游戏开发系列教程-坦克大战游戏之敌方坦克AI的编写
在上篇我们完成了子弹和地图碰撞的检测,在这篇我们将完成敌方坦克AI的编写. 具体思路是屏幕中保持有四个敌方坦克,然后坦克随机方向运动,并且子弹消失后1秒发射一次 1.我们新建一个敌方坦克的AI类来控制 ...
- cocos2d-x游戏开发系列教程-坦克大战游戏之子弹的碰撞检测处理
在上篇我们加上了简单的坦克之间的碰撞检测,这篇我们继续加上子弹之间, 子弹与坦克之间的碰撞检测,对于上一篇碰撞处理不太完美的地方我们继续改进. 1.子弹之间的碰撞 //玩家子弹和敌方子弹之间的碰撞 C ...
- cocos2d-x游戏开发系列教程-坦克大战游戏之所有坦克之间的碰撞检测
上篇我们完成了简单的AI编写,但是各个坦克移动时之间是可以重合的, 这节课我们来完成坦克之间的碰撞检测,还是在上篇的EnemyAI中完成. 1.我先现在坦克类Tank中添加两个成员变量: CC_SYN ...
- cocos2d-x游戏开发系列教程-坦克大战游戏之虚拟手柄控制坦克移动
上篇显示了控制手柄,但是还不能用来控制坦克, 这篇将会讲手柄和坦克的移动结合起来. 1.先在CityScene场景中实现场景的虚函数virtual void onEnter(); onEnter在进入 ...
- cocos2d-x游戏开发系列教程-坦克大战游戏之坦克和地图碰撞的检测下
上篇我们完成了地图的信息获取和碰撞检测,这篇我们整合到程序中. 在这之前我们改造一下Tank类,使它更加模块化,共容易理解: 1.改造后的Tank类声明如下: class Tank : public ...
- cocos2d-x游戏开发系列教程-坦克大战游戏之虚拟手柄的显示
上篇文章我们有了坦克,但是没有手柄,无法控制坦克. 1.这篇我们编写虚拟手柄来控制坦克.头文件大致内容如下: #define RES_PADDLE_LEFT "paddle/left.png ...
- cocos2d-x游戏开发系列教程-坦克大战游戏之坦克的显示
1.先定义坦克的一些属性 class Tank : public CCSprite { public : Tank(); ~Tank(); static Tank* createTankWithTan ...
- cocos2d-x游戏开发系列教程-坦克大战游戏加载地图的编写
上节课写了关卡选择场景,那么接下来写关卡内容,先写最基本的地图的加载 我们新建一个场景类,如下所示: class CityScene : public cocos2d::CCLayer { publi ...
随机推荐
- 循环训练(for的嵌套、while、do while)以及异常处理
For的嵌套 练习一: 练习二: 练习三: 练习四: while的使用方法: 示例一: 示例二: 示例三: while的练习题: do while的使用示例: 异常处理示例: try catch ...
- Lowest Common Multiple Plus
Lowest Common Multiple Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
- Python3 将configparser从ini文件中读取的内容转换成字典格式
因为写脚本的用到了,所以研究了下怎么将configparser从ini文件中读取的内容转换成字典格式. 整理一下,希望能对大家有帮助. 从http://stackoverflow.com/questi ...
- linux shell 执行多个命令的方法
(1)在每个命令之间用:(分号)隔开. (2)在每个命令之间用&&隔开. &&表示:若前一个命令执行成功,才会执行下一个.这样,可确保所有的命令执行完毕后,其执行过程都 ...
- MySQL Cluster-备份恢复初步测试
参考文档 http://blog.chinaunix.net/uid-20639775-id-1617795.html http://xxtianxiaxing.iteye.com/blog/5 ...
- Hadoop HDFS分布式文件系统设计要点与架构
Hadoop HDFS分布式文件系统设计要点与架构 Hadoop简介:一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群 ...
- cocos2dx进阶学习之CCLayer
继承关系 CCLayer -> CCNode,CCTouchDelegate,CCAccelerometerDelegate,CCKeypadDelegate CCLayer在cocos2dx中 ...
- AFNetworking GET和POST请求
GET请求 代码展示: 在storyBoard中每个请求关联一个Button #pragma mark - get请求 - (IBAction)getRequest:(id)sender { // 参 ...
- ThinkPHP - F函数,更新配置文件
Html代码: <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset=&quo ...
- tomcat环境变量的配置(网上摘,全部验证通过)
tomcat环境变量的配置 1.===> 进入bin目录下,双击startup.bat看是否报错.一般肯定会报. 2.===> 右键我的电脑===>高级===>环境变量 ...