• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

SFML nie mogę zaimplementować deltatime

VPS Starter Arubacloud
0 głosów
330 wizyt
pytanie zadane 30 lipca 2021 w C i C++ przez tonn204 Mądrala (7,440 p.)

Witam, co robię nie tak w poniższej implementacji DT? kiedy naciskam klawisze postać cały czas stoi jednym miejscu.

Mam jeszcze jedno pytanie dotyczące usuwania postaci przeciwnika. Jak czy dobrym wyborem było by stworzenie klasy np enemy, która dziedziczy po klasie sf::Sprite i potem stworzenie po prostu destruktora dla tej klasy?

#include <iostream>
#include <stdlib.h>
#include <time.h>

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML works!", sf::Style::Close);

    sf::Texture player_texture;
    if (!player_texture.loadFromFile("player.png"))
    {
        std::cout << "Failed to load player texture" << std::endl;
    }

    sf::Sprite player;
    player.setTexture(player_texture);
    player.setPosition(sf::Vector2f(400.0f, 500.0f));

    sf::Texture enemy_texture;
    if (!enemy_texture.loadFromFile("enemy.png"))
    {
        std::cout << "Failed to load enemy texture" << std::endl;
    }

    sf::Sprite enemies[5];

    srand(time(NULL));

    for (int i = 0; i < 5; i++)
    {
        enemies[i].setTexture(enemy_texture);
        enemies[i].setPosition(sf::Vector2f(float(rand() % 790 + 1), float(rand() % 300 + 20)));
    }

    bool space_key_pressed = false; 
    sf::Clock clock;

    while (window.isOpen())
    {
        float dt = clock.restart().asSeconds();
        sf::Event event;
        while (window.pollEvent(event))
        {
            switch (event.type)
            {
            case sf::Event::Closed:
                window.close();
                break;
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
            {
                player.move(sf::Vector2f(-1.0f*dt, 0.0f));
            }
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
            {
                player.move(sf::Vector2f(1.0f*dt, 0.0f));
            }
            if (event.type == sf::Event::KeyPressed)
            {
                if (event.key.code == sf::Keyboard::Space && !space_key_pressed)
                {
                    space_key_pressed = true;
                }
            }
            else if (event.type == sf::Event::KeyReleased)
            {
                if (event.key.code == sf::Keyboard::Space && space_key_pressed)
                {
                    space_key_pressed = false;
                }
            }
        }

        for (int i = 0; i < 5; i++)
        {
            enemies[i].move(sf::Vector2f(5.0f, 2.0f));
            if (enemies[i].getPosition().x >= 800)
            {
                enemies[i].move(sf::Vector2f(-5.0f, 2.0f));
            }
        }

        window.clear();
        window.draw(player);
        for (int i = 0; i < 5; i++)
        {
            window.draw(enemies[i]);
        }
        window.display();     
    }
}

 

1 odpowiedź

0 głosów
odpowiedź 7 sierpnia 2021 przez dziablo Użytkownik (940 p.)

Hej,

z tego co widze w dokumentacji

float dt = clock.restart().asSeconds();

https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1Clock.php#a123e2627f2943e5ecaa1db0c7df3231b

zawsze zwroci zero bo restart zeruje zegar

po drugie jedna klatka w grze przy 60 fps to 16ms, jak bedziesz wyciagal sekundy to zawsze dostaniesz 0, wiec musisz wyciagac milisekundy.

 

po trzecie delta time to powinna byc wartosc ile czasu zajelo przeliczenie klatki

dt to delta time czyli ile czasu minelo od ostatniej klatki wiec z  tym clockiem to raczej powinno wygladac mniej wiecej tak (przesunalem tylko metody od clock w inne miejsce):

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            switch (event.type)
            {
            case sf::Event::Closed:
                window.close();
                break;
            }

            float dt = clock.asMilliseconds();
            clock.restart();
 
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
            {
                player.move(sf::Vector2f(-1.0f*dt, 0.0f));
            }
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
            {
                player.move(sf::Vector2f(1.0f*dt, 0.0f));
            }
            if (event.type == sf::Event::KeyPressed)
            {
                if (event.key.code == sf::Keyboard::Space && !space_key_pressed)
                {
                    space_key_pressed = true;
                }
            }
            else if (event.type == sf::Event::KeyReleased)
            {
                if (event.key.code == sf::Keyboard::Space && space_key_pressed)
                {
                    space_key_pressed = false;
                }
            }
        }
 
        for (int i = 0; i < 5; i++)
        {
            enemies[i].move(sf::Vector2f(5.0f, 2.0f));
            if (enemies[i].getPosition().x >= 800)
            {
                enemies[i].move(sf::Vector2f(-5.0f, 2.0f));
            }
        }
 
        window.clear();
        window.draw(player);
        for (int i = 0; i < 5; i++)
        {
            window.draw(enemies[i]);
        }
        window.display();     
    }

 

komentarz 7 sierpnia 2021 przez dziablo Użytkownik (940 p.)
Co do pytania o sprite to zalezy czy zalezy ci na performance czy chcesz robic proste gry. Jak to drugie to hulaj dusza, rob co chcesz.

Jak zalezy ci na performance to zwalnianie zasobow jak sprity powinno byc robione w jednej operacji, tzn jak nie potrzebujesz juz 10 spritow to usuwasz je na raz, pozwolenie zeby w konstruktorze kazdy pojedynczy obiekt zwalnial sie osobno odpada.
komentarz 9 sierpnia 2021 przez tonn204 Mądrala (7,440 p.)
A co w sytuacje jeżeli mam np. 200 obiektów muszę sprawdzić czy w któryś nie uderzył gracz. Muszę to robić w pętali for i po kolei sprawdzać każdy obiekt czy można to jakoś bardziej zoptymalizować?
komentarz 9 sierpnia 2021 przez dziablo Użytkownik (940 p.)
Moze jest jakiś szalony algorytm żeby to zrobić jakoś sprytnie, nie wiem , ale myślę, że spokojnie możesz zrobić to w pętli i sprawdzać wszystkie obiekty. Jeśli planujesz mieć dużą liczbę obiektów która musiałbys sprawdzać co klatkę to wtedy trzeba pomyśleć, ale optymalizacja zależy od gry jaka robisz, jeśli to gra gdzie mapa jest podzielona na plansze to sprawdzaj kolizje tylko dla obiektów które są na tej samej planszy co bohater, jeśli to platformówka to możesz np dynamicznie co klatkę tworzyć listę obiektow które są 15m od bohatera i sprawdzac tylko je, ale moim zdaniem nie przejmuj się tym aż nie napotkasz problemów z wydajnością.

Podobne pytania

0 głosów
1 odpowiedź 420 wizyt
pytanie zadane 28 lipca 2021 w C i C++ przez tonn204 Mądrala (7,440 p.)
0 głosów
0 odpowiedzi 150 wizyt
pytanie zadane 16 marca 2021 w C i C++ przez tonn204 Mądrala (7,440 p.)
0 głosów
1 odpowiedź 130 wizyt
pytanie zadane 20 sierpnia 2020 w C i C++ przez tonn204 Mądrala (7,440 p.)

92,830 zapytań

141,771 odpowiedzi

320,817 komentarzy

62,159 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...