cocos2d-x遊戲開發 跑酷(二) 物理世界
阿新 • • 發佈:2019-02-14
泰然的跑酷用的chipmunk物理引擎,我沒有仔細學過這個東西。不過我看了一下他們的用法,感覺跟box2d差不多。box2d用純真的面向物件C++開發,用在這裡應該沒有問題,試一下。
泰然的工程沒有加入box2d模組,所以需要新增。將external/Box2D加入工程,將無用的引用刪掉,加入後結構如下
然後新建一個PlayScene類,開始建立物理世界。
為了方便除錯box2d物理世界,需要接入debug渲染器,將TestCpp/Classes/Box2DTestBed/下的GLES-Render.h和GLES-Render.cpp加入到工程,這個可以繪製出物理模型的形狀。
因為box2d針對0-10米的模擬做過優化,所以我這裡將畫素大小對映到10左右
#define RATIO 32
看下PlayScene.h
// // PlayScene.h // Parkour // // Created by lerry on 14-3-14. // Copyright (c) 2014年 Goonear Co.,Ltd. All rights reserved. // #ifndef __Parkour__PlayScene__ #define __Parkour__PlayScene__ #include "cocos2d.h" #include "Box2D.h" #include "GLES-Render.h" #define RATIO 32 #define GROUND_HEIGHT 57 #define RUUNER_STARTX 80 class PlayScene : public cocos2d::CCLayer { b2World* mWorld; GLESDebugDraw* mDebugDraw; private: // 初始化物理世界 void initPhysics(); // 繪製物理世界debug區域 void draw(); // 開啟物理世界debug void setDebug(bool isDebug); public: virtual bool init(); virtual void update(float dt); CREATE_FUNC(PlayScene); static cocos2d::CCScene* scene(); }; #endif /* defined(__Parkour__PlayScene__) */
現在主要有一個初始化物理世界的函式initPhysics()函式,在這裡建立了一個地板。
void PlayScene::initPhysics() { mWorld = new b2World(b2Vec2(0, -10)); mWorld->SetAllowSleeping(true); mWorld->SetContinuousPhysics(true); // mWorld->SetContactListener(this); // 地板body b2Body* ground = NULL; b2BodyDef bd; ground = mWorld->CreateBody(&bd); // 地板 b2EdgeShape shape; shape.Set(b2Vec2(0, GROUND_HEIGHT / RATIO), b2Vec2(INT_MAX, GROUND_HEIGHT / RATIO)); ground->CreateFixture(&shape, 0.0f); setDebug(true); }
這裡建立了一個邊緣形狀,邊緣形狀類似靜態物體,但是它沒有體積。box2d裡面的碰撞演算法要求碰撞的兩個物體至少一個要有體積,所以邊緣形狀不能和邊緣形狀碰撞,可以和其他形狀類物體碰撞。
box2d的物理世界有自己的世界迴圈函式,跟cocos2d-x的update函式類似,所以在update函式裡面呼叫box2d的迭代函式
void PlayScene::update(float dt)
{
// 物理世界的迭代函式
mWorld->Step(dt, 10, 8);
}
Step函式的引數解釋一下,第一個時間引數,單步迭代步長,第二個引數單步時間內速度迭代次數,第三個引數但不是件內位置迭代次數。這幾個引數有建議值,我這裡就取這幾個值。
然後在MainScene.cpp的onPlay函式裡面填上回調的實現:
// start按鈕回撥
void MainScene::onPay()
{
CCLog("onPlay click");
// 建立帶過渡的場景
CCScene* s = CCTransitionFade::create(1, PlayScene::scene());
CCDirector::sharedDirector()->replaceScene(s);
}
這裡加了一個過渡場景,跑起來看到一條線,初步完成。