Udawanie grafiki izometrycznej w kosmicznej grze 2D

15

Po pierwsze, wiem dokładnie jaki jest mój problem z rysowaniem i mam różne pomysły, jak podejść do jego rozwiązania. Jestem tutaj, aby dowiedzieć się, jak ustawić, która ramka jest rysowana, aby zachować izometryczne „złudzenie”.

Piszę 2D, grę z lotu ptaka, która rozgrywa się w kosmosie. Próbuję używać grafiki izometrycznej w świecie, w którym Up is North, bez obracania się w świecie gry, jak w tradycyjnych grach izometrycznych (pamiętaj, że gra odbywa się w przestrzeni, bez terenu). Oto przykładowy duszek, którego próbuję użyć: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64.png Obrócony 64 razy wokół własnej osi pionowej z kątem widzenia 35 stopni (aka, iso). Obraz został wygenerowany, więc można to zmienić.

Dla jasności podyktowałem, że północ (góra) wynosi 0 stopni, a wschód (prawo) wynosi 90.

Mój problem polega na tym, że mój duszek nie zawsze wygląda tak, jakby był skierowany w stronę, o której myśli, że jest to spowodowane różnicą w używanych samolotach 3D. Nie jestem pewien, czy używam terminologii poprawnie, ale mój statek kosmiczny został obrócony na jednej płaszczyźnie, a płaszczyzna widoku oczekuje, że rzeczy zostaną obrócone na własnej płaszczyźnie. Oto opis problemu:

http://cell.stat-life.com/images/stories/AsteroidOutpost/ProjectionIssue.png Po lewej stronie mam widoki z boku, po prawej mam widoki z góry na dół. Na górze mam widok statku kosmicznego / duszka na świecie. Na dole mam to, co wygląda duszek gdy jest on rysowany na ekranie.

W prawym górnym rogu znajduje się uproszczona wersja tego, w jaki sposób mój statek kosmiczny został obrócony (nawet równe odstępy między poszczególnymi ramkami). W prawym dolnym rogu znajduje się kąt, w którym duszek wygląda tak, jakby był zwrócony, gdy na ekranie zostanie narysowany określony kąt. Problem jest najbardziej widoczny przy około 45 stopniach. Oto obraz, który jest nałożony linią „płaszczyzny ekranu” skierowaną w kierunku, w którym powinien być skierowany statek: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLine.png Czerwona linia powinna zawsze być skierowana dokładnie w tym samym kierunku co statek, ale jak widać problem z projekcją powoduje problem. Mam nadzieję, że wystarczająco dobrze opisuję ten problem.

EDYCJA: Czerwona linia jest obracana na płaszczyźnie ekranu, podczas gdy statek kosmiczny jest obracany na „płaszczyźnie statku”, stąd duża różnica między kątem statku a kątem ekranu podczas rysowania. EDYCJA KOŃCOWA

Wygląda to dość dziwnie, gdy ten statek strzela wiązką lasera w cel, który znajduje się z boku, gdy powinien strzelać prosto.

Więc ... rozwiązania, które wymyśliłem to:

  1. Przestań próbować sfałszować widok izometryczny, idź na całość lub idź do domu. Obróć już mój świat. (PS: to rozwiąże mój problem, prawda?)
  2. Zmień mój arkusz sprite (jakoś), aby mieć ramki reprezentujące „kąt ekranu”, na którym będzie oglądany model. Kiedy więc poproszę o obraz 45 stopni, na ekranie będzie wyglądać tak, jakby był skierowany pod kątem 45 stopni.
  3. Zmień mój system renderowania duszka, aby złapać inną ramkę niż arkusz duszka (jakoś), wiedząc, że chwytanie „normalnej” ramki będzie wyglądało śmiesznie. Zamiast chwycić ramkę 45 stopni, uchwyci ramkę ... 33 stopnie (tylko zgaduję), aby wyglądała poprawnie dla użytkownika.
  4. Po prostu użyj 3D! To o wiele łatwiejsze człowieku

Po pierwsze: jakie rozwiązanie poleciłbyś? Pochylam się do 2, chociaż wiem, że to źle. Pamiętaj, że mam pełny dostęp do narzędzia do generowania ikonek. Metoda 3 byłaby moim drugim wyborem. Obie metody wymagają po prostu zastosowania matematyki do kąta (kątów), aby uzyskać pożądany rezultat. Przy okazji dodałem tam # 4 jako żart, nie chcę przejść do 3D.

Dwa: w jaki sposób wyregulować kąty wejściowe lub wyjściowe? Nie jestem aż tak dobry w projekcjach 3D i matrycach 3D (nie mówiąc już o matrycach 2D) i jakiejkolwiek innej matematyce, która mogłaby zostać wykorzystana do osiągnięcia pożądanego rezultatu.

Myślenie tutaj głośno: jeśli wezmę wektor jednostkowy skierowany w kierunku, w którym chcę, aby statek patrzył (na płaszczyźnie ekranu), to rzutuj go na płaszczyznę statku, a następnie ustal, jaki jest kąt między tą rzutowaną linią a płaszczyzną samolotu na północ powinienem mieć kąt grafiki statku, który chcę wyświetlić. Dobrze? (rozwiązanie dla # 3?) Człowieku ... Nie mogę tego wypracować.

EDYTOWAĆ:

Wiem, że problem jest trudny do zwizualizowania z obrazami statycznymi, więc wykonałem test wizualny biblioteki Sprite Library, aby wyświetlić problem: http://cell.stat-life.com/downloads/SpriteLibVisualTest.zip Wymaga XNA 4.0 Ta aplikacja jest po prostu obracając duszka i rysując linię od jej środkowego punktu na zewnątrz pod kątem, który gra myśli, że statek powinien być skierowany.

EDYCJA 8 września

Kontynuując mój akapit „głośno myśląc”: Zamiast używać projekcji (ponieważ wygląda na trudną) Myślę, że mógłbym wziąć wektor jednostek północy (0x, 1y, 0z), użyć matrycy, aby obrócić go o kąt duszek jest rzeczywiście skierowany w stronę, a następnie obróć go ponownie z „płaszczyzny widzenia” na zewnątrz do „płaszczyzny duszka” wokół osi X, a następnie ... spłaszczyć? wektor (w zasadzie rzutuj go) z powrotem na płaszczyznę obserwacji, używając tylko X i Y (ignorując Z). Następnie za pomocą tego nowego spłaszczonego wektora mogłem określić jego kąt i użyć go do ... czegoś. Pomyślę później.

EDYCJA 8 września (2)

Próbowałem z góry podążać za moim pomysłem, tak! Więc ... aby czerwona linia wyglądała, jakby wychodziła prosto z mojego statku kosmicznego (tylko w celach testowych), zrobiłem następujące:

Vector3 vect = new Vector3(0, 1, 0);
vect = Vector3.Transform(vect, Matrix.CreateRotationZ(rotation));
vect = Vector3.Transform(vect, Matrix.CreateRotationY((float)((Math.PI / 2) - MathHelper.ToRadians(AngleFromHorizon))));
Vector2 flattenedVect = new Vector2(vect.X, vect.Y);

float adjustedRotation = (float)(getAngle(flattenedVect.X, flattenedVect.Y));

Gdzie rotationjest kąt ekranu, a adjustedRotationteraz ten kąt ekranu wygląda na płaszczyźnie duszka. Nie wiem, dlaczego musiałem obracać Y zamiast X, ale prawdopodobnie ma to coś wspólnego z 3D, o czym nie wiem.

Więc teraz mam dodatkową informację, ale jak mam to wykorzystać, aby wybrać bardziej odpowiednią ramkę? Może zamiast obracać się z płaszczyzny widoku do płaszczyzny duszka, a następnie wyświetlać wstecz, powinienem spróbować zrobić to na odwrót. Oto mój duszek z dopasowaną czerwoną linią, ale tak naprawdę chcę zrobić model, a nie linię: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLineCorrected.png

EDYCJA 9 września

DZIŚ! Jest naprawione! Opiszę, co zrobiłem, aby to naprawić:

Postępowałem zgodnie z radą eBiznesu i „zgniatałem” światowy układ współrzędnych (lub naciągnąłem…?). Jest to zasadniczo rozwiązanie nr 1, chociaż miałem wrażenie, że musiałbym obrócić mój światowy układ współrzędnych w stosunku do układu współrzędnych ekranu. Nie prawda! W górę jest nadal + y, a w prawo nadal + x. Zmodyfikowałem moje metody WorldToScreen i ScreenToWorld, aby poprawnie konwertować świat i współrzędne ekranu. Te metody mogą nie być optymalne, ale oto jedyne dwie metody w mojej bazie kodu, które musiały się zmienić.

public Vector2 ScreenToWorld(float x, float y)
{
    float deltaX = x - (size.Width / 2f);
    float deltaY = y - (size.Height / 2f);

    deltaX = deltaX * scaleFactor / (float)Math.Sqrt(3);
    deltaY = deltaY * scaleFactor;

    return new Vector2(focusWorldPoint.X + deltaX, focusWorldPoint.Y + deltaY);
}

public Vector2 WorldToScreen(float x, float y)
{
    float deltaX = x - focusWorldPoint.X;
    float deltaY = y - focusWorldPoint.Y;

    deltaX = deltaX / scaleFactor * (float)Math.Sqrt(3);
    deltaY = deltaY / scaleFactor;

    return new Vector2(size.Width / 2f + deltaX, size.Height / 2f + deltaY);
}

To było to! Zmiana tych dwóch metod wpłynęła na wszystko inne: na co patrzyłem, gdzie rysowano obiekty, gdzie klikałem, wszystko. Mój statek kosmiczny patrzy teraz bezpośrednio na cel, który strzela, i wszystko układa się na swoim miejscu. Będę eksperymentować z rzutem ortograficznym, zobaczę, czy dzięki temu wszystko wydaje się bardziej „realne”.

John McDonald
źródło
Gratulacje. Nie zapomnij mnie szturchnąć, gdy będziesz mieć coś do gry, chciałbym zobaczyć, dokąd to zmierza.
aaaaaaaaaaaa
@eBusiness Zgodnie z obietnicą: cell.stat-life.com/images/stories/AsteroidOutpost/… i cell.stat-life.com/images/stories/AsteroidOutpost/AOOhNoes.png Zauważ, jak wygląda statek , patrząc na tę wieżę? : D Dzięki!
John McDonald
@eBusiness, film youtube.com/watch?v=Q8pR9KDBsCo Istnieje również link do pobrania, ponieważ zapytałeś.
John McDonald

Odpowiedzi:

4

Po wybraniu perspektywy izometrycznej należy poprawić skalę między osią X i Y. Jeśli dana odległość rzutuje na 1 na ekranach w osi Y, wówczas ta sama odległość będzie rzutowana do sqrt (3) na ekranach w osi X. Więc jeśli narysujesz rzeczy płasko na ekranie, zrobiłbyś coś takiego:

draw(object.image, object.x*sqrt(3), object.y)

Uwagi bez odpowiedzi:

  • Dlaczego miałbyś zadzierać z arkuszami sprite i tym podobne? Jeśli chcesz, możesz uzyskać renderowanie 3D do izometrycznego.
  • Skoro używasz arkuszy sprite, dlaczego nie są one antyaliasingowane?
  • Izometryczny w przestrzeni, nie sądzę, żebym kiedykolwiek widział tę grę, nie jestem pewien, jak dobrze będzie działać, biorąc pod uwagę brak wyraźnie izometrycznej podstawy do odniesienia wizualnego.
aaaaaaaaaaaa
źródło
1
Myślę, że to może naprawić wszystko. To łatwa naprawa i mogę zostawić kartkę w spokoju. Spróbuję to jak najszybciej i dam znać, jak to działa. Aby odpowiedzieć na twoje uwagi: 1) Korzystam z 2D, ponieważ to, co znam i generuję swoje arkusze z modeli 3D. 2) Krawędzie powinny być ostre, ale wewnątrz twardych krawędzi mógłbym użyć kanału alfa do anty-aliasu, który nadejdzie. 3) Nie planuję symulować trzeciego wymiaru (dużo), chcę głównie grafiki 2D, które nie są z góry na dół i pozwalają zobaczyć boki rzeczy.
John McDonald,
5

Jak powstaje obrócony duszek? Czy to zrzuty ekranu z obracającego się modelu 3D? Kąt patrzenia może być wyłączony ze względu na perspektywę kamery narzędzia do modelowania 3D. Perspektywa izometryczna nie jest dokładnym odwzorowaniem przestrzeni 3D. Rzeczy daleko od „aparatu” nie stają się mniejsze.

Jeśli chcesz tylko szybką naprawę. Rozwiązanie 2 może być trudne do znalezienia. Rozwiązanie 3 wydaje się łatwe, wystarczy zamienić ramki niepasujące do kąta na taki, który lepiej pasuje do kąta.

Czasami lasery nadal będą wyłączone. Ponieważ nie wykonujesz płynnego obrotu, ale pokazujesz różne klatki dla określonych zakresów stopni.

EDYTOWAĆ:

Problem polega na tym, że generowane zrzuty ekranu nie są perspektywą izometryczną, ale normalnym widokiem kamery 3D.

wprowadź opis zdjęcia tutaj

Widok izometryczny symuluje przestrzeń 3D, ale nie jest dokładną reprezentacją. Rzeczy stają się coraz mniejsze wraz ze wzrostem odległości od aparatu. Nie dotyczy to perspektywy izometrycznej, ponieważ spowodowałoby to brzydkie skalowanie artefaktów w ikonce.

Zrzuty ekranu statku kosmicznego są tworzone z perspektywy kamery 3D. Właśnie dlatego strzelanie laserowe jest wyłączone. Porównaj czerwoną linię w „izometryczny” i „perspektywiczny”.

Twój generator sprite powinien używać Matrix.CreateOrthographic () zamiast Matrix.CreatePerspective () dla matrycy projekcji.

Stephen
źródło
Duszek jest generowany za pomocą narzędzia 3D na 2D, które opracowuję, więc problem może być bardzo dobry w tym narzędziu. Narzędzie po prostu ładuje model 3D, a następnie, aby osiągnąć Spaceship64.png (powyżej), obraca model o (360/64) = 5,625 stopni, zapisuje go jako ramkę, a następnie obraca go ponownie o tę samą wartość, aż będzie miał wszystko 64 klatki. Kod użyty do renderowania modelu znajduje się tutaj: code.google.com/p/sprite-maker/source/browse/trunk/XNAWindow/… Obracanie odbywa się w innej klasie. Myślałem również, że rozwiązanie 2 i 3 były odwrotne względem siebie, prawda?
John McDonald,
Edytowałem moją odpowiedź. Patrz wyżej.
Stephen
Myślę, że mógłbym zrobić jedno i drugie: sprawić, by mój generator spriteów używał rzutu ortograficznego ORAZ zmienił mój światowy układ współrzędnych, tak jak mówi @eBusiness. Próbowałem wczoraj projekcji ortograficznej i na pewno zmieniło to wygląd mojego statku, ale samo to nie rozwiązało problemu kąta, którego doświadczam.
John McDonald,
Właśnie zobaczyłem twoją edycję. Skorygowany duszek wygląda tak, jakby środek statku znajdował się poza środkiem czerwonej linii. Może wystarczy narysować statek o jeden lub dwa piksele wyżej niż punkt początkowy czerwonej linii. Czy widoczny błąd zmienia się podczas oddalania się statku od świata? Następnie skalowanie osi X może to naprawić.
Stephen
1

Myślę, że masz tutaj po prostu wygląd izometryczny. Masz rację, mówiąc wizualnie, wydaje się, że istnieje większa różnica między 0deg a 10deg niż między 90deg a 100deg. . . ale to dlatego, że izometrycznie wewnętrznie ściska jedną oś. Jeśli nie chcesz tego wyglądu, nie chcesz izometryczny.

To powiedziawszy, myślę, że problemy wizualne, które masz, wynikają z braku wizualnego punktu odniesienia. Twój mózg zakłada, że ​​patrzysz na niego z góry na dół - hej, to przestrzeń, dlaczego byś nie był - i podobnie interpretuje to jako standardowy widok z góry na dół. Dla celów testowych spróbuj dodać kilka pływających holograficznych punktów odniesienia. Na przykład siatka ukośna pod kątem 45 stopni lub zestaw kół zasięgu wokół statku kosmicznego. Upewnij się, że są odpowiednio zniekształcone, jakby znajdowały się na tej samej płaszczyźnie izometrycznej, na której renderowany jest statek kosmiczny. Założę się, że twój mózg obliczy perspektywę i nagle będzie wyglądał dobrze.

Teraz zastanawiam się, jak przekazać to użytkownikom. . . to zupełnie inna sprawa.

ZorbaTHut
źródło
Czy nie muszę też obracać osi świata, aby ukończyć iluzję za pomocą tej metody (metoda nr 1 w pytaniu)?
John McDonald,
O ile wiem, statek jest już renderowany poprawnie - widoki z boku pokazują go pod kątem, pod jakim powinien być izometryczny, aby wyglądał „poprawnie”. Przypuszczam, że nie jestem pewien, co rozumiesz przez „obrót osi świata”.
ZorbaTHut,
Pod pojęciem „obróć oś świata” mam na myśli obrót świata względem kamery o 45 stopni, aby „północ” była skierowana w prawy górny róg lub lewy górny róg ekranu po przekątnej, zamiast „północ” była prosto w górę w kierunku górnej części ekranu.
John McDonald,
To może pomóc, ale w kosmosie i tak nie powinno mieć tak wielkiego znaczenia. Chyba że masz siatkę nałożoną na świat, to po prostu nie powinno mieć znaczenia.
ZorbaTHut,