[Pygame] Isometrische Engine

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
deets

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.
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

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.
glocke
User
Beiträge: 66
Registriert: Mittwoch 23. Februar 2011, 21:18

Also sollten alle Kacheln die beim Bewegen vom Bildschirm verschwinden aus der SpriteGroup entfernt und alle Kacheln die dabei erscheinen hinzugefügt werden?
Benutzeravatar
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:
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
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

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

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

Sammel einfach ausgehend von der Kamerposition alle notwendigen Kacheln ein, und mal die. Punkt.
deets

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.
glocke
User
Beiträge: 66
Registriert: Mittwoch 23. Februar 2011, 21:18

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.

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_)
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 ...

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_)
(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
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wenn du die Transformation umkehren willst, musst du lediglich

Code: Alles auswählen

x_ = w/2 + tw/2 * (x-y)
nach x und

Code: Alles auswählen

y_ = th/2 * (1+x+y)
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
Das Leben ist wie ein Tennisball.
glocke
User
Beiträge: 66
Registriert: Mittwoch 23. Februar 2011, 21:18

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

Code: Alles auswählen

from __future__ import division
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
Antworten