Skip to content

Instantly share code, notes, and snippets.

@takashi1975
Last active February 7, 2016 07:11
Show Gist options
  • Save takashi1975/d1ea2be790035a7fdbec to your computer and use it in GitHub Desktop.
Save takashi1975/d1ea2be790035a7fdbec to your computer and use it in GitHub Desktop.
Box2dを動かしてみた (Cocos2d-x v3.9)
#include "HelloWorldScene.h"
#include "GLES-Render.h"
USING_NS_CC;
#pragma mark
const float HelloWorld::PTM_RATIO = (32.0f);
#pragma mark -
HelloWorld::HelloWorld()
: _world(nullptr)
{
}
HelloWorld::~HelloWorld()
{
}
#pragma mark -
Scene * HelloWorld::createScene()
{
auto scene = Scene::create();
if (scene)
{
if (auto layer = HelloWorld::create())
{
scene->addChild(layer);
}
}
return scene;
}
#pragma mark -
bool HelloWorld::init()
{
bool result = false;
do
{
if (! Layer::init())
{
break;
}
this->initPhysics();
auto visibleRect = Rect::ZERO;
{
visibleRect.origin = Director::getInstance()->getVisibleOrigin();
visibleRect.size = Director::getInstance()->getVisibleSize();
}
if (auto world = this->_world)
{
//ボール
if (auto ball = Sprite::create("CloseNormal.png"))
{
//TEST 読み込み時のサイズ
ball->setScale(3.0f);
const auto ballSize = ball->getBoundingBox().size;
{
const auto pos = Point(visibleRect.getMidX(), visibleRect.getMidY());
ball->setPosition(pos);
//TEST
ball->setRotation(45.0f);
ball->setName("ball");
this->addChild(ball);
ball->setOpacity(64);
}
b2Body * body = nullptr;
{
b2BodyDef bodyDef;
{
bodyDef.type = b2_dynamicBody;
auto pos = Point::ZERO;
{
pos = ball->getPosition();
pos *= (1.0f / HelloWorld::PTM_RATIO);
}
bodyDef.position.Set(pos.x, pos.y);
auto angle = 0.0f;
{
angle = ball->getRotation();
angle = -1.0f * CC_DEGREES_TO_RADIANS(angle);
}
bodyDef.angle = angle;
bodyDef.userData = ball;
}
body = world->CreateBody(&bodyDef);
}
if (body)
{
//スコープに注意 (iOSはOKでもAndroidで落ちる)
b2CircleShape shape;
{
const auto size = ballSize;
const auto length = MAX(size.width, size.height);
//半径
shape.m_radius = length * 0.5f * (1.0f / HelloWorld::PTM_RATIO);
}
b2FixtureDef fixtureDef;
{
fixtureDef.shape = &shape;
fixtureDef.density = 0.4f; //密度
fixtureDef.friction = 0.5f; //摩擦
fixtureDef.restitution = 0.0f; //反発
}
body->CreateFixture(&fixtureDef);
}
}
//壁
{
const Point point[] = {
Point(rect.getMinX(), rect.getMinY()) * (1.0f / HelloWorld::PTM_RATE),
Point(rect.getMaxX(), rect.getMinY()) * (1.0f / HelloWorld::PTM_RATE),
Point(rect.getMaxX(), rect.getMaxY()) * (1.0f / HelloWorld::PTM_RATE),
Point(rect.getMinX(), rect.getMaxY()) * (1.0f / HelloWorld::PTM_RATE),
};
struct PointList {
b2Vec2 pos1;
b2Vec2 pos2;
};
const PointList list[] = {
{ b2Vec2(point[0].x, point[0].y), b2Vec2(point[1].x, point[1].y) },
{ b2Vec2(point[1].x, point[1].y), b2Vec2(point[2].x, point[2].y) },
{ b2Vec2(point[2].x, point[2].y), b2Vec2(point[3].x, point[3].y) },
{ b2Vec2(point[3].x, point[3].y), b2Vec2(point[0].x, point[0].y) },
};
{
b2Body * body = nullptr;
{
b2BodyDef bodydef;
{
bodydef.type = b2BodyType::b2_staticBody;
const auto pos = list[0];
bodydef.position.Set(pos.pos1.x, pos.pos1.y);
}
body = world->CreateBody(&bodydef);
}
if (body)
{
const auto count = sizeof(list)/sizeof(*list);
for (int i = 0; i < count; i++)
{
const auto pos = list[i];
b2EdgeShape shape;
{
shape.Set(pos.pos1, pos.pos2);
}
b2FixtureDef fixturedef;
{
fixturedef.shape = &shape;
fixturedef.density = 0.0f;
fixturedef.friction = 0.0f;
fixturedef.restitution = 1.0f;
}
body->CreateFixture(&fixturedef);
}
}
}
}
}
result = true;
} while (0);
return result;
}
#pragma mark -
void HelloWorld::initPhysics()
{
const auto gravity = b2Vec2(0.0f, -9.8f);
if (auto world = new b2World(gravity))
{
if (auto debug = new GLESDebugDraw(HelloWorld::PTM_RATIO))
{
uint32 flags = 0;
{
flags += b2Draw::e_shapeBit;
// flags += b2Draw::e_jointBit;
// flags += b2Draw::e_aabbBit;
// flags += b2Draw::e_pairBit;
// flags += b2Draw::e_centerOfMassBit;
}
debug->SetFlags(flags);
world->SetDebugDraw(debug);
}
this->_world = world;
}
}
#pragma mark -
void HelloWorld::onEnter()
{
//super
Layer::onEnter();
}
void HelloWorld::onEnterTransitionDidFinish()
{
//super
Layer::onEnterTransitionDidFinish();
this->scheduleUpdate();
}
void HelloWorld::onExitTransitionDidStart()
{
//super
Layer::onExitTransitionDidStart();
this->unscheduleUpdate();
}
void HelloWorld::onExit()
{
//super
Layer::onExit();
}
#pragma mark -
void HelloWorld::update(float delta)
{
if (auto world = this->_world)
{
const auto velocityIterations = 10;
const auto positionIterations = 10;
world->Step(delta, velocityIterations, positionIterations);
for (auto body = world->GetBodyList(); body; body = body->GetNext())
{
if (auto sprite = static_cast<Sprite *>(body->GetUserData()))
{
if (sprite->getName().compare("ball") == 0)
{
auto pos = Point::ZERO;
{
auto vec2Pos = body->GetPosition();
pos = Point(vec2Pos.x, vec2Pos.y);
pos *= HelloWorld::PTM_RATIO;
}
auto angle = 0.0f;
{
angle = body->GetAngle();
angle = -1.0f * CC_RADIANS_TO_DEGREES(angle);
}
sprite->setRotation(angle);
sprite->setPosition(pos);
}
}
}
}
}
void HelloWorld::draw(Renderer *renderer, const Mat4& transform, uint32_t flags)
{
//super
Layer::draw(renderer, transform, flags);
if (auto world = this->_world)
{
if (auto director = Director::getInstance())
{
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION);
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
world->DrawDebugData();
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
}
}
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
#include "Box2D/Box2D.h"
class HelloWorld : public cocos2d::Layer
{
public:
static const float PTM_RATIO;
protected:
HelloWorld();
virtual ~HelloWorld();
public:
static cocos2d::Scene* createScene();
CREATE_FUNC(HelloWorld);
protected:
virtual bool init() override;
private:
void initPhysics();
protected:
virtual void onEnter() override;
virtual void onEnterTransitionDidFinish() override;
virtual void onExitTransitionDidStart() override;
virtual void onExit() override;
protected:
virtual void update(float delta) override;
virtual void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4& transform, uint32_t flags) override;
private:
b2World * _world;
};
#endif
@takashi1975
Copy link
Author

iOS では問題なく動作する。
...が、Android は... コンパイルはOKだが、動作させると エラーで落ちる。

D/cocos2d-x debug info: create rendererRecreatedListener for GLProgramState
D/cocos2d-x debug info: create rendererRecreatedListener for GLProgramState
A/libc: Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1)

... ググったり、試した感じは... Android.mk, Application.mk は多分大丈夫?(soファイルができているし ^^;)
... コードが悪いので調査中... orz

[解決]
b2FixtureDef の shape を作るときのスコープが問題でした。
よく 処理の塊を { ... } で囲むので...自分はやらかしがちですね...。
iOSはOKだけど、Android ではダメ。
...やっぱりなるべくAndroid でも随時確認したほうがいいですね ^^;;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment