zoukankan      html  css  js  c++  java
  • cocos2d-x游戏开发系列教程-坦克大战游戏之所有坦克之间的碰撞检测

    上篇我们完成了简单的AI编写,但是各个坦克移动时之间是可以重合的,

    这节课我们来完成坦克之间的碰撞检测,还是在上篇的EnemyAI中完成。


    1.我先现在坦克类Tank中添加两个成员变量:

    	CC_SYNTHESIZE(CCRect, mMovedRect, MovedRect);
    	CC_SYNTHESIZE(bool, IsBlock, Block);
    mMovedRect是移动后的位置,目的是保存移动后的位置来检测碰撞,

    如果发现与其他坦克碰撞了,则不执行移动动作;

    IsBlock是用来标记坦克是否被碰撞的。


    2.然后我们还得在Tank类中添加一个移动函数,根据是否阻塞来控制坦克移动:

    	void move();
    具体实现很简单,如下:

    void Tank::move()
    {
    	if (!IsBlock)
    	{
    		setPosition(ccp(mMovedRect.getMidX(), mMovedRect.getMidY()));
    	}
    }

    3.既然是碰撞检测,当然得有简单的碰撞函数先是检测两个矩形区域是否相交:

    bool EnemyAI::IsRectIntersect(CCRect rectA, CCRect rectB)
    {
    	float left = max(rectA.getMinX(), rectB.getMinX());
    	float right = min(rectA.getMaxX(), rectB.getMaxX());
    	if (left > right)
    		return false;
    
    	float top = min(rectA.getMaxY(), rectB.getMaxY());
    	float bottom = max(rectA.getMinY(), rectB.getMinY());
    	if (top < bottom)
    		return false;
    
    	return true;
    }
    如上,检测原理很简单,

    假设A矩形在B矩形左边,那么A矩形的右边的X坐标小于B矩形左边的X坐标,

    那么两个矩形不相交,反之A矩形在B矩形右边亦然。

    在假设A矩形在B矩形上方或下方,检测原理和上面相同。

    如果检测到矩形相交,则返回true。


    4.我们再到EnemyAI中添加一个函数,来检测所有坦克之间的碰撞:

    void EnemyAI::collisionTest()
    {
    	//坦克和敌方坦克之间的碰撞检测
    	CCObject* pObj;
    	CCARRAY_FOREACH(mEnemyTanks, pObj)
    	{
    		Tank* enemyTank = (Tank*)pObj;
    		if (IsRectIntersect(mTank->getMovedRect(), enemyTank->getMovedRect()))
    		{
    			enemyTank->setBlock(true);
    			mTank->setBlock(true);
    		}
    	}
    
    	//敌方坦克之间的碰撞
    	CCArray* ccTmpArray = CCArray::create();
    	ccTmpArray->addObjectsFromArray(mEnemyTanks);
    	while (ccTmpArray->count())
    	{
    		CCObject* pObj;
    		Tank* tmpTank = (Tank*)ccTmpArray->lastObject();
    		ccTmpArray->removeLastObject();
    		CCARRAY_FOREACH(ccTmpArray, pObj)
    		{
    			if (IsRectIntersect(tmpTank->getMovedRect(), ((Tank*)pObj)->getMovedRect()))
    			{
    				tmpTank->setBlock(true);
    				((Tank*)pObj)->setBlock(true);
    				ccTmpArray->removeObject(pObj);
    			}
    		}
    	}
    }

    如上,我们先单个检测玩家坦克和地方坦克的碰撞,然后检测敌方坦克之间的碰撞:

    我们先从敌方坦克数组中取出一辆坦克,然后将他从数组中移除,

    再跟其他所有坦克进行碰撞检测,如果发现有碰撞的坦克,设置他的IsBlock阻塞标记为true,

    然后将它从数组中移除,如此循环,直到数组中所有坦克检测完成。


    5.最后我们需要在EnemyAI中的void EnemyAI::tankAction(float delta)

    中检测碰撞以及控制坦克行为:

    void EnemyAI::tankAction(float delta)
    {
    	CCObject* pObj;
    	CCARRAY_FOREACH(mEnemyTanks, pObj)
    	{
    		Tank* tank = (Tank*)pObj;
    
    		//坦克按照上次的方向一直往前走
    		int Rotation = tank->getRotation();
    		tank->command((enumOrder)(Rotation / 90 + 1));
    
    		//坦克每隔一秒开一次火
    		tank->setBulletDelta(tank->getBulletDelta() + delta);
    		if (tank->getBulletDelta() > 1)
    		{
    			//开火后,如果子弹在飞行中,归零计时
    			if (tank->command(cmdFire))
    			{
    				tank->setBulletDelta(0.0);
    			}
    		}
    
    		//检测坦克之间的碰撞
    		collisionTest();
    
    		//如果坦克阻塞,换个方向
    		if (tank->getBlock())
    			tank->setRotation((int)(CCRANDOM_0_1() * 3.2) * 90);
    		//如果上面的判断完成后,坦克根据自己的阻塞状态移动
    		tank->move();
    	}
    	mTank->move();
    }
    可以看到在检测了碰撞后,用move来控制坦克的移动。


    下面我们编译运行程序看看效果:




    完整代码下载地址:

    http://download.csdn.net/detail/yincheng01/6773421

  • 相关阅读:
    PDF文件中的Form保存问题
    Understanding IP Fragmentation
    tcp ip guide IPsec IKE
    Windows安全事件日志中的事件编号与描述
    Cisco PIX fix up and Juniper firewall FTP ALG
    很好的IPSec介绍,详细解释了IKE协商的2个阶段的作用
    virtualbox 下运行Ubuntu 8.10的分辨率和guest additions的问题。
    Fixing the ‘Do you want to display nonsecure items’ message
    windows xp 开始菜单里面所有项目右键不起作用。
    HP backup and recovery manager
  • 原文地址:https://www.cnblogs.com/new0801/p/6177287.html
Copyright © 2011-2022 走看看