2011-06-13 20:35:39 +08:00
|
|
|
//
|
|
|
|
// HelloWorldScene.cpp
|
|
|
|
// ___PROJECTNAME___
|
|
|
|
//
|
|
|
|
// Created by ___FULLUSERNAME___ on ___DATE___.
|
|
|
|
// Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
|
|
|
|
//
|
|
|
|
#include "HelloWorldScene.h"
|
|
|
|
#include "SimpleAudioEngine.h"
|
|
|
|
|
|
|
|
using namespace cocos2d;
|
|
|
|
using namespace CocosDenshion;
|
|
|
|
|
|
|
|
#define PTM_RATIO 32
|
2012-05-02 12:51:48 +08:00
|
|
|
|
|
|
|
enum {
|
|
|
|
kTagParentNode = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
PhysicsSprite::PhysicsSprite()
|
|
|
|
: m_pBody(NULL)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhysicsSprite::setPhysicsBody(b2Body * body)
|
|
|
|
{
|
|
|
|
m_pBody = body;
|
|
|
|
}
|
|
|
|
|
|
|
|
// this method will only get called if the sprite is batched.
|
|
|
|
// return YES if the physics values (angles, position ) changed
|
|
|
|
// If you return NO, then nodeToParentTransform won't be called.
|
|
|
|
bool PhysicsSprite::isDirty(void)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns the transform matrix according the Chipmunk Body values
|
|
|
|
CCAffineTransform PhysicsSprite::nodeToParentTransform(void)
|
2011-06-13 20:35:39 +08:00
|
|
|
{
|
2012-05-02 12:51:48 +08:00
|
|
|
b2Vec2 pos = m_pBody->GetPosition();
|
|
|
|
|
|
|
|
float x = pos.x * PTM_RATIO;
|
|
|
|
float y = pos.y * PTM_RATIO;
|
|
|
|
|
2012-06-22 12:00:27 +08:00
|
|
|
if ( isIgnoreAnchorPointForPosition() ) {
|
2012-05-02 12:51:48 +08:00
|
|
|
x += m_tAnchorPointInPoints.x;
|
|
|
|
y += m_tAnchorPointInPoints.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make matrix
|
|
|
|
float radians = m_pBody->GetAngle();
|
|
|
|
float c = cosf(radians);
|
|
|
|
float s = sinf(radians);
|
|
|
|
|
|
|
|
if( ! CCPoint::CCPointEqualToPoint(m_tAnchorPointInPoints, CCPointZero) ){
|
|
|
|
x += c*-m_tAnchorPointInPoints.x + -s*-m_tAnchorPointInPoints.y;
|
|
|
|
y += s*-m_tAnchorPointInPoints.x + c*-m_tAnchorPointInPoints.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rot, Translate Matrix
|
|
|
|
m_tTransform = CCAffineTransformMake( c, s,
|
|
|
|
-s, c,
|
|
|
|
x, y );
|
|
|
|
|
|
|
|
return m_tTransform;
|
|
|
|
}
|
2011-06-13 20:35:39 +08:00
|
|
|
|
|
|
|
HelloWorld::HelloWorld()
|
|
|
|
{
|
2012-06-22 12:00:27 +08:00
|
|
|
setTouchEnabled( true );
|
|
|
|
setAccelerometerEnabled( true );
|
2012-05-02 12:51:48 +08:00
|
|
|
|
|
|
|
CCSize s = CCDirector::sharedDirector()->getWinSize();
|
|
|
|
// init physics
|
|
|
|
this->initPhysics();
|
|
|
|
|
2012-06-22 12:00:27 +08:00
|
|
|
CCSpriteBatchNode *parent = CCSpriteBatchNode::create("blocks.png", 100);
|
2012-05-02 12:51:48 +08:00
|
|
|
m_pSpriteTexture = parent->getTexture();
|
|
|
|
|
|
|
|
addChild(parent, 0, kTagParentNode);
|
|
|
|
|
|
|
|
|
|
|
|
addNewSpriteAtPosition(ccp(s.width/2, s.height/2));
|
|
|
|
|
2012-06-22 12:00:27 +08:00
|
|
|
CCLabelTTF *label = CCLabelTTF::create("Tap screen", "Marker Felt", 32);
|
2012-05-02 12:51:48 +08:00
|
|
|
addChild(label, 0);
|
|
|
|
label->setColor(ccc3(0,0,255));
|
|
|
|
label->setPosition(ccp( s.width/2, s.height-50));
|
2011-06-13 20:35:39 +08:00
|
|
|
|
2012-05-02 12:51:48 +08:00
|
|
|
scheduleUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
HelloWorld::~HelloWorld()
|
|
|
|
{
|
|
|
|
delete world;
|
|
|
|
world = NULL;
|
2011-06-13 20:35:39 +08:00
|
|
|
|
2012-05-02 12:51:48 +08:00
|
|
|
//delete m_debugDraw;
|
|
|
|
}
|
|
|
|
|
|
|
|
void HelloWorld::initPhysics()
|
|
|
|
{
|
|
|
|
|
|
|
|
CCSize s = CCDirector::sharedDirector()->getWinSize();
|
|
|
|
|
2012-04-19 14:35:52 +08:00
|
|
|
b2Vec2 gravity;
|
|
|
|
gravity.Set(0.0f, -10.0f);
|
|
|
|
world = new b2World(gravity);
|
2012-05-02 12:51:48 +08:00
|
|
|
|
|
|
|
// Do we want to let bodies sleep?
|
|
|
|
world->SetAllowSleeping(true);
|
|
|
|
|
2012-04-19 14:35:52 +08:00
|
|
|
world->SetContinuousPhysics(true);
|
2012-05-02 12:51:48 +08:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
|
|
|
|
// Define the ground body.
|
2012-04-19 14:35:52 +08:00
|
|
|
b2BodyDef groundBodyDef;
|
2012-05-02 12:51:48 +08:00
|
|
|
groundBodyDef.position.Set(0, 0); // bottom-left corner
|
|
|
|
|
2012-04-19 14:35:52 +08:00
|
|
|
// Call the body factory which allocates memory for the ground body
|
|
|
|
// from a pool and creates the ground box shape (also from a pool).
|
|
|
|
// The body is also added to the world.
|
|
|
|
b2Body* groundBody = world->CreateBody(&groundBodyDef);
|
2012-05-02 12:51:48 +08:00
|
|
|
|
2012-04-19 14:35:52 +08:00
|
|
|
// Define the ground box shape.
|
2012-05-02 12:51:48 +08:00
|
|
|
b2EdgeShape groundBox;
|
|
|
|
|
2011-12-01 17:00:30 +08:00
|
|
|
// bottom
|
2012-05-02 12:51:48 +08:00
|
|
|
|
|
|
|
groundBox.Set(b2Vec2(0,0), b2Vec2(s.width/PTM_RATIO,0));
|
|
|
|
groundBody->CreateFixture(&groundBox,0);
|
|
|
|
|
2011-12-01 17:00:30 +08:00
|
|
|
// top
|
2012-05-02 12:51:48 +08:00
|
|
|
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO));
|
|
|
|
groundBody->CreateFixture(&groundBox,0);
|
|
|
|
|
2011-12-01 17:00:30 +08:00
|
|
|
// left
|
2012-05-02 12:51:48 +08:00
|
|
|
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(0,0));
|
|
|
|
groundBody->CreateFixture(&groundBox,0);
|
2011-06-13 20:35:39 +08:00
|
|
|
|
2012-05-02 12:51:48 +08:00
|
|
|
// right
|
|
|
|
groundBox.Set(b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,0));
|
|
|
|
groundBody->CreateFixture(&groundBox,0);
|
2011-06-13 20:35:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void HelloWorld::draw()
|
|
|
|
{
|
2012-05-02 12:51:48 +08:00
|
|
|
//
|
|
|
|
// IMPORTANT:
|
|
|
|
// This is only for debug purposes
|
|
|
|
// It is recommend to disable it
|
|
|
|
//
|
|
|
|
CCLayer::draw();
|
|
|
|
|
|
|
|
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
|
|
|
|
|
|
|
|
kmGLPushMatrix();
|
|
|
|
|
|
|
|
world->DrawDebugData();
|
|
|
|
|
|
|
|
kmGLPopMatrix();
|
2011-06-13 20:35:39 +08:00
|
|
|
}
|
|
|
|
|
2012-05-02 13:03:47 +08:00
|
|
|
void HelloWorld::addNewSpriteAtPosition(CCPoint p)
|
2011-06-13 20:35:39 +08:00
|
|
|
{
|
2012-05-02 13:03:47 +08:00
|
|
|
CCLOG("Add sprite %0.2f x %02.f",p.x,p.y);
|
|
|
|
CCNode* parent = getChildByTag(kTagParentNode);
|
2012-04-19 14:35:52 +08:00
|
|
|
|
|
|
|
//We have a 64x64 sprite sheet with 4 different 32x32 images. The following code is
|
|
|
|
//just randomly picking one of the images
|
|
|
|
int idx = (CCRANDOM_0_1() > .5 ? 0:1);
|
|
|
|
int idy = (CCRANDOM_0_1() > .5 ? 0:1);
|
2012-05-02 13:03:47 +08:00
|
|
|
PhysicsSprite *sprite = new PhysicsSprite();
|
|
|
|
sprite->initWithTexture(m_pSpriteTexture, CCRectMake(32 * idx,32 * idy,32,32));
|
|
|
|
sprite->autorelease();
|
2012-04-19 14:35:52 +08:00
|
|
|
|
2012-05-02 13:03:47 +08:00
|
|
|
parent->addChild(sprite);
|
2012-04-19 14:35:52 +08:00
|
|
|
|
|
|
|
sprite->setPosition( CCPointMake( p.x, p.y) );
|
|
|
|
|
|
|
|
// Define the dynamic body.
|
|
|
|
//Set up a 1m squared box in the physics world
|
|
|
|
b2BodyDef bodyDef;
|
|
|
|
bodyDef.type = b2_dynamicBody;
|
|
|
|
bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
|
2012-05-02 13:03:47 +08:00
|
|
|
|
2012-04-19 14:35:52 +08:00
|
|
|
b2Body *body = world->CreateBody(&bodyDef);
|
|
|
|
|
|
|
|
// Define another box shape for our dynamic body.
|
|
|
|
b2PolygonShape dynamicBox;
|
|
|
|
dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box
|
|
|
|
|
|
|
|
// Define the dynamic body fixture.
|
|
|
|
b2FixtureDef fixtureDef;
|
|
|
|
fixtureDef.shape = &dynamicBox;
|
|
|
|
fixtureDef.density = 1.0f;
|
|
|
|
fixtureDef.friction = 0.3f;
|
|
|
|
body->CreateFixture(&fixtureDef);
|
2012-05-02 13:03:47 +08:00
|
|
|
|
|
|
|
sprite->setPhysicsBody(body);
|
2011-06-13 20:35:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-22 12:00:27 +08:00
|
|
|
void HelloWorld::update(float dt)
|
2011-06-13 20:35:39 +08:00
|
|
|
{
|
2012-04-19 14:35:52 +08:00
|
|
|
//It is recommended that a fixed time step is used with Box2D for stability
|
|
|
|
//of the simulation, however, we are using a variable time step here.
|
|
|
|
//You need to make an informed choice, the following URL is useful
|
|
|
|
//http://gafferongames.com/game-physics/fix-your-timestep/
|
|
|
|
|
|
|
|
int velocityIterations = 8;
|
|
|
|
int positionIterations = 1;
|
|
|
|
|
|
|
|
// Instruct the world to perform a single step of simulation. It is
|
|
|
|
// generally best to keep the time step and iterations fixed.
|
|
|
|
world->Step(dt, velocityIterations, positionIterations);
|
|
|
|
|
|
|
|
//Iterate over the bodies in the physics world
|
|
|
|
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
|
|
|
|
{
|
|
|
|
if (b->GetUserData() != NULL) {
|
|
|
|
//Synchronize the AtlasSprites position and rotation with the corresponding body
|
|
|
|
CCSprite* myActor = (CCSprite*)b->GetUserData();
|
|
|
|
myActor->setPosition( CCPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO) );
|
|
|
|
myActor->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );
|
|
|
|
}
|
|
|
|
}
|
2011-06-13 20:35:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
|
|
|
|
{
|
2012-04-19 14:35:52 +08:00
|
|
|
//Add a new body/atlas sprite at the touched location
|
|
|
|
CCSetIterator it;
|
|
|
|
CCTouch* touch;
|
2011-06-13 20:35:39 +08:00
|
|
|
|
2012-04-19 14:35:52 +08:00
|
|
|
for( it = touches->begin(); it != touches->end(); it++)
|
|
|
|
{
|
|
|
|
touch = (CCTouch*)(*it);
|
|
|
|
|
|
|
|
if(!touch)
|
|
|
|
break;
|
2011-06-13 20:35:39 +08:00
|
|
|
|
2012-05-02 12:01:53 +08:00
|
|
|
CCPoint location = touch->locationInView();
|
2011-06-13 20:35:39 +08:00
|
|
|
|
2012-04-19 14:35:52 +08:00
|
|
|
location = CCDirector::sharedDirector()->convertToGL(location);
|
2011-06-13 20:35:39 +08:00
|
|
|
|
2012-05-02 13:03:47 +08:00
|
|
|
addNewSpriteAtPosition( location );
|
2012-04-19 14:35:52 +08:00
|
|
|
}
|
2011-06-13 20:35:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CCScene* HelloWorld::scene()
|
|
|
|
{
|
|
|
|
// 'scene' is an autorelease object
|
2012-06-22 12:00:27 +08:00
|
|
|
CCScene *scene = CCScene::create();
|
2011-06-13 20:35:39 +08:00
|
|
|
|
|
|
|
// add layer as a child to scene
|
|
|
|
CCLayer* layer = new HelloWorld();
|
|
|
|
scene->addChild(layer);
|
|
|
|
layer->release();
|
|
|
|
|
|
|
|
return scene;
|
|
|
|
}
|