*****HelloWorld.h
//
// HelloWorldScene.h
// B2Ball
//
// Created by 方怀义 on 4/2/13.
// Copyright __MyCompanyName__ 2013. All rights reserved.
//
#ifndef __HELLO_WORLD_H__
#define __HELLO_WORLD_H__
// When you import this file, you import all the cocos2d classes
#include "cocos2d.h"
#include "Box2D.h"
using namespace cocos2d;
class HelloWorld : public cocos2d::CCLayerColor {
public:
~HelloWorld();
HelloWorld();
// returns a Scene that contains the HelloWorld as the only child
static cocos2d::CCScene* scene();
void initPhysics();
// adds a new sprite at a given coordinate
void addNewSpriteAtPosition(cocos2d::CCPoint p);
virtual void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void update(float dt);
private:
b2World* world;
cocos2d::CCTexture2D* m_pSpriteTexture; // weak ref
b2Body *_body;
CCSprite *_ball;
};
#endif // __HELLO_WORLD_H__
*****HelloWorld.cpp
//
// HelloWorldScene.cpp
// B2Ball
//
// Created by 方怀义 on 4/2/13.
// Copyright __MyCompanyName__ 2013. All rights reserved.
//
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
using namespace cocos2d;
using namespace CocosDenshion;
#define PTM_RATIO 32
enum {
kTagParentNode = 1,
};
HelloWorld::HelloWorld()
{
if(!CCLayerColor::initWithColor(ccc4(255, 255, 255, 255))){
return;
}
setTouchEnabled( true );
setAccelerometerEnabled( true );
CCSize s = CCDirector::sharedDirector()->getWinSize();
// init physics
this->initPhysics();
addNewSpriteAtPosition(ccp(s.width/2, s.height/2));
CCLabelTTF *label = CCLabelTTF::create("Tap screen", "Marker Felt", 32);
addChild(label, 0);
label->setColor(ccc3(0,0,255));
label->setPosition(ccp( s.width/2, s.height-50));
scheduleUpdate();
}
HelloWorld::~HelloWorld()
{
delete world;
world = NULL;
//delete m_debugDraw;
}
void HelloWorld::initPhysics()
{
CCSize s = CCDirector::sharedDirector()->getWinSize();
b2Vec2 gravity;
gravity.Set(0.0f, -30.0f);
world = new b2World(gravity);
// Do we want to let bodies sleep?
world->SetAllowSleeping(true);
world->SetContinuousPhysics(true);
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.
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0); // bottom-left corner
// 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);
// Define the ground box shape.
b2EdgeShape groundBox;
// bottom
groundBox.Set(b2Vec2(0,0), b2Vec2(s.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
// top
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO));
groundBody->CreateFixture(&groundBox,0);
// left
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(0,0));
groundBody->CreateFixture(&groundBox,0);
// right
groundBox.Set(b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
}
void HelloWorld::addNewSpriteAtPosition(CCPoint p)
{
CCLOG("Add sprite %0.2f x %02.f",p.x,p.y);
_ball = CCSprite::create("Icon.png");
this->addChild(_ball);
_ball->setPosition( CCPointMake( p.x, p.y) );
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
b2BodyDef ballBodyDef;
ballBodyDef.type = b2_dynamicBody;
ballBodyDef.position.Set(p.x / PTM_RATIO, p.y / PTM_RATIO);
ballBodyDef.userData = _ball;
_body = world->CreateBody(&ballBodyDef);
b2CircleShape circle;
circle.m_radius = 26.0 / PTM_RATIO;
b2FixtureDef ballShapeDef;
ballShapeDef.shape = &circle;
ballShapeDef.density = 1.0f;
ballShapeDef.friction = 0.2f;
ballShapeDef.restitution = 0.8f;
_body->CreateFixture(&ballShapeDef);
// _body->ApplyForceToCenter(b2Vec2(-1000, -1000));
_body->ApplyForce(b2Vec2(1000, 1000), _body->GetWorldCenter());
}
void HelloWorld::update(float dt)
{
//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()) );
}
}
}
void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
//Add a new body/atlas sprite at the touched location
CCSetIterator it;
CCTouch* touch;
for( it = touches->begin(); it != touches->end(); it++)
{
touch = (CCTouch*)(*it);
if(!touch)
break;
CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
addNewSpriteAtPosition( location );
}
}
CCScene* HelloWorld::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
// add layer as a child to scene
CCLayer* layer = new HelloWorld();
scene->addChild(layer);
layer->release();
return scene;
}