ApplyLinearImpulse的结果与第一个结果不同 - Box2D

时间:2014-01-10 05:09:38

标签: box2d cocos2d-x

我正在使用cocos2d-x 3.x和box2d制作突破性游戏,引用http://www.raywenderlich.com/

我的游戏逻辑就是这个。

  1. 在init中,调用StartGame函数。在这里,我使用ApplyLinearImpulse移动球。

  2. 如果球击中底壁,球会停止移动。

  3. 单击屏幕,然后调用StartGame函数,再次转换球的位置和ApplyLinearImpulse。

  4. 重复编号2和3

  5. 问题是球的速度在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;
    }
    

0 个答案:

没有答案