Skocz do zawartości

Utrzymywanie odległości image_angle w stepie


odex

Rekomendowane odpowiedzi

Po pierwsze chciałem z góry przeprosić za temat pod tematem bo nie chcę być "tym gościem", jednak chyba potrzebuje waszej pomocy.

 

W każdym razie do rzeczy. Gra typu top-down twin stick shooter. Sterujemy osobno postacią (klawiatura) i celownikiem/strzelaniem (myszka). W grze oczywiście są różne przedmioty ala Isaac, które zmieniają nasze możliwości strzelania. Jednym z nich jest laser, który jest jedyną bronią strzelający ciągłą wiązką (usuwanie obiektu po puszczeniu klawisza). Inne to przedmioty dodające możliwość strzelania kilku pocisków (2, 3, 4) na raz. Problem w tym, że o ile inne pociski albo pojawiają się na parę klatek, albo są wytrzeliwane, tak laser mieć cały czas kontakt ze statkiem i jednocześnie się z nim obracać. Problem polega, że gdy chce wystrzeliwać kilka laserów jednocześnie powinno one się obracać ze statkiem. Wiem, że wtedy potrzebuje po prostu ustalać pozycję tego laseru w stepie i tutaj pojawia się problem ponieważ nie mam pojęcia jak zatrzymać ich pierwotny kąt względem siebie i jednocześnie je przesuwać. Jeśli dam coś w stylu image_angle = statek.image_angle to zamiast np 4 laserów mam jedną wiązkę co jest logiczne. Domyślam się, że trzeba pewnie pobierać pierwotną pozycję i jakoś ją potem przeliczać w stepie ale jak - nie mam pojęcia.

Docelowo powinno to wyglądać tak: http://i.imgur.com/1VoRsLC.png

a mam tylko jedną wiązkę gdy obraca się laser za statkiem.

 

Kod tworzenia laseru:

 

GML
switch (global.bron)

{

case 1:

aktualnabron = obj_bullet;

break;

case 2:

aktualnabron = obj_beam;

break;

case 3:

aktualnabron = obj_laser;

break;

 

}

 

if global.iloscpociskow = 4 // 4 pociski

{

pocisk1 = instance_create(x, y, aktualnabron);

pocisk2 = instance_create(x, y, aktualnabron);

pocisk3 = instance_create(x, y, aktualnabron);

pocisk4 = instance_create(x, y, aktualnabron);

 

pocisk1.direction = direction+10;

pocisk2.direction = direction+5;

pocisk3.direction = direction-5;

pocisk4.direction = direction-10;

 

pocisk1.image_angle = direction+10;

pocisk2.image_angle = direction+5;

pocisk3.image_angle = direction-5;

pocisk4.image_angle = direction-10;

 

canshoot = 0

alarm[0] = global.szybkoscstrzalu;

}

 

Z góry dzięki za pomoc, mam nadzieję, że mój opis jest stosunkowo jasny, czasami trudno przelać na papier swoje myśli.

Odnośnik do komentarza
Udostępnij na innych stronach

Oks, więc wystrzelasz sobie 4 lasery i one mają zawsze z najbliższym laserem kąt dajmy 30*. Więc chcesz przesuwać laserami i żeby zostawało to 30*. Mam nadzieje, że dobrze zrozumiałem. Musisz zamiast ustawiać ich image_angle, dodawać. Tzn. jeśli ruszając myszką stworzyłeś coś co przesunęłoby je o kąt 15*, to one wszystkie muszą dodać te 15*. Przy tworzeniu laserów twórz zmienną o ich początkowym kierunku. I od tego kierunku odejmuj image_angle? Nawet nie wiem jaki to da efekt. Powiedzmy, że dałem Ci troszkę teorii, może pomogłem.

 

(tak, uznałem to * za stopnie)

Odnośnik do komentarza
Udostępnij na innych stronach

Oczywiście, że pomogłeś. Próbowałem już wcześniej różne kombinację z taką metodą ale nie przynosiły rozwiązania. Jednak chyba znalazłem problem. w Create obiektu obj_laser (czyli naszego lasera nieszczęsnego) dałem angle = image_angle. Problem jest tylko taki, że ta zmienna zwraca wartość jak sprawdziłem w debuggerze. Ma to sens bo bez znaczenia czy ją potem dodaje, odejmuje czy cokolwiek to i tak lasery są zawsze w tym samym miejscu. Jakiś pomysł czego znów nie rozumiem w kwestii przypisywania wartości do zmiennej?

Odnośnik do komentarza
Udostępnij na innych stronach

W drugiej części kodu dokonałbym paru poprawek. Przede wszystkim, skorzystaj z pętli for i tablicy pocisk, zamiast 4 różnych zmiennych. Dzięki temu niezależnie od ilości pocisków, zawsze wystrzeliwane są w równej odległości od siebie i środka linii strzału.

 

Nie kminię trochę, czemu pocisk laserowy ma jednocześnie zmieniane wartości direction i image_angle. W końcu jest stacjonarny względem gracza, tzn nie ma fizycznej prędkości, więc jego kierunek nie ma znaczenia. Ale ok. Inne rodzaje broni mają prędkość, a tworzone są jednym kodem, więc niech zostanie.

 

Wywal wszystko po pętli switch, a zamiast tego proponuję

 

GML
if global.iloscpociskow==1

{

odleglosc_katowa=0;

suma_katow=0;

}

else

{

odleglosc_katowa=15; //pociski co 15 stopni

suma_katow=odleglosc_katowa*(global.iloscpociskow-1);

//mając tylko jeden pocisk, suma wynosi 0. mając dwa - 15, itp.

}

 

for (ktorypocisk=0; ktorypocisk<global.iloscpociskow; ktorypocisk++)

{

if global.iloscpociskow==1

delta=0;

else

delta = -(suma_katow/2)+(ktorypocisk*odleglosc_katowa);

 

kat_pocisku=direction+delta;

 

pocisk[ktorypocisk]=instance_create(x,y,aktualnabron);

pocisk[ktorypocisk].direction=kat_pocisku;

pocisk[ktorypocisk].image_angle=kat_pocisku;

pocisk[ktorypocisk].delta=delta;

 

canshoot = 0;

alarm[0] = global.szybkoscstrzalu;

}

 

I teraz w obiekcie obj_laser, w Step Event, następujący kod (zakładając że obiekt gracza nazywa się obj_character):

GML
x=obj_character.x;

y=obj_character.y;

image_angle=point_direction(obj_character.x,obj_character.y,mouse_x,mouse_y)+delta;

 

Nie sprawdzałem czy działa, skompilowałem sobie w głowie, i teoretycznie powinno - ale sprawdź :) Jak czegoś nie rozumiesz, daj znać. Nie mam pojęcia, na ile poznałeś GML.

 

EDIT: Ups. Poprawiłem, bom spartolił. Teraz powinno działać.

Odnośnik do komentarza
Udostępnij na innych stronach

Teraz powinno działać.

Zmieniłem kąt z 15 na 10, poprawiłem nazwy obiektów i... działa perfekcyjnie ze wszystkim, dokładnie tak jak ja próbowałem to zrobić więc wielkie dzięki.

 

Aczkolwiek jestem trochę niezadowolony bo nie bardzo rozumiem kod. Rozumiem z dokumentacji, że pętla FOR polega na inicjacji w pierwszym warunku, sprawdzaniu poprawności w drugim, trzeci warunek wykonuje akcje, po czym pętla wraca do początku. Reszta to już matematyka + logiczne myślenie jak mniemam :)

 

Nie kminię trochę, czemu pocisk laserowy ma jednocześnie zmieniane wartości direction i image_angle. W końcu jest stacjonarny względem gracza, tzn nie ma fizycznej prędkości, więc jego kierunek nie ma znaczenia. Ale ok. Inne rodzaje broni mają prędkość, a tworzone są jednym kodem, więc niech zostanie.

Jeszcze tylko dopowiem na swoją obronę, że miałem pełną świadomość, że w niektórych przypadkach te wartości są kompletnie niepotrzebne, jednak miał to być system uniwersalny więc, jak jak pisałem potem, do jednych działało to, do innych to więc dlatego zostały oba :)

Odnośnik do komentarza
Udostępnij na innych stronach

Aczkolwiek jestem trochę niezadowolony bo nie bardzo rozumiem kod. Rozumiem z dokumentacji, że pętla FOR polega na inicjacji w pierwszym warunku, sprawdzaniu poprawności w drugim, trzeci warunek wykonuje akcje, po czym pętla wraca do początku. Reszta to już matematyka + logiczne myślenie jak mniemam :)

 

No więc od początku. Nie ma sensu, byś coś powielał bez zrozumienia.

 

GML
//jezeli jest tylko jeden pocisk, to nie tworzy zadnego kata. jego odleglosc

//wynosi wiec 0, tak samo jak suma.

if global.iloscpociskow==1

{

odleglosc_katowa=0;

suma_katow=0;

}

else //ale jezeli jest wiecej niz 1 pocisk

{

odleglosc_katowa=10; //pociski co 10 stopni, niech bedzie

suma_katow=odleglosc_katowa*(global.iloscpociskow-1);

//mając tylko jeden pocisk, suma wynosi 0. mając dwa - 15, itp.

}

 

for (ktorypocisk=0; ktorypocisk<global.iloscpociskow; ktorypocisk++)

//ktorypocisk++ to to samo co ktorypocisk+=1

//najlatwiej zapamietac tak: zmienna ktorypocisk bedzie wzrastala o 1

//w kazdej iteracji, czyli wykonaniu petli. w pierwszej iteracji wynosi ona

//0. gdy warunek ktorypocisk<global.iloscpociskow w koncu nie zostanie

//spelniony, gdyz zmienna ktorypocisk bedzie wieksza niz iloscpociskow.

//Latwo wiec wywnioskowac, ze petla wykona sie cztery razy - i wartosc

//zmiennej ktorypocisk bedzie wynosila kolejno 0, 1, 2, i 3 - dla czterech

//pociskow, az sie zatrzyma.

{

//delta to przesuniecie katowe wzgledem lini strzalu - czyli relatywna

//wartosc, jakiej obj_laser bedzie sie trzymal obliczajac nowy kat.

//tak wiec jezeli jest tylko jeden pocisk, tak jak poprzednio - jest

//przesuniety o 0.

if global.iloscpociskow==1

delta=0;

else //jednakze jezeli pociskow jest wiecej, dajmy na to 4

//to delta, czyli indywidualne przesuniecie kazdego pocisku,

//obliczane jest nastepujaco:

delta = -(suma_katow/2)+(ktorypocisk*odleglosc_katowa);

/*

Najpierw brana pod uwage jest suma katow. Dla 4 pociskow

wynosi ona global.iloscpociskow-1, czyli 3*15°=45°. Kazdy

pocisk zaczyna z delta wynoszaca polowe sumy katow - tak,

aby srodek tego kata znalazl sie na linii strzalu. stad

-(suma_katow/2) - minus stad, ze od kata lini strzalu

(zaraz sie dowiesz, jak go obliczac) odejmujemy polowe sumy.

W naszym przypadku jest to 45°/2=-22.5°.

Nastepnie dodajemy (ktorypocisk*odleglosc_katowa) - czyli

lecimy w druga strone, w strone lini strzalu. Pamietaj, ze zmienna

ktorypocisk wzrasta za kazdym rozpatrywanym przypadkiem.

Dla pierwszego (a wlasciwie zerowego) lasera jest to (0*15),

czyli 0. Dla drugiego(1*15), dla trzeciego 30°, a dla czwartego

45°.

I teraz wiedzac, ze "rysowanie" katow tworzonych przez lasery

zaczynamy od -22.5°, dodajac kolejno wzrastajace wielokrot-

nosci liczby 15, lasery ladnie i rowno sie ukladaja w, kolejno:

 

-22.5°,-22.5°+15°=-7.5°,-22.5°+30°=7.5°,-22.5°+45=22.5°

*/

 

kat_pocisku=direction+delta;

//i teraz ostateczny kat pocisku to kat tworzony przez linie strzalu

//PLUS delta. Gdyz dodajac liczby ujemne, jak wiadomo, odejmu-

//jemy. Gdybysmy delte zrobili dodatnia, teraz bysmy ja odejmowali,

//zamiast dodawac.

//mam nadzieje ze tutaj wszystko jasne. Wiesz, jak sie uzywa tablic?

//jesli nie, poczytaj w dokumentacji o arrays. Generalnie prosta

//sprawa. Tablica to zmienne tego samego typu i tej samej nazwy -

//a kazda ma unikalny indeks. W tym wypadku wzrastajaca za kazda

//iteracja zmienna ktorypocisk sluzy za indeks tablicy - chociaz

//jezeli nie odwolujesz sie do konkretnych pociskow z poziomu

//obiektu gracza, rownie dobrze moglibysmy napisac

//pocisk=instance_create(...

//pocisk.direction=kat_po...

//itp. W kazdej iteracji zmienna pocisk bylaby nadpisywana wartoscia

//nowoutworzonego lasera. Tak czy siak.

//Tutaj mysle ze prosta sprawa - nadajemy laserom odpowiednie

//wartosci. Kazdy laser "wie", o ile katow powinien byc przesuniety

//wzgledem linii strzalu, dzieki zmiennej delta, indywidualnej

//dla kazdej iteracji.

 

pocisk[ktorypocisk]=instance_create(x,y,aktualnabron);

pocisk[ktorypocisk].direction=kat_pocisku;

pocisk[ktorypocisk].image_angle=kat_pocisku;

pocisk[ktorypocisk].delta=delta;

 

canshoot = 0;

alarm[0] = global.szybkoscstrzalu;

}

 

I teraz w obiekcie obj_laser, w Step Event, następujący kod (zakładając że obiekt gracza nazywa się obj_character):

GML
x=obj_character.x;

y=obj_character.y; //no to chyba wiadome

image_angle=point_direction(obj_character.x,obj_character.y,mouse_x,mouse_y)+delta;

 

//okej. funkcja point_direction jest bardzo uzyteczna, tak samo jak jej brat - point_distance,

//i odwrotnosci - lengthdir_x i lengthdir_y - poczytaj koniecznie.

//funkcja ta, na podstawie par wspolrzednych, wyznacza kierunek linii przecinajacy oba

//punkty. Czyli de facto oblicza kat od gracza do celownika, ktory nastepnie, po dodaniu

//indywidualnej delty lasera, przyznawany jest laserowi jako kat, pod ktorym powinien

//sie ustawic - jego nowy image_angle. point_direction zwraca ilosc stopni. Jezeli walisz

//laserem centralnie w prawo, jest to 0. W gore - 90, w lewo - 180, w dol - 270, itp.

//Ale to pewnie wiesz.</span>

 

Mam nadzieję że teraz wszystko jasne

Odnośnik do komentarza
Udostępnij na innych stronach

O kurde, wielkie dzięki za dedykację i poświęcony czas. Nawet nie chodziło tutaj o kwestię niezrozumiałości do robi dana funkcja (od tego jest dokumentacja), tylko jak ona rzeczywiście się przekłada na kolejny krok dotarcia do celu. To właśnie w takich momentach podziwiam osoby zajmujące się na poważnie programowaniem za umiejętność dotarcia z punktu A bo punktu B. Powiedziała to osoba, która zajmuje się tym głównie jako odstresowacz po pracy :)

Jeszcze raz wielki dzięki, pewnie jeszcze kiedyś się tutaj pojawię z kolejnym dziwolągiem :)

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ę...