C ++ SFML Движение спрайта не работает должным образом - PullRequest
0 голосов
/ 22 мая 2019

Я использую SFML с C ++, чтобы попытаться переместить спрайт с определенной текстурой, но он не двигается так, как я хочу.

Я новичок в SFML, я прочитал учебники о перемещении на веб-сайте sfml и посмотрел несколько учебников на Youtube по этому поводу. Материал, который я видел, является либо очень простым, либо достаточно сложным на данный момент (в основном это материал для разработки игр)

#include <SFML/Graphics.hpp>

#include <thread>
#include <chrono>

#include<iostream>

using namespace sf;
using namespace std;

    int main()
    {
        sf::RenderWindow window(sf::VideoMode(600, 600), "test!");

        Texture t;
        t.loadFromFile("/*texture directory*/");

        Sprite s(t);
        s.setScale(Vector2f(0.25f, 0.25f));

        float temp = 0;

        while (window.isOpen())
        {
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    window.close();
            }

            window.clear(Color::White);
            window.draw(s);
            window.display();

            s.move(Vector2f(temp, temp));


            for (int i = 0; i < 3; i++) {
                if (i == 0) {
                    this_thread::sleep_for(chrono::milliseconds(1000));
                    temp = 10;
                }
                else if (i == 1) {
                    this_thread::sleep_for(chrono::milliseconds(1000));
                    temp = 20;
                }
                else {
                    this_thread::sleep_for(chrono::milliseconds(1000));
                    temp = -10;
                }
            }
        }
        return 0;
    }

Я ожидаю, что спрайт переместится в (10,10), затем через секунду, (20,20), затем через секунду вернется в (10,10). Вместо этого спрайт перемещается только (-10, -10) каждые три секунды, поэтому он принимает только значение temp в конце цикла. То же самое относится и к setPosition.

Здесь есть что-то очень простое, но исследования привели меня к еще большему количеству вопросов, чем ответов, и именно поэтому я пришел сюда.

Ответы [ 2 ]

0 голосов
/ 22 мая 2019

Избегайте использования sleep в потоке рендеринга.

Вместо этого вы будете измерять пройденное время и пропорционально увеличивать его:

#include <SFML/Graphics.hpp>

#include <thread>
#include <chrono>

#include<iostream>

using namespace sf;
using namespace std;

    int main()
    {
        sf::RenderWindow window(sf::VideoMode(600, 600), "test!");

        Texture t;
        t.loadFromFile("/*texture directory*/");

        Sprite s(t);
        s.setScale(Vector2f(0.25f, 0.25f));

        float speed = 10.0;
        sf::Clock clock;

        while (window.isOpen())
        {
            sf::Event event;

            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    window.close();
            }

            float time = clock.getElapsedTime().asSeconds();
            s.move(Vector2f(speed*time, speed*time));
            clock.restart();

            window.clear(Color::White);
            window.draw(s);
            window.display();


        }
        return 0;
    }

Этот код позволяет вашему спрайтудвигаться на фиксированной скорости.Вы можете изменить скорость, используя дополнительные sf :: clock

0 голосов
/ 22 мая 2019

Самая внешняя петля while управляет рисованием. Вы поместили еще один for цикл внутри него. Внутренний цикл должен закончить , прежде чем внешний цикл сможет продолжить свою итерацию, то есть нарисовать другой кадр. Выполнение не происходит асинхронно, поэтому ваш цикл for с вызовами std::this_thread::sleep_for блокирует цикл рендеринга всего на 3 секунды. Это меняет его на temp, что, безусловно, равно -10 в конце.

Вместо этого вы хотите создать состояние , которое сохраняется в цикле рендеринга и создает небольшой конечный автомат. Это состояние будет вашим i. Объявите и инициализируйте его рядом с temp (ну, вы также можете использовать temp в своих операторах if) и удалите цикл for. Не забудьте установить i обратно на 0 при настройке temp на -10, если вы хотите продолжить анимацию.

Другой, возможный, но худший подход:

  1. поместить код рендеринга (и, возможно, обработки событий) в функцию;
  2. вызывайте эту функцию каждый раз, когда вы хотите обновить графику, т. Е. После каждого задания temp, но не забудьте обновить s заранее.

Наконец, я считаю, что sf::Sprite имеет функции-члены для доступа к состоянию, а не только к изменениям, поэтому вы должны иметь возможность работать только с s, без необходимости temp. Сохраняйте это простым и думайте с точки зрения потока управления.

...