Przesuwanie postaci po kafelkowej mapie o 32px

0

Witam.

Piszę sobie prostą grę RPG w Bibliotece SDL C++.
Mam już napisane poruszanie mapą (ludzik stoi na środku, a rusza się mapą). Ludzik poruszał się tak długo, aż nie puściłem klawisza. Poruszał się o 2px. Chcę zrobić poruszanie się o jedną kratkę. Koncept miałem taki: poruszam sobie normalnie mapą o 2px, a w momencie puszczenia klawisza program oblicza odległość pozostałą do pełnej kratki i przesuwa o te piksele bez trzymania przycisku.

Zrobiłem już to prawie, ale mam pewien problem.

else if((!keystate[SDLK_RCTRL]) && (keystate[SDLK_LEFT]))
{
	map_position.x++;
	map_position.x++;
	frame++;
	frame++;
	frame++;
	if( frame > 40) frame=0;  
	if( frame<20) { players_frame = 9;}
	else if( frame>=20 && frame<40) { players_frame = 10; } 
	player_dir=4;
	keyleft1 = true;				// Ustawia zmienną która przechowuje informacje czy strzałka w lewo była wciśnięta
	tilpos_x=position_x;
}
			

else if ((player_dir == 4) && (!keystate[SDLK_LEFT]) && (collision[til_position_y][til_position_x-2] == 0))
{
	keyleft = true;
			
	if (keyleft2 == true)
	{
		tilpos_x1=tilpos_x-32;
	}

	if (keyleft1 ==  true)			// Sprawdza czy strzałka w lewo była wciśnięta
	{
		if (keyleft ==  true)
		{
			if (position_x-tilpos_x1 != 0)		// Oblicza odległość do następnej kratki
			{
				map_position.x++;
				map_position.x++;
				frame++;
				frame++;
				frame++;
				if( frame > 40) frame=0;  
				if( frame<20) { players_frame = 5; }
				else if( frame>=20 && frame<40) { players_frame = 6; } 		
				keyleft2=false;				// I to mój problem, o tym niżej w poście.
			}
		}
	}

			players_frame = 4;
}

Więc w komentarzach napisane jest co do czego służy. Podczas wciskania przycisku zmienna keyleft1 zmienia się na TRUE, po czym odczytywana jest w innym warunku (przycisk NIE jest wciśnięty), po czym odlicza odległość pozostałą do przebycia i przesuwa o tyle ludzika. Wszystko działa perfekcyjnie, ale tylko jeden raz. Ludzik ładnie przechodzi o 1 kratkę, a jak próbuję następną to nie zatrzymuje się już wcale. Przypuszczam że jest to związane z tym, że zmienianie zmiennej keyleft na FALSE znajduje się w złym miejscu.

Ktoś wie może jak rozwiązać ten problem?

0

A czy nie prościej przesuwać ludzika o te 2 pixele

if(keystate[SDLK_RIGHT]) ludyik.x +=2;

a gdy klawisz jest puszczony obliczać w którym kaflu znajduje się ludzik i go wyrównywać z pozycją kafla?

else{
     Uint8 kafel = ludzik.x  / TILE_WIDTH;
     ludzik.x = kafel * TILE_WIDTH;
}

?

0

@up Nie jeśli chce się mieć ludzika cały czas na środku ekranu.

0

@up: Od tego się robi viewport.
Poza tym nie wiem czemu kolega w jednym warunku wywołuje
3x frame++, zamiast np frame+=3;
oraz dwa razy inkrementację x'a mapy

1

najłatwiej to zrobić trzy rodzaje współrzędnych - wszystkie liczone od lewego górnego rogu:

  • współrzędne na mapie - czyli po prostu (x,y) kafla,
  • współrzędne globalne (piksele) - współrzędne na mapie, z tym że względem lewego górnego rogu kafla o współrzędnych na mapie (0,0) w pikselach,
  • współrzędne na ekranie (piksele)
    najłatwiej jeśli każde z tych współrzędnych będą klasą z operatorami które konwertują je między sobą (w zasadzie mogłby też dziedziczyć po jakimś interfejsie klasy Współrzędnych, ale niekoniecznie - osobiście myślę że byłoby to dość wygodne)

dodatkowo zrobić funkcję/metodę:

  • wyśrodkuj ekran do kafla,
  • wyśrodkuj ekran do współrzędnych (globalnych)

ludzika można np zaprojektować tak:

  • WspolrzedneGlobalne, - gdzie znajduje się dokładnie, na ich podstawie obliczać gdzie jest na ekranie
  • WspolrzedneNaMapie, - miejsce w którym się aktualnie znajduje (obj), miejsce z ktorego idzie (obj), miejsce kolejne do którego idzie (wskaznik)
  • CzyIdzie - boolean ktory mowi czy wlasnie sie przemieszczasz
  • poczatekruchu - czas w ktorym ruch sie zaczal, jesli korzystasz z GetTickCount to jest to DWORD
  • predkosc - czas przemieszczania sie z kafla na kafel

przykład: początkowo ludzik stoi na kaflu (5,5) i nie porusza sie (czyidzie=false).
uzytkownik klika strzalke w prawo:

  • wspolrzedneglobalne=aktualnapozycja, miejscezktoregoidzie=aktualnapozycja, miejsce w ktorym aktuanie sie znajduje zmienia sie na (6,5), czyidzie=true, poczatekruchu=GetTickCount()
    uzytkownik klika strzalke w dol (w trakcie jak jeszcze idzie w prawo):
  • miejscekolejnedoktoregoidzie = new WspolrzedneNaMapie(6,6)
0

Tylko problem jest taki, że ta funkcja 'jeśli klawisz jest wciśnięty' wykonuje się cały czas, i jeśli ustawie sobie zmienną mojapozycja = cośtam, to ta zmienna zostanie zmodyfikowana w ciągu ruchu o kratkę około 64 razy, czyli 64 razy zmieni mi się ta zmienna i jeśli będę chciał ją odczytać gdzie indziej (if klawisz nie jest wciśnięty) to odczyta sie ostatnia zapisana przy 64 wykonaniu pozycja, czyli prawie że aktualna.

Ja napisał(a)

A czy nie prościej przesuwać ludzika o te 2 pixele a gdy klawisz jest puszczony obliczać w którym kaflu znajduje się ludzik i go wyrównywać z pozycją kafla?
?

Ale on ma się wyrównać idąc płynnie o 2px, a nie przeskakując na pozycję docelową.

0

Już sobie poradziłem. Zamiast poprawiać ten zagmatwany kod co wklejałem tu wcześniej, rozpisałem sobie na kartce "algorytm", napisałem to od nowa i działa.
Dzięki za odpowiedzi, temat można zamknąć.

1 użytkowników online, w tym zalogowanych: 0, gości: 1