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

Allegro 5 - problem z implementacją delta time i timestep

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
0 głosów
404 wizyt
pytanie zadane 31 sierpnia 2019 w C i C++ przez niezalogowany

Witam, chcąc zaimplementować delta time i timestep natknąłem się na problem z niestałymi wartościami timestep. Otóż, gdy przytrzymuje jakiś klawisz ruchu, if po Inpucie jest pomijany przez co wartość timestep jest dużo mniejsza, co z kolei wpływa na movement gracza (nie jest on już płynny).

Tak wygląda główna pętla gry.

void Run()
{
	float time;

	while (!gameOver)
	{
		time = (float)al_get_time() * 1000.0;
		timeStep = time - lastFrameTime;
		lastFrameTime = time;

		Input();

		if (draw && al_is_event_queue_empty(eventQueue))
		{
			game->draw = false;

			UpdateSnake(timeStep, direction);
			Logic();
			Draw();

			al_flip_display();
			al_clear_to_color(al_map_rgb(0, 0, 0));
		}
	}
}

A tak wygląda Input()

void Input()
{
	ALLEGRO_EVENT events;
	al_wait_for_eventeventQueue, &events);

	switch (events.type)
	{
		case ALLEGRO_EVENT_TIMER:
		{
			game->draw = true;

			switch (keys)
			{
				case UP:
					direction = (Position) { 0, -1 };
					break;

				case DOWN:
					direction = (Position) { 0, 1 };
					break;

				case LEFT:
					direction = (Position) { -1, 0 };
					break;

				case RIGHT:
					direction = (Position) { 1, 0 };
					break;
				}
			}

			break;
		}

		case ALLEGRO_EVENT_KEY_DOWN:
		{
			if (events.keyboard.keycode == ALLEGRO_KEY_UP || events.keyboard.keycode == ALLEGRO_KEY_W)
				game->keys = UP;
	
			if (events.keyboard.keycode == ALLEGRO_KEY_DOWN || events.keyboard.keycode == ALLEGRO_KEY_S)
				game->keys = DOWN;
					
			if (events.keyboard.keycode == ALLEGRO_KEY_LEFT || events.keyboard.keycode == ALLEGRO_KEY_A)
				game->keys = LEFT;

			if (events.keyboard.keycode == ALLEGRO_KEY_RIGHT || events.keyboard.keycode == ALLEGRO_KEY_D)
				game->keys = RIGHT;

			break;
		}

		case ALLEGRO_EVENT_DISPLAY_CLOSE:
		{
			gameOver = true;
			break;
		}
	}
}

 

1 odpowiedź

0 głosów
odpowiedź 31 sierpnia 2019 przez tangarr Mędrzec (155,140 p.)

Jestem niewyspany (gorąca noc, wyjący wiatrak) i nie piłem jeszcze kawy.
Wydaje mi się, że zmienna lastFrameTime powinna być aktualizowana podczas rysowania.
 

void Run()
{
    float time = (float)al_get_time() * 1000.0;
    lastFrameTime = time;
 
    while (!gameOver)
    {
        time = (float)al_get_time() * 1000.0;
        timeStep = time - lastFrameTime;
 
        Input();
 
        if (draw && al_is_event_queue_empty(eventQueue))
        {
            lastFrameTime = time;
            game->draw = false;
 
            UpdateSnake(timeStep, direction);
            Logic();
            Draw();
 
            al_flip_display();
            al_clear_to_color(al_map_rgb(0, 0, 0));
        }
    }
}
komentarz 31 sierpnia 2019 przez niezalogowany
edycja 31 sierpnia 2019
Niestety to raczej nie w tym rzecz, mam wrażenie że to coś z obsługą eventów w Allegro. Jeśli chcesz możesz zobaczyć jak to wygląda (najlepiej jest przemieścić się do jednej krawędzi i przemieszczając się do drugiej przytrzymać klawisz, i przegrać): https://www.mediafire.com/file/b3mg9cetm54w6zf/Snake.rar/file

Mogę również udostępnić cały kod lub projekt w VS 2017.
komentarz 31 sierpnia 2019 przez tangarr Mędrzec (155,140 p.)

Ewentualnie mógłbyś spróbować obsłużyć wszystkie eventy z kolejki przed rysowaniem.

while (!al_is_event_queue_empty(eventQueue)) {
    Input()
}
if (draw) {
    // rysowanie
}

 

komentarz 31 sierpnia 2019 przez tangarr Mędrzec (155,140 p.)
Jeżeli podzielisz się kodem to spróbuję później zdebugować problem.
komentarz 31 sierpnia 2019 przez niezalogowany
Kod jest kompilowany w C.

Skoro wysyłam już kod to skorzystam z okazji, mógłbyś ocenić czy mój kod się do czegoś nadaje? Nie znam żadnych patternów dla C, więc nie wiem czy tak powinno się pisać. Jakieś rady byłyby mile widziane :)

https://www.mediafire.com/file/ncuvoag2gwkmc2v/Kod-Snake-Allegro5.rar/file
komentarz 31 sierpnia 2019 przez niezalogowany

Dopiero zauważyłem, że wysłałem wersje ze złym main.c, poprawiam.

#include "Game.h"

int main(void)
{
	Game GAME;

	Setup(&GAME);
	Run(&GAME);
	Free(&GAME);

	return EXIT_SUCCESS;
}

 

komentarz 31 sierpnia 2019 przez tangarr Mędrzec (155,140 p.)

Testowałem na Ubuntu.
Liczenie delty w warunku if (draw && ...) naprawiło mi problem z szarpaniem podczas trzymania klawisza. Jednak sterowanie ciągle było "ociężałe". Zastosowałem drugi pomysł który ci zaproponowałem i wszystkie moje problemy znikły.

void Run(Game *game)
{
    float time = (float)al_get_time() * 1000.0;
    lastFrameTime = time;

    while (!game->gameOver)
    {
        while (!al_is_event_queue_empty(game->eventQueue)) 
            Input(game);

        if (game->draw)
        {
            time = (float)al_get_time() * 1000.0;
            timeStep = time - lastFrameTime;
            lastFrameTime = time;

            /* reszta kodu */
        }
    }
} 

Na pierwszy rzut oka kod ładnie się prezentuje. Widzę, że część logiki jeszcze nie jest zaimplementowana. Brakuje mi sprawdzania błędów podczas wczytywania zasobów.
Później poszukam czy nie ma problemów z zarządzaniem zasobami.

komentarz 31 sierpnia 2019 przez niezalogowany

Udało mi się znaleźć na forum Allegro algorytm interpolacji napisany przez jednego z twórców tej biblioteki i w nim była jedna różnica, otóż:

while (al_get_next_event(eventQueue, &events))

Wszystko było w takim while zamiast al_wait_for_event().

Przesyłam zaaktualizowany plik Game.c i folder res: https://www.mediafire.com/file/fw8eiygtt0xlnf7/updated.rar/file

Podobne pytania

0 głosów
1 odpowiedź 1,931 wizyt
pytanie zadane 14 grudnia 2019 w C i C++ przez Szymczak_7 Obywatel (1,860 p.)
0 głosów
1 odpowiedź 176 wizyt
pytanie zadane 27 sierpnia 2019 w C i C++ przez niezalogowany
+1 głos
0 odpowiedzi 561 wizyt
pytanie zadane 12 maja 2019 w Nasze projekty przez niezalogowany

93,166 zapytań

142,177 odpowiedzi

321,946 komentarzy

62,495 pasjonatów

Advent of Code 2024

Top 15 użytkowników

  1. 688p. - dia-Chann
  2. 676p. - CC PL
  3. 675p. - Łukasz Piwowar
  4. 664p. - Marcin Putra
  5. 662p. - Łukasz Eckert
  6. 649p. - Michal Drewniak
  7. 641p. - rafalszastok
  8. 641p. - rucin93
  9. 629p. - Piotr Aleksandrowicz
  10. 629p. - Adrian Wieprzkowicz
  11. 621p. - Dawid128
  12. 612p. - Mikbac
  13. 611p. - ksalekk
  14. 606p. - Mariusz Fornal
  15. 602p. - Michał Telesz
Szczegóły i pełne wyniki

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

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...