인디 게임 강좌

전체보기

모바일 상단 메뉴

본문 페이지

[코코스2D] [Box2D] #06 - 리볼루트 조인트

아이콘 내폰젤무거워
조회: 1685
2017-07-06 22:37:28

Document Version : V1.3 - 2017.07.06 with cocos2d-x 3.15.1

Document Version : V1.2 - 2015.06.08 with cocos2d-x 3.6

Document Version : V1.1 - 2014.03.14 with cocos2d-x 3.0beta2

Document Version : V1.0 - 2013.07.10 with cocos2d-x 2.1.4


제 책인 "시작하세요! Cocos2d-x 3.0 프로그래밍" 내용을  3.15.1 버전에 맞게 수정하여 올리고 있습니다.

이 글은 네이버카페 "Cocos2d-x 사용자 모임"에 동시에 게재되고 있습니다.


개발환경 : 

  • Windows7
  • Visual Studio Community 2017
  • Cocos2d-x 3.15.1
  • 사용 프로젝트 : proj.win32


리볼루트 조인트

커맨드창을 열어 원하는 디렉터리로 이동한 후에, 다음과 같이 cocos 명령어를 이용하여 새로운 프로젝트를 생성합니다.


c:> cocos new Box2dEx05 -p com.study.box05 -l cpp  ↵


Box2dEx04의 모든 코드를 방금 만든 Box2dEx05에 적용시킵니다.

Box2dEx04의 Classes 폴더의 다음 파일들을 Box2dEx05의 Classes 폴더에 덮어 쓰면 됩니다.


■ HelloWorldScene.h

■ HelloWorldScene.cpp

■ GLES-Render.h

■ GLES-Render.cpp



그러고 나서 다음의 디렉터리에서 

{Cocos2d-x가 설치된 디렉터리} / tests / cpp-tests / Resources / Images

아래의 파일을 찾아 리소스 폴더에 추가합니다.


■  blocks.png


Box2dEx05는 Box2dEx04 - 마우스 조인트까지 적용된 상태에서 시작합니다.



헤더 부분은 변경된 점이 없습니다.

[ HelloWorldScene.h  박스2D 리볼루트 조인트 ]

     생략 : Box2dEx04의 코드와 같음 




다음은 리볼루트 조인트 프로젝트에서 Box2dEx04와 달라진 코드 부분입니다.
setBox2dWorld 메서드에서 리볼루트 조인트를 생성하는 부분만이 추가되고 다른 것은 변한 것이 없습니다.
앞으로의 모든 조인트 예제는 이 부분만 고쳐서 테스트를 할 것입니다.

[ HelloWorldScene.cpp – 박스2D 리볼루트 조인트 ]

#include "HelloWorldScene.h"


SceneHelloWorld::createScene()

{

    return HelloWorld::create();

}


bool HelloWorld::init()

{

    if ( !Scene::init() )

    {

        return false;

    }

    

    /////////////////////////////


    // 윈도우 크기를 구한다.

    winSize = Director::getInstance()->getWinSize();


    // 이미지의 텍스쳐를 구한다.

    texture = Director::getInstance()->getTextureCache()->addImage("blocks.png");


    // 월드 생성

    if (this->createBox2dWorld(true))

    {

        srand((int)time(nullptr));

        this->setBox2dWorld();

        this->schedule(schedule_selector(HelloWorld::tick));

    }


    return true;

}


bool HelloWorld::createBox2dWorld(bool debug)

{

     생략 : Box2dEx04의 코드와 같음 

}


void HelloWorld::setBox2dWorld()

{

    // 마우스 조인트 바디를 생성해서 월드에 추가한다.

    bDrag = false;

    gbody = this->addNewSprite(Vec2(00), Size(00), b2_staticBodynullptr0);


    // *****************************************************************************


    // 바디를 생성해서 월드에 추가한다.

    b2Body* body1 = this->addNewSprite(Vec2(240160), Size(3232),

                                                                 b2_staticBody"test"0);

    b2Body* body2 = this->addNewSprite(Vec2(140160), Size(3232),

                                                                 b2_dynamicBody"test"0);


    b2RevoluteJointDef revJointDef;

    b2RevoluteJoint* revJoint;


    revJointDef.Initialize(body1, body2, body1->GetPosition());

    //revJointDef.enableLimit = true;

    //revJointDef.lowerAngle = -90;

    //revJointDef.upperAngle = 0;


    revJoint = (b2RevoluteJoint *)_world->CreateJoint(&revJointDef);

}


HelloWorld::~HelloWorld()

{

     생략 : Box2dEx04의 코드와 같음 

}


void HelloWorld::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)

{

     생략 : Box2dEx04의 코드와 같음 

}


void HelloWorld::onDraw(const Mat4 &transform, uint32_t flags)

{

     생략 : Box2dEx04의 코드와 같음 

}


void HelloWorld::onEnter()

{

     생략 : Box2dEx04의 코드와 같음 

}


void HelloWorld::onExit()

{

     생략 : Box2dEx04의 코드와 같음 

}


void HelloWorld::tick(float dt)

{

     생략 : Box2dEx04의 코드와 같음 

}


b2BodyHelloWorld::addNewSprite(Vec2 point, Size size, b2BodyType bodytype,

                             const char* spriteName, int type)

{

     생략 : Box2dEx04의 코드와 같음 

}


b2BodyHelloWorld::getBodyAtTab(Vec2 p)

{

     생략 : Box2dEx04의 코드와 같음 

}


bool HelloWorld::onTouchBegan(Touch* touch, Event* event)

{

     생략 : Box2dEx04의 코드와 같음 

}


void HelloWorld::onTouchMoved(Touch* touch, Event* event)

{

     생략 : Box2dEx04의 코드와 같음 

}


void HelloWorld::onTouchEnded(Touch* touch, Event* event)

{

     생략 : Box2dEx04의 코드와 같음 

}





위 코드에서 리볼루트 조인트는 다음 코드에서 만들어집니다.

b2RevoluteJointDef revJointDef;

b2RevoluteJoint *revJoint;

    

revJointDef.Initialize(body1, body2, body1->GetPosition());


revJoint = (b2RevoluteJoint *)_world->CreateJoint(&revJointDef);


body1과 body2 를 조인트로 연결하는데, body1의 위치에 리볼루트 조인트 위치를 지정한 것입니다. 즉, body1의 위치가 축이 됩니다.
조인트로 연결하는데 두 바디가 꼭 겹쳐 있을 필요는 없습니다.


이제 코드를 실행하면 다음과 같은 화면을 볼 수 있습니다. 아래쪽에 흔들리는 바디를 마우스로 잡아 세게 휘둘러 보면 고정돼 있는 바디의 위치를 축으로 원운동을 하게 됩니다. 
( 마우스 조인트가 적용되어 있기 때문에 가능한 동작입니다. )
또한 주석 처리된 부분을 풀면 제한된 움직임을 보이게 됨을 확인할 수 있습니다.




디버그 모드에서 다음처럼 조인트 비트의 주석을 풀어 활성화 화면, 두 바디 사이에 선으로 연결해 두 바디가 조인트로 연결되어 있음을 표시합니다. 

// 디버그 드로잉 설정

if (debug) {

// 적색 : 현재 물리 운동을 하는 것

// 회색 : 현재 물리 운동량이 없는 것

m_debugDraw = new GLESDebugDraw(PTM_RATIO);

_world->SetDebugDraw(m_debugDraw);


uint32 flags = 0;

flags += b2Draw::e_shapeBit;

flags += b2Draw::e_jointBit;

//flags += b2Draw::e_aabbBit;

//flags += b2Draw::e_pairBit;

//flags += b2Draw::e_centerOfMassBit;

m_debugDraw->SetFlags(flags);

}



그리고 다음과 같이 모터를 지정해 자동으로 원 운동을 하게 만들 수도 있습니다.

b2RevoluteJointDef revJointDef;

b2RevoluteJoint *revJoint;

    

revJointDef.Initialize(body1, body2, body1->GetPosition());

revJointDef.enableMotortrue;

revJointDef.motorSpeed = 5// radians per second. 1 radian = 180/pi degrees

revJointDef.maxMotorTorque = 20// 회전력


revJoint = (b2RevoluteJoint *)_world->CreateJoint(&revJointDef);

 


모터의 스피드와 회전력에 의해 돌아가는 속도가 달라지므로 여러 가지 값으로 바꿔보면서 테스트해 보기 바랍니다.









Lv28 내폰젤무거워

모바일 게시판 하단버튼

댓글

새로고침
새로고침

모바일 게시판 하단버튼

지금 뜨는 인벤

더보기+

모바일 게시판 리스트

모바일 게시판 하단버튼

글쓰기

모바일 게시판 페이징