我正在使用cocos2d-x 3.x和box2d制作突破性游戏,引用http://www.raywenderlich.com/
我的游戏逻辑就是这个。
在init中,调用StartGame函数。在这里,我使用ApplyLinearImpulse移动球。
如果球击中底壁,球会停止移动。
单击屏幕,然后调用StartGame函数,再次转换球的位置和ApplyLinearImpulse。
重复编号2和3
问题是球的速度在1号时与其他人的结果不同,即使我给予同样的力量。在开始时球的速度很慢但是在一个循环之后,球的速度非常快。 我不知道为什么......我需要帮助。 这是我的源代码。
#include "GameScene.h"
#define PTM_RATIO 32
USING_NS_CC;
Scene* GameScene::createScene() {
Scene* scene = Scene::create();
Layer* layer = GameScene::create();
scene->addChild(layer);
return scene;
}
bool GameScene::init() {
if(!Layer::init()){
return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
// Create a world
b2Vec2 gravity = b2Vec2(0.0f, 0.0f);
_world = new b2World(gravity);
// create contact listener
_contactListener = new MyContactListener();
_world->SetContactListener(_contactListener);
CreateWall(visibleSize);
CreateBall();
CreatePaddle(visibleSize);
label = LabelTTF::create("Game Over", "Arial", 32);
label->setColor(Color3B(255,255,255));
label->setPosition(Point(visibleSize.width/2, visibleSize.height/2));
this->addChild(label);
b2PrismaticJointDef jointDef;
b2Vec2 worldAxis(1.0f, 0.0f);
jointDef.collideConnected = true;
jointDef.Initialize(_paddleBody, _groundBody, _paddleBody->GetWorldCenter(), worldAxis);
_world->CreateJoint(&jointDef);
// add touch events
auto dispatcher = Director::getInstance()->getEventDispatcher();
_touchListener = EventListenerTouchOneByOne::create();
_touchListener->onTouchBegan = CC_CALLBACK_2(GameScene::onTouchBegan, this);
_touchListener->onTouchMoved = CC_CALLBACK_2(GameScene::onTouchMoved, this);
_touchListener->onTouchCancelled = CC_CALLBACK_2(GameScene::onTouchCancelled, this);
_touchListener->onTouchEnded = CC_CALLBACK_2(GameScene::onTouchEnded, this);
dispatcher->addEventListenerWithSceneGraphPriority(_touchListener, this);
Director::getInstance()->getScheduler()->scheduleSelector(schedule_selector(GameScene::tick), this, 1/60, false);
StartGame(0);
return true;
}
void GameScene::tick(float dt) {
_world->Step(dt, 10, 10);
if(!gameOver) {
for(b2Body *b = _world->GetBodyList(); b; b = b->GetNext()) {
if(b->GetUserData() != NULL) {
Sprite *s = static_cast<Sprite*>(b->GetUserData());
if(s->getTag() == 1) {
b2Vec2 velocity = b->GetLinearVelocity();
float32 speed = velocity.Length();
if(speed > maxSpeed)
b->SetLinearDamping(0.5f);
else if(speed < maxSpeed)
b->SetLinearDamping(0.0f);
}
s->setPosition(Point(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO));
s->setRotation(-1 * CC_RADIANS_TO_DEGREES(b->GetAngle()));
}
}
for_each(_contactListener->_contacts.begin(), _contactListener->_contacts.end(),
[&](MyContact contact) {
if(contact.contain(_bottomFixture, _ballFixture)) {
cocos2d::log("Ball hit Bottom");
GameOver();
}
} );
}
}
bool GameScene::onTouchBegan(Touch *touch, Event *event){
if(gameOver) {
StartGame(1);
return true;
}
if(_mouseJoint != NULL) return true;
cocos2d::log("touch began test");
Point location = touch->getLocation();
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
if(_paddleFixture->TestPoint(locationWorld)) {
b2MouseJointDef md;
md.bodyA = _groundBody;
md.bodyB = _paddleBody;
md.target = locationWorld;
md.collideConnected = true;
md.maxForce = 1000.0f * _paddleBody->GetMass();
_mouseJoint = static_cast<b2MouseJoint*>(_world->CreateJoint(&md));
_paddleBody->SetAwake(true);
}
return true;
}
void GameScene::onTouchMoved(Touch *touch, Event *event) {
if(_mouseJoint == NULL) return;
Point location = touch->getLocation();
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
_mouseJoint->SetTarget(locationWorld);
}
void GameScene::onTouchCancelled(Touch *touch, Event *event) {
if(_mouseJoint) {
_world->DestroyJoint(_mouseJoint);
_mouseJoint = NULL;
}
}
void GameScene::onTouchEnded(Touch *touch, Event *event) {
if(_mouseJoint) {
_world->DestroyJoint(_mouseJoint);
_mouseJoint = NULL;
}
}
void GameScene::CreateWall(Size visibleSize) {
// Create edges around the entire class
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0);
_groundBody = _world->CreateBody(&groundBodyDef);
b2EdgeShape groundBox;
b2FixtureDef groundBoxDef;
groundBoxDef.shape = &groundBox;
groundBox.Set(b2Vec2(0,0), b2Vec2(visibleSize.width/PTM_RATIO,0));
_bottomFixture = _groundBody->CreateFixture(&groundBoxDef);
groundBox.Set(b2Vec2(0,0), b2Vec2(0,visibleSize.height/PTM_RATIO));
_groundBody->CreateFixture(&groundBoxDef);
groundBox.Set(b2Vec2(0,visibleSize.height/PTM_RATIO), b2Vec2(visibleSize.width/PTM_RATIO,visibleSize.height/PTM_RATIO));
_groundBody->CreateFixture(&groundBoxDef);
groundBox.Set(b2Vec2(visibleSize.width/PTM_RATIO,visibleSize.height/PTM_RATIO), b2Vec2(visibleSize.width/PTM_RATIO,0));
_groundBody->CreateFixture(&groundBoxDef);
}
void GameScene::CreateBall() {
// create ball texture
ball = Sprite::create("ball.png");
ball->setPosition(Point(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.angle = 0;
ballBodyDef.userData = ball;
ballBody = _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;
_ballFixture = ballBody->CreateFixture(&ballShapeDef);
}
void GameScene::CreatePaddle(Size visibleSize) {
//create paddle
userPaddle = Sprite::create("paddle.png");
userPaddle->setPosition(Point(visibleSize.width/2, 50));
this->addChild(userPaddle);
// create paddle body
b2BodyDef paddleBodyDef;
paddleBodyDef.type = b2_dynamicBody;
paddleBodyDef.position.Set(visibleSize.width/2/PTM_RATIO, 50/PTM_RATIO);
paddleBodyDef.userData = userPaddle;
_paddleBody = _world->CreateBody(&paddleBodyDef);
// create paddle shape
b2PolygonShape paddleShape;
paddleShape.SetAsBox(userPaddle->getContentSize().width/2/PTM_RATIO, userPaddle->getContentSize().height/2/PTM_RATIO);
// create shape definition and add to body
b2FixtureDef paddleShapeDef;
paddleShapeDef.shape = &paddleShape;
paddleShapeDef.density = 10.0f;
paddleShapeDef.friction = 0.4f;
paddleShapeDef.restitution = 0.1f;
_paddleFixture = _paddleBody->CreateFixture(&paddleShapeDef);
}
void GameScene::GameOver() {
gameOver = true;
_world->ClearForces();
ballBody->SetAngularVelocity(0);
ballBody->SetLinearVelocity(b2Vec2(0,0));
ballBody->SetLinearDamping(0);
label->setVisible(true);
}
void GameScene::StartGame(int stage) {
ballBody->SetTransform(b2Vec2(100/PTM_RATIO, 100/PTM_RATIO), 0);
b2Vec2 force = b2Vec2(150,150);
//ballBody->ApplyForceToCenter(force);
ballBody->ApplyLinearImpulse(force, ballBody->GetWorldCenter());
gameOver = false;
label->setVisible(false);
}
GameScene::~GameScene() {
delete _world;
delete _contactListener;
_groundBody = NULL;
}