Skocz do zawartości

Blokada ruchu czołgu, jeśli napotka solidny obiekt - GM 8.0


Rekomendowane odpowiedzi

Witam,

 

Od niedawna zacząłem bawić się w robienie w GMie małej gierki z czołgami w roli głównej :)

Aktualnie zatrzymałem się na fragmencie gdzie sprawdza się czy czołg nie jest przez coś blokowany.

A oto moje wypociny:

1. Sprawdzanie czy może obrócić się w lewo - skrypt Check_left:

GML
sprheight = sprite_get_height(spr_tank1)

sprwidth = sprite_get_width(spr_tank1)

 

py1 = obj_tank.y - lengthdir_y(sprheight/2,obj_tank.direction)

px1 = obj_tank.x - lengthdir_x(sprwidth/2,obj_tank.direction)

 

py2 = obj_tank.y + lengthdir_y(sprheight/2,obj_tank.direction)

px2 = obj_tank.x + lengthdir_x(sprwidth/2,obj_tank.direction)

 

if place_free(px1, py1) && place_free(px2,py2)

return (1)

else

return (0)

2. Sprawdzanie czy może obrócić się w prawo - Skrypt Check_right:

GML
sprheight = sprite_get_height(spr_tank1)

sprwidth = sprite_get_width(spr_tank1)

 

py1 = obj_tank.y - lengthdir_y(sprheight/2,obj_tank.direction)

px1 = obj_tank.x + lengthdir_x(sprwidth/2,obj_tank.direction)

 

py2 = obj_tank.y + lengthdir_y(sprheight/2,obj_tank.direction)

px2 = obj_tank.x - lengthdir_x(sprwidth/2,obj_tank.direction)

 

if place_free(px1, py1) && place_free(px2,py2)

return (1)

else

return (0)

3. Sprawdzanie czy może poruszać się do przodu - Skrypt Check_forward:

GML
sprheight = sprite_get_height(spr_tank1)

sprwidth = sprite_get_width(spr_tank1)

 

py1 = obj_tank.y - lengthdir_y(sprheight/2,obj_tank.direction)

px1 = obj_tank.x - lengthdir_x(sprwidth/2,obj_tank.direction)

 

py2 = obj_tank.y - lengthdir_y(sprheight/2,obj_tank.direction)

px2 = obj_tank.x + lengthdir_x(sprwidth/2,obj_tank.direction)

 

py3 = obj_tank.y - lengthdir_y(sprheight/2,obj_tank.direction)

px3 = obj_tank.x

 

if place_free(px1, py1) && place_free(px2,py2) && place_free(px3,py3)

return (1)

else

return (0)

4. Sprawdzanie czy może poruszyć się do tyłu - Skrypt Check_backward:

GML
sprheight = sprite_get_height(spr_tank1)

sprwidth = sprite_get_width(spr_tank1)

 

py1 = obj_tank.y + lengthdir_y(sprheight/2,obj_tank.direction)

px1 = obj_tank.x - lengthdir_x(sprwidth/2,obj_tank.direction)

 

py2 = obj_tank.y + lengthdir_y(sprheight/2,obj_tank.direction)

px2 = obj_tank.x + lengthdir_x(sprwidth/2,obj_tank.direction)

 

py3 = obj_tank.y + lengthdir_y(sprheight/2,obj_tank.direction)

px3 = obj_tank.x

 

if place_free(px1, py1) && place_free(px2,py2) && place_free(px3,py3)

return (1)

else

return (0)

return(1) - Nic go nie blokuje

return(0) - Jakiś blok solidny stoi i blokuje

 

Znajdzie się jakiś miszczu co pomoże biednemu w potrzebie? :D

Odnośnik do komentarza
Udostępnij na innych stronach

Przedstawię na obrazku, gdyż nie potrafię tego dokładnie opisać oraz chciałbym ominąć nieporozumienia:

 

Brązowe - czołg

Czerwone - punkty sprawdzające podczas obrotu w lewo czy coś nie blokuje

Zielone - tak samo jak czerwone, ale w prawo

 

eymDZX4.png

 

Edit: Pobawię się draw'em tak jak napisałeś.

Odnośnik do komentarza
Udostępnij na innych stronach

Ależ ja wiem o co ci chodzi :P

 

Wyświetl sobie te punkty w draw, podczas obracania czołgu nie będą się ruszać tak jak chciałeś. No chyba że sprit czołgu jest kwadratowy to wtedy będzie ok.

 

https://forum.gmclan.org/index.php?showtopic=28090

Odnośnik do komentarza
Udostępnij na innych stronach

To teraz sprostowanie, użyłem skryptu Check_left, by sprawdzić gdzie są te punkty.

Pierwszy pojawia się u góry między dwoma zaznaczonymi, a drugi an dole także między zaznaczonymi na powyższym rysunku.

Czołg jest prostokątny o wymiarach 34x48. Punkty ruszają się podczas obrotu czołgu.

 

Edit: Przy użyciu drawa na skrypt Check_right kropki pokazują się w tym samym miejscu co przy Check_left, ale jak obracam czołg to kręcą się w drugą stronę.

Edit2: Przy skrycie na Check_forward zostałem rozwalony, nie wiem jak opisać obrót tych punktów :D

Odnośnik do komentarza
Udostępnij na innych stronach

Jeżeli origin jest na środku to:

BeDpmDR.png

 

GML
czerwony = obj_tank.y + lengthdir_y(28,obj_tank.direction+123)

czerwony = obj_tank.x + lengthdir_x(28,obj_tank.direction+123)

 

niebieski = obj_tank.y + lengthdir_y(28,obj_tank.direction+53)

niebieski = obj_tank.x + lengthdir_x(28,obj_tank.direction+53)

 

fioletowy = obj_tank.y + lengthdir_y(28,obj_tank.direction-123)

fioletowy = obj_tank.x + lengthdir_x(28,obj_tank.direction-123)

 

rozowy = obj_tank.y + lengthdir_y(28,obj_tank.direction-53)

rozowy = obj_tank.x + lengthdir_x(28,obj_tank.direction-53)

 

Może zajść potrzeba odwrócenia direction czyli -obj_tank.direction ale tego nie jestem pewien.

Odnośnik do komentarza
Udostępnij na innych stronach

Rozumiem, że te punktu są przystosowane już do rozmiarów mojego zacnego prostokątnego czołgu? :D

A co do punktu równo na górze albo równo na dole muszę dać tak?

GML
gora = obj_tank.y + lengthdir_y(24,obj_tank.direction)

gora = obj_tank.x + lengthdir_x(24,obj_tank.direction)

 

dol = obj_tank.y + lengthdir_y(24,obj_tank.direction-180)

dol = obj_tank.x + lengthdir_x(24,obj_tank.direction-180)

Chciałbym też dowiedzieć się jak dorwałeś LEN 28?

Odnośnik do komentarza
Udostępnij na innych stronach

No niestety napotkałem kolejny problem, mianowicie:

Niby punkty do sprawdzania kolizji działają, ale małe skurczybyki działają na większą skale niż chciałem.

Czerwone kropki to punkty kolizji, czarny blok to obiekt solidny.

EPlxOiv.jpg

Otóż jak na obrazku widać, jest jeszcze sporo miejsca między punktami kolizji i solidną ścianką, lecz pokazane punkty już wykrywają solidna ścianę :(

Jakiś pomysł?

Odnośnik do komentarza
Udostępnij na innych stronach

Czyli jeśli chciałbym użyć instance_position, by wykrywał bloki solidne to jakoś tak:

GML
instance_position(obj_tank.x,obj_tank.y+24, obj_solid_block) ?

Jeśli dobrze rozumiem to będzie reagować tylko na obiekty, które mu podam?

Da się to jakoś wykorzystać, by reagował na każdy obiekt, który jest solidny?

Odnośnik do komentarza
Udostępnij na innych stronach

Musisz sobie stworzyć hierarchię obiektów.

Stwórz pusty obiekt o np nazwie parent_sciany. I każdemu obiektowi który jest ścianą ustaw parent>parent_sciany

 

Teraz przy kolizji (zakładam że kolizje sprawdzasz w obj_tank)

GML
colid = instance_position(px1,py1, parent_sciany)

if ( colid )

{

// nastąpiła kolizja

// dalej można coś zrobić ze ścianą np zniszczyć

with ( colid ) instance_destroy();

}

Odnośnik do komentarza
Udostępnij na innych stronach

Check_backward

GML
py1 = obj_tank.y + lengthdir_y(18,obj_tank.direction+143) + obj_tank.vspeed

px1 = obj_tank.x + lengthdir_x(18,obj_tank.direction+143) + obj_tank.hspeed

py2 = obj_tank.y + lengthdir_y(18,obj_tank.direction+213) + obj_tank.vspeed

px2 = obj_tank.x + lengthdir_x(18,obj_tank.direction+213) + obj_tank.hspeed

py3 = obj_tank.y + lengthdir_y(14,obj_tank.direction-180) + obj_tank.vspeed

px3 = obj_tank.x + lengthdir_x(14,obj_tank.direction-180) + obj_tank.hspeed

 

if instance_position(px1, py1, solid) || instance_position(px2,py2, solid) || instance_position(px3,py3, solid)

return (0)

else

return (1)

 

Check_forward

GML
py1 = obj_tank.y + lengthdir_y(19,obj_tank.direction+37) + obj_tank.vspeed

px1 = obj_tank.x + lengthdir_x(19,obj_tank.direction+37) + obj_tank.hspeed

py2 = obj_tank.y + lengthdir_y(19,obj_tank.direction-33) + obj_tank.vspeed

px2 = obj_tank.x + lengthdir_x(19,obj_tank.direction-33) + obj_tank.hspeed

py3 = obj_tank.y + lengthdir_y(15,obj_tank.direction) + obj_tank.vspeed

px3 = obj_tank.x + lengthdir_x(15,obj_tank.direction) + obj_tank.hspeed

 

if instance_position(px1, py1, solid) || instance_position(px2,py2, solid) || instance_position(px3,py3, solid)

return (0)

else

return (1)

 

Check_left

GML
py1 = obj_tank.y + lengthdir_y(19,obj_tank.direction+37) + obj_tank.vspeed

px1 = obj_tank.x + lengthdir_x(19,obj_tank.direction+37) + obj_tank.hspeed

py2 = obj_tank.y + lengthdir_y(18,obj_tank.direction+213) + obj_tank.vspeed

px2 = obj_tank.x + lengthdir_x(18,obj_tank.direction+213) + obj_tank.hspeed

 

if instance_position(px1, py1, solid) || instance_position(px2,py2, solid)

return (0)

else

return (1)

 

Check_right

GML
py1 = obj_tank.y + lengthdir_y(19,obj_tank.direction-33) + obj_tank.vspeed

px1 = obj_tank.x + lengthdir_x(19,obj_tank.direction-33) + obj_tank.hspeed

py2 = obj_tank.y + lengthdir_y(18,obj_tank.direction+143) + obj_tank.vspeed

px2 = obj_tank.x + lengthdir_x(18,obj_tank.direction+143) + obj_tank.hspeed

 

if instance_position(px1, py1, solid) || instance_position(px2,py2, solid)

return (0)

else

return (1)

 

Edit: Teraz znowu sprawdzam i już blokuje dobrze, ale teraz mam problem z "wbijaniem" się w ścianę, jak czołg osiągnie dużą prędkość to może wbić się lekko w ścianę. Jak temu zapobiec?

Odnośnik do komentarza
Udostępnij na innych stronach

Są 2 sposoby obliczania kolizji

  1. Sprawdzanie czy po skończonym ruchu będzie kolizja. Jeśli nie to przemieszczenie.
  2. Przemieszczenie i dopiero potem sprawdzenie czy zaszła kolizja. Jeżeli zaszła to cofnięcie przemieszczenia.

Ty wybrałeś pierwszy, bo wydaje się bardziej sensowny. W drugim jest obawa że będzie widoczne to cofnięcie, ale jeżeli wszystko odbędzie się w obrębie jednego step (przed narysowaniem) to będzie dobrze.

Odnośnik do komentarza
Udostępnij na innych stronach

Tak, wolałbym pierwszy sposób, lecz nawet jak dodam do sprawdzania kolizji vspeed albo hspeed to nadal przy większej prędkości widać jak się wbija.

Taki jest efekt aktualnego kodu.

(Rozpędziłem się czołgiem do maksimum i wbiłem się w ściankę)

UwP0l4D.jpg

Odnośnik do komentarza
Udostępnij na innych stronach

Korzystając z instance_position brana jest pod uwagę tylko maska obiektu z trzeciego argumentu. Maska obiektu który wykonuje ten kod nie jest brana pod uwagę. place_free, position_free albo event kolizji powinny być użyte.

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...