인디 게임 강좌

내글

모바일 상단 메뉴

본문 페이지

[코코스2D] [Box2D] #20 - 중력을 이용한 점프

아이콘 내폰젤무거워
조회: 4565
2017-07-20 19:19:29

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

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


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


개발환경 : 

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


Click Velocity

이번 예제는 약간의 응용입니다. 터치를 하면 위쪽 방향으로 힘을 주어 던지는 동작을 반복하여 바디가 아래로 떨어지지 않게 하는 것입니다. 결과적으로는 플래피버드의 동작을 하게 합니다.

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


c:> cocos new Box2dEx19 -p com.study.box19 -l cpp  ↵


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

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


■ HelloWorldScene.h

■ HelloWorldScene.cpp

■ GLES-Render.h

■ GLES-Render.cpp



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

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

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


■  blocks.png


Box2dEx19는 Box2dEx02 - 디버그 모드까지 적용된 상태에서 시작합니다.




헤더 부분에는 터치를 처리할 메서드의 선언을 추가합니다.
아래 표시된 부분처럼 기존의 코드는 메서드 선언을 삭제하고 필요한 것을 다음과 같이 추가합니다.

[ HelloWorldScene.h  박스2D Click Velocity ]

#ifndef __HELLOWORLD_SCENE_H__

#define __HELLOWORLD_SCENE_H__


#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)

#pragma execution_character_set("utf-8")

#endif


#include "cocos2d.h"

#include "Box2D/Box2D.h"

#include <GLES-Render.h>


#define PTM_RATIO 32


using namespace cocos2d;


class HelloWorld : public cocos2d::Scene

{

public:

    static cocos2d::Scene* createScene();

    virtual bool init();

    CREATE_FUNC(HelloWorld);


    Size winSize;

//    Texture2D* texture;

    b2World* _world;


    // For debugging

    GLESDebugDraw* m_debugDraw;

    cocos2d::CustomCommand _customCmd;


    bool createBox2dWorld(bool debug);

    void setBox2dWorld();

    ~HelloWorld();

    virtual void draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform,

                               uint32_t flags) override;

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


    void onEnter();

    void onExit();

    void tick(float dt);


    b2Body* myBall;

    float  playerVelocity;

    bool   playerIsFlying;


    b2Body* addNewSprite(Vec2 point, Size size, b2BodyType bodytype,

                                          const char* spriteName, int type);

    b2Body* getBodyAtTab(Point p);

    void addNewSpriteAtPosition(Vec2 location);

    bool onTouchBegan(Touch* touch, Event* event);

    void onTouchEnded(Touch* touch, Event* event);

};


#endif // __HELLOWORLD_SCENE_H__



다음은 클릭벨로서티 프로젝트에서 Box2dEx02와 달라진 코드 부분입니다.
터치 리스너를 등록하고 터치 이벤트 메서드에서 터치를 감지하고 tick 메서드에서 바디에 힘을 주어 공중으로 띄워 줍니다.

[ HelloWorldScene.cpp  박스2D Click Velocity ]

#include "HelloWorldScene.h"


SceneHelloWorld::createScene()

{

     생략 : Box2dEx02의 코드와 같음 

}


bool HelloWorld::init()

{

     생략 : Box2dEx02의 코드와 같음 

}


bool HelloWorld::createBox2dWorld(bool debug)

{

     생략 : Box2dEx02의 코드와 같음 

}


void HelloWorld::setBox2dWorld()

{

    playerIsFlying = false;


    // 새로운 물리 객체의 바디와 해당 스프라이트를 추가한다.

    addNewSpriteAtPosition(Vec2(240160));

}


HelloWorld::~HelloWorld()

{

     생략 : Box2dEx02의 코드와 같음 

}


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

{

     생략 : Box2dEx02의 코드와 같음 

}


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

{

     생략 : Box2dEx02의 코드와 같음 

}


void HelloWorld::onEnter()

{

    Scene::onEnter();


    // 싱글터치모드로 터치리스너 등록

    auto listener = EventListenerTouchOneByOne::create();

    listener->setSwallowTouches(true);

    listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBeganthis);

    listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEndedthis);


    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

}


void HelloWorld::onExit()

{

     생략 : Box2dEx02의 코드와 같음 

}


void HelloWorld::tick(float dt)

{

    int velocityIterations = 8;

    int positionIterations = 3;


    // Step : 물리 세계를 시뮬레이션한다.

    _world->Step(dt, velocityIterations, positionIterations);


    // 만들어진 객체 만큼 루프를 돌리면서 바디에 붙인 스프라이트를 여기서 제어한다.

    for (b2Body* b = _world->GetBodyList(); b; b = b->GetNext())

    {

        if (b->GetUserData() != nullptr) {

            Sprite* spriteData = (Sprite *)b->GetUserData();


            spriteData->setPosition(Vec2(b->GetPosition().x * PTM_RATIO,

                                                            b->GetPosition().y * PTM_RATIO));

            spriteData->setRotation(-1 * CC_RADIANS_TO_DEGREES(b->GetAngle()));

        }

    }


    if (playerIsFlying)

    {

        myBall->ApplyLinearImpulse(b2Vec2(0playerVelocity),

                                                       myBall->GetWorldCenter(),

                                                       true);

        playerVelocity += 0.01f;


        if (playerVelocity > 1.5f)

            playerVelocity = 1.5f;

    }

}


void HelloWorld::addNewSpriteAtPosition(Vec2 location)

{

    // 바디데프 만들고 속성들을 지정한다.

    b2BodyDef bodyDef;

    bodyDef.type = b2_dynamicBody;

    bodyDef.position.Set(location.x / PTM_RATIO, location.y / PTM_RATIO);


    // 보통은 유져데이터에 스프라이트를 붙이는데

    // 여기서는 아무 데이타를 넣지 않고 디버그 드로잉만 수행한다.

    bodyDef.userData = nullptr;


    // 월드에 바디데프의 정보로 바디를 만든다.

    myBall = _world->CreateBody(&bodyDef);


    // 바디에 적용할 물리 속성용 바디의 모양을 만든다. 여기서는 원을 만든다.

    b2CircleShape circle;

    // 바디의 크기 지정 - 원의 경우엔 반지름

    circle.m_radius = 0.45f;


    b2FixtureDef fixtureDef;

    // 모양

    fixtureDef.shape = &circle;

    // 밀도

    fixtureDef.density = 1.0f;

    // 마찰력

    fixtureDef.friction = 0.2f;

    // 반발력

    fixtureDef.restitution = 0.6f;


    myBall->CreateFixture(&fixtureDef);

}


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

{

    playerVelocity = 0.5f;

    playerIsFlying = true;


    return true;

}


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

{

    playerIsFlying = false;

    playerVelocity = 0.0f;

}




코드를 완성했으면 실행시켜 봅니다.

상태를 표시하는 변수(playerIsFlying)를 통해 tick에서 힘을 주고 있기 때문에, 터치를 오래 하고 있으면 위쪽에 부딪히게 될 것이고, 터치를 오래동안 하지 않으면 바닥으로 떨어지게 됩니다. 











다음은 이것을 응용해서 만든 학생의 작품입니다.


2016년 경일게임스쿨 3기 윤지용 : DogHero



Lv28 내폰젤무거워

모바일 게시판 하단버튼

댓글

새로고침
새로고침

모바일 게시판 하단버튼

지금 뜨는 인벤

더보기+

모바일 게시판 리스트

모바일 게시판 하단버튼

글쓰기

모바일 게시판 페이징