c++ - 如何使用此代码设置重力?

标签 c++ sfml

我正在尝试制作一款游戏并被重力卡住......在下面的代码中,一个矩形代表一个玩家,当我按下键时它在 y 轴上移动但是当我激活它的重力时(即重置其先前的位置)它不会动画(即它不会跳跃)而是它只是停留在它的位置。我正在使用 C++ 的 SFML 库,这是一个游戏开发工具。请帮忙!

#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);
}
}

最佳答案

理论上你的代码可以工作,但有一个严重的问题:

  • 您的初始仓位是 350。

  • 现在您的“跳跃代码”(它将允许玩家无限期飞行!)触发并且您的位置更改为 349。

  • 但是,您的代码阻止播放器离开屏幕 (y >= 350-1) 基本上解析为检查 y >= 349,这将是真实的,因此您的位置将永久重置为 350。

要解决此问题,只需删除 -1 或将 >= 运算符替换为 >


虽然您的方法应该有效(应用上述修复后),但您应该重新考虑您的策略并存储速度和位置。我最近编写了以下示例代码。它远非完美,但它应该教给你一些关于跳跃和奔跑游戏的基础知识(不一定是做这些事情的唯一方法):

  • 允许玩家跳跃。
  • 应用重力。
  • 允许玩家根据按住按键的时间来确定跳跃高度。
#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++ - 如何使用此代码设置重力?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20867336/

相关文章:

c++ - 在鼠标单击 Qt 时将信号从子级发送到父级

c++ - sfml sf::Image() 类问题

c++ - boost::filesystem 递归获取每个文件的大小

c++ - 将给定类型的任何枚举作为函数参数传递

c++ - 将组合框信号连接到 Qt 中的 std::function 的问题

c++ - 将 SFML 的 RenderWindow 对象传递给模板函数

c++ - SFML 未静态链接到 openal32(静态链接到所有其他依赖项)

c++ - 构建 SFML 蓝图小行星游戏时调试断言失败?

opengl - 一种生成 block 的方法

c++ - boost::bind 与具有引用参数的函数绑定(bind)