#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;
}