接上一节内容:cocos2dx - 生成怪物及AI

本节主要讲如何通过创建简单的矩形区域来造成伤害

  在小游戏中简单的碰撞需求应用box2d等引擎会显得过于臃肿复杂,且功能不是根据需求定制,还要封装,为此本节讲述一下如何自己实现简单的碰撞,来达到伤害效果。

这里先看下效果图:

一、定义小组类别

  定义如下:

// 组别mask
enum enGroupMask
{
GROUP_NONE = 0x0000,
GROUP_PLAYER = 0x0001,
GROUP_MONSTER = 0x0002,
};

  用二进制位来定义小组,方便后面判断用位快速判断。

二、定义CBody类用于碰撞实现

  代码如下:

#ifndef __CBody_H__
#define __CBody_H__
#include "IGameDef.h"
#include "cocos2d.h"
#define DRAW_BODY 1
#ifdef DRAW_BODY
#include "GLES-Render.h"
#endif USING_NS_CC;
class CBody : public Node
{
public:
// implement the "static create()" method manually
CREATE_FUNC(CBody); virtual bool init(); void SetRect(float x, float y, float w, float h){ m_cRect = Rect(x,y,w,h); } void SetGroupMask(enGroupMask nGroupMask){ m_nGroupMask = nGroupMask; } enGroupMask GetGroupMask() const{ return m_nGroupMask; } enGroupMask CanContactGroup() const; //判断是否可以碰撞该类别
bool IsGroupCanContact(enGroupMask nGroupMask) const; const Rect GetRect() const; //判断矩形是否交叉
bool IntersectsRect(const Rect& rect) const; void SetContactCallback(const std::function<void(CBody*)>& callback){ m_constactFunc = callback; } // 碰撞回调函数
void OnContact(CBody* pBody); // 绘制矩形区域
#ifdef DRAW_BODY
virtual void draw(Renderer *renderer, const Mat4& transform, uint32_t flags);
virtual void onDraw(const Mat4 &transform, uint32_t flags);
#endif private: CBody();
~CBody(); #ifdef DRAW_BODY
CustomCommand m_pCustomCommand;
b2Draw* m_debugDraw;
#endif Rect m_cRect; std::function<void(CBody*)> m_constactFunc; enGroupMask m_nGroupMask;
}; #endif __CBody_H__

关键实现有以下几个:

  1、用位快速判断是否可以产生碰撞

bool CBody::IsGroupCanContact(enGroupMask nGroupMask)  const
{
return nGroupMask&CanContactGroup();
}

  2、获取矩形实际的坐标,利用cocos2dx矩形相交判断方法,判断重叠

const Rect CBody::GetRect()  const
{
const Vec2& pt =this->convertToWorldSpace(this->getPosition());
return Rect(pt.x + m_cRect.origin.x, pt.y + m_cRect.origin.y, m_cRect.size.width, m_cRect.size.height);
} bool CBody::IntersectsRect(const Rect& rect) const
{
return GetRect().intersectsRect(rect);
}

  3、将创建的CBody类添加到管理中vector的实例m_vBody管理

CBody::~CBody()
{
CBattleMgr::getInstance()->EreaseBody(this);
#ifdef DRAW_BODY
if (m_debugDraw)
{
delete m_debugDraw;
m_debugDraw = NULL;
}
#endif
} bool CBody::init()
{
#ifdef DRAW_BODY
m_debugDraw = new GLESDebugDraw(1.0);
#endif
CBattleMgr::getInstance()->InsertBody(this);
return true;
}

  同时每帧在管理类中的update进行碰撞判断如下:

void CBattleMgr::update(float dt)
{
while (m_vBody.size()>)
{
size_t nLast = m_vBody.size() - ;
CBody* pBody = m_vBody[nLast];
m_vBody.pop_back();
if (pBody)
{
m_vSwapBody.push_back(pBody);
for (size_t i = ; i < nLast; ++i)
{
CBody* pTempBody = m_vBody[i];
if (pTempBody )
{
bool hurt1 = pTempBody->IsGroupCanContact(pBody->GetGroupMask());
bool hurt2 = pBody->IsGroupCanContact(pTempBody->GetGroupMask());
if ((hurt1 || hurt2)&&pTempBody->IntersectsRect(pBody->GetRect()))
{
if (hurt1)
{
pTempBody->OnContact(pBody);
}
if (hurt2)
{
pBody->OnContact(pTempBody);
}
}
}
}
}
}
m_vSwapBody.swap(m_vBody);
}

  上述代码通过2个vector管理CBody,在update时进行一次判断碰撞并调用OnContact方法。

  4、为了方便显示上图的灰色矩形框需要用以下的类进行显示图形

/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/ #ifndef RENDER_H
#define RENDER_H #include "Box2D/Box2D.h"
#include "cocos2d.h" struct b2AABB; // This class implements debug drawing callbacks that are invoked
// inside b2World::Step.
class GLESDebugDraw : public b2Draw
{
float32 mRatio;
cocos2d::GLProgram* mShaderProgram;
GLint mColorLocation; void initShader( void );
public:
GLESDebugDraw(); GLESDebugDraw( float32 ratio ); virtual void DrawPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color); virtual void DrawSolidPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color); virtual void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color); virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color); virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color); virtual void DrawTransform(const b2Transform& xf); virtual void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color); virtual void DrawString(int x, int y, const char* string, ...); virtual void DrawAABB(b2AABB* aabb, const b2Color& color);
}; #endif
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/ #include "GLES-Render.h"
#include "cocos2d.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h> USING_NS_CC; GLESDebugDraw::GLESDebugDraw()
: mRatio( 1.0f )
{
this->initShader();
} GLESDebugDraw::GLESDebugDraw( float32 ratio )
: mRatio( ratio )
{
this->initShader();
} void GLESDebugDraw::initShader( void )
{
mShaderProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_U_COLOR); mColorLocation = glGetUniformLocation( mShaderProgram->getProgram(), "u_color");
} void GLESDebugDraw::DrawPolygon(const b2Vec2* old_vertices, int vertexCount, const b2Color& color)
{
mShaderProgram->use();
mShaderProgram->setUniformsForBuiltins(); b2Vec2* vertices = new b2Vec2[vertexCount];
for( int i=;i<vertexCount;i++)
{
vertices[i] = old_vertices[i];
vertices[i] *= mRatio;
} mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, ); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , vertices);
glDrawArrays(GL_LINE_LOOP, , vertexCount); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(,vertexCount); CHECK_GL_ERROR_DEBUG(); delete[] vertices;
} void GLESDebugDraw::DrawSolidPolygon(const b2Vec2* old_vertices, int vertexCount, const b2Color& color)
{
mShaderProgram->use();
mShaderProgram->setUniformsForBuiltins(); b2Vec2* vertices = new b2Vec2[vertexCount];
for( int i=;i<vertexCount;i++) {
vertices[i] = old_vertices[i];
vertices[i] *= mRatio;
} mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r*0.5f, color.g*0.5f, color.b*0.5f, 0.5f); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , vertices); glDrawArrays(GL_TRIANGLE_FAN, , vertexCount); mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, );
glDrawArrays(GL_LINE_LOOP, , vertexCount); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(,vertexCount*); CHECK_GL_ERROR_DEBUG(); delete[] vertices;
} void GLESDebugDraw::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color)
{
mShaderProgram->use();
mShaderProgram->setUniformsForBuiltins(); const float32 k_segments = 16.0f;
int vertexCount=;
const float32 k_increment = 2.0f * b2_pi / k_segments;
float32 theta = 0.0f; GLfloat* glVertices = new GLfloat[vertexCount*];
for (int i = ; i < k_segments; ++i)
{
b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
glVertices[i*]=v.x * mRatio;
glVertices[i*+]=v.y * mRatio;
theta += k_increment;
} mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, );
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , glVertices); glDrawArrays(GL_LINE_LOOP, , vertexCount); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(,vertexCount); CHECK_GL_ERROR_DEBUG(); delete[] glVertices;
} void GLESDebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color)
{
mShaderProgram->use();
mShaderProgram->setUniformsForBuiltins(); const float32 k_segments = 16.0f;
int vertexCount=;
const float32 k_increment = 2.0f * b2_pi / k_segments;
float32 theta = 0.0f; GLfloat* glVertices = new GLfloat[vertexCount*];
for (int i = ; i < k_segments; ++i)
{
b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
glVertices[i*]=v.x * mRatio;
glVertices[i*+]=v.y * mRatio;
theta += k_increment;
} mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r*0.5f, color.g*0.5f, color.b*0.5f, 0.5f);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , glVertices);
glDrawArrays(GL_TRIANGLE_FAN, , vertexCount); mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, );
glDrawArrays(GL_LINE_LOOP, , vertexCount); // Draw the axis line
DrawSegment(center,center+radius*axis,color); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(,vertexCount*); CHECK_GL_ERROR_DEBUG(); delete[] glVertices;
} void GLESDebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{
mShaderProgram->use();
mShaderProgram->setUniformsForBuiltins(); mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, ); GLfloat glVertices[] =
{
p1.x * mRatio, p1.y * mRatio,
p2.x * mRatio, p2.y * mRatio
};
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , glVertices); glDrawArrays(GL_LINES, , ); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(,); CHECK_GL_ERROR_DEBUG();
} void GLESDebugDraw::DrawTransform(const b2Transform& xf)
{
b2Vec2 p1 = xf.p, p2;
const float32 k_axisScale = 0.4f;
p2 = p1 + k_axisScale * xf.q.GetXAxis();
DrawSegment(p1, p2, b2Color(,,)); p2 = p1 + k_axisScale * xf.q.GetYAxis();
DrawSegment(p1,p2,b2Color(,,));
} void GLESDebugDraw::DrawPoint(const b2Vec2& p, float32 size, const b2Color& color)
{
mShaderProgram->use();
mShaderProgram->setUniformsForBuiltins(); mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, ); // glPointSize(size); GLfloat glVertices[] = {
p.x * mRatio, p.y * mRatio
}; glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , glVertices); glDrawArrays(GL_POINTS, , );
// glPointSize(1.0f); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(,); CHECK_GL_ERROR_DEBUG();
} void GLESDebugDraw::DrawString(int x, int y, const char *string, ...)
{
// NSLog(@"DrawString: unsupported: %s", string);
//printf(string);
/* Unsupported as yet. Could replace with bitmap font renderer at a later date */
} void GLESDebugDraw::DrawAABB(b2AABB* aabb, const b2Color& color)
{
mShaderProgram->use();
mShaderProgram->setUniformsForBuiltins(); mShaderProgram->setUniformLocationWith4f(mColorLocation, color.r, color.g, color.b, ); GLfloat glVertices[] = {
aabb->lowerBound.x * mRatio, aabb->lowerBound.y * mRatio,
aabb->upperBound.x * mRatio, aabb->lowerBound.y * mRatio,
aabb->upperBound.x * mRatio, aabb->upperBound.y * mRatio,
aabb->lowerBound.x * mRatio, aabb->upperBound.y * mRatio
}; glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , glVertices);
glDrawArrays(GL_LINE_LOOP, , ); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(,); CHECK_GL_ERROR_DEBUG();
}

  然后在CBody的draw中做如下处理进行绘制

#ifdef DRAW_BODY
void CBody::onDraw(const Mat4 &transform, uint32_t flags)
{ if (m_debugDraw)
{
b2Vec2 vs[];
const Rect rect = GetRect();
vs[].Set(rect.origin.x, rect.origin.y);
vs[].Set(rect.origin.x + rect.size.width, rect.origin.y);
vs[].Set(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
vs[].Set(rect.origin.x, rect.origin.y + rect.size.height);
m_debugDraw->DrawSolidPolygon(vs, , b2Color(0.6f, 0.6f, 0.6f));
}
}
void CBody::draw(Renderer *renderer, const Mat4& transform, uint32_t flags)
{
//_globalZOrder
m_pCustomCommand.init();
m_pCustomCommand.func = CC_CALLBACK_0(CBody::onDraw, this, transform, flags);
renderer->addCommand(&m_pCustomCommand);
}
#endif

  5、最后在Monster等实体类init中添加该CBody的实例,即可为其添加碰撞形状。

如下:

        m_pBody = CBody::create();
m_pBody->SetGroupMask(enGroupMask::GROUP_MONSTER);
m_pBody->SetRect(-, -, , );
this->addChild(m_pBody);

三、定义CDamage用于创建伤害

主要实现以下方法:

#ifndef __CDamage_H__
#define __CDamage_H__
#include "IGameDef.h"
#include "Body.h"
#include <set>
USING_NS_CC;
class CDamage : public Node
{
public:
// implement the "static create()" method manually
CREATE_FUNC(CDamage); virtual bool init(); void update(float dt); void SetRect(float x, float y, float w, float h); void SetGroupMask(enGroupMask nGroupMask); void OnContact(CBody* pBody);
private: CDamage();
~CDamage(); int m_nDieTime; // 伤害区域消失时间 CBody *m_pBody; std::set<CBody*> m_sContact;
};
#endif __CDamage_H__

关键点:
  1、m_nDieTime在update中实现控制伤害区域存在时间

  2、m_sContact控制一个CDamage实例对每个实体仅造成一次伤害。

在怪物等攻击动作中添加事件并在事件回调中添加如下代码创建伤害

void  CEntity::ActionEvent(Frame *frame)
{
cocostudio::timeline::EventFrame* evnt = dynamic_cast<cocostudio::timeline::EventFrame*>(frame);
if (!evnt)
return;
std::string str = evnt->getEvent();
if (str == "attack")
{
auto damage = CDamage::create();
damage->SetRect(-, -, , );
damage->SetGroupMask(m_nGroupMask);
if (this->getScaleX()<)
{
damage->setPositionX(-);
}
this->addChild(damage);
}
}

添加事件方法,即在特定帧添加以下的帧事件
     

至此,游戏的基本元素已经都有了。

剩下的自己可以进行扩展了,如:血量为0时,播放死亡动画,并显示失败等。

  

在怪物死亡创建一个新的怪物:

  

  

cocos2dx - 伤害实现的更多相关文章

  1. cocos2dx - android环境配置及编译

    接上一节内容:cocos2dx - 伤害实现 本节主要讲Android环境配置及编译 在第一节中setup.py的配置里,我们没有配置对应的ndk,sdk,ant的路径,在这里需要先配置好环境变量. ...

  2. 【cocos2d-x 手游研发小技巧(1)自定义制作怪物伤害数值】

    直插主题了,今天写了一下午,早就想要写这类似东西的,首先我不会选用CCLabelAtlas了,我直接用帧图片做. 首先我们要准备素材,我先把素材帖出来给大家: 这个是一张比较全的素材图,它包含了扣血的 ...

  3. 【cocos2d-x 手游研发----目录】

    感谢大家一直支持我写这样一系列的博客,从中我自己也获益良多,cocos2d-x这样一款非常棒的引擎,是值得我们去学习和分享的,谈到分享,那我就把这套写了差不多一两个月的框架给大家开源下载,写的很一般, ...

  4. Cocos2d-x 3.0 事件系统【转】

    事件系统,是一个软件的核心组成部分.从小处讲它是应用程序内部各模块交互的设计模式,从大处讲,它是软件架构的组成模块.在现代软件开发中,操作系统通常通过一些预定义的事件,告知应用程序发生的一些事情如用户 ...

  5. Cocos2dx 小技巧(十一) 小人虽短,但能够旋转

    转眼五一就到了,放假三天应该做些什么呢?窝在家里钻研技术?写博客?no no no no,这样的"伤害"自己的方式实在让我无法忍受.本来和大学那伙人越好了一起去哪里玩玩,喝酒聊天啥 ...

  6. Cocos2d-x 使用物理引擎进行碰撞检测

    [转自]: http://blog.csdn.net/cbbbc/article/details/38541099 通常在游戏简单逻辑判断和模拟真实的物理世界时,我们只需要在定时器中判断游戏中各个精灵 ...

  7. cocos2d-x游戏开发系列教程-超级玛丽07-CMGameMap

    背景 在上一篇博客中,我们提到CMGameScene,但是CMGameScene只是个框架,实际担任游戏逻辑的是CMGameMap类,这个博文就来了解下CMGameMap 头文件 class CMGa ...

  8. cocos2dx调用浏览器打开网址

    安卓端cocos2dx/platform/android路径下CCApplication.h: virtual void openURL(const char* pszUrl); CCApplicat ...

  9. 使用“Cocos引擎”创建的cpp工程如何在VS中调试Cocos2d-x源码

    前段时间Cocos2d-x更新了一个Cocos引擎,这是一个集合源码,IDE,Studio这一家老小的整合包,我们可以使用这个Cocos引擎来创建我们的项目. 在Cocos2d-x被整合到Cocos引 ...

随机推荐

  1. vSphere笔记01~02

    Vmware vsphere 虚拟化 云和大数据的底层!!!! 分类 1.开源:openstack:Linux:难(无图形化) nosqleasystack公司 2.企业版本:vsphere sdn! ...

  2. The Last

    第八次课程作业 感慨 没想到这就最后一次课程作业了,还以为会跟我到大学毕业呢.既然是最后一次就说说心里话.起初收到做博客作业的消息还觉得蛮有新意的(因为第一次作业不难),后来不断的作业涌现出来了,还都 ...

  3. SNS团队第一次站立会议(2017.04.22)

    一.当天站立式会议照片 本次会议主要内容:进一步明确了团队中各个成员的定位,说明了下一步团队工作的方向 二.每个人的工作 成员 昨天已完成的工作 今天计划完成的工作 罗于婕 系统架构设计及项目数据库设 ...

  4. 201521123080《Java程序设计》第7周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 源代码如下 分析: ...

  5. Sublime text 3编辑python时出现方框的解决办法

    如图: 经过探究发现,出现这个问题的原因是我在Sublime text 3中,安装了Anaconda这款用来增强Python 编辑的插件导致了标题即图片中的问题,解决方法也非常简单,如果是因为使用an ...

  6. 201521123059 《Java程序设计》第十四周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 1.关系型数据库 --建立表格时表中一列中的数据类型必须一致.关系表中的行必须是唯一的,列是不可分的,某些行的某 ...

  7. Vue.js项目模板搭建

    前言 从今年(2017年)年初起,我们团队开始引入「Vue.js」开发移动端的产品.作为团队的领头人,我的首要任务就是设计 整体的架构 .一个良好的架构必定是具备丰富的开发经验后才能搭建出来的.虽然我 ...

  8. mapreduce新旧api对比

    对比:hadoop版本1.x 新版,hadoop版本0.x 旧版 1.新api引用包一般是mapreduce ,旧版api引用的包一般是mapred 2.新api使用Job,旧版api使用JobCon ...

  9. JVM菜鸟进阶高手之路四

    转载请注明原创出处,谢谢! 由于很多的jvm分析最好是基于gc日志的,所以添加参数如下即可: -verbose:gc -XX:+HeapDumpOnOutOfMemoryError -XX:+Prin ...

  10. IBAction&IBOutlet

    IB:Interface Builder 1>IBAction 需要操作,例如按钮的点击 2> IBOutlet 需要获得.修改该属性 然后就可以与Storyboard建立起联系