Ich habe da ein / zwei grundsätzliche Fragen bzgl. Animation von Sprites und hoffe, jemand kennt sich da super aus und hat mir ein paar nützliche Tipps oder einen Denkanstoss.
Ich schildere mal die Ausgangslage:
Ich habe schon einige 2D Spiele gecodet (selten bis zum finalen Produkt aber immerhin...), und sehr oft besteht meine 2D Spielwelt aus Tiles und es bewegen sich Objekte darin, welche 4 Richtungen haben können (UP DOWN LEFT RIGHT). Manchmal sinds auch nur 2, wenn's strikt von der Seite dargestellt werden soll.
Mein Game Loop ist nicht ultradynamisch (möchte ich auch nicht); aber die FPS werden limitiert auf 50, sprich: Ein Frame dauert 20 ms. Ich lasse mir jeweils auf den Screen blitten, wieviel Zeit mein Game noch "übrig" hat für Berechnungen pro Frame, so kann ich eigentlich stabile Spiele programmieren, welche auf vielen Maschinen tadellos und gleich schnell laufen. So weit, so gut.
Nun zu meinem Anliegen:
Mein Game Loop datet up, es sind 20 ms vergangen. Nun werden meine Spielobjekte (Chars etc) upgedated und sie wissen, dass 20 ms vergangen sind im Spiel. Bzgl. Animation habe ich das nun bisher so gemacht, dass sich ein Char beim Instanzieren seine Bilder merkt als dict (self.images). Auch merkt er sich seine Richtung (self.direction). Der Char hat ein Attribut a_counter und a_trigger; zudem ein Attribut i_index. Nun wird jedes Frame a_counter um 20 (ms) erhöht und wenn a_trigger erreicht wird, wird i_index um 1 erhöht. (i_index ist die Indexzahl des aktuellen Bildes in self.images, das angezeigt werden soll). Das images dict habe ich so aufgebaut, dass es in states und directions unterteilt ist:
Code: Alles auswählen
self.images = {RIGHT : {STAND : (img, ),
WALK : (img, img, img),
RUN : (img, img, img, img),
JUMP : (img, img)},
UP : {STAND : (img, ),
WALK : (img, img, img),
RUN : (img, img, img, img),
JUMP : (img, img)},
LEFT : {STAND : (img, ),
WALK : (img, img, img),
RUN : (img, img, img, img),
JUMP : (img, img)},
DOWN : {STAND : (img, ),
WALK : (img, img, img),
RUN : (img, img, img, img),
JUMP : (img, img)}}
Der Char hat ein img property, welches immer sein aktuelles Bild zurückgibt: self.images[self.direction][self.state][self.i_index]
Soweit hat das gut funktioniert eigentlich - der Char konnte seine direction und seinen state updaten und auch animieren, und self.img repräsentiert dabei das gerade aktuelle Bild.
Diese Methode hat aber auch Nachteile irgendwie hab ich mit der Zeit nun festgestellt:
- jede Animation ist gleich schnell, weil sie abhängig ist vom self.a_trigger Attribut.
- Auch muss für jede Animation ein neuer state her für den Char, das ist irgendwie unschön, weil der state eines chars ja nichts mit seiner Animation zu tun haben sollte - glaube ich zumindest
Ich habe mir nun deshalb überlegt eine Animation Klasse zu proggen, welche ich für alle kommenden Projekte nutzen kann. Ich denke da an ein Objekt, welchem man beim instanzieren eine Liste von Images mitgibt sowie einen Animation Speed, einen loop bool etc etc.
Wenn man dieses Objekt updated, ändert sich allenfalls dessen Bild - self.img.
Wenn ich nun einen Char progge, muss ich ihm kein img Zeugs mehr geben; er merkt sich nur seine Animation - eben so ein Objekt. Und dieses wird dann vom char upgedated jedes Frame. So habe ich den Animationsteil von der Char Klasse outgesourced und das Ganze wird wieder etwas hübscher und dynamischer, nicht? Zudem möchte ich noch eine (neue) SpriteSheet Klasse proggen, weil es mit der Zeit mühsam wird, die vielen Bilder als einzelne Dateien zu handeln. Aber das sollte eigentlich klappen. Das Zeugs mit der Animation und den Chars ist eher das, wobei ich froh um Hilfe wäre.
Ich möchte einfach mal die "Fühler strecken" nach Inputs, wie sich dieser Lösungsansatz bzgl. Animation für Euch da draussen anhört und allenfalls wie ihr das macht mit Animation in Spielen; ganz grundsätzlich.
Danke schon mal und Gruss,
Don Polettone