#include "HelloWorldScene.h"
#include "GameOverLayer.h"
#include "SimpleAudioEngine.h"
using namespace cocos2d;
#define PTM_RATIO 32 // 比例
HelloWorld::HelloWorld()
{
m_world = NULL;
m_groundBody = NULL;
m_bottomFixture = NULL;
m_ballFixture = NULL;
m_paddleBody = NULL;
m_paddleFixture = NULL;
m_mouseJoint = NULL;
m_contactListener = NULL;
}
HelloWorld::~HelloWorld()
{
delete m_world;
m_groundBody = NULL;
m_paddleBody = NULL;
delete m_contactListener;
}
CCScene* HelloWorld::scene()
{
CCScene * scene = NULL;
do
{
// 'scene' is an autorelease object
scene = CCScene::create();
CC_BREAK_IF(! scene);
// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();
CC_BREAK_IF(! layer);
// add layer as a child to scene
scene->addChild(layer);
} while (0);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
bool bRet = false;
do
{
CC_BREAK_IF(! CCLayer::init());
// quit menu
CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
this,
menu_selector(HelloWorld::menuCloseCallback));
CC_BREAK_IF(! pCloseItem);
pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20));
CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
pMenu->setPosition(CCPointZero);
CC_BREAK_IF(! pMenu);
this->addChild(pMenu, 1);
// game world
initWorld();
// draw block
drawBlock();
setTouchEnabled(true);
scheduleUpdate();
bRet = true;
} while (0);
return bRet;
}
void HelloWorld::initWorld()
{
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
// create world
b2Vec2 gravity = b2Vec2(0.0f, 0.0f); // 模仿真空
m_world = new b2World(gravity);
m_world->SetAllowSleeping(true);
// create edge around the screen
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0);
m_groundBody = m_world->CreateBody(&groundBodyDef);
b2EdgeShape groundBox;
b2FixtureDef groundBoxDef;
groundBoxDef.shape = &groundBox;
groundBox.Set(b2Vec2(0, 0), b2Vec2(winSize.width / PTM_RATIO, 0)); // bottom
m_bottomFixture = m_groundBody->CreateFixture(&groundBoxDef);
groundBox.Set(b2Vec2(0, 0), b2Vec2(0, winSize.height / PTM_RATIO)); // left
m_groundBody->CreateFixture(&groundBoxDef);
groundBox.Set(b2Vec2(0, winSize.height / PTM_RATIO), b2Vec2(winSize.width / PTM_RATIO, winSize.height / PTM_RATIO)); // up
m_groundBody->CreateFixture(&groundBoxDef);
groundBox.Set(b2Vec2(winSize.width / PTM_RATIO, 0), b2Vec2(winSize.width / PTM_RATIO, winSize.height / PTM_RATIO)); // right
m_groundBody->CreateFixture(&groundBoxDef);
// create sprite and add it to the layer
CCSprite *ball = CCSprite::create("ball.jpg");
ball->setPosition(ccp(100, 100));
ball->setTag(1);
this->addChild(ball);
// create ball body
b2BodyDef ballBodyDef;
ballBodyDef.type = b2_dynamicBody;
ballBodyDef.position.Set(100 / PTM_RATIO, 100 / PTM_RATIO);
ballBodyDef.userData = ball;
b2Body *ballBody = m_world->CreateBody(&ballBodyDef);
// create circle shape
b2CircleShape circle;
circle.m_radius = 26.0 / PTM_RATIO;
// create shape definition and add to body
b2FixtureDef ballShapeDef;
ballShapeDef.shape = &circle;
ballShapeDef.density = 1.0f;
ballShapeDef.friction = 0.0f;
ballShapeDef.restitution = 1.0f;
m_ballFixture = ballBody->CreateFixture(&ballShapeDef);
// 施加一个冲量,作为球的初始动力
b2Vec2 force = b2Vec2(15, 15);
ballBody->ApplyLinearImpulse(force, ballBodyDef.position);
// create paddle and add it to the layer
CCSprite *paddle = CCSprite::create("Paddle.jpg");
paddle->setPosition(ccp(winSize.width / 2, 50));
this->addChild(paddle);
// create paddle body
b2BodyDef paddleBodyDef;
paddleBodyDef.type = b2_dynamicBody;
paddleBodyDef.position.Set(winSize.width / 2 / PTM_RATIO, 50 / PTM_RATIO);
paddleBodyDef.userData = paddle;
m_paddleBody = m_world->CreateBody(&paddleBodyDef);
// create paddle shape
b2PolygonShape paddleShape;
paddleShape.SetAsBox(paddle->getContentSize().width / PTM_RATIO / 2,
paddle->getContentSize().height / PTM_RATIO / 2);
b2FixtureDef paddleShapeDef;
paddleShapeDef.shape = &paddleShape;
paddleShapeDef.density = 10.0f;
paddleShapeDef.friction = 0.4f;
paddleShapeDef.restitution = 0.1f;
m_paddleFixture = m_paddleBody->CreateFixture(&paddleShapeDef);
// restrict paddle along the x axis
b2PrismaticJointDef jointDef;
b2Vec2 worldAxis(1.0f, 0.0f); // 限定的方向
jointDef.collideConnected = true; // 可能碰撞需要设置为true
// 初始化四个参数:被限定物体,限定区域,限定点,限定方向
jointDef.Initialize(m_paddleBody, m_groundBody, m_paddleBody->GetWorldCenter(), worldAxis);
m_world->CreateJoint(&jointDef);
// create contact listener
m_contactListener = new MyContactListener();
m_world->SetContactListener(m_contactListener);
}
void HelloWorld::drawBlock()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 4; j++)
{
static int padding = 20;
CCSprite *block = CCSprite::create("block.png");
int xOffset = padding + block->getContentSize().width / 2 + (block->getContentSize().width + padding) * i;
block->setPosition(ccp(xOffset, 460 - j*40));
block->setTag(2);
this->addChild(block);
b2BodyDef blockBodyDef;
blockBodyDef.type = b2_dynamicBody;
blockBodyDef.position.Set(xOffset / PTM_RATIO, (450 - j*40)/ PTM_RATIO);
blockBodyDef.userData = block;
b2Body *blockBody = m_world->CreateBody(&blockBodyDef);
b2PolygonShape blockShape;
blockShape.SetAsBox(block->getContentSize().width / PTM_RATIO / 2,
block->getContentSize().height / PTM_RATIO /2);
b2FixtureDef blockShapeDef;
blockShapeDef.shape = &blockShape;
blockShapeDef.density = 10.0f;
blockShapeDef.friction = 0.0f;
blockShapeDef.restitution = 0.1f;
blockBody->CreateFixture(&blockShapeDef);
}
}
}
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
// "close" menu item clicked
CCDirector::sharedDirector()->end();
}
void HelloWorld::update(float dt)
{
m_world->Step(dt, 10, 10);
for (b2Body *b = m_world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL)
{
CCSprite *sprite = (CCSprite*)b->GetUserData();
if (sprite->getTag() == 1)
{
int maxSpeed = 20;
b2Vec2 velocity = b->GetLinearVelocity();
float32 speed = velocity.Length();
// 添加线性阻尼来限制速度
if (speed > maxSpeed)
b->SetLinearDamping(0.8f);
else if (speed < maxSpeed)
b->SetLinearDamping(0.0f);
}
sprite->setPosition(ccp(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO));
sprite->setRotation(-1 * CC_RADIANS_TO_DEGREES(b->GetAngle()));
}
}
std::vector<MyContact>::iterator pos; // 碰撞
std::vector<b2Body*>toDestory; // 销毁的block
for (pos = m_contactListener->m_contacts.begin(); pos != m_contactListener->m_contacts.end(); ++ pos)
{
// 碰撞到bottom
MyContact contact = *pos;
if (contact.fixtureA == m_bottomFixture && contact.fixtureB == m_ballFixture ||
contact.fixtureA == m_ballFixture && contact.fixtureB == m_bottomFixture)
{
// CCLog("Ball hit bottom!");
CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("applause.wav");
CCScene *scene = CCScene::create();
scene->addChild(GameOverLayer::create());
CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(2.0f, scene,ccWHITE));
}
// 碰撞到block
b2Body *bodyA = contact.fixtureA->GetBody();
b2Body *bodyB = contact.fixtureB->GetBody();
if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL)
{
CCSprite *spriteA = (CCSprite*)bodyA->GetUserData();
CCSprite *spriteB = (CCSprite*)bodyB->GetUserData();
// spriteA is ball, spriteB is block
if (spriteA->getTag() == 1 && spriteB->getTag() == 2)
{
if ( std::