Bessere Animation von Elementen in SFML / C ++

7

Hier geht es nicht darum, einzelne Charaktere oder Elemente zu animieren, dafür bin ich mit Spritesheets zufrieden. Was ich suche, ist die Animation von Elementen auf dem Bildschirm.

Zum Beispiel startet mein Spiel und das Logo fliegt aus einer zufälligen Richtung, dreht sich dann oder so und stoppt in einer Position, dann kommt ein Spielcharakter (einer oder mehrere) von der Seite und führt eine Aktion aus.

Ich habe noch nicht viele Projekte gemacht, ich habe nur ein komplettes Spiel geschrieben, daher weiß ich nicht, ob ich die Frage richtig formuliert habe.

Was ich getan habe, ist, dem Element eine Anfangs- und Endposition zu geben und es entsprechend zu bewegen und Statusflags zu verwenden, um seinen Status zu überprüfen. Das Problem ist, wenn ich es auf mehr als eine Weise verschieben möchte. Natürlich kann ich nur die Zustandsvariablen verwenden und sie verschieben, aber ich habe gedacht, dass es eine elegante Methode dafür geben muss

EDIT: Ich betrachte Animationen wie in World of Goo usw.

Tecfreak
quelle

Antworten:

4

Dies scheint so, als ob Sie die Position und Drehung von Objekten im Laufe der Zeit ändern möchten. AFAIK sfml bietet diese Funktionalität nicht sofort an, aber es sollte ziemlich einfach und unkompliziert sein, sie selbst zu implementieren.

Ich habe einmal eine ähnliche Lösung für eine dreidimensionale Simulation erstellt, die sich jedoch gut in eine grafische 2D-Anwendung übersetzen lässt.

Zunächst haben Sie zwei Konzepte: das Manipulatorund das entsprechende ManipulatorManager. Manipulatorist eine abstrakte Basisklasse für alle Arten von Manipulationen eines bestimmten Objekts, beispielsweise eines Sprites. Manipuliert können alle Eigenschaften wie Position oder Drehung, Bewegung auf einem Pfad oder ähnliches sein. Das Managerüberwacht den Status der Manipulatorsund aktualisiert sie bei jedem Frame.

Die Schnittstelle für den Manipulator sieht ungefähr so ​​aus:

class Manipulator {
public:
    Manipulator(float expiration_time) : expiration_time(expiration_time);
    bool is_expired() { return expiration_time < 0.f; }
    void update(float dt) { this->expiration_time -= dt; }
protected:
    float expiration_time;
}

Eine Implementierung dieser Klasse ist die, SimpleLineManipulatordie die Position eines Sprites über einen bestimmten Zeitraum auf einer geraden Linie beeinflusst:

class SimpleLineManipulator {
    SimpleLineManipulator(Sprite *spr, Vector2f begin, Vector2f end, float expiration_time);
    ...
private:
    Sprite* sprite;
    Vector2f begin, end;
    float total_time; // initialized with expiration_time
}

Und so sieht die Aktualisierungsmethode aus (wo der größte Teil der Arbeit stattfindet):

void SimpleLineManipulator::update(float dt) {
    Manipulator::update(dt);
    Vector2f position = lerp(end, begin, total_time/expiration_time);
    spr->SetPosition(position.x, position.y);
}

Jetzt müssen Sie nur noch die update()Methode für jeden Frame aufrufen . Es sollte einfach sein, einen Rotationsmanipulator oder Manipulatoren zu implementieren, die auf einem Pfad arbeiten (eine Liste von Positionen). Sie können diese Manipulatoren jetzt auch kombinieren, um kombinierte Effekte zu erstellen.

Ich hoffe, ich konnte die Architektur klar umreißen. Fragen Sie nur :)

Constantinius
quelle
Das war eine ziemlich gute Erklärung! Vielen Dank. Nur eine kurze Frage, sollten die Elementklassen von der Manipulator-Klasse erben?
Tecfreak
1

Constantinius bietet bereits einen guten Ausgangspunkt, von dem aus Sie mit der eigentlichen Codierung beginnen können. Wenn Sie jedoch wissen möchten, was Sie hier im Allgemeinen tun, möchte ich einige Wörter hinzufügen.

Das Verschieben von Objekten über die Zeit von Punkt A nach Punkt B erfolgt durch Anwenden einer Funktion f (x) auf die Position des Objekts, wobei x alles sein kann, von einfach der aktuellen Position des Sprites bis zu der Zeit, die zwischen ihnen verstrichen ist zwei Frames usw.

Dieser Vorgang wird normalerweise mithilfe eines Teilfelds der numerischen Analyse durchgeführt, das als Interpolation bezeichnet wird.

Ein häufiges Beispiel wäre die lineare Interpolation. Wenn Sie den konstanten Startpunkt A und Endpunkt B kennen, wäre eine mögliche Funktion einfach f (t) = A + (B - A) * (t_max - t), wobei

  • t ist die Zeit, die vergangen ist, seit das Objekt von Punkt A aus gestartet wurde
  • t_max ist die Zeit, die das Objekt dauern soll, bis es sein Ziel erreicht
  • 0 <= t <= t_max.

Wie Sie sehen, gibt die Funktion einen Vektor zurück, sodass Sie ihn problemlos auf die Position Ihres Objekts anwenden können.

Dies ist natürlich nur eine grobe Einführung, damit Sie vielleicht ein wenig Blut schmecken und Ihr Interesse wecken können. Daher werde ich Sie zu Google weiterleiten, wenn Sie mehr darüber erfahren möchten.

TravisG
quelle
Danke für deine Antwort! Ich habe darüber nachgedacht, was Lerp in Constantinius 'Antwort ist, und Sie haben genau diesen Punkt getroffen!
Tecfreak