- 메이플 배상액 1758만원 감사합니다. [100]
- 로아 미터기 해외 서버 상황 [372]
- 검은사막 1000일차 검은사막 完 [39]
- 치어리더 삐끼삐키 이주은 치어리더 맨날 지겹지도 않냐 [12]
- 해외겜 스팀 동접 최고 경신 “3,830만명의 온라인 유저” [1]
- 오공 검은신화오공 구매고려하시는분들께!
Document Version : V1.3 - 2017.07.05 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 사용자 모임"에 동시에 게재되고 있습니다.
개발환경 :
c:> cocos new Box2dEx04 -p com.study.box04 -l cpp ↵
Box2dEx02에서 한 것처럼 아래의 파일을 클래스 폴더에 추가합니다.
■ GLES-Render.h
■ GLES-Render.cpp
그러고 나서 다음의 디렉터리에서
{Cocos2d-x가 설치된 디렉터리} / tests / cpp-tests / Resources / Images
아래의 파일을 찾아 리소스 폴더에 추가합니다.
이제 헤더에서는 다음과 같이 색으로 표시된 부분이 Box2dEx02 코드에서 추가 또는 수정된 부분이므로 이 부분을 기존 코드에 추가하거나 수정하면 됩니다.
[ HelloWorldScene.h – 박스2D 마우스 조인트 ]
#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);
bool bDrag;
b2Body* dragBody;
b2MouseJoint* mouseJoint;
b2Body* gbody;
b2Body* addNewSprite(Vec2 point, Size size, b2BodyType bodytype,
const char* spriteName, int type);
b2Body* getBodyAtTab(Vec2 p);
bool onTouchBegan(Touch* touch, Event* event);
void onTouchMoved(Touch* touch, Event* event);
void onTouchEnded(Touch* touch, Event* event);
};
#endif // __HELLOWORLD_SCENE_H__
다음은 마우스 조인트 프로젝트에서 HelloWorldScene 클래스 cpp의 풀 소스입니다.
[ HelloWorldScene.cpp – 박스2D 마우스 조인트 ]
#include "HelloWorldScene.h"
Scene* HelloWorld::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)
{
… 생략 : Box2dEx02의 코드와 같음 …
}
void HelloWorld::setBox2dWorld()
{
// 마우스 조인트 바디를 생성해서 월드에 추가한다.
bDrag = false;
gbody = this->addNewSprite(Vec2(0, 0), Size(0, 0), b2_staticBody, nullptr, 0);
// 바디를 생성해서 월드에 추가한다.
this->addNewSprite(Vec2(240, 160), Size(32, 32), b2_dynamicBody, "test", 0);
}
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::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
}
void HelloWorld::onExit()
{
… 생략 : Box2dEx02의 코드와 같음 …
}
void HelloWorld::tick(float dt)
{
… 생략 : Box2dEx02의 코드와 같음 …
}
b2Body* HelloWorld::addNewSprite(Vec2 point, Size size, b2BodyType bodytype,
const char* spriteName, int type)
{
// 바디데프 만들고 속성들을 지정한다.
b2BodyDef bodyDef;
bodyDef.type = bodytype;
bodyDef.position.Set(point.x / PTM_RATIO, point.y / PTM_RATIO);
if (spriteName) {
if (strcmp(spriteName, "test") == 0) {
int idx = (CCRANDOM_0_1() > .5 ? 0 : 1);
int idy = (CCRANDOM_0_1() > .5 ? 0 : 1);
Sprite* sprite = Sprite::createWithTexture(texture,
Rect(32 * idx, 32 * idy, 32, 32));
sprite->setPosition(point);
this->addChild(sprite);
bodyDef.userData = sprite;
}
else {
Sprite* sprite = Sprite::create(spriteName);
sprite->setPosition(point);
this->addChild(sprite);
bodyDef.userData = sprite;
}
}
// 월드에 바디데프의 정보로 바디를 만든다.
b2Body* body = _world->CreateBody(&bodyDef);
// 바디에 적용할 물리 속성용 바디의 모양을 만든다.
b2FixtureDef fixtureDef;
b2PolygonShape dynamicBox;
b2CircleShape circle;
if (type == 0) {
dynamicBox.SetAsBox(size.width / 2 / PTM_RATIO, size.height / 2 / PTM_RATIO);
fixtureDef.shape = &dynamicBox;
}
else {
circle.m_radius = (size.width / 2) / PTM_RATIO;
fixtureDef.shape = &circle;
}
// Define the dynamic body fixture.
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3f;
fixtureDef.restitution = 0.0f;
body->CreateFixture(&fixtureDef);
return body;
}
b2Body* HelloWorld::getBodyAtTab(Vec2 p)
{
b2Fixture* fix;
// 바디를 터치했는지 모든 바디 리스트를 돌면서 체크한다.
for (b2Body* b = _world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != nullptr) {
if (b->GetType() == b2_staticBody) continue;
fix = b->GetFixtureList();
if (fix->TestPoint(b2Vec2(p.x / PTM_RATIO, p.y / PTM_RATIO))) {
// 터치된 바디를 리턴한다.
return b;
}
}
}
return nullptr;
}
bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
{
Vec2 touchPoint = touch->getLocation();
if (b2Body* b = this->getBodyAtTab(touchPoint))
{
dragBody = b;
bDrag = true;
// 터치된 바디에 마우스 조인트를 생성한다.
b2MouseJointDef md;
md.bodyA = gbody;
md.bodyB = dragBody;
md.target.Set(dragBody->GetPosition().x, dragBody->GetPosition().y);
md.maxForce = 300.0 * dragBody->GetMass();
mouseJoint = (b2MouseJoint *)_world->CreateJoint(&md);
}
return true;
}
void HelloWorld::onTouchMoved(Touch* touch, Event* event)
{
Vec2 touchPoint = touch->getLocation();
if (bDrag) {
mouseJoint->SetTarget(b2Vec2(touchPoint.x / PTM_RATIO, touchPoint.y / PTM_RATIO));
}
}
void HelloWorld::onTouchEnded(Touch* touch, Event* event)
{
if (bDrag) {
// 마우스 조인트를 제거한다.
_world->DestroyJoint(mouseJoint);
mouseJoint = nullptr;
dragBody->SetAwake(true);
}
bDrag = false;
}
b2MouseJointDef md;
md.bodyA = gbody;
md.bodyB = dragBody;
md.target.Set(dragBody->GetPosition().x, dragBody->GetPosition().y);
md.maxForce = 300.0 * dragBody->GetMass();
mouseJoint = (b2MouseJoint *)_world->CreateJoint(&md);
mouseJoint->SetTarget(b2Vec2(touchPoint.x / PTM_RATIO, touchPoint.y / PTM_RATIO));
_world->DestroyJoint(mouseJoint);mouseJoint = nullptr;
앞으로 만들게 될 조인트 관련 예제들은 모두 마우스 조인트를 포함하고 있습니다. 그러므로 이 이후의 예제들은 Box2dEx04번 코드에 추가로 코드를 작성하면 됩니다.
내폰젤무거워