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:
- 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?)
- 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.
- 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.
- 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 rotation
jest kąt ekranu, a adjustedRotation
teraz 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”.