cocos2dx随机函数在碰撞检测函数里面应该如何计算BOSS血量?

cocos2dx物理引擎和碰撞检测(八)接触(Contants)
cocos2dx物理引擎和碰撞检测(八)接触(Contants)
接触就是表明物体间重叠的属性,或者说发生了碰撞。
概述定义:
接触是Box2D物理引擎创建用于管理框架间碰撞的对象。接触也具有很多的类型。它们都派生自基类b2Contant。之所以有类似的划分,是为了用于管理不同类型形状之间的接触。例如有管理多边形碰撞的类,也有管理圆形碰撞的类。下面先来熟悉一些与接触有关的术语:
1.接触点(contant point)
接触点就是两个形状相互接触的点。在引擎中近似的认为接触区是由少数的点组成的。
2.接触法线(contant normal)
接触法线是一个单位向量,用来标明两个框架接触时的方向。它是由一个框架对象指向另一个的。按照引擎中的惯例,向量由fixtureA指向fixtureB。
3.接触分隔(contant separation)
接触分隔正好与穿透(重叠)区域相反。当形状相互接触时,会有一段重叠的区域,而分隔就是与其相反的。因此接触分隔的数值为负。
4.接触群组(contant manifold)
考虑一下圆和圆,圆和多边形的碰撞,只会得到一个接触点和向量。两个凸变形相互接触,有可能产生两个接触点。这些点都有相同的法线,将它们分成一组构成了接触群组。
Box2D引擎选择了一种方式,引擎当中会先创建接触来分析碰撞,如果形状之间没有发生碰撞,则会正确的删除接触,否则可能一直等到物体不再重叠,再删除接触点。
接触类(Contant Class)
接触对象是由引擎内部创建和摧毁的,并不是由开发者来创建的。开发者只要得到物理模拟后的结果。然而,我们还是能够访问接触类并和它交互的。开发者可以通过下述函数来访问原始的接触群组。
b2Manifold *GetManifold();
const b2Manifold *GetManifold()
上述函数返回的接触点信息,是基于物体本身坐标的。如果开发者需要将其转换为物理世界中的坐标系,则可以使用下面函数:
void GetWorldManifold(b2WorldManifold *worldManifold)
这使用了物体的当前位置去计算接触点在world坐标下的位置。还有一点需要注意,对于传感器Sensors,引擎并不会创建接触群组,如果开发者想要获得碰撞的信息,则要使用下面的方式:
bool touching = sensorContant-&IsTouching();
另外,这个函数对非传感器的其他框架对象也是有效果的。从接触对象中,开发者可以得到发生接触的框架对象,从而得到物体对象:
b2Fixture *fixtureA = myContact-&GetFixtureA();
b2Body *bodyA = fixtureA-&GetBody();
MyActor *actorA =(MyActor *)bodyA-&GetUserData();
访问接触:
接触对象包含了一系列与物体碰撞有关的信息。作为开发者该如何访问这些信息呢?Box2D引擎提供了几种函数访问的方法:为了访问接触,首先可以直接查询物理世界或者物体结构中的接触对象:
//遍历所有的接触对象
for(b2Contant *c =myWorld-&GetContantList();c;c=c-&GetNext())
//process C;
//遍历物体中的所有接触对象
for(b2ContantEdge *ce = myBody-&GetContantList();ce=ce-&GetNext())
b2Contact *c = ce-&
//process C;
注意:通过b2World或者b2Body直接访问,有可能会错过一些时间步产生的临时接触。而使用b2ContactListener就可以很精确的得到全部结果。
接触监听器:
通过实现接触监听器的对象,开发者就可以收到接触数据。接触监听器支持四种事件:开始(begin),结束(end),求解前(pre-slove)和求解后(post-slove)。它们表示了物体碰撞的过程,代码如下:
class MyContactListener:public b2ContactListener
//开始接触
void BeginContact(b2Contact *contact);
//结束接触
void EndContact(b2Contact *contact);
//求解之前的
void PreSolve(b2Contact *contact,const b2Manifold *oldManifold);
//求解之后的
void PostSolve(b2Contact *contact,const b2Manifold *oldManifold);
在物理世界运行的过程中,读者可以创建监听器的实力对象,并使用函数b2World::SetContactListener来注册这个对象。但要保证当世界对象存在时,监听器要留在作用域中。
BeginContact函数:当两个框架开始重叠时,触发函数,这个过程只能在时间步发生,也就是说会在b2World::step函数执行的过程中调用。
EndContact函数:当两个函数不再重叠时或一个物体被摧毁时,就会触发结束的事件,这个事件不仅会发生在时间步之内,也有可能发生时间步之外。
PreSolve函数:在碰撞检测之后,但在碰撞求解(物理模拟)之前,此函数事件触发。这样是为了给开发者一个机会,根据当前情况来决定是否使这个接触失败。在回调的函数中使用一个设置函数就可以实现单侧碰撞的功能。每次碰撞碰撞处理时,接触会重新生效,开发者不得不在每一个时间步中都设置同一个接触无效。由于连续碰撞检测,preslove时间在单个时间步可能发生多次,代码如下:
void PreSolve(b2Contact* contact,const b2Manifolf *oldManifold)
//获得接触群组
b2WorldManifold worldM
contact-&GetWorldManifold(&worldManifold);
if(worldManifold.normal.y&-0.5f){
//设置此接触无效
contact-&SetEnabled(false);
PostSolve函数:当引擎完成了碰撞求解,也就是物理模拟过程之后,开发者可以得到碰撞冲量的结果,调用此函数。这将是提供给开发者附加碰撞结果的机会。
在一个接触回调函数PostSolve中去改变物理世界的模拟数据,是一件神神奇的工作。例如,在游戏中可能会以碰撞的方式来消灭敌人。此时,在游戏中可能会以碰撞的方式来消灭敌人。此时开发者可以在此函数施加伤害,并试图摧毁关联的角色和它的刚体。这样的话可能会摧毁引擎正在运算的对象,造成访问错误。如果想处理这样的情况,就需要缓冲所有游戏中的关注的接触对象,然后再时间步之后处理它们。因为在时间步之后,物理模拟和碰撞检测的过程暂时停止。此时就应该立即处理它们,否则等到下一个时间步,物理世界就会发生改变。那么缓冲的对象也会失效。
下面来一段代码延时了再错做接触缓冲时如何处理那些物体,代码中假定了所有触点都缓冲于b2ContactPoint数组m_points中:
//打算摧毁和contact有所关联的物体指针
//必须先缓存那些需要摧毁的物体,因为它们有可能被多个触点所共有
const int32 k_maxNuke = 6;
//将要摧毁的物体数组
b2Body* nuke[k_maxNuke];
int32 nukeCount = 0;
//遍历contact缓存,摧毁相互接触时无重复的物体
for(int32 i =0; i&m_pointC++i)
ContactPoint* point = m_points[i];
//得到物体
b2Body* body1 = point-&shape1-&GetBody();
b2Body* body2 = point-&shape2-&GetBody();
//得到物体的质量
float32 mass1 = body1-&GetMass();
flost32 mass2 = body2-&GetMass();
//存储物体
if(mass1&0.0f && mass2&0.0f){
if(mass2 & mass1){
nuke[nukeCount++]=body1;
nuke[nukeCount++]=body2;
if(nukeCount == k_maxNuke){}
//将nuke数组排序,使得重复的指针归在一起
std::sort(nuke,nuke+nukeCount);
//删除body,跳过重置的
int32 i=0;
while(i & nukeCount)
b2Body *b =nuke[i++];
while(i&nukeCount && nuke[i]==b){
m_world-&DestroyBody(b);
接触筛选:
开发者可以通过实现类b2ContactFilter对象就可以倒到筛选接触的目的。引擎是允许开发者定制接触筛选内容的。通过实现一个函数ShouleCollide的代码,开发者可以自由地定义碰撞筛选的规则。这个函数会传递两个形状对象b2Shape的指针作为参数。如果发生碰撞返回true,否则为false。
//默认筛选函数
bool b2ContactFilter::shouldCollide(b2Shape *shape1,b2Shape *shape2)
//得到筛选的数值
const b2FilterData & filter1 = shape 1-&GetFilterData();
const b2FilterData & filter2 = shape 2-&GetFilterData();
//判断是否符合规则
if(filter1.groupIndex == filter2.groupIndex && filter.groupIndex !=0){
filter1.groupIndex&0;
bool collide = (filter1.maskBits & filter2.categoryBits)!=0 && (filter2.maskBits & filter1.categoryBits)!=0;//返回是否发生碰撞
在物理世界运行期间,开发者可以创建自定义的接触筛选案例,不过要保证筛选器对象要保留在作用域中,下面是代码:
MyContactF
world-&SetContactFilter(&filter);//确保filter留在作用域中
感谢关注 Ithao123精品文库频道,是专门为互联网人打造的学习交流平台,全面满足互联网人工作与学习需求,更多互联网资讯尽在 IThao123!
Laravel是一套简洁、优雅的PHP Web开发框架(PHP Web Framework)。它可以让你从面条一样杂乱的代码中解脱出来;它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁、富于表达力。
Hadoop是一个由Apache基金会所开发的分布式系统基础架构。
用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。
Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求,可以以流的形式访问(streaming access)文件系统中的数据。
Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,则MapReduce为海量的数据提供了计算。
产品设计是互联网产品经理的核心能力,一个好的产品经理一定在产品设计方面有扎实的功底,本专题将从互联网产品设计的几个方面谈谈产品设计
随着国内互联网的发展,产品经理岗位需求大幅增加,在国内,从事产品工作的大部分岗位为产品经理,其实现实中,很多从事产品工作的岗位是不能称为产品经理,主要原因是对产品经理的职责不明确,那产品经理的职责有哪些,本专题将详细介绍产品经理的主要职责
IThao123周刊14493人阅读
cocos2d/x(5)
在上一篇的基础上增加了一点内容,必要的注释都写在代码里了,,就直接贴代码吧,我也懒得写详细的过程。
HelloWorldSence.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include &cocos2d.h&
using namespace cocos2d;
class HelloWorld : public cocos2d::CCLayerColor
// Method 'init' in cocos2d-x returns bool, instead of 'id' in cocos2d-iphone (an object pointer)
virtual bool init();
// there's no 'id' in cpp, so we recommend to return the class instance pointer
static cocos2d::CCScene* scene();
// a selector callback
void menuCloseCallback(CCObject* pSender);
// preprocessor macro for &static create()& constructor ( node() deprecated )
CREATE_FUNC(HelloWorld);
void addTarget();
void spriteMoveFinished(CCNode *sender);
void gameLogic(cocos2d::CCTime dt);
void ccTouchesEnded(CCSet *touches, CCEvent *event);
CCArray *aarayT//敌人
CCArray *arrayP//飞镖
void update(CCTime dt);
#endif // __HELLOWORLD_SCENE_H__
HelloWorldScence.cpp
#include &HelloWorldScene.h&
#include &SimpleAudioEngine.h&
using namespace cocos2d;
using namespace CocosD
CCScene* HelloWorld::scene()
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();
// add layer as a child to scene
scene-&addChild(layer);
// return the scene
// on &init& you need to initialize your instance
bool HelloWorld::init()
//////////////////////////////
// 1. super init first
if ( CCLayerColor::initWithColor(ccc4(255, 255, 255, 255)) )
CCSize winSize = CCDirector::sharedDirector()-&getWinSize();//获取屏幕大小
arrayProjectile = CCArray::create();
aarayTarget = CCArray::create();
float sprite_scale = 2.0;
CCSprite *Player =
CCSprite::create(&Player.png&);
Player-&setScale(sprite_scale);
Player-&setPosition(ccp(Player-&getContentSize().width*sprite_scale/2.0, winSize.height/2.0));
this-&addChild(Player);
aarayTarget-&retain();
arrayProjectile-&retain();
this-&schedule(schedule_selector(HelloWorld::gameLogic), 1.0);
this-&schedule(schedule_selector(HelloWorld::update));
this-&setTouchEnabled(true);
void HelloWorld::gameLogic(cocos2d::CCTime dt){
this-&addTarget();
void HelloWorld::addTarget(){
CCSize winSize = CCDirector::sharedDirector()-&getWinSize();
CCSprite *target = CCSprite::create(&Target.png&);
//随机位置
int minY = target-&getContentSize().height/2.0;
int maxY = winSize.height - target-&getContentSize().height/2.0;
int rangeY = maxY - minY;
int actualY = rand()%rangeY + minY;
target-&setPosition(ccp(winSize.width - target-&getContentSize().width/2.0, actualY));
target-&setTag(1);
this-&addChild(target);
aarayTarget-&addObject(target);
//随机速度
float minDuration = 2.0;
float maxDuration = 4.0;
int rangeDuration = maxDuration - minD
float actualDuration = rand()%rangeDuration + minD
CCFiniteTimeAction *actionMove = CCMoveTo::create(actualDuration, ccp(0 - target-&getContentSize().width/2.0, actualY));//0代表屏幕外,这句表示在3秒内从初始位置移动到屏幕外
//增加一个回调函数,回收移动到屏幕外的精灵
CCFiniteTimeAction *actionMoveDone = CCCallFuncN::create(this, callfuncN_selector(HelloWorld::spriteMoveFinished));
target-&runAction(CCSequence::create(actionMove,actionMoveDone,NULL));
void HelloWorld::spriteMoveFinished(cocos2d::CCNode *sender){
CCSprite *sprite = (CCSprite *)
// this-&removeChild(sprite, true);
if (sprite-&getTag() == 1) {
aarayTarget-&removeObject(sprite);//清除敌人
}else if(sprite-&getTag() == 2){
arrayProjectile-&removeObject(sprite);//清除飞镖
//发射飞镖
void HelloWorld::ccTouchesEnded(cocos2d::CCSet *touches, cocos2d::CCEvent *event){
CCTouch *touch = (CCTouch *)touches-&anyObject();
CCPoint location = touch-&getLocationInView();
location = this-&convertTouchToNodeSpace(touch);
CCSize winSize = CCDirector::sharedDirector()-&getWinSize();
CCSprite *projectile = CCSprite::create(&Projectile.png&);
projectile-&setPosition(ccp(20, winSize.height/2));
float offX = location.x - projectile-&getPositionX();
float offY = location.y - projectile-&getPositionY();
if (offX &= 0) {
projectile-&setTag(2);
this-&addChild(projectile);
arrayProjectile-&addObject(projectile);
float angle = offY/offX;
float realX= winSize.width + projectile-&getContentSize().width/2;
float realY = realX * angle + projectile-&getPositionY();
CCPoint finalPosition = ccp(realX, realY);
//获取飞镖飞行时间
float length = sqrtf(realX *realX + realY*realY);
float velocity = 480;
float realMoveDuration = length/
projectile-&runAction(CCSequence::create(CCMoveTo::create(realMoveDuration, finalPosition),CCCallFuncN::create(this, callfuncN_selector(HelloWorld::spriteMoveFinished)),NULL));
//碰撞检测,消除飞镖和敌人
void HelloWorld::update(cocos2d::CCTime dt){
for (int i = 0; i & aarayTarget-&count(); i++) {
CCSprite *target = (CCSprite *)aarayTarget-&objectAtIndex(i);
for (int j = 0; j & arrayProjectile-&count(); j++) {
CCSprite *projectile = (CCSprite *)arrayProjectile-&objectAtIndex(j);
if (target-&boundingBox().intersectsRect(projectile-&boundingBox())) {
aarayTarget-&removeObjectAtIndex(i);
arrayProjectile-&removeObjectAtIndex(j);
this-&removeChild(target);
this-&removeChild(projectile);
void HelloWorld::menuCloseCallback(CCObject* pSender)
CCDirector::sharedDirector()-&end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
运行结果截图:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1000269次
积分:10778
积分:10778
排名:第1175名
原创:171篇
转载:153篇
评论:97条Cocos2d-x 精灵碰撞检测(方法一)
声明函数碰撞检测函数,两个精灵和重写update
bool isCollision( CCPoint p1,CCPoint p2,int w1,int h1,int w2,int h2 );
CCSprite *sp2;
CCSprite *sp1;
virtual void update(float delta);
//重写触摸事件
virtual void registerWithTouchDispatcher();
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
cpp文件实现
初始2个精灵
sp1 = CCSprite::create("5.png");
sp1->setScale(0.3);
sp1->setPosition(ccp(100, visibleSize.height/2));
this->addChild(sp1);
sp2 = CCSprite::create("6.png");
sp2->setScale(0.3);
sp2->setPosition(ccp(300, visibleSize.height/2));
this->addChild(sp2);
开启触摸及定时器
setTouchEnabled(true);
scheduleUpdate();
触摸移动精灵sp2与精灵sp1发生碰撞
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
//移动精灵
void HelloWorld::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
CCSize winSize = CCDirector::sharedDirector()->getVisibleSize();
if (sp2) {
CCPoint pos = pTouch->getDelta();
CCPoint currentPos = sp2->getPosition();
currentPos = ccpAdd(currentPos, pos);
currentPos = ccpClamp(currentPos, CCPointZero, ccp(winSize.width, winSize.height));//限制精灵出屏幕
sp2->setPosition(currentPos);//移动重设精灵坐标
void HelloWorld::registerWithTouchDispatcher()
CCDirector* pDirector = CCDirector::sharedDirector();
pDirector->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
update函数检测碰撞,isCollision参数顺序:精灵1的坐标,精灵2的坐标,精灵1的宽,高, 精灵2的宽,高
bool HelloWorld::isCollision( CCPoint p1,CCPoint p2,int w1,int h1,int w2,int h2 )
if(abs(p1.x - p2.x) < w1 + w2 && abs(p1.y - p2.y) getPosition(),sp2->getPosition(), 45, 28.3 , 47.5, 35))
CCLOG("--------Is Collision, sp2.x: %f, sp2.y: %f", sp2->getPositionX(), sp2->getPositionY());
CCLOG("++++++++ Is&#39;t Collision, sp2.x: %f, sp2.y: %f", sp2->getPositionX(), sp2->getPositionY());
下载地址:http://download.csdn.net/detail/oyangyufu/7415923
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'Cocos2dx(19)
飘字特效主要常见与游戏里面的掉血表示伤害输出等。碰撞检测常见于一些横版过关或者跑酷的手游,判断是否有碰到食物,或者什么障碍物等,都是比较常见的功能,下面就用一个小例子,来说明这两个特效如何完成。
如下图所示,有两个按钮,点击/触摸屏幕,则下方的按钮则会跳起来。碰到处于屏幕中央的按钮,则会弹出飘字特效,显示碰撞。
同时,左上角的时刻,这两个按钮是否碰撞,也就是是否交汇,相互接触,相交,intersection就是这个意思。
0、首先利用(cocos2d-x-2.2.6安装目录).\tools\project-creator下的create_project.py创建一个FlowWords的Cocos2dx工程,之后打开其中的proj.win32中的HelloCpp.sln利用vs2010进行编辑,先在AppDelegate.h关闭调试信息,设置窗口大小。这些简单的创建Cocos2dx工程步骤,我就不再赘述了。详情可以参考《【Cocos2dx】Windows平台下Cocos2dx 2.x的下载、安装、配置,打造自己的Helloworld》()
1、之后新建一个飘字特效的类,包含FlowWord.h与FlowWord.cpp,工程的目录如下图所示:
飘字特效,本质其实就是一个标签文本CCLabelTTF的放大-&移动-&缩小的动作序列,没什么大不了,关于Cocos2dx的动作序列具体可以参考《【Cocos2dx】基本动作、动作序列与动作合并》(),FlowWord.h代码如下,主要用于一些函数的声明,showWord是暴露给其它类调用的方法,private是完成showWord中的一些必须的类成员变量与类成员函数,这里由于用到了CCLabelTTF,注意引入cocos2d.h的头文字,当然using
namespace cocos2d;也就可以的,看上去没什么区别,当然建议使用#include &cocos2d.h&,因为你不用在FlowWord.cpp再写一次using namespace cocos2d;了:
#ifndef _FlowWord_H_
#define _FlowWord_H_
#include &cocos2d.h&
USING_NS_CC;
class FlowWord : public CCNode {
void showWord(const char* text, CCPoint pos);//飘字方法,text为飘字的内容,pos为飘字的位置
CCLabelTTF*//类成员
void flowEnd();//飘字结束时的回调(处理)函数,主要用于删除自己
#endif之后的FlowWord.cpp则按照如下的逻辑完成一个动作序列,完成飘字特效:
#include &FlowWord.h&
void FlowWord::showWord( const char* text, CCPoint position){//text为飘字的内容,pos为飘字的位置
/*初始化*/
label=CCLabelTTF::create(text,&Arial&,18);//创建一个字体为Arial,字号为18,内容为text的CCLabelTTF,也就是标签文本
label-&setColor(ccc3(255, 255, 0));//设置其颜色为黄色
label-&setPosition(position);//设置其位置
this-&addChild(label);//在场景上添加这个标签文本
/*三个动作,放大-&移动-&缩小*/
CCSize visibleSize = CCDirector::sharedDirector()-&getVisibleSize();//获取屏幕的尺寸、位置信息等
CCFiniteTimeAction* action1=CCScaleTo::create(0.2f,3.0f,3.0f);//0.2s内在x、y上方向皆放大为原尺寸的3倍
CCFiniteTimeAction* action2=CCMoveTo::create(0.3f,ccp(visibleSize.width/4,3*visibleSize.height/4));//在0.3s内,移动到坐标为(x=屏幕宽度的25%,y=屏幕高度的75%处)
CCFiniteTimeAction* action3 = CCScaleTo::create(0.2f, 0.1f,0.1f);//之后在0.2s内在x、y上皆缩小为原尺寸的0.1倍
CCCallFunc* callFunc = CCCallFunc::create(this, callfunc_selector(FlowWord::flowEnd));//声明一个回调(处理)函数,为FlowWord类中的flowEnd()
CCFiniteTimeAction* action = CCSequence::create(action1,action2,action3,callFunc, NULL);//以上的所有动作组成动作序列action
/*对label实行action这个动作*/
label-&runAction(action);
void FlowWord::flowEnd() {//动作结束,从父节点中删除自身
label-&setVisible(false);//先隐藏显示
label-&removeFromParentAndCleanup(true);//再删除
}2、完成了飘字特效的构建,我们要在HelloWorld这个场景中,完成效果图的所有内容。实质是在《【Cocos2dx】精灵触摸跳跃功能》()这个工程进一步衍生,在里面多增多一个精灵,再增加一个类&#20284;《【Cocos2dx】连续滚动的场景》()中的即时更新事件完成碰撞检测的功能。
首先HelloWorldScene.h修改成如下的样子,删去原有的关闭程序的按钮的回调函数,添加一些我们需要的声明:
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include &cocos2d.h&
using namespace cocos2d;//精灵等属于Cocos2dx东西,因此要在此文件的开始声明使用cocos2dx的命名空间,即使有#include &cocos2d.h&也要引用,不知道为什么
class HelloWorld : public cocos2d::CCLayer
// Here&#39;s a difference. Method &#39;init&#39; in cocos2d-x returns bool, instead of returning &#39;id&#39; in cocos2d-iphone
virtual bool init();
// there&#39;s no &#39;id&#39; in cpp, so we recommend returning the class instance pointer
static cocos2d::CCScene* scene();
// implement the &static node()& method manually
CREATE_FUNC(HelloWorld);
void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);//触摸事件的函数声明
void jumpEnd();//声明跳跃结束的回调函数
virtual void update(float delta);//即时更新事件
CCLabelTTF *//文字1
CCSprite* sprite1;//精灵1
bool isJ//精灵1,是否跳跃的flag
CCSprite* sprite2;//精灵2
bool isF//即时更新事件中,判断此时是否正在飘字的flag
#endif // __HELLOWORLD_SCENE_H__
最后是HelloWorldScene.cpp,也就是整个工程的核心了。
1、将原有的HelloWorldScene.cpp中的初始化函数bool HelloWorld::init(){}中的所有内容删去。我们要在里面声明一个位于左上角标签文本CCLabelTTF与2个按钮精灵。
2、在声明左上角标签文本CCLabelTTF的时候用到setAnchorPoint,这个设置中心点的函数,里面的参数的效果具体如下图所示,以下的按钮精灵的中心店都处于屏幕的中央,然而由于中心点的不同,导致,按钮精灵的位置最终不同。
3、碰撞检测之所以搞这么复杂,要根据中心点与精灵尺寸创建矩形,也是没有办法,这不是单纯的两只的中心点是否相交的问题,比如如下图,两飞机的中心点并没有相交,然而两飞机是相交、已经碰撞的。Cocos2dx自带矩形创建函数已经算给面子了,在原生的JavaScript中,《【JavaScript】黑点捉红点并躲绿点游戏》()if里面N个无聊的、同质化的不等式写得我想打人。
4、飘字特效必须有个flag控制它,不然在下方的按钮精灵跳跃经过上方的按钮精灵的时候,会疯狂地飘字,极其占有资源,我们仅仅是让其飘一次!
5、其余在注释写明了,个人感觉基本都说明清楚了。
#include &HelloWorldScene.h&
#include &FlowWord.h& //飘字特效
USING_NS_CC;
CCScene* HelloWorld::scene()
// &#39;scene&#39; is an autorelease object
CCScene *scene = CCScene::create();
// &#39;layer&#39; is an autorelease object
HelloWorld *layer = HelloWorld::create();
// add layer as a child to scene
scene-&addChild(layer);
// return the scene
// on &init& you need to initialize your instance
/*初始化*/
bool HelloWorld::init()
//获取屏幕的尺寸、位置信息等
CCSize visibleSize = CCDirector::sharedDirector()-&getVisibleSize();
//声明这个场景是存在触摸事件的
this-&setTouchEnabled(true);
//声明这个场景是存在即时更新事件的
this-&scheduleUpdate();
//声明一个表示是否碰撞的文字
label = CCLabelTTF::create(&Collision:false&,&arial&,36);//声明文字内容
label-&setAnchorPoint(ccp(0,1));//设置label的中心点在左上角,默认是label-&setAnchorPoint(ccp(0.5,0.5));中心点在精灵的中央,label-&setAnchorPoint(ccp(1,0));中心点则去了右下角了
label-&setPosition(ccp(0,visibleSize.height));//把中心点摆在屏幕的左上交
this-&addChild(label);//添加此文字到场景中
isFlowing=
//声明2只精灵
sprite1 = CCSprite::create(&CloseSelected.png&);
sprite1-&setPosition(ccp(visibleSize.width / 2, visibleSize.height / 6));
this-&addChild(sprite1);
//开始精灵处于未跳跃的状态,由于头文件中“只有静态常量整型数据成员才可以在类中初始化”,因此在这里初始化声明变量
isJumping=
sprite2 = CCSprite::create(&CloseNormal.png&);
sprite2-&setPosition(ccp(visibleSize.width / 2, visibleSize.height / 2));
this-&addChild(sprite2);
/*触摸导致精灵1跳跃*/
//开始触摸
void HelloWorld::ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent){
//获取屏幕的尺寸、位置信息等
CCSize visibleSize = CCDirector::sharedDirector()-&getVisibleSize();
//如果主角还在跳跃中,则不重复执行
if(isJumping) {
//标记主角为跳跃状态
isJumping =
//在2.0秒内,先跳起 屏幕尺寸的2/3 再落下0px,该动作重复1次
CCJumpBy* jump = CCJumpBy::create(1.5f, ccp(0, 0),2* visibleSize.height / 3, 1);
//创建回调函数,声明跳跃结束后调用jumpEnd函数
CCCallFunc* callFunc = CCCallFunc::create(this, callfunc_selector(HelloWorld::jumpEnd));
//将回调函数与跳跃动作结合起来
CCActionInterval* jumpActions = CCSequence::create(jump, callFunc, NULL);
//执行动作
sprite1-&runAction(jumpActions);
void HelloWorld::jumpEnd() {
isJumping =
/*碰撞检测*/
//判断两只精灵是否相交的函数
bool is_collision(CCSprite* sprite1,CCSprite* sprite2){
//建立精灵1的矩形
CCSize sprite_size1=sprite1-&getContentSize();//求精灵的尺寸
CCPoint sprite_position1=sprite1-&getPosition();//求精灵的中心点坐标
CCRect sprite_rect1=CCRectMake(//以精灵的中心点为中心点、以精灵的尺寸为宽与高,建立一个矩形。
sprite_position1.x-sprite_size1.width/2,
sprite_position1.y-sprite_size1.height/2,
sprite_size1.width,
sprite_size1.height);
//建立精灵2的矩形,同理
CCSize sprite_size2=sprite2-&getContentSize();
CCPoint sprite_position2=sprite2-&getPosition();
CCRect sprite_rect2=CCRectMake(
sprite_position2.x-sprite_size2.width / 2,
sprite_position2.y-sprite_size2.height / 2,
sprite_size2.width,
sprite_size2.height);
return sprite_rect1.intersectsRect(sprite_rect2);//如果是判断矩形与一个像素点则用Rect实例.containsPoint(像素点);这里是判断两个矩形是否相交
//即时更新事件,就是在程序一开始就不停地执行这个函数
void HelloWorld::update(float delta){//这里的函数名、参数都不能改,即时你没有用到。
if(is_collision(sprite1,sprite2)){//判断精灵1是否碰到精灵2
if(!isFlowing){//如果现在不是在飘字
label-&setString(&Collision:true&);//左上角的文字内容改变
FlowWord* flowWord=new FlowWord();//初始化FlowWord
this-&addChild(flowWord);//将FlowWord飘字特效放上舞台,尽管飘字特效,一不是精灵,二在showWord中同样有将字体放上舞台的代码,然而没有这一句,HelloWorldScene这个场景根本不会与FlowWord联系起来,也就是FlowWord中添加的Label根本无法在HelloWorldScene中显示。
flowWord-&showWord(&collision!&,sprite2-&getPosition());//执行飘字collision!,位置在不动的sprite2位置开始。
isFlowing=//表示现在正在飘字
label-&setString(&Collision:false&);//精灵1没有碰到精灵2才允许继续飘字
isFlowing=
当然,其实还可以写得更好一些,将精灵1与精灵1本身的触摸跳跃事件打包成一个事件,以致于不用在HelloWorldScene.cpp中写这么长的代码。至此,整个程序最终完成。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:583057次
积分:12346
积分:12346
排名:第870名
原创:648篇
评论:221条
先用屏幕录制软件Freez Screen Video Capture录制屏幕,再把得到的AVI,利用GIF Movie Gear转化成GIF}

我要回帖

更多关于 cocos2dx 碰撞 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信