Box2D

2D ¹°¸®¿£ÁøÀÎ Box2D¿¡ ´ëÇؼ­ ¾Ë¾Æº¸ÀÚ.

´Ù¿î·Îµå À§Ä¡´Â ´ÙÀ½°ú °°´Ù.

Box2D ¿£Áø ¼Ò½º :  http://code.google.com/p/box2d/

Box2DÀÇ ¶óÀÌÆ® ¹öÀü :  http://box2d.googlecode.com/files/Box2D_Lite.zip

ÅÍÄ¡Çϸé ÅÍÄ¡ÇÑ À§Ä¡¿¡ Ŭ·ÎÁî ½ºÇÁ¶óÀÌÆ®°¡ Çϳª¾¿ ¶³¾îÁø´Ù.

¹°¸® ¿ë¾î

RigidBody : °­Ã¼
¿ÜºÎ Èû¿¡ ÀÇÇØ º¯Çü µÇÁö ¾Ê´Â ´Ü´ÜÇÑ ¹°Áú

constraint : Á¦¾à
bodyÀÇ ÀÚÀ¯µµ¸¦ Á¦°ÅÇÏ´Â ¹°¸®ÀûÀÎ ¿¬°á, RigidBody´Â 2°³ÀÇ À̵¿Ãà, ÇÑ °³ÀÇ È¸ÀüÃà 3°³ÀÇ ÀÚÀ¯µµ¸¦ °¡Áø´Ù.

contract constraint : °è¾àÀû Á¦¾à
RigidBody ³¢¸® °üÅëÇÏ´Â °ÍÀ» ¸·°í, ¸¶Âû·Â, ¹Ý¹ß·ÂÀ» ½Ã¹Ä·¹ÀÌ¼Ç Çϱâ À§ÇØ  µðÀÚÀÎµÈ Æ¯º°ÇÑ constraintÀÌ´Ù.  contract constraint´Â box2D¿¡ ÀÇÇØ ÀÚµ¿À¸·Î ¸¸µé¾îÁø´Ù.

fixture : °íÁ¤¹°
shape¿Í ¿©·¯ °¡Áö ¼Ó¼ºÀ» °¡Áø´Ù.

joint : °üÀý
µÎ °³ ÀÌ»óÀÇ bodyµéÀ» Á¢ÇÕ ÇÒ ¶§ »ç¿ëµÇ´Â constraintÀÌ´Ù.
revolute, prismatic, distanceµîÀÇ joint¸¦ Á¦°øÇÑ´Ù.
joint¿¡ µû¶ó ÇÑ°èÄ¡(limint)¿Í  ¸ðÅÍ(motor)¸¦ °¡Áø´Ù.

joint limit : °üÀý ÇÑ°èÄ¡
jointÀÇ motorÀÇ ¹üÀ§¸¦ Á¦ÇÑ ÇÑ´Ù. ¿¹¸¦ µé¾î »ç¶÷ÀÇ ÆȲÞÄ¡´Â ƯÁ¤ÇÑ ¹üÀ§ÀÇ °¢µµ¸¸ Çã¿ë ÇÑ´Ù.

joint motor : °üÀý ¸ðÅÍ
joint motor´Â jointÀÇ ÀÚÀ¯µµ¿¡ ¸ÂÃç bodyµéÀÇ ¿òÁ÷ÀÓÀ» µ¿ÀÛ ½ÃŲ´Ù.
¿¹) ÆȲÞÄ¡µéÀ» µ¿ÀÛ ½Ãų ¶§ motor¸¦ »ç¿ë ÇÒ ¼ö ÀÖ´Ù.

world : ¼¼°è
body, fixture, constraint°¡ »óÈ£ ÀÛ¿ëÇÏ´Â ¹°¸® ¼¼°è
¿©·¯°³ÀÇ ¿ùµå¸¦ ¸¸µå´Â °ÍÀ» Çã¿ëÇÏ°í ÀÖÀ¸³ª, °¡±ÞÀû ÇϳªÀÇ ¿ùµå¸¸ ¸¸µå´Â °ÍÀÌ ÁÁ´Ù.

solver : ÇØ°á»ç
world´Â ½Ã°£À» ÁøÇà ½ÃÅ°°í, contract, joint constraintµéÀ» Ç®¾îÁÖ´Â solver¸¦ °¡Áø´Ù. Box2DÀÇ sovler´Â º¹Àâµµ NÀ» °®´Â ³ôÀº ¼º´ÉÀÇ iterative solverÀÌ´Ù.(NÀº constraintÀÇ °¹¼ö)

continuous collision : ¿¬¼ÓÀûÀÎ Ãæµ¹
solver´Â À̻꠰è»êÀ» ÇÏ¿© body¸¦ ó¸®ÇÑ´Ù.. Áß°£ °³ÀÔ ¾øÀ̵µ, ÀÌ´Â tunnelingÀ» À̲ø¾î ³½´Ù.
Box2D´Â tunnelingÀ» ´Ù·ç±â À§ÇÑ Æ¯º°ÇÑ ¾Ë°í¸®ÁòÀ» Æ÷ÇÔÇÏ°í ÀÖ´Ù. ¿ì¼±, Ãæµ¹ ¾Ë°í¸®ÁòÀº ù ¹ø° Ãæµ¹ ±¸°£(Time of impact, TOI)À» ã±â À§Çؼ­ µÎ °³ÀÇ bodyÀÇ ¿òÁ÷ÀÓÀ» º¸°£ ÇÒ ¼ö ÀÖ´Ù. µÎ¹ø°·Î, bodyµéÀ» ù ¹ø° Ãæµ¹ ±¸°£(TOI)À¸·Î À̵¿½ÃÄÑ, Ãæµ¹À» ´À½¼ÇÏ°Ô ÇØÁÖ´Â ´Ü°èºÐÇÒ(sub-stepping) solver°¡ ÀÖ´Ù.

restitution : ¹Ý¹ß·Â
¹°Ã¼°¡ ´Ù¸¥ ¹°Ã¼¿¡ ´ê¾ÒÀ» ¶§ ƨ±â´Â °ª

¾ÀÀÇ Çì´õ ÆÄÀÏ

,box2D ¹°¸®¿£ÁøÀ» »ç¿ëÇÑ´Ù¸é Çì´õ ÆÄÀÏ¿¡ ²À Ãß°¡ µÇ¾î¾ß ÇÒ »çÇ×ÀÌ´Ù.

#include "Box2D/Box2D.h"   //box2D Çì´õ ÆÄÀÏ

#define PTM_RATIO 32  //1¹ÌÅÍ´ç Çȼ¿ÀÇ ¼ö

b2World *mPhysicsWorld  //¹°¸® ¿ùµå

header
#include "cocos2d.h"

#include "Box2D/Box2D.h"

#include "SimpleAudioEngine.h"

#define PTM_RATIO 32

using namespace cocos2d;

class HelloWorld : public cocos2d::CCLayerColor
{
public:
    //ÄÚµå »ý·«
    virtual void ccTouchesEnded(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);
    
    void createPhysicsWorld();
    void UpdatePhysics( float dt);
    void addCircleRigidBody( const CCPoint& pos);

private:
    CCSize mWindowSize;
    CCTexture2D *mTexture;
    b2World *mPhysicsWorld;
};

 

¿ùµå »ý¼º

¹°¸® ½Ã¹Ä·¹ÀÌ¼Ç °ø°£À» ¸¸µé±â À§ÇØ ¿ùµå( b2World )¸¦ »ý¼ºÇÑ´Ù.
Áß·Â, Á¤Áö½Ã ¿¬»ê, Ãæµ¹ °¨Áö °ü·ÃÇÏ¿© ¼³Á¤ÇÑ´Ù.

¿ùµå »ý¼º
void HelloWorld::createPhysicsWorld()
{
    //Áß·Â ¼³Á¤
    b2Vec2 gravity = b2Vec2( 0.0f, -9.8f);

    //¿ùµå »ý¼º
    mPhysicsWorld = new b2World( gravity);

    //¹°Ã¼°¡ Á¤Áö ÇßÀ»¶§ ¿¬»êÀ» ¾ÈÇÔ
    mPhysicsWorld->SetAllowSleeping( true);
    
    //Áö¼ÓÀûÀ¸·Î Ãæµ¹ °¨Áö
    mPhysicsWorld->SetContinuousPhysics( true);
}

±×¶ó¿îµå RigidnBody »ý¼º

½ºÅ©¸° ¿µ¿ªÀ¸·Î 4°³ÀÇ ¶óÀÎÀ» ¸¸µé¾î ±×¶ó¿îµå RigidBody¸¦ ¸¸µç´Ù.
Box2D¿¡¼­ ´ëºÎºÐÀÇ ¼³Á¤Àº Á¢¹Ì»ç ~Def·Î ¿É¼ÇÀ» ¼³Á¤ÇÑ´Ù.

¸®Áöµå¹Ùµð »ý¼ºÀº 4´Ü°è¸¦ °ÅÄ£´Ù.

  1. BodyDef·Î ÁÂÇ¥µîÀ» ¼³Á¤
  2. BodyDef·Î Body »ý¼º
  3. FixtureDef·Î Shape »ý¼º, Ư¼º ¼³Á¤
  4. Body¿¡ Fixtureµî·Ï

b2EdgeShape´Â  : µÎÁ¡À» Áö³ª´Â Á÷¼±À» ¸¸µç´Ù.

Hellow::int( )¿¡ ´ÙÀ½°ú °°ÀÌ Ãß°¡ ÇÑ´Ù.

    this->setTouchEnabled(true);

    mWindowSize = CCDirector::sharedDirector()->getWinSize();

    //box2d ¸®Áöµå¹Ùµð¿ë ÅؽºÃÄ
    mTexture = CCTextureCache::sharedTextureCache()->addImage( "CloseNormal.png");

    createPhysicsWorld();

    CreateGround( mPhysicsWorld, mWindowSize);
    this->schedule( schedule_selector( HelloWorld::UpdatePhysics));

 

CreateGround

void CreateGround( b2World *pWorld, const CCSize &size)
{
    //1. BodyDef·Î ÁÂÇ¥µîÀ» ¼³Á¤
    b2BodyDef groundDef;
    groundDef.position.Set( 0, 0);

    //2. BodyDef·Î Body »ý¼º
    b2Body *groundBody = pWorld->CreateBody( &groundDef);

    //3. FixtureDef·Î Shape »ý¼º, Ư¼º ¼³Á¤
    b2EdgeShape shape;
    b2FixtureDef boxShapeDef;
    boxShapeDef.shape = &shape;
    
    //4. Body¿¡ Fixture µî·Ï
    //¾Æ·¡ÂÊ
    shape.Set( b2Vec2(0, 0), b2Vec2( size.width / PTM_RATIO, 0));
    groundBody->CreateFixture( &boxShapeDef);

    //¿ÞÂÊ
    shape.Set( b2Vec2(0, 0), b2Vec2( 0, size.height / PTM_RATIO));
    groundBody->CreateFixture( &boxShapeDef);

    //À§ÂÊ
    shape.Set( b2Vec2( 0, size.height / PTM_RATIO),
               b2Vec2( size.width / PTM_RATIO, size.height / PTM_RATIO));
    groundBody->CreateFixture( &boxShapeDef);

    //¿À¸¥ÂÊ
    shape.Set( b2Vec2( size.width / PTM_RATIO, size.height / PTM_RATIO),
               b2Vec2( size.width / PTM_RATIO, 0));

    groundBody->CreateFixture( &boxShapeDef);
}

 

Circle RigidBody »ý¼º

¿òÁ÷ÀÌ´Â RigidBody À̹ǷΠµ¿ÀûÀÎ ¹ÙµðÇüÀ¸·Î ¼±¾ð ÇØÁØ´Ù.

bodyDef.type = b2_dynamicBody

b2CircleShape·Î Ãæµ¹ ¼ÎÀÌÇÁ¸¦ »ý¼ºÇÏ¿´´Ù.

À¯Àú µ¥ÀÌÅÍ( userData )¸¦ ¼³Á¤ÇÏ¿© ½Ã¹Ä·¹ÀÌ¼Ç ÇÒ ¶§, ½ºÇÁ¶óÀÌÆ®¸¦ ÂüÁ¶ ÇÒ ¼ö ÀÖµµ·Ï ÇÏ¿´´Ù.

void HelloWorld::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)
{
    CCSetIterator iter = pTouches->begin();
    CCTouch *touch = (CCTouch*)(*iter);
    CCPoint touchPoint = touch->getLocation();

    addCircleRigidBody( touchPoint);
}

ÅÍÄ¡ ÇÑ À§Ä¡¿¡ Ŭ·ÎÁî ¿øÇü ¹öÆ°ÀÌ Ãß°¡µÈ´Ù.

addCircleRigidBody
void HelloWorld::addCircleRigidBody( const CCPoint& pos)
{
    //0. ½ºÇÁ¶óÀÌÆ® »ý¼º
    CCSprite *pSprite = CCSprite::createWithTexture( mTexture, CCRectMake( 0, 0, 37, 37));
    pSprite->setPosition( pos);
    this->addChild( pSprite);

    //1. BodyDef·Î ÁÂÇ¥µîÀ» ¼³Á¤
    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set( pos.x / PTM_RATIO, pos.y / PTM_RATIO);
    bodyDef.userData = pSprite;

    //2. BodyDef·Î Body »ý¼º
    b2Body *body = mPhysicsWorld->CreateBody( &bodyDef);

    //3. FixtureDef·Î Shape »ý¼º, Ư¼º ¼³Á¤
    b2CircleShape circleShape;
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &circleShape;

    circleShape.m_radius = 0.55f;

    fixtureDef.density = 1.0f;  //¹Ðµµ
    fixtureDef.friction = 0.2f; //¸¶Âû·Â 0 ~ 1
    fixtureDef.restitution = 0.7f; //¹Ý¹ß·Â

    //4. Body¿¡ Fixture µî·Ï
    body->CreateFixture( &fixtureDef);
}

 

½Ã¹Ä·¹À̼Ç

b2World::step¿¡¼­ ¹°¸® ½Ã¹Ä·¹À̼ÇÀ» ÇÑ´Ù.

box2d´Â ÀûºÐ±â(integrator) ¾Ë°í¸®ÁòÀ» »ç¿ëÇؼ­ °è»êÇÑ´Ù.
constraint°£¿¡ °è»ê ¹Ýº¹ Ƚ¼ö¸¦ ´Ã¸±¼ö·Ï °è»êÀÇ Á¤È®µµ´Â ÁÁ¾ÆÁöÁö¸¸ CPU ºÎ´ãÀº Áõ°¡ÇÑ´Ù.
box2d¿¡¼­ ±ÇÀåÇÏ´Â iterationÀº ¼Óµµ 8ÀÌ°í À§Ä¡ 3ÀÌ´Ù.

box2D¿¡¼­ 1´ÜÀ§´Â 1m·Î ¼³Á¤ÇÏ°í ÄÚÄÚ½º 2D¿¡¼­´Â 32¸¦ 1m  ¼³Á¤ÇÏ¿´´Ù.

#define PTM_RATIO 32

ÄÚÄÚ½º 2D´Â ½Ã°è ¹æÇâÀ¸·Î ȸÀüÇÑ´Ù.
http://dolphin.ivyro.net/file/mobile/cocos2dx/tutorial11.html

Box2D´Â ¹Ý½Ã°è ¹æÇâÀ¸·Î ȸÀüÇϱ⠶§¹®¿¡ -1À» °öÇÔ( È®½ÇÇÏÁö ¾Ê°í ÃßÃøÀÓ)

this->schedule( schedule_selector( HelloWorld::UpdatePhysics))

½ºÄÉÁ층À» ÅëÇÏ¿© ¹°¸® ¾÷µ¥ÀÌÆ®°¡ µÇµµ·Ï ÇÏ¿´´Ù.

Simulation
void HelloWorld::UpdatePhysics( float dt)
{
    int velocityInerations = 8;
    int positionInerations = 3;

    //½Ã¹Ä·¹À̼Ç
    mPhysicsWorld->Step( dt, velocityInerations, positionInerations);

    for(b2Body *body = mPhysicsWorld->GetBodyList(); body; body = body->GetNext())
    {
        if( body->GetUserData() != NULL)
        {
            CCSprite *spriteData = (CCSprite*)body->GetUserData();
            spriteData->setPosition( ccp( body->GetPosition().x * PTM_RATIO,
                                          body->GetPosition().y * PTM_RATIO) );
            spriteData->setRotation( -1 * CC_RADIANS_TO_DEGREES( body->GetAngle()) );
                                    
        }
    }
}

´Ù¿î·Îµå :        HelloWorldScene.h     HelloWorldScene.cpp