在游戏中我们通常会涉及到两个精灵之间的碰撞的计算,那么在Cocos2d-x里面我们通常会用矩形碰撞检测来计算两个精灵在运动的过程中是否碰撞到了。原理很简单,就是当运动的时候通过精灵的矩形坐标进行遍历来计算精灵之间是否有重合,如果有重合那就证明是碰撞上了。

下面看一下下面的例子:

Ball精灵会根据帧速率来进行运动的,下面是Ball精灵的实现代码:

#ifndef _BALL_H_
#define _BALL_H_ #include "cocos2d.h"
/*
创建一个球的精灵
*/
class Paddle; using namespace cocos2d; class Ball : public CCSprite
{
CCPoint m_velocity;
public:
Ball(void);
virtual ~Ball(void); float radius();
//BOOL initWithTexture(CCTexture2D* aTexture);
//virtual void setTexture(CCTexture2D* newTexture);
void move(ccTime delta);
void collideWithPaddle(Paddle* paddle); public:
void setVelocity(CCPoint velocity){m_velocity = velocity;}
CCPoint getVelocity(){return m_velocity;} public:
static Ball* ballWithTexture(CCTexture2D* aTexture);
}; #endif #include "pch.h"
#include "Ball.h"
#include "Paddle.h" Ball::Ball(void)
{
} Ball::~Ball(void)
{
} float Ball::radius()
{
return getTexture()->getContentSize().width / ;
}
//使用CCTexture2D创建ball精灵
Ball* Ball::ballWithTexture(CCTexture2D* aTexture)
{
Ball* pBall = new Ball();
pBall->initWithTexture(aTexture);
pBall->autorelease(); return pBall;
}
//移动ball精灵
void Ball::move(ccTime delta)
{
//根据m_velocity的数值设置ball精灵的位置
this->setPosition( ccpAdd(getPosition(), ccpMult(m_velocity, delta)) ); if (getPosition().x > - radius())
{
setPosition( ccp( - radius(), getPosition().y) );
m_velocity.x *= -;
}
else if (getPosition().x < radius())
{
setPosition( ccp(radius(), getPosition().y) );
m_velocity.x *= -;
}
}
//判断是否碰撞到paddle精灵
void Ball::collideWithPaddle(Paddle* paddle)
{
//获取paddle精灵的矩形位置
CCRect paddleRect = paddle->rect();
//转化成绝对的位置
paddleRect.origin.x += paddle->getPosition().x;
paddleRect.origin.y += paddle->getPosition().y;
//获取paddle精灵的矩形的相关数值
float lowY = paddleRect.getMinY(); //CCRect::getMidY(paddleRect);
float midY = paddleRect.getMidY(); //CCRect::CCRectGetMidY(paddleRect);
float highY =paddleRect.getMaxY();// CCRect::CCRectGetMaxY(paddleRect); float leftX = paddleRect.getMinX();//CCRect::CCRectGetMinX(paddleRect);
float rightX =paddleRect.getMaxX(); //CCRect::CCRectGetMaxX(paddleRect); if (getPosition().x > leftX && getPosition().x < rightX) { bool hit = false;
float angleOffset = 0.0f;
//判断是否碰撞到paddle精灵
if (getPosition().y > midY && getPosition().y <= highY + radius())
{
setPosition( CCPointMake(getPosition().x, highY + radius()) );
hit = true;
angleOffset = (float)M_PI / ;
}
else if (getPosition().y < midY && getPosition().y >= lowY - radius())
{
setPosition( CCPointMake(getPosition().x, lowY - radius()) );
hit = true;
angleOffset = -(float)M_PI / ;
} if (hit)
{
//碰撞到则调整方向
float hitAngle = ccpToAngle(ccpSub(paddle->getPosition(), getPosition())) + angleOffset; float scalarVelocity = ccpLength(m_velocity) * 1.05f;
float velocityAngle = -ccpToAngle(m_velocity) + 0.5f * hitAngle; m_velocity = ccpMult(ccpForAngle(velocityAngle), scalarVelocity);
}
}
}

Paddle精灵相当于是挡板的意思,Paddle精灵是静止的,当Ball精灵碰撞到Paddle精灵的时候,运动的轨迹就会发生变化。

Paddle精灵的代码:

#ifndef _PADDLE_H_
#define _PADDLE_H_ #include "cocos2d.h" using namespace cocos2d;
/*
创建一个挡板精灵
*/
typedef enum tagPaddleState
{
kPaddleStateGrabbed,
kPaddleStateUngrabbed
} PaddleState; class Paddle : public CCSprite, public CCTargetedTouchDelegate
{
PaddleState m_state; public:
Paddle(void);
virtual ~Paddle(void); CCRect rect();
bool initWithTexture(CCTexture2D* aTexture);
virtual void onEnter();
virtual void onExit();
bool containsTouchLocation(CCTouch* touch);
virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
virtual void ccTouchEnded(CCTouch* touch, CCEvent* event); virtual void touchDelegateRetain();
virtual void touchDelegateRelease(); static Paddle* paddleWithTexture(CCTexture2D* aTexture);
}; #endif #include "pch.h"
#include "Paddle.h" Paddle::Paddle(void)
{
} Paddle::~Paddle(void)
{
}
//获取paddle精灵的矩形位置
CCRect Paddle::rect()
{
CCSize s = getTexture()->getContentSize();
return CCRectMake(-s.width / , -s.height / , s.width, s.height);
} Paddle* Paddle::paddleWithTexture(CCTexture2D* aTexture)
{
Paddle* pPaddle = new Paddle();
pPaddle->initWithTexture( aTexture );
pPaddle->autorelease(); return pPaddle;
} bool Paddle::initWithTexture(CCTexture2D* aTexture)
{
if( CCSprite::initWithTexture(aTexture) )
{
m_state = kPaddleStateUngrabbed;
} return true;
} void Paddle::onEnter()
{
CCTouchDispatcher* pDispatcher = CCDirector::sharedDirector()->getTouchDispatcher();
pDispatcher->addTargetedDelegate(this, , true);
CCSprite::onEnter();
} void Paddle::onExit()
{
CCTouchDispatcher* pDispatcher = CCDirector::sharedDirector()->getTouchDispatcher();
pDispatcher->removeDelegate(this);
CCSprite::onExit();
} bool Paddle::containsTouchLocation(CCTouch* touch)
{
return rect().containsPoint(convertTouchToNodeSpaceAR(touch));;//CCRect::containsPoint(rect(), convertTouchToNodeSpaceAR(touch));
} bool Paddle::ccTouchBegan(CCTouch* touch, CCEvent* event)
{
if (m_state != kPaddleStateUngrabbed) return false;
if ( !containsTouchLocation(touch) ) return false; m_state = kPaddleStateGrabbed;
return true;
}
//移动paddle精灵
void Paddle::ccTouchMoved(CCTouch* touch, CCEvent* event)
{
CCAssert(m_state == kPaddleStateGrabbed, L"Paddle - Unexpected state!"); CCPoint touchPoint = touch->getLocationInView();
touchPoint = CCDirector::sharedDirector()->convertToGL( touchPoint ); setPosition( CCPointMake(touchPoint.x, getPosition().y) );
} void Paddle::ccTouchEnded(CCTouch* touch, CCEvent* event)
{
CCAssert(m_state == kPaddleStateGrabbed, L"Paddle - Unexpected state!"); m_state = kPaddleStateUngrabbed;
} void Paddle::touchDelegateRetain()
{
this->retain();
} void Paddle::touchDelegateRelease()
{
this->release();
}

下面是实现碰撞的Layer:

//------------------------------------------------------------------
//
// 初始化[碰撞的Layer
//
//------------------------------------------------------------------
PongLayer::PongLayer()
{
m_ballStartingVelocity = CCPointMake(20.0f, -100.0f);
//创建ball精灵
m_ball = Ball::ballWithTexture( CCTextureCache::sharedTextureCache()->addImage("cat.png") );
m_ball->setPosition( CCPointMake(160.0f, 240.0f) );
m_ball->setVelocity( m_ballStartingVelocity );
addChild( m_ball );
m_ball->retain(); //创建4个Paddle精灵
CCTexture2D* paddleTexture = CCTextureCache::sharedTextureCache()->addImage("paddle.png");
m_paddles = new CCArray();
Paddle* paddle = Paddle::paddleWithTexture(paddleTexture);
paddle->setPosition( CCPointMake(, ) );
m_paddles->addObject( paddle ); paddle = Paddle::paddleWithTexture( paddleTexture );
paddle->setPosition( CCPointMake(, - kStatusBarHeight - ) );
m_paddles->addObject( paddle ); paddle = Paddle::paddleWithTexture( paddleTexture );
paddle->setPosition( CCPointMake(, ) );
m_paddles->addObject( paddle ); paddle = Paddle::paddleWithTexture( paddleTexture );
paddle->setPosition( CCPointMake(, - kStatusBarHeight - ) );
m_paddles->addObject( paddle ); CCObject* arrayItem;
CCARRAY_FOREACH(m_paddles, arrayItem){
paddle = (Paddle*)(arrayItem);
if(!paddle)
break;
addChild(paddle);
}
//每一帧刷新ball精灵的运动
schedule( schedule_selector(PongLayer::doStep) );
} PongLayer::~PongLayer()
{
m_ball->release();
m_paddles->release();
} void PongLayer::resetAndScoreBallForPlayer(int player)
{
m_ballStartingVelocity = ccpMult(m_ballStartingVelocity, -1.1f);
m_ball->setVelocity( m_ballStartingVelocity );
m_ball->setPosition( CCPointMake(160.0f, 240.0f) );
} void PongLayer::doStep(ccTime delta)
{
//移动ball精灵
m_ball->move(delta);
Paddle* paddle;
CCObject* arrayItem;
CCARRAY_FOREACH(m_paddles, arrayItem){
paddle = (Paddle*)(arrayItem);
if(!paddle)
break;
//判断ball精灵是否碰到paddle精灵
m_ball->collideWithPaddle( paddle );
}
//判断是否碰到边界
if (m_ball->getPosition().y > - kStatusBarHeight + m_ball->radius())
resetAndScoreBallForPlayer( kLowPlayer );
else if (m_ball->getPosition().y < -m_ball->radius())
resetAndScoreBallForPlayer( kHighPlayer );
m_ball->draw();
}

在helloworld项目中加入该Layer

CCScene* HelloWorld::scene()
{
CCScene * scene = NULL;
do
{ // 'scene'是一个可以自动释放的对象
scene = CCScene::create();
//创建失败跳出循环
CC_BREAK_IF(! scene);
PongLayer *pongLayer = new PongLayer();
scene->addChild(pongLayer);
} while (); // 返回scene
return scene;
}

运行的效果:

[Cocos2d-x For WP8]矩形碰撞检测的更多相关文章

  1. 写一些封装part1 (事件绑定移除,圆形矩形碰撞检测)

    var EventHandle = { addEvent:function(ele,type,handle){ if (ele.addEventListener) { ele.addEventList ...

  2. 旋转矩形碰撞检测 OBB方向包围盒算法

    在cocos2dx中进行矩形的碰撞检测时需要对旋转过的矩形做碰撞检查,由于游戏没有使用Box2D等物理引擎,所以采用了OBB(Oriented bounding box)方向包围盒算法,这个算法是基于 ...

  3. Cocos2d-三维拾取Ray-AABB碰撞检测算法【转】

    1.三维拾取技术 在3D游戏中通常会有这样的需求,用户可以选取3D世界中的某些物体进行如拖拽等操作,这时便需要程序通过将二维屏幕上的点坐标转换为三维世界中的坐标,并进行比对,这个过程就需要用到三维拾取 ...

  4. 2D游戏中的碰撞检测:圆形与矩形碰撞检测(Javascrip版)

    一,原理介绍 这回有点复杂,不过看懂了还是很好理解的.当然,我不敢保证这种算法在任何情况下都会起效果,如果有同学测试时,发现出现错误,请及时联系我. 我们首先来建立一个以圆心为原点的坐标系: 然后要检 ...

  5. canvas中的碰撞检测笔记

    用 canvas 做小游戏或者特效,碰撞检测是少不了的.本文将会涉及普通的碰撞检测,以及像素级的碰撞检测.(本文的碰撞检测均以矩形为例) 普通碰撞检测 普通的矩形碰撞检测比较简单.即已知两个矩形的各顶 ...

  6. 白鹭引擎 - 碰撞检测 ( hitTestPoint )

    1, 矩形碰撞检测 class Main extends egret.DisplayObjectContainer { /** * Main 类构造器, 初始化的时候自动执行, ( 子类的构造函数必须 ...

  7. Cocos2d-x游戏移植到WP8之路 -- c++和c#交互

    Cocos2d-x是眼下最流行的手机游戏引擎之中的一个,开源.轻量.多平台等的诸多特性使得它被非常多国内外手游开发人员所喜爱. 利用Cocos2d-x来开发Windows Phone 8的游戏相同也是 ...

  8. Java游戏之碰撞检测

    在进行Java游戏开发时,我们经常会遇到碰撞检测的问题.如坦克大战中,炮弹与坦克相遇发生爆炸:守卫者游戏中,守卫者发射的箭与怪物相遇使怪物失血:打飞机游戏中,飞机发送的子弹与敌机相遇干掉敌机.这些都需 ...

  9. java图形界面写个小桌面,内置简单小软件

    一.做个这样的效果,双击图标打开相应的应用 二.主界面类,使用JavaSwing的JDesktopPane类创建这个桌面 package com.swing; import java.awt.Bord ...

随机推荐

  1. SQLServer多表连接查询

    双表内部连接查询 select wName,dName from DepartMent,Worker where DepartMent.dID=Worker.did select wName,dNam ...

  2. gdo图形引擎中的旋转角

    横滚角(Roll) bank.roll  绕y轴 z轴正向为起点逆时针方向:往左为正,往右为负,水平时为0:有效范围:-180度-180度 注:下图是从飞机的尾部-->头部方向观察所得 俯仰角( ...

  3. HDU5792 World is Exploding(树状数组)

    一共6种情况,a < b且Aa < Ab, c < d 且Ac > Ad,这两种情况数量相乘,再减去a = c, a = d, b = c, b = d这四种情况,使用树状数组 ...

  4. 异常:System.BadImageFormatException,未能加载正确的程序集XXX

    IDE:VS2015 语言:C# 异常:System.BadImageFormatException,未能加载正确的程序集XXX或其某一依赖项... 一般是由于目标程序的目标平台与其某一依赖项的目标编 ...

  5. OS X thrift setup

    OS X Setup The following command install all the required tools and libraries to build and install t ...

  6. 第十七篇:使用窗口的cache属性加速SOUI的渲染

    内容渲染速度是决定一个UI成败的关键.无论UI做得多华丽,没有速度都没有意义. 在MFC,WTL等开发框架下,每个控件都是一个窗口,窗口只需要画前景,背景.因为窗口之间的内容不需要做混合,一个子窗口的 ...

  7. 图说设计模式(UML和设计模式)

    https://github.com/me115/design_patterns http://design-patterns.readthedocs.org/zh_CN/latest/index.h ...

  8. Font Awesome符号字体

    http://www.fontawesome.com.cn/ 引用CSS包之后根据图标库找到所需的图标代码 使用i标签或者a标签皆可,符号为文字性质,可以直接通过修改text颜色从而修改符号颜色

  9. 【SQL 触发器】

    一.MySQL上触发器的使用 示例: CREATE TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW t ...

  10. Android 自定义实现switch开关按钮

    前几天在看蘑菇街上有个开关按钮: 就在想是怎样实现的,于是反编译了它的源码,但是这时得到了下面的几张图片: 图片对应的名称: 无色长条:switch_frame; 白色圆点:switch_btn_pr ...