在SFML中移动Rectangle,如何使其更流畅?

时间:2014-06-22 18:35:42

标签: c++ sfml

这是我的代码:

#include <SFML/Graphics.hpp>
#include <iostream>
#include <Windows.h>


int main()
{

    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Game");
    window.setFramerateLimit(200);

    //Variable that keeps the game loop running
    bool play = true;

    //Event object holding all events
    sf::Event event;

    //States for button/events
    bool Left = false;
    bool Right = false;
    bool space = false;

    //Variables
    int rectXPosition = 375;    //Rectangles X position
    int rectYPosition = 400;    //Rectangles Y position

    //Images
    sf::Texture image1;
    if (image1.loadFromFile("Images/GreekSoldier.png") == -1)
    {
        std::cout << "FAILED!!!" << "\n";
        return 1;
    }

    //Render shapes
    sf::RectangleShape rect;
    rect.setSize(sf::Vector2f(77, 150)); //Width and height
    rect.setPosition(375, 400); //Position
    rect.setFillColor(sf::Color::White); //Color
    rect.setTexture(&image1);

    //Game loop
    while (play == true)
    {
        //EVENTS
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Left)
            {
                //Set the state to true
                Left = true;
            }

            if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Right)
            {
                Right = true;
            }

            if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space)
            {
                space = true;
            }

            //Event type is window closed
            if (event.type == sf::Event::Closed)
            {
                //Set play to false in order to stop the game loop
                play = false;
            }
        }

        //LOGIC
        if (Left == true)
        {
            int x = 0;
            for (x = 1; x < 2; x++)
            {   
                rectXPosition-=5; //X position variable of the rectangle
                rect.setPosition(rectXPosition, rectYPosition);
                window.clear();
                window.draw(rect);
                window.display();
                Sleep(5);
            }
            Left = false;
        }

        if (Right == true)
        {
            int x = 0;
            for (x = 1; x < 2; x++)
            {   
                rectXPosition+= 5; //X position variable of the rectangle
                rect.setPosition(rectXPosition, rectYPosition);
                window.clear();
                window.draw(rect);
                window.display();
                Sleep(5);
            }

            Right = false;
        }

        if (space == true)
        {
            int x = 0;
            for (x = 1; x < 15; x++)
            {   
                rectYPosition-= 3; //X position variable of the rectangle
                rect.setPosition(rectXPosition, rectYPosition);
                window.clear();
                window.draw(rect);
                window.display();
                Sleep(10);
            }

            for (x = 1; x < 15; x++)
            {   
                rectYPosition+= 3; //X position variable of the rectangle
                rect.setPosition(rectXPosition, rectYPosition);
                window.clear();
                window.draw(rect);
                window.display();
                Sleep(10);
            }
            space = false;
        }


        //RENDERING
        window.clear();

        //Draw the rectangle shape
        window.draw(rect);
        window.display();
    }

    //Clean up and close the window
    window.close();

    return 0;
}

如何让运动更顺畅?如何制作矩形(士兵)可以同时跳跃和移动?我如何阻止它,当向左按住它不需要3秒才能实际移动?

我已经添加了一个youtube视频,如果你们不能为编译它而烦恼,只是想看看我在谈论什么。 https://www.youtube.com/watch?v=g_JLwGh1Wgo

1 个答案:

答案 0 :(得分:2)

当有人按下某个键然后经常重复(但不是每一帧,这使得它不平滑)时,会生成KeyPressed个事件。例如,它们旨在用于文本输入。

按下另一个键也会中断前一个键的重复事件,因此您的其他问题也有同样的原因。

您应该仅针对某些即时操作处理KeyPressed事件,例如按菜单按钮。在这个特定的例子中,你应该完全摆脱这一点,只使用sf::Keyboard替换行:

        if (Left == true)

使用:

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))

依旧......

我会解释为什么sf::Keyboard在这里是正确的,但文档做得很好。


另一个大问题是你有多个循环不会在游戏中发生任何其他事情。你应该熟悉事件循环,速度和重力的概念(并制作相应的变量)。

当玩家按下 Space 时,你不应硬编码角色向上移动N像素,向下移动N像素同时停止游戏中的其他所有可能动作,而是改变角色的垂直速度并用它来改变角色在每一帧中的位置(并且还可以通过重力降低速度)。

最重要的一点是,您必须只有一个调用window.display的主要事件循环。