cocos基础教程(13)使用Physicals代替Box2D和chipmunk
1、 概述
游戏中模拟真实的世界是个比较麻烦的事情,通常这种事情都是交给物理引擎来做。首屈一指的是Box2D了,它几乎能模拟所有的物理效果。而chipmunk则是个更轻量的引擎,能够满足简单的物理需求,比如最常用的的碰撞检测等。这些引擎在使用的过程中有个令人讨厌的地方,它们参数太多了。通常为了初始化一个简单的场景要写很多代码。在cocos2d-x 3.0版本中,出现了一个新类族——physicals。它将Box2D或者chipmunk做了一层封装,使我们的上层调用有更友好的接口。它通过宏来切换使用哪种物理引擎,目前的版本只有chipmunk的实现,Box2D的实现没有写,所以手动将宏切换的话是不行的。
2、 原理分析
相信大家都对物理引擎的使用有所了解,篇幅有限,一些基本概念就不复述了。如果你曾经用过Box2D或者chipmunk,再使用这套封装,你只会有一种爽到爆的感觉。
在这个版本中,物理世界的概念被加入到Scene中,即当创建一个场景时,就可以指定这个场景是否使用物理引擎。相对应的,每一个Sprite中也有body的概念。可以直接将body关联到Sprite上。Listener当然也不需要再弄一套东西来监听,只要注册到场景中就可以了。
不知你听到这个改动有和感想,反正我是震惊了。
接下来我们动手做一个吧。
3、创建场景
首先,运行脚本创建一个新工程:testNewPhy,编译运行确保一切正常,找到 CreateScene函数,更改scene的初始化。
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setDebugDraw(true); //此句仅3.0 alpha0 有效
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL); // 'layer' is an autorelease object
auto layer = HelloWorld::create(); // add layer as a child to scene
scene->addChild(layer); // return the scene
return scene;
}
更改create,创建一个支持物理的世界,打开debugDrawMask,两行就可以搞定了。DrawMask参数可以选择打开绘制哪些部分比如,Joint、Shape等等。接下来,我们要将这个World传到Layer中。所以我们在HelloWorld类中加入一个函数。将这个world存起来。
//……
void setPhyWorld(PhysicsWorld* world){m_world = world;}
private:
PhysicsWorld* m_world;
}
同时在creatScene创建layer完成后,将这个值设定上。
// ……
auto layer = HelloWorld::create();
layer->setPhyWorld(scene->getPhysicsWorld());
/ ……
另外,我们更改一下menuItem的响应,来控制debugDraw的绘制:
void HelloWorld::menuCloseCallback(Object* pSender)
{
if(m_world->getDebugDrawMask() != PhysicsWorld::DEBUGDRAW_NONE)
{
m_world->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_NONE);
}
else
{
m_world->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
} }
4、创建边界
创建了物理世界,还要有东西才行。接下来,我们着手创建一个边界。我们可以方便的使用PhysicalsBody的create方法创建自己想要的物体,在init中进行更改:
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
// 1. super init first
if ( !Layer::init() )
{
return false;
} Size visibleSize = Director::getInstance()->getVisibleSize();
Point origin = Director::getInstance()->getVisibleOrigin();
auto edgeSp = Sprite::create();
auto body = PhysicsBody::createEdgeBox(visibleSize,); //此句仅3.0 alpha0 有效
auto body = PhysicsBody::createEdgeBox(visibleSize,PHYSICSBODY_MATERIAL_DEFAULT,);
edgeSp->setPosition(Point(visibleSize.width/,visibleSize.height/));
edgeSp->setPhysicsBody(body);
this->addChild(edgeSp);
edgeSp->setTag();
return true;
}
其中,PHYSICSBODY_MATERIAL_DEFAULT宏表示的是创建的Body的默认材质,3是边线宽度。编译运行我们会看到场景边上有红色的边界。
5、添加元素
我们先将点击响应搭建起来,在init中将touchEnable设置为true,重新onTouchesEnd方法:
void HelloWorld::onTouchesEnded(const std::vector<Touch*>& touches, Event *event)
{
for(auto touch:touches)
{
auto location = touch->getLocation();
addNewSpriteAtPosition(location);
}
}
然后我们来实现addNewSpriteAtPosition函数。关联body与sprite从未如此简单,我们只需创建一个body,创建一个sprite然后将body设置为sprite的body
void HelloWorld::addNewSpriteAtPosition(Point p)
{
auto sp = Sprite::create("1.png");
sp->setTag();
auto body = PhysicsBody::createBox(Size(, ));
sp->setPhysicsBody(body);
sp->setPosition(p);
this->addChild(sp);
}
6、碰撞检测
碰撞检测的回调是在Scene中注册Listener来实现的。当有碰撞发生时,就会调用对应的Listener。所有的碰撞都使用EventListenerPhysicsContact类。我们可以通过重写它的onContactBegin、onContactPreSolve、onContactPostSolve、onContactSeperate方法来更改它的行为。
void HelloWorld::onEnter()
{
Layer::onEnter();
auto listener = EventListenerPhysicsContact::create();
listener->onContactBegin = [=](EventCustom* event, const PhysicsContact& contact)
{
auto sp = (Sprite*)contact.getShapeA()->getBody()->getNode();
int tag = sp->getTag();
if(tag == )
{
Texture2D *texture = TextureCache::getInstance()->addImage("2.png");
sp->setTexture(texture);
} sp = (Sprite*)contact.getShapeB()->getBody()->getNode();
tag = sp->getTag();
if(tag == )
{
Texture2D *texture = TextureCache::getInstance()->addImage("1.png");
sp->setTexture(texture);
}
return true;
};
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(listener,); //第二个参数是优先级,10是随意写的
}
其中,我们将listener的onContactBegin方法重写。并通过shape->body->owner的方式来取到sprite。更改它的显示。最后将listener注册到m_world中。
编译运行,然后点击menuItem,将debugDrow关闭,即可。
7、总结
通过创建一个支持Physicals的场景,来创建物理系统。将body创建出来,并调用sprite的setPhysicsBody来为一个sprite设定body。通过PhysicsContactListener来创建一个Listener并通过registerContactListener将其注册,来处理碰撞。
原文博客地址:http://blog.csdn.net/fansongy/article/details/14142323
cocos基础教程(13)使用Physicals代替Box2D和chipmunk的更多相关文章
- 【GStreamer开发】GStreamer基础教程13——播放速度
目标 快进,倒放和慢放是trick模式的共同技巧,它们有一个共同点就是它们都修改了播放的速度.本教程会展示如何来获得这些效果和如何进行逐帧的跳跃.主要内容是: 如何来变换播放的速度,变快或者变慢,前进 ...
- cocos基础教程(3)cocos3.x版本目录结构介绍
简介 cocos2d-x-3.x版本进行了很多优化,比如:将TTF字体用Atlas缓存,节点重排序官方声称提升了10倍速度,查找.移除节点方面也提高了10%,拆分渲染层到独立的线程运行: 另外,coc ...
- cocos基础教程(1)Mac环境下搭建
下面主要介绍cocos2d-x环境的设置以及android的环境搭建 1.下载cocos2d-x 3.0正式版 http://www.cocos2d-x.org/download 2.下载a ...
- cocos基础教程(2)Window环境下搭建(补充)
一.环境搭建 1.JDK.Eclipse与SDK 我用的JDK是1.7 Eclipse用的是Luna版的 这些之前都已经设好了,相关下载自己网上找吧 2. 下载最新的Cocos2d-x,我下的是3.5 ...
- cocos基础教程(2)Window环境下搭建
第一步:开始安装VS2012 第二步:下载Cocos2d-x 3.4源码 配置环境变量 COCOS_CONTROL = E:\cocos2d-x-3.4\tools\cocos2d-console ...
- Java基础教程(13)--包
为了使类型更易于查找,避免命名冲突和访问控制,我们应该使用包来对自己定义的类型进行管理.这里说的类型可以是类.接口.枚举和注解(枚举和注解的内容会在后续教程中介绍).使用包来管理我们的代码,有以下 ...
- cocos基础教程(12)点击交互的三种处理
1.概述 游戏也好,程序也好,只有能与用户交互才有意义.手机上的交互大致可以分为两部分:点击和输入.其中点击更为重要,几乎是游戏中全部的交互.在Cocos2d-x 3.0中,更改了dispatch机制 ...
- cocos基础教程(9)声音和音效
使用音效引擎 我们可以使用Cocos2d-x自带的CocosDension库来使用声音引擎.CocosDesion实现了简单易用的SimpleAudioEngine类,为了使用它,我们只需引入他的头文 ...
- cocos基础教程(10)纹理缓存技术
Cocos2d通过调用CCTextureCache或者CCSpriteFrameCache来缓存精灵的纹理. 当这个精灵调用CCTextureCache 或 CCSpriteFrameCache的方法 ...
随机推荐
- XP明年就被停止技术支持,这会带来什么?谈谈如何做决策
XP是MS的一款老牌操作系统,相信大家都不陌生,甚至还有继续使用的人,当然了,在虚拟机里用它也是很好用的,不过,再漂亮的姑娘,也有嫁人的时候,作为XP的父母,MS微软明年四月将停止支持有十多年历史的 ...
- [USACO2005][POJ3045]Cow Acrobats(贪心)
题目:http://poj.org/problem?id=3045 题意:每个牛都有一个wi和si,试将他们排序,每头牛的风险值等于前面所有牛的wj(j<i)之和-si,求风险值最大的牛的最小风 ...
- asp.net 预编译和动态编译
在asp.net中,编译可以分为:动态编译Dynamical Compilation和预编译(Precompilation). 动态编译 深入剖析ASP.NET的编译原理之一:动态编译(Dynamic ...
- JavaScript基础---语言基础(1)
写在前面: 通过四篇博客把JS基础中的基础整理一下,方便自己查阅,这些内容对于实际项目开发中也许并不会在意,但是作为JS的语言基础,自觉还是应该熟悉.在完成这三篇博客(JavaScript基础---语 ...
- [转]Java总结篇系列:Java泛型
一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: 1 public class GenericTest { 2 3 public static void main(Stri ...
- hdu3535 混合背包
分三种情况. 至少取一种 那可以直接取 或者从上一种情况来取.dp[i][k]=max(dp[i][k],dp[i-1][k-a[j].c]+a[j].v,dp[i][k-a[j].c]+a[j].v ...
- Linux中的TUN/TAP设备
今天才发现这家伙...怎么讲...深以为耻.晚上的任务是加深对它的了解,就这么定了. 1. General questions.1.1 What is the TUN ? The TUN is Vi ...
- java对象存储管理
java程序在内存中的存储分配情况: 堆区: 1.存储的全部是对象,每个对象都包含一个与之对应的class的信息.(class的目的是得到操作指令) 2.jvm只有一个堆区(heap)被所有线程共享, ...
- KVM切换声音关闭
Scroll Lock 2次+左右键 实现切换 Scroll Lock 2次+"B" 实现声音的开关
- ecshop后台导航修改教程说明
ecshop后台导航修改教程说明 ECSHOP教程/ ecshop教程网(www.ecshop119.com) 2014-06-25 需要操作的文件为: 1.修改admin\includes\in ...