[Pygame] Isometrische Engine
Das mit den nicht-sichtbaren Kacheln solltest du tunlichst sein lassen. Dafuer ja mein Tipp mit BSPs/Quadtrees. Und du solltest dir die Arbeit mit dem Profiler angewoehnen - nur so erfaehrst du wirklich, was passiert.
Stichwort diesbezüglich wäre Culling, d.h. das Prüfen ob etwas gezeichnet werden muss anhand vereinfachter Bedingungen. Es ist eine verhältnismäßig schlichte Optimierung mit viel Performancegewinn im Gegensatz zu den Sachen, die man als Neuling sonst geneigt ist ohne jegliche Tests zu tun um das Programm auf Trab zu bringen.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Wo ich da grad etwas von `SpriteGroup` gelesen habe... arbeitest Du ausschließlich mit Sprites? Ich habe das für die Tiles einer Engine noch nie gesehen - aber vielleicht ist das ja auch eine gute Idee.
Zumindest was das Hinzufügen zu / Wegnehmen von einer Gruppe anbelangt, kann Dich die Doku beruhigen:
Zumindest was das Hinzufügen zu / Wegnehmen von einer Gruppe anbelangt, kann Dich die Doku beruhigen:
The groups are designed for high efficiency in removing and adding Sprites to them.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Eigentlich sollte Culling ja im Renderer implementiert werden statt mit den Objekten zu hantieren. Wie gesagt wird vor dem Zeichnen geprüft ob das aktuell drankommende Objekt sichtbar wäre, wenn ja wirds gezeichnet, wenn nein, dann nicht. Profilen solltest du dennoch.
Wozu brauchst du diese Group ueberhaupt? Ich wuerde die loswerden. Alleine schon, weil sie keine Ordnung beim zeichnen einhaelt - womit dir bei Kacheln die eine Hoehe haben das ganze Ding um die Ohren fliegt - du musst ja von hinten nach vorne rendern.glocke hat geschrieben:Also sollten alle Kacheln die beim Bewegen vom Bildschirm verschwinden aus der SpriteGroup entfernt und alle Kacheln die dabei erscheinen hinzugefügt werden?
Sammel einfach ausgehend von der Kamerposition alle notwendigen Kacheln ein, und mal die. Punkt.
Und noch ein Hinweis: habe mir gerade mal das hier angeschaut:
https://github.com/christiangloeckner/P ... /isomap.py
Und da hast du natuerlich einen gigantischen konzeptionellen Fehler drin. Um deine Bildschirmtransformation zu machen, veraenderst du die Koordinaten der Tiles!! Das ist natuerlich dramatisch, denn dadurch erzeugst du Komplexitaet proportional zur Groesse deines Levels! Das ist quadratisch, und damit algorithmisch unguenstig - und unnoetig!
Die Koordinaten haben natuerlich fest zu bleiben. Stattdessen waehlst du ausgehend von der Kameraposition alle sichtbaren Tiles - damit wird das Problem in der Groesse reduziert auf die Anzahl der *darstellbaren* Tiles. Und die blittest du dann an ihre entsprechende Position.
https://github.com/christiangloeckner/P ... /isomap.py
Und da hast du natuerlich einen gigantischen konzeptionellen Fehler drin. Um deine Bildschirmtransformation zu machen, veraenderst du die Koordinaten der Tiles!! Das ist natuerlich dramatisch, denn dadurch erzeugst du Komplexitaet proportional zur Groesse deines Levels! Das ist quadratisch, und damit algorithmisch unguenstig - und unnoetig!
Die Koordinaten haben natuerlich fest zu bleiben. Stattdessen waehlst du ausgehend von der Kameraposition alle sichtbaren Tiles - damit wird das Problem in der Groesse reduziert auf die Anzahl der *darstellbaren* Tiles. Und die blittest du dann an ihre entsprechende Position.
Hi, an der ganzen Sache bastel ich schon ne Weile ... hab gemerkt dass es absolut mistig ist, und bin gerade dabei das Modul neu zu schreiben. Allerdings habe ich bei der Umrechnung der Koordinaten einige Probleme.
Die Methode klappt einwandfrei. Ich habe mir eine kleine Karte skizziert (0,0 dabei oben in der mitte) und eine Formel hergeleitete wie ich die Tile-Positionen auf dem Bildschirm berechne. Nur scheitere ich daran den Rückschluss von ScreenPosition auf MapPosition hinzubekommen. *rumgoogle* Das Umstellen der Formel ...
(mit wxMaxima, hoffentlich habe ich keine Tippfehler) ... wirkt bisschen derb und bringt auch falsche Ergebnisse. Beide Funktionen arbeiten nun unabhängig von der Kameraperspektive.
Bei map2screen ziehe ich danach noch die Kameraposition ab.
LG
Code: Alles auswählen
def map2screen(self, (x, y)):
"""Convert map coordinate to screen coordinate"""
tw = self.tilesize
th = tw / 2
w = self.mapsize.x * tw
# convert
x_ = w/2 + tw/2 * (x-y)
y_ = th/2 * (1+x+y)
return (x_, y_)
Code: Alles auswählen
def screen2map(self, (x, y)):
"""Convert screen coordinate to map coordinate"""
tw = self.tilesize
th = tw / 2
w = self.mapsize.x * tw
# convert
x_ = (tw * 2 * y - tw * th + 2 * th * x - th * w) / (2 * th * tw)
y_ = (tw * th - 2 * y * th + 2 * th * x - th * w) / (2 * th * tw)
return (x_, y_)
Bei map2screen ziehe ich danach noch die Kameraposition ab.
LG
Wenn du die Transformation umkehren willst, musst du lediglich
nach x und
nach y auflösen und entsprechend einsetzen. Ich sehe gar nicht, was man da groß mit Google versuchen möchte, das lässt sich doch schon im Kopf lösen. Zur Not tun es auch drei Zeilen auf Papier.
Da du offensichtlich Python 2.x verwendest, solltest du auch mit den Divisionen vorsichtig sein. ``x/2`` ist eine ganzzahlige Division, wenn x ein Integer ist. Das könnte bei dir das eine oder andere Problemchen verursachen.
Sebastian
Code: Alles auswählen
x_ = w/2 + tw/2 * (x-y)
Code: Alles auswählen
y_ = th/2 * (1+x+y)
Da du offensichtlich Python 2.x verwendest, solltest du auch mit den Divisionen vorsichtig sein. ``x/2`` ist eine ganzzahlige Division, wenn x ein Integer ist. Das könnte bei dir das eine oder andere Problemchen verursachen.
Sebastian
Das Leben ist wie ein Tennisball.
Umgestellt habe ich es (wie geschrieben mit wxMaxima, ich mach beim Umstellen sonst zu viele kleine Schusselfehler). Ich mag nur gerade nicht akzeptieren dass es damit gewesen sein soll O_o xD
Wegen der Divisions-Sache hast du Recht, hab die 2 im Divisor durch 2.0 ersetzt um explizit nen Float zu erzwingen. Damit müsste die Division imho im Float ausgeführt werden.
Wäre es ratsam zu verwenden? Ich würde ja Python 3 verwenden aber darauf möchte ich wegen http://www.pygame.org/wiki/FrequentlyAs ... ython%203? verzichten.
Den aktuellen Code hab ich mal hochgesynct damit alle das gleiche als Basis haben.
/EDIT: hatte 3 Tippfehler, die erklärten auch die Abweichungen xD Kamera auf ein Tile zentriert setzen (via Konstruktor) funktioniert auch. Dann kümmere ich mich jetzt wieder um das Selektieren der sichtbaren und unsichtbaren Kacheln.
/EDIT2: Erledigt (erstmal). Aber wahrscheinlich wäre es sinnvoller beim Bewegen der Kamera alle sichtbaren Tiles zu erfassen (und in einer Liste entsprechend der Renderreihenfolge einzuordnen) anstatt das beim Rendern jedes mal zu tun.... änder ich später.
/EDIT3: Hab den Repo-Namen gekürzt https://github.com/christiangloeckner/pare
Wegen der Divisions-Sache hast du Recht, hab die 2 im Divisor durch 2.0 ersetzt um explizit nen Float zu erzwingen. Damit müsste die Division imho im Float ausgeführt werden.
Wäre es ratsam
Code: Alles auswählen
from __future__ import division
Den aktuellen Code hab ich mal hochgesynct damit alle das gleiche als Basis haben.
/EDIT: hatte 3 Tippfehler, die erklärten auch die Abweichungen xD Kamera auf ein Tile zentriert setzen (via Konstruktor) funktioniert auch. Dann kümmere ich mich jetzt wieder um das Selektieren der sichtbaren und unsichtbaren Kacheln.
/EDIT2: Erledigt (erstmal). Aber wahrscheinlich wäre es sinnvoller beim Bewegen der Kamera alle sichtbaren Tiles zu erfassen (und in einer Liste entsprechend der Renderreihenfolge einzuordnen) anstatt das beim Rendern jedes mal zu tun.... änder ich später.
/EDIT3: Hab den Repo-Namen gekürzt https://github.com/christiangloeckner/pare