【麦可网】Cocos2d-X跨平台游戏开发---学习笔记
第二十五课:Cocos2D-X物理引擎之Box2D8-10
=======================================================================================================================================================================
课程目标:
- 学习Box2D
课程重点:
- BOX2D概念
- BOX2D常用操作
- 使用物理编辑器
考核目标:
- 能够使用Box2D常用操作
- 使用物理编辑器完成物理对象编辑
=======================================================================================================================================================================
一、物理编辑器
1.vertexHelper(mac)
2.PhysicsEditor
二、使用PhysicsEditor的实例
HelloPhysicEditor.h
-------------------------------------
#pragma once
#include "cocos2d.h"
#include "Box2D/Box2D.h"
USING_NS_CC;
class HelloPhysicEditor : public cocos2d::CCLayer
{
private:
CCTexture2D* m_pSpriteTexture;
b2World* world;
public:
HelloPhysicEditor();
~HelloPhysicEditor();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::CCScene* scene();
// a selector callback
void menuCloseCallback(CCObject* pSender);
// implement the "static node()" method manually
CREATE_FUNC(HelloPhysicEditor);
virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent);
void initPhysics();
void addNewSpriteAtPosition(CCPoint p);
void updata(float dt);
};
HelloPhysicEditor.cpp
-------------------------------------
#include "HelloPhysicEditor.h"
#include "cocos-ext.h"
#include "GB2ShapeCache-x.h"
using namespace cocos2d::extension;
USING_NS_CC;
enum{
kTagParentNode = 1,
};
#define PTM_RATIO 32.0f
string names[] = {
"hotdog",
"drink",
"icecream",
"icecream2",
"icecream3",
"hamburger",
"orange"
};
CCScene* HelloPhysicEditor::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
// 'layer' is an autorelease object
HelloPhysicEditor *layer = HelloPhysicEditor::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
HelloPhysicEditor::HelloPhysicEditor():
m_pSpriteTexture(NULL),
world(NULL)
{
//加载physicsEditor生成的文件
GB2ShapeCache::sharedGB2ShapeCache()->addShapesWithFile("physic_all.plist");
}
HelloPhysicEditor::~HelloPhysicEditor()
{
CC_SAFE_DELETE(world);
}
// on "init" you need to initialize your instance
bool HelloPhysicEditor::init()
{
//
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
setTouchEnabled(true);
setAccelerometerEnabled(true);
this->initPhysics();
CCSpriteBatchNode* blocks = CCSpriteBatchNode::create("blocks.png",100);
m_pSpriteTexture = blocks->getTexture();
addChild(blocks, 0, kTagParentNode);
//scheduleUpdate();
this->schedule(schedule_selector(HelloPhysicEditor::updata));
return true;
}
void HelloPhysicEditor::menuCloseCallback(CCObject* pSender)
{
}
void HelloPhysicEditor::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)
{
CCSetIterator it;
CCTouch* touch;
for (it=pTouches->begin(); it!=pTouches->end();it++)
{
touch = (CCTouch*)(*it);
if (!touch) break;
CCPoint location = touch->getLocation();
addNewSpriteAtPosition( location );
}
}
void HelloPhysicEditor::initPhysics()
{
b2Vec2 gravity;
gravity.Set(0.0f,-10.0f);
world = new b2World(gravity);
world->SetAllowSleeping(true);
world->SetContinuousPhysics(true);
//创建物理空间的范围
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0);
//创建刚体
b2Body* groundBody = world->CreateBody(&groundBodyDef);
//创建形状
b2EdgeShape groundBox;
//创建夹具
//将形状绑定到刚体上
//button
groundBox.Set(b2Vec2(0,0), b2Vec2(480/PTM_RATIO, 0));
groundBody->CreateFixture(&groundBox, 0);
//top
groundBox.Set(b2Vec2(0,320/PTM_RATIO), b2Vec2(480/PTM_RATIO, 320/PTM_RATIO));
groundBody->CreateFixture(&groundBox, 0);
//left
groundBox.Set(b2Vec2(0,320/PTM_RATIO), b2Vec2(0, 0));
groundBody->CreateFixture(&groundBox, 0);
//right
groundBox.Set(b2Vec2(480/PTM_RATIO,320/PTM_RATIO), b2Vec2(480/PTM_RATIO, 0));
groundBody->CreateFixture(&groundBox, 0);
}
void HelloPhysicEditor::addNewSpriteAtPosition(CCPoint p)
{
string name = names[rand()%7];
//定义刚体
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
b2Body *body = world->CreateBody(&bodyDef);
//定义多边形
// b2PolygonShape dynamicBox;
// dynamicBox.SetAsBox(.5f, .5f);
GB2ShapeCache* sc = GB2ShapeCache::sharedGB2ShapeCache();
sc->addFixturesToBody(body, name.c_str());
//定义夹具
// b2FixtureDef fixtureDef;
// fixtureDef.shape = &dynamicBox; //形状
// fixtureDef.density = 1.0f; //密度
// fixtureDef.friction = 0.3f; //摩擦系数
// body->CreateFixture(&fixtureDef);
//
// CCNode* parent = this->getChildByTag(kTagParentNode);
//
// int idx = (CCRANDOM_0_1() < 0.5 ? 0 : 1);
// int idy = (CCRANDOM_0_1() < 0.5 ? 0 : 1);
// if (idx==0 && idy==0)
// {
// int a =100;
// body->SetUserData(&a);
// }
// CCPhysicsSprite* sprite = CCPhysicsSprite::createWithTexture(m_pSpriteTexture, CCRectMake(32*idx, 32*idy, 32, 32));
// parent->addChild(sprite);
// sprite->setB2Body(body);
// sprite->setPTMRatio(PTM_RATIO);
//sprite->setPosition( ccp( p.x, p.y) );//添加上这句在快速创建物理精灵时会出错
CCPhysicsSprite* sprite = CCPhysicsSprite::create( (name+".png").c_str());
this->addChild(sprite);
sprite->setB2Body(body);
sprite->setPTMRatio(PTM_RATIO);
//sprite->setPosition( ccp(p.x , p.y) );
sprite->setAnchorPoint(sc->anchorPointForShape(name.c_str()));
}
void HelloPhysicEditor::updata(float dt)
{
int velocityIterations = 8;
int positionIterations = 1;
world->Step(dt, velocityIterations, positionIterations);
#if 0
//遍历刚体
for (b2Body* b=world->GetBodyList(); b; b=b->GetNext())
{
int* tmp = (int*)b->GetUserData();
if (*tmp == 100)
{
//千万不要在这里直接删除b指向的body对象,缓存后在后面删除
CCLOG("body is a");
}
}
//遍历碰撞点
for ( b2Contact* c=world->GetContactList(); c; c=c->GetNext() )
{
千万不要在这里直接删除c指向的碰撞点对象,缓存后在后面删除
}
#endif
}
视频中GB2ShapeCache-x.cpp的下载地址:
http://download.youkuaiyun.com/download/yclmy/8408533
===================================================================
总结:
物理编辑器真的太方便啦!
开心一刻:
蝙蝠深爱麻雀,却被拒绝,
蝙蝠:“为什么,这一切都是为什么?”
麻雀:“俺妈说了,长得黑也就算了,总爱晚上出去的男人都不是好鸟!”
【麦可网】Cocos2d-X跨平台游戏开发---教程下载:http://pan.baidu.com/s/1kTio1Av
【麦可网】Cocos2d-X跨平台游戏开发---笔记系列:http://blog.youkuaiyun.com/qiulanzhu