Animationen in 2D-Spielen
-
Hallo zusammen,
ich schreibe gerade ein 2D-Spiel mit Hilfe von SDL und
bräuchte mal einen Tipp in Sachen Animationen.Hätte da ein paar Fragen:
-
Sollte ich für die Zeichnung des jeweils aktuellen Bildschirms eine eigene Funktion
schreiben, die aus dem Rest des Programmes Infos sammelt, was gerade gezeichnet werden muss
und dies dann durchführt?
Oder gebe ich jeder eigenen Klasse (Hauptfigur, Monster, etc) eine eigene Funktion zum
Zeichnen der jeweiligen Figur auf den Hauptscreen? -
Wie kann ich es schaffen, dass zwei Figuren gleichzeitig eine Animation durchführen?
Beispiel: User drückt nach rechts => Animation der Bewegung der Hauptfigur wird durchgeführt
Allerdings bewegt sich ja auch der Gegner zurselben Zeit und seine Animation müsste ja
gleichzeitig gezeichnet werden? Da blicke ich bisher noch gar nicht durch...
Es könnte ja auch sein, dass zB die Animation des Users 7 Bilder sind, innerhalb einer Sekunde
und für die Gegner-Bewegung 3 in der gleichen Zeit
Kann mir da jemand weiterhelfen?
-
-
- Sollte ich für die Zeichnung des jeweils aktuellen Bildschirms eine eigene Funktion
schreiben, die aus dem Rest des Programmes Infos sammelt, was gerade gezeichnet werden muss
und dies dann durchführt?
Oder gebe ich jeder eigenen Klasse (Hauptfigur, Monster, etc) eine eigene Funktion zum
Zeichnen der jeweiligen Figur auf den Hauptscreen?
Ich würde sagen du solltest eine eigene Klasse schreiben die das ganze für dich behandelt. Also nicht jede einzelne Sprite/Hintergrund/USW. Klasse sollte eine Funktion haben, sondern eine große.
Zu deiner 2ten Frage hab ich leider keine Antwort.
hoffe dir kann da jemand helfen.gruß michi
- Sollte ich für die Zeichnung des jeweils aktuellen Bildschirms eine eigene Funktion
-
Barcellona schrieb:
- Sollte ich für die Zeichnung des jeweils aktuellen Bildschirms eine eigene Funktion
schreiben, die aus dem Rest des Programmes Infos sammelt, was gerade gezeichnet werden muss
und dies dann durchführt?
Oder gebe ich jeder eigenen Klasse (Hauptfigur, Monster, etc) eine eigene Funktion zum
Zeichnen der jeweiligen Figur auf den Hauptscreen?
Nein, ein Monster muss nicht wissen, wie es gezeichnet wird. Das ist Aufgabe einer anderen Klasse, an deren Memberfunktionen das Monster übergeben wird.
Barcellona schrieb:
- Wie kann ich es schaffen, dass zwei Figuren gleichzeitig eine Animation durchführen?
Beispiel: User drückt nach rechts => Animation der Bewegung der Hauptfigur wird durchgeführt
Allerdings bewegt sich ja auch der Gegner zurselben Zeit und seine Animation müsste ja
gleichzeitig gezeichnet werden? Da blicke ich bisher noch gar nicht durch...
Es könnte ja auch sein, dass zB die Animation des Users 7 Bilder sind, innerhalb einer Sekunde
und für die Gegner-Bewegung 3 in der gleichen Zeit
Kommt drauf an, wie du deine Spielschleife gestaltest. Hast du zum Beispiel eine feste Framerate, ist das Unterfangen recht einfach: Du speicherst in jeder Figur einen Integer für die Animation. Dann erhöhst du den in jedem Hauptschleifendurchgang und zum Beispiel nach 10 Erhöhungen kommt das nächste Animationsbild. Wenn du den Integer durch 10 dividierst, hast du also gerade die Nummer des Bilds, das gezeichnet wird. Soll sich die Animation wiederholen, kannst du Modulo-Arithmetik einsetzen, um den Vorgang wieder zurückzusetzen.
Und distanziere dich bitte von manuellen Zeilenumbrüchen, jeder brauchbare Browser kann selber umbrechen. Der Text ist sonst nämlich etwas mühsam zu lesen, besonders wenn man einen breiteren Bildschirm hat.
- Sollte ich für die Zeichnung des jeweils aktuellen Bildschirms eine eigene Funktion
-
zu 2:
naja, erstmal ist eine sekunde ziemlich lang, du wirst ja mindestens 15 bilder pro sekunde haben, damit alles spielbar bleibt. dabei wird pro bild doch deine hauptschleife abgearbeitet. und dort passiert ungefähr folgendes (pseudocode)://hauptschleife if(eingabe_erfolgt) { draw->SpielerAnimation[i]; if(i<7) i++; else i=0; } if(gegnerSollSichBewegen) { draw->Gegneranimation[j]; if(j<3) j++; else j=0; }
das ist natürlich nur die billige version, in der nicht auf die zeit eingegangen wird. das heißt, jede figur geht pro bild eine animationsstufe weiter. da musste dann beim i und j halt was dazurechnen (dazu steht hier viel im forum)...
-
ich finde, du solltest für jedes ding das gezeichnet wird ein Objekt erstellen ( z.b. nen struct oder auch ne klasse)
das die verschiedenen Informationen beinhaltet, z.b. Position, geschwindigkeit, animationsframe usw.
So kannst du dein gezeichnetes bild relativ einfach handlen indem du in der update schleife die postition und auch die animationsphasen updatest... und in der renderschleife musst du dann nur noch zeichnen und der ganze code haufen sieht dann auch übersichtlich aus.
was die animationsphasen angeht, empfehle ich dir einen double anzulegen, der den animationsframe angibt und immer die delta zeit aufzuaddieren ( diese bekommst du aus einem performancecounter ), und diesen dann in der updateschleife auf einen integer wert mittels modulo umzurechnen.
Damit hast du zeitgesteuerte Animationen, diese laufen im gegensatz zu der integer variante auch auf jedem rechner gleich schnell, denn schnellere rechner werden bei der integer variante auch schneller addieren.
Bei Animationen verwende ich ein großes Bild in der alle animationphasen dargestellt sind. und verschiebe dann zeitabhängig immer das rect, das im endeffekt die richtige Figur aus der großen grafik ausschneidet.
-
el_presidente schrieb:
was die animationsphasen angeht, empfehle ich dir einen double anzulegen, der den animationsframe angibt und immer die delta zeit aufzuaddieren ( diese bekommst du aus einem performancecounter ), und diesen dann in der updateschleife auf einen integer wert mittels modulo umzurechnen.
Danke für die Infos, aber was meinst du mit Double? Was ist die Delta-Zeit? Und wie erstelle ich einen Performance-Counter (misst das Durchlaufen der Schleife???). Und was meinst du mit Modulo?
el_presidente schrieb:
Bei Animationen verwende ich ein großes Bild in der alle animationphasen dargestellt sind. und verschiebe dann zeitabhängig immer das rect, das im endeffekt die richtige Figur aus der großen grafik ausschneidet.
Von der Technik hab' ich schon mal gehört... aber was genau ist daran der Vorteil im Gegensatz zum einzelnen Einlesen der Bilder der Animation?
Bessere Performance?
-
Danke für die Infos, aber was meinst du mit Double? Was ist die Delta-Zeit? Und wie erstelle ich einen Performance-Counter (misst das Durchlaufen der Schleife???). Und was meinst du mit Modulo?
also, ok, nochmal langsam.
Ein performance Counter ist ein Zeitmesser, der sich die aktuellen Ticks vom Rechner geben lässt, ist genauer als GetTickCount() und damit zu empfehlen...
diese Zeit misst du in jeder Schleife, und aus der Differenz kannst du quasi die DeltaZeit ermitteln. Weißt also wie lang er für einen Durchlauf gebraucht hat.
was ich mit dem double meine ist, das du eine variable anlegst ( double name ) und auf diese immer die deltazeit addierst. Und in jedem Frame rechnest du diese Zahl auf ein int um und erhälst dann prima einzelne Frames, die Du natürlich nochmal in Rects umrechnen musst.
Ich Zeig dir mal etwas Code:
m_animationsframe += deltaZeit*20 ; //( bedeutet 20 Bilder pro Sekunde, ist eine angenehme Animationsgeschwindigkeit) int framenr = (int)(m_animationsframe)%20; //% = Modulo 20, bedeutet mein bild hat 20 Animationen, und soll natürlich nciht darüber hinausgehen, sonst seh ich ja nichts mehr. RECT r = { (framenr%m_spaltenanzahl) * m_width, (framenr/m_spaltenanzahl) * m_height, ((framenr%m_spaltenanzahl)+1)* m_width, (framenr/m_spaltenanzahl+1) * m_height }; //width und height sind die dimensionen des rects, und spaltenanzahl wieviele animationen nebeneinander in der textur liegen //so jetz hab ich dir ja schon alles verraten ^^
dann brauchst du das bild nur noch im Rect r rendern lassen und fertig.
ich finde es prinzipiell besser eine grafik zu nutzen, weil es einfach einfacher zu handlen ist und vielleicht auch ressourcenschonender ^^