[align=center][size=6]第一章:box2d[/size][/align][align=left][size=3]为何不用带的物理引擎…嗯.[s:10] …虽然方便不少但是…呵呵…[/size][/align][align=left][size=3]box2d物理引擎不多介绍…[/size][/align][align=left][size=3]先说说这款游戏<The Arrow>,希望能更新下去…毕竟是边发帖边开发…希望不要弃坑[/size][/align][align=left][size=3]
[/size][/align][align=left][size=3]这款游戏就是<AngryArrows[/size][size=3]>和<泰坦之魂>之类的游戏…[/size][/align][align=left][size=3]cocos2d版本 3.5[/size][/align][align=left][size=3]VS2013[/size][/align][align=left][size=3]
[/size][/align][align=left][size=3]本章介绍如何构建box2d世界[/size][/align][hr]
[list][li][size=3]绘制物体的准备[/size][/li][/list][align=left]这里面有4个文件,先加入工程,分别是:[/align][align=left]B2DebugDrawLayer.cpp------这个是box2d世界的用来描绘物体的关节,形状,角度,中心等等的Layer[/align][align=left]B2DebugDrawLayer.h[/align][align=left]GLESDebugDraw.cpp---------这个是具体绘制方法,不用管(cocos2d教程里有这个类GLES-Render.h,GLES-Render.ccp)跟这里的一样的[/align][align=left]GLESDebugDraw.h[/align] [attachment=97477]
因为很多人说没能成功绘制物体,原因是版本不同,或者是被精灵覆盖了
B2DebugDrawLayer.cpp这里类里面的注意,这里有绘制的flags,不需要绘制的注释掉就可以
<pre class="brush:cpp; toolbar: true; auto-links: false;">
uint32 flags = 0;
flags+= b2Draw::e_shapeBit; //绘制形状
flags+= b2Draw::e_jointBit;//绘制关节
//flags += b2Draw::e_aabbBit; //绘制AABB框,通常不需要
flags+= b2Draw::e_pairBit; //这个是啥忘记了
flags+= b2Draw::e_centerOfMassBit; //绘制物体的质量中心
//flags += b2Draw::e_particleBit; //这个是绘制box2d升级组件流体引擎liquidfun里面的粒子用的,这个没有添加liquidfun不需要
mB2DebugDraw->SetFlags(flags);
</pre>
GLESDebugDraw.cpp和.h这个类里面也是注释了绘制liquidfun里面的粒子的方法.如需要可以取消掉注释
<pre class="brush:cpp; toolbar: true; auto-links: false;">
//GLESDebugDraw.h
virtual void DrawParticles(const b2Vec2 *centers, float32 radius, const b2ParticleColor *colors, int32 count);
</pre>
[hr][list][li]构建世界[/li][/list]
GameScene.h游戏的场景
<pre class="brush:cpp; toolbar: true; auto-links: false;">
#ifndef GAMESCENE_SCENE_H
#define GAMESCENE_SCENE_H
#include "cocos2d.h"
#include "Box2D/Box2D.h"
#include "B2DebugDrawLayer.h" //绘制物体的图层
#include "cocos-ext.h" //注意这个需要在项目–属性-配置属性–C\C+±-附加包含目录–最后添加$(EngineRoot)
#define PTM_RATIO 32//注意这个是box2d世界与cocos2d的单位比例
//如cocos2d精灵的宽度=100,则在box2d世界里对应精灵的物体宽度=100/ PTM_RATIO
//box2d世界若要检测物体碰撞需要继承这个b2ContactListener
class GameScene : public cocos2d::Layer, public b2ContactListener
{
public:
b2World* world;
void initPhysics(); //初始化物理世界
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(GameScene);
void update(float dt);
private:
virtual void BeginContact(b2Contact *contact); //碰撞开始后调用的方法
virtual void EndContact(b2Contact *contact);//碰撞结束后调用的方法
B2DebugDrawLayer debugdrawlayer;//我们加入的绘制图层
void debugdraw(Ref pSender, ui::Widget::TouchEventType type);//这个按钮功能是方便关闭物体绘制和打开物体绘制的功能
};
#endif
</pre>
GameScene.ccp游戏的场景[i]
<pre class="brush:cpp; toolbar: true; auto-links: false;">
#include "GameScene.h"
USING_NS_CC;
Scene* GameScene::createScene()
{
auto scene = Scene::create();
auto layer = GameScene::create();
this->addChild(layer);
return scene;
}
void GameScene::initPhysics()
{
Size s = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
b2Vec2 gravity;
gravity.Set(0.0f, 0.0f);//世界的重力,因为是平面.所以我们没有重力
world = new b2World(gravity);
// 是否允许睡眠
world->SetAllowSleeping(true);
// 是否开启连续物理测试,避免穿透
world->SetContinuousPhysics(true);
// 开启碰撞测试
world->SetContactListener(this);
//这就是B2DebugDrawLayer的使用方法就两段,初始化先关闭显示,按按钮即可开启绘制
//调试绘制物体,注意这个绘制图层需要放在较高的Z轴,这样才不会被精灵覆盖掉,9999
debugdrawlayer=B2DebugDrawLayer::create(world, PTM_RATIO);
debugdrawlayer->setVisible(false);
this->addChild(debugdrawlayer, 9999);
//下面这个是创建一个4边墙壁
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0);
b2Body* groundBody = world->CreateBody(&groundBodyDef);
b2EdgeShape groundBox;
groundBox.Set(b2Vec2(origin.x / PTM_RATIO, origin.y / PTM_RATIO), b2Vec2(origin.x + s.width / PTM_RATIO, origin.y + 0));
groundBody->CreateFixture(&groundBox, 0);
groundBox.Set(b2Vec2(0, s.height - 10 / PTM_RATIO), b2Vec2(s.width - 10 / PTM_RATIO, s.height - 10 / PTM_RATIO));
groundBody->CreateFixture(&groundBox, 0);
groundBox.Set(b2Vec2(0, s.height - 10 / PTM_RATIO), b2Vec2(0, 0));
groundBody->CreateFixture(&groundBox, 0);
groundBox.Set(b2Vec2(s.width / PTM_RATIO, s.height - 10 / PTM_RATIO), b2Vec2(s.width - 10 / PTM_RATIO, 0));
groundBody->CreateFixture(&groundBox, 0);
//关闭和打开绘制功能的按钮
ui::Button*button = ui::Button::create();
button->setTitleText("DeBugDraw");
button->setTitleColor(Color3B::WHITE);
button->setTitleFontSize(30);
button->setPosition(Vec2(origin.x, origin.y + s.height)); //放在左上角
button->setAnchorPoint(Point(0, 1));
button->addTouchEventListener(CC_CALLBACK_2(GameScene::debugdraw, this));
this->addChild(button);
}
void GameScene::BeginContact(b2Contact *contact)
{
log("begin contact");
//每次碰撞开始时都会调用这个方法
}
void GameScene::EndContact(b2Contact *contact)
{
log("end contact");
//每次碰撞结束时都会调用这个方法
}
bool GameScene::init()
{
if (!Layer::init())
{
return false;
}
initPhysics();
this->scheduleUpdate();
return true;
}
void GameScene::update(float dt)
{
int velocityIterations = 8;
int positionIterations = 1;
world->Step(dt, velocityIterations, positionIterations);
//这里是把精灵与物理世界的物体绑定,物体去哪精灵去哪,物体旋转精灵跟着旋转
for(b2Body b = world->GetBodyList(); b; b = b->GetNext()) {
if(b->GetUserData() != NULL) {
SpriteData = (Sprite *)b->GetUserData();
Data->setPosition(ccp(b->GetPosition().x * PTM_RATIO,
b->GetPosition().y * PTM_RATIO));
Data->setRotation(-1 * CC_RADIANS_TO_DEGREES(b->GetAngle()));
}
}
}
void GameScene::debugdraw(Ref* pSender, ui::Widget::TouchEventType type)
{
switch(type)
{
case cocos2d::ui::Widget::TouchEventType::BEGAN:
break;
case cocos2d::ui::Widget::TouchEventType::MOVED:
break;
case cocos2d::ui::Widget::TouchEventType::ENDED:
if (debugdrawlayer->isVisible()){ debugdrawlayer->setVisible(false); }
else {debugdrawlayer->setVisible(true); }
break;
case cocos2d::ui::Widget::TouchEventType::CANCELED:
break;
default:
break;
}
}
</pre>
下一节将介绍:游戏人物的方向控制器,摇杆Joystick类[/b]
