How can I set gravity using this code?

2019-02-19 23:12发布

问题:

I am trying to make a game and am stuck on gravity..... In the following code a rectangle stands for a player and when I press up key it moves in y-axis but when I activate gravity on it (i.e resetting its previous position) it does not animate (i.e. It does not jumps) instead it just stays in its position. I am using SFML library of C++ and that's a game development tool. Please Help!

#include <SFML/Graphics.hpp>

int main(){
sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Gravity");


sf::RectangleShape rectangle;
rectangle.setSize(sf::Vector2f(100, 100));
rectangle.setFillColor(sf::Color::Black);
rectangle.setPosition(sf::Vector2f(10, 350));

while(window.isOpen())
{
    sf::Event Event;
    while(window.pollEvent(Event))
    {
        if(Event.type == sf::Event::Closed)
        {
            window.close();
        }
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
    {
        rectangle.move(0, -1);
    }
    if(rectangle.getPosition().y >= 350-1)
    {
        rectangle.setPosition(0, 350);
    }
    window.display();
    window.clear(sf::Color::Cyan);
    window.draw(rectangle);
}
}

回答1:

Theoretically your code would work, but there's one significant problem:

  • Your initial position is 350.

  • Now your "jumping code" (which will allow the player to fly indefinitely!) triggers and your position is changed to 349.

  • However, your code keeping the player from dropping off the screen (y >= 350-1) essentially resolves to the check y >= 349, which will be true, so your position is permanently reset to 350.

To solve this, just remove the -1 or replace the >= operator with >.


While your approach should be working (once the fix above is applied), you should rethink your strategy and store a velocity in addition to a position. I've recently written the following example code. It's far from being perfect, but it should teach you a few basics for a jump and run game (not necessarily the only way to do such things):

  • Allow the player to jump.
  • Apply gravity.
  • Allow the player to determine jump height based on how long he holds down a key.
#include <SFML/Graphics.hpp>

int main(int argc, char **argv) {
    sf::RenderWindow window;
    sf::Event event;

    sf::RectangleShape box(sf::Vector2f(32, 32));
    box.setFillColor(sf::Color::White);
    box.setOrigin(16, 32);

    box.setPosition(320, 240);

    window.create(sf::VideoMode(640, 480), "Jumping Box [cursor keys + space]");
    window.setFramerateLimit(60);
    window.setVerticalSyncEnabled(false);

    // player position
    sf::Vector2f pos(320, 240);

    // player velocity (per frame)
    sf::Vector2f vel(0, 0);

    // gravity (per frame)
    sf::Vector2f gravity(0, .5f);

    // max fall velocity
    const float maxfall = 5;

    // run acceleration
    const float runacc = .25f;

    // max run velocity
    const float maxrun = 2.5f;

    // jump acceleration
    const float jumpacc = -1;

    // number of frames to accelerate in
    const unsigned char jumpframes = 10;

    // counts the number of frames where you can still accelerate
    unsigned char jumpcounter = 0;

    // inputs
    bool left = false;
    bool right = false;
    bool jump = false;

    while (window.isOpen()) {
        while (window.pollEvent(event)) {
            switch(event.type) {
            case sf::Event::KeyPressed:
            case sf::Event::KeyReleased:
                switch (event.key.code) {
                case sf::Keyboard::Escape:
                    window.close();
                    break;
                case sf::Keyboard::Left:
                    left = event.type == sf::Event::KeyPressed;
                    break;
                case sf::Keyboard::Right:
                    right = event.type == sf::Event::KeyPressed;
                    break;
                case sf::Keyboard::Space:
                    jump = event.type == sf::Event::KeyPressed;
                    break;
                }
                break;
            case sf::Event::Closed:
                window.close();
                break;
            }
        }

        // logic update start

        // first, apply velocities
        pos += vel;

        // determine whether the player is on the ground
        const bool onground = pos.y >= 480;

        // now update the velocity by...
        // ...updating gravity
        vel += gravity;

        // ...capping gravity
        if (vel.y > maxfall)
            vel.y = maxfall;

        if (left) { // running to the left
            vel.x -= runacc;
        }
        else if (right) { // running to the right
            vel.x += runacc;
        }
        else { // not running anymore; slowing down each frame
            vel.x *= 0.9;
        }

        // jumping
        if (jump) {
            if (onground) { // on the ground
                vel.y += jumpacc * 2;
                jumpcounter = jumpframes;
            }
            else if (jumpcounter > 0) { // first few frames in the air
                vel.y += jumpacc;
                jumpcounter--;
            }
        }
        else { // jump key released, stop acceleration
            jumpcounter = 0;
        }

        // check for collision with the ground
        if (pos.y > 480) {
            vel.y = 0;
            pos.y = 480;
        }

        // check for collision with the left border
        if (pos.x < 16) {
            vel.x = 0;
            pos.x = 16;
        }
        else if (pos.x > 624) {
            vel.x = 0;
            pos.x = 624;
        }


        // logic update end

        // update the position
        box.setPosition(pos);

        window.clear();
        window.draw(box);
        window.display();
    }
    return 0;
}


标签: c++ sfml