2012-04-03 12 views
14

Zanim o to zapytałem, zrobiłem DUŻO wyszukiwania w sieci. Po prostu nie mogę tego zrobić. Trochę trudno mi to zrozumieć. Jak więc rysować obrazy na odpowiednich pozycjach ekranu odpowiadających ciałom na pozycji światowej? Thanx.Slick2D i JBox2D. Jak narysować

Jeśli ktokolwiek inny znajdzie go przed tą samą przeszkodą, zamieściłem W JAKI SPOSÓB, na dobre wyjaśnienie normalności. Można go znaleźć tutaj: http://romeo.akademx.ro/2012/04/06/slick-and-box2d/

Jest to funkcja render:

public void render(GameContainer container, StateBasedGame game, Graphics g) 
     throws SlickException { 
    g.setBackground(Color.white); 

    g.pushTransform(); 
    g.translate(worldToScreen(body.getPosition()).x, worldToScreen(body.getPosition()).y); 
    g.rotate(15, 15, (float) Math.toDegrees(body.getAngle())); 
    part.draw(); 
    g.popTransform(); 

    g.drawString("Count: " + cont, 5, 40); 
    //world.drawDebugData(); 
} 

A to funkcja używam przekształcić uzgodnien świat ekranowym

public Vec2 screenToWorld(Vec2 screenV) { 
    return new Vec2((screenV.x - offset.x)/scaleFactor, yFlip 
      * (screenV.y - offset.y)/scaleFactor); 
} 

public Vec2 worldToScreen(Vec2 worldV) { 
    return new Vec2(worldV.x * scaleFactor + offset.x, yFlip * worldV.y 
      * scaleFactor + offset.y); 
} 

ja też zdarzyć używać SlickDebugDraw znaleziony pod tym linkiem: http://slick.javaunlimited.net/viewtopic.php?f=19&t=3610&sid=69614ac53aaf5724b808b75173e8e48e

Ale jego DebugDraw rysuje zupełnie inną rzecz niż funkcję renderowania. Jestem nieco zdezorientowany.

+0

Czy możesz przesłać nam kod, z którym masz problemy? To pomogłoby nam odpowiedzieć na twoje pytanie. –

+0

Chodź, nikt nie wie? Tak bardzo tego potrzebuję, że mogę kontynuować pracę nad moim projektem. – Romeo

Odpowiedz

64

Jeśli wszystko, co robisz, to rysowanie sprite'ów w świecie 2D, to są dwie rzeczy, których potrzebujesz, aby zdecydować, które duchy narysować na ekranie i gdzie na ekranie je narysować. Musisz myśleć, że twoje duchy istnieją w określonym miejscu na świecie, a to, co widzisz na ekranie, to tylko jeden widok świata, koncentrujący się na danym obszarze.

Dwie rzeczy, które trzeba śledzić to:

  1. Każdy sprite musi mieć swoje położenie w świecie
  2. Twój „kamera” musi śledzić jego położenie w stosunku do świata.

Załóżmy, że masz duży, duży świat o współrzędnych 2D (x, y) o wymiarach 1 000 000 x 1 000 000 pikseli (używam tutaj pikseli jako jednostki miary, ale to arbitralne wybór, a rozmiar świata nie ma znaczenia, właśnie wybrałem duży). Następnie powiedzmy, że masz "kamerę" wskazaną na ten świat, a widok tej kamery jest wyświetlany na ekranie. Wyświetlany przez aparat rozmiar ma 1024 x 768 pikseli.

Załóżmy również, że używasz klawiszy strzałek, aby przenieść kamerę na cały świat.

Więc twój świat współrzędnych mapy przestrzeń na ekranie, takie jak:

(0, 0)  +x 
     +------------------> 
     | 
    +y | 
     |  * <= example sprite in your world @ coordinates (x=200, y=200) 
     | 
    \/

Gdy skrzaty przenieść „prawo” zwiększają ich x współrzędnych. Kiedy poruszają się "w lewo", zmniejszają swoją współrzędną x. Podczas przesuwania "w górę" zmniejszają one swoją współrzędną (ponieważ ich współrzędne zmniejszają się (ponieważ na monitorach rośnie), a podczas przesuwania "w dół" współrzędne zwiększają się o ich współrzędne.

To, co widzisz na naszym ekranie, jest po prostu widokiem aparatu na świat. Ustawmy więc, że górny lewy róg aparatu to (x=500, y=500).Że będzie wyglądać następująco:

(0, 0)  +x 
     +----------------------------------> 
     | 
    +y | 
     |  * <= example sprite in your world @ coordinates (x=200, y=200) 
     | 
     | 
     |   +===================+ 
     |   |  the area  | 
     |   | that the camera | 
     |   | "sees" and  | 
     |   | shows on your | 
     |   |  screen  | 
     |   +===================+ 
    \/

Dzięki tej konfiguracji, powiedzmy, że aparat znajduje się w (500, 500) (to znaczy, że lewy górny róg widoku kamery, jak pokazano w tym przykładzie, jest na światowym współrzędnych (500, 500). A ponieważ kamera pokazuje obszar o rozmiarze 1024x768, wówczas przeciwległy, dolny prawy róg to (500 + 1024, 500 + 768) = (x=1524, y=1268).

Notatka że ikonka w naszym świecie jest wewnątrz obszaru widoku kamery, co oznacza, że ​​gdy wyrenderujemy widok kamery na ekranie, nie zobaczymy sprite'a:

Jeśli zamiast tego aparat przesunie się do (200, 200), obszar widoku kamery będzie obejmował współrzędne światowe od górnej lewej @ (200, 200) do dolnego prawego @ (1224, 968), oraz wyglądać mniej więcej tak:

(0, 0)  +x 
     +----------------------------------> 
     | 
    +y | +===================+ 
     | |     | 
     | | * <= sprite  | 
     | |     | 
     | |     | <= camera's view of the world 
     | +===================+ 
     | 
     | 
     | 
     | 
    \/

Gdy aparat jest w tej pozycji, ikonka jest widoczna. Jeśli ikonka to @ (500, 500), a kamera jest w (200, 200), to kiedy narysujemy ikonkę na ekranie, pojawi się ikonka, na naszym ekranie o współrzędnych 300, 300.

Dlaczego?

powodu, a to jest naprawdę odpowiedź na swoje pytanie, gdzie narysować rzeczy na ekranie jest Sprite lokalizacja świat (500, 500), minus lokalizacja (200, 200) aparatu, co równa się (300, 300).

Więc recenzję:

przenieść pozycję kamery na całym świecie za pomocą klawiszy strzałek (lub myszy, czy cokolwiek innego systemu sterowania chcesz), a renderowanie skrzaty położenie względem kamery pozycję, odejmując pozycję ikonki i odejmując pozycję kamery od , a otrzymasz współrzędne ekranu , gdzie powinien się pojawić ikonka.

Ale jest jeszcze jedna rzecz ...

To naprawdę nieefektywne wyciągnąć każdy sprite w świecie. Trzeba tylko narysować sprite'y, które są w widoku kamery, w przeciwnym razie rysujesz rzeczy, których nie zobaczysz na ekranie, a zatem marnujesz czas renderowania/CPU/GPU.

Tak więc, gdy renderujesz widok z kamery, musisz powtórzyć proces przez swoje duszki, sprawdzając, czy są "w aparacie" (to znaczy, czy są w widoku kamery) i tylko rysując je, jeśli są w tym widoku.

Aby to zrobić, trzeba podjąć wymiary z aparatem (1024x768, w naszym przykładzie), i sprawdzić, czy pozycja ikonki jest wewnątrz prostokąta widzenia kamery - co jest pozycja górnego lewego rogu kamery oraz szerokość i wysokość kamery.

Tak więc, jeśli nasza kamera pokazuje nam, że znajduje 1024x768 pikseli w rozmiarze, i to w lewym górnym rogu znajduje się (200, 200), a następnie widok prostokąt jest:

(200, 200)      (1224, 200) 
      +===================+ 
      |     | 
      | *    | 
      |     | 
      |     | 
      +===================+ 
(200, 968)      (1224, 968) 

pozycja ikonki na @ (500, 500) jest w tym przypadku w zasięgu kamery.

Jeśli potrzebujesz więcej przykładów, mam działającą demonstrację techniczną Slick2D o nazwie Pedestrians, która ma kod, który możesz obejrzeć. Aby uzyskać szczegółowe informacje na temat obliczania obszaru świata, który ma być renderowany, spójrz na metodę render wewnątrz this file i zwróć szczególną uwagę na zmienne startX, startY, stopX, stopY, które dla mnie kontrolują obszar ikonek, które mam zamierzam narysować. Należy również zauważyć, że moje duszki (lub "piesi") istnieją na TileMap, więc nie są one wielkością 1 piksela - mają swoją szerokość i wysokość. Dodaje to trochę złożoności do sposobu decydowania o tym, co należy narysować, ale w zasadzie sprowadza się do "narysowania tego, co jest w widoku kamery, plus trochę więcej wokół krawędzi".

Sklonuj repozytorium Pedeestrians na swoim komputerze, uruchom je, dodając takie same zależności do projektu, jak każdy inny projekt Slick2D, i odtwarzaj/modyfikuj kod renderujący, dopóki nie zrozumiesz, co się dzieje. Tylko dzięki praktyce i studiowaniu uzyskasz wszystkie informacje na temat tego, jak to działa. Dobrą wiadomością jest to, że po ustaleniu sposobu renderowania za pomocą tej podstawowej metody 2D w porównaniu do metody kamery, będziesz wiedział, jak renderować grafikę dla wszystkich aplikacji 2D, ponieważ pojęcia tłumaczą się na wszystkie języki.

Mam też różne filmy o Piesiach prowadzonych na my YouTube channel (najważniejszym filmem jest prawdopodobnie this one, który pokazuje, że moi zwykli przechodnie są renderowani, a kamera porusza się), dzięki czemu można zobaczyć, jak to wszystko wygląda bez konieczności najpierw zbudować projekt.

+8

Jedna z najlepszych i bardziej szczegółowych odpowiedzi, które przeczytałem na SO. Wspaniały post. –

+1

Stajesz się moim idolem. Tak bardzo cię kocham. Rozumiem to wszystko. Dziękuję bardzo. Od teraz jestem twoim największym fanem. Jeszcze raz! – Romeo

+0

Nie ma za co. FYI, jest też http://gamedev.stackexchange.com/ - która jest inną witryną StackExchange, ale poświęcona jest tworzeniu gier. Chociaż patrzę na tag 'slick2d' na tej stronie, ponieważ zadajesz więcej pytań związanych z grą, związanych z deweloperem, podczas pracy nad projektem strona gamedev może okazać się dobrym miejscem, aby spróbować uzyskać odpowiedź. – jefflunt