Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

15.03.2013, 11:40

statischer Timer will nicht funktionieren

Hallo liebes Forum,

ich arbeite momentan an der 2DAnimationsklasse aus dem Wiki. Das ganze versuche ich auf C++/SFML zu übertragen.
Meine Klasse funktioniert soweit, allerdings benutze ich bislang keinen statischen Timer.

Jetzt habe ich eine kleine Funktion geschrieben, die Zeit anzeigen und später dazu dienen soll, bequem die Zeit in Sekunden / Milisekunden / etc.. wieder zu gebebn ohne das ich das in x-stellen im Quellcode tun muss. Hier würde ich dann gerne auf den statischen Timer umstellen, aber ich kriege dauernd compilerfehler

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
class cSpriteAnimation
{
private:
    static sf::Clock testTimer;
    static sf::Time testTime;

        ....
        ....
public:
        ....
        ....
    float getTime();
};


C-/C++-Quelltext

1
2
3
4
5
6
float cSpriteAnimation::getTime()
{
    testTime = testTimer.getElapsedTime();
    std::cout << "time: " << testTime.asSeconds() << std::endl;
    return testTime.asSeconds();
};


Ich bekomme folgende Fehlermeldung:

Zitat

1>cSpriteAnimation.obj : error LNK2001: unresolved external symbol "private: static class sf::Time cSpriteAnimation::testTime" (?testTime@cSpriteAnimation@@0VTime@sf@@A)
1>cSpriteAnimation.obj : error LNK2001: unresolved external symbol "private: static class sf::Clock cSpriteAnimation::testTimer" (?testTimer@cSpriteAnimation@@0VClock@sf@@A)



Ich weiß leider nicht, was ich falsch mache.

Kann mir jemand auf die Sprünge helfen ?

Viele Grüße

Casi

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

15.03.2013, 12:07

Du hast testTimer und testTime nur deklariert, aber nirgendwo definiert. Du musst irgendwo in einer .cpp Datei noch eine Definition schreiben:

C-/C++-Quelltext

1
2
sf::Clock cSpriteAnimation::testTimer;
sf::Time cSpriteAnimation::testTime;


Aber wieso genau müssen die eigentlich static sein?

3

15.03.2013, 12:15

Du hast testTimer und testTime nur deklariert, aber nirgendwo definiert. Du musst irgendwo in einer .cpp Datei noch eine Definition schreiben:

C-/C++-Quelltext

1
2
sf::Clock cSpriteAnimation::testTimer;
sf::Time cSpriteAnimation::testTime;


Aber wieso genau müssen die eigentlich static sein?


Hallo dot,

erstmal vielen Dank für deine Antwort. Leider bin ich noch noch etwas verwirrt.
Warum muss ich die so noch mal definieren? Muss man das generell bei statischen Elementen machen?



Aber wieso genau müssen die eigentlich static sein?


Müssen nicht, aber ist es nicht von der Performance her sinnvoller, wenn alle Instanzen auf einen Timer zugreifen, statt jede Instanz seinen eigenen Timer hat? Weil die Werte die der Timer zurückgibt ändern sich ja eigentlich nicht (?). So zumindest meine Überlegung - wie siehst du das?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

15.03.2013, 12:38

Warum muss ich die so noch mal definieren?

Weil das in der Klasse keine Definition ist, sondern nur eine Deklaration. Du sagst dort nur, dass es einen statischen Member Namens testTimer gibt, erzeugst damit aber noch nicht das Objekt selbst.

Muss man das generell bei statischen Elementen machen?

Jap


Aber wieso genau müssen die eigentlich static sein?


Müssen nicht, aber ist es nicht von der Performance her sinnvoller, wenn alle Instanzen auf einen Timer zugreifen, statt jede Instanz seinen eigenen Timer hat? Weil die Werte die der Timer zurückgibt ändern sich ja eigentlich nicht (?). So zumindest meine Überlegung - wie siehst du das?

Nachvollziehbar, aber die sf::Clock macht intern wohl genau das, was du da zu basteln versuchst. Du kannst also genausogut einfach jeder cSpriteAnimation eine eigene sf::Clock geben und fertig... ;)

Btw: Ich persönlich würd die Klasse einfach SpriteAnimation nennen. Solche Präfixe für Klassennamen sind imo völlig sinnlos.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

5

15.03.2013, 12:49

Eigentlich muss eine Animation ja keinen Timer zurück geben können. Eine Animation muss ja im Normalfall nur die Zeit seit der letzten Aktualisierung bekommen um sich selbst so zu berechnen. Anstatt dessen könnte auch einfach die aktuelle Zeit übergeben werden. So nun nimmt er die Zeit und kann daraus berechnen, ob er sein aktuelles Bild ändern soll oder nicht. Der Workflow sollte klar sein. Du musst also nur die Zeit irgendwie übergeben. Das kannst du nun in einer gesonderten Updatemethode machen, oder aber direkt in der Rendermethode.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

6

15.03.2013, 12:49


Müssen nicht, aber ist es nicht von der Performance her sinnvoller, wenn alle Instanzen auf einen Timer zugreifen, statt jede Instanz seinen eigenen Timer hat? Weil die Werte die der Timer zurückgibt ändern sich ja eigentlich nicht (?). So zumindest meine Überlegung - wie siehst du das?

Nachvollziehbar, aber die sf::Clock macht intern wohl genau das, was du da zu basteln versuchst. Du kannst also genausogut einfach jeder cSpriteAnimation eine eigene sf::Clock geben und fertig... ;)[/quote]

Okey verstehe ich. Gilt das dann auch für ein sf::Time Objekt? Weil das brauch ich ja, um die Zeit bspw. in Sekunden umwandeln zu können.
Kann mir das imo nur schlecht vorstellen, wie das implementiert ist. Nach meinen Wissen würden für jede Instanz 2 extra Objekte erzeugt werden, eins das die Zeit zählt (sf::Clock) und ein anderes das mir dann die Zeit gewünscht zurückgibt (sf::Time).


Btw: Ich persönlich würd die Klasse einfach SpriteAnimation nennen. Solche Präfixe für Klassennamen sind imo völlig sinnlos.


Hast recht. Das werde ich mal umbauen :) !

7

15.03.2013, 12:54

Eigentlich muss eine Animation ja keinen Timer zurück geben können. Eine Animation muss ja im Normalfall nur die Zeit seit der letzten Aktualisierung bekommen um sich selbst so zu berechnen. Anstatt dessen könnte auch einfach die aktuelle Zeit übergeben werden. So nun nimmt er die Zeit und kann daraus berechnen, ob er sein aktuelles Bild ändern soll oder nicht. Der Workflow sollte klar sein. Du musst also nur die Zeit irgendwie übergeben. Das kannst du nun in einer gesonderten Updatemethode machen, oder aber direkt in der Rendermethode.


Ja ich wollte so eine Updatemethode schreiben.

Weil ich müsste ja jedes mal im Quellcode die Zeit aus dem sf::Clock objekt "ziehen". und dann per sf::Time dann bspw. per .asSeconds() die entsprechende Zeit bekommen um dann eine Berechnung durchzuführen - und das kommt ja öfters in der Klasse vor. Da dacht ich pack ich mir das einfach in eine getTime() Methode, die das alles immer macht und mir dann nur den gewünschten Wert im richtigen Format zurückgibt. So kann ich dann immer mit getTime() verrechnen und hätte eine zentrale Stelle im Quellcode, wo ich z. B. von Sekunden auf Milisekunden umstellen kann.

Ist doch eigentlich "richtig" gedacht - oder?

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

8

15.03.2013, 13:02

Bei mir sieht es so aus, dass in meiner Hauptschleife mit der Clock Klasse das Timeobjekt berechnet wird. Dieses wird dann an meine Update und meine Render Methode weitergegeben. Die GameStates und alles weitere reichen dieses Timeobjekt so weit wie benötigt durch. Zum Beispiel auch zur Animation. Meine Animationsklasse besitzt nur die Rendermethode. Diese bekommt als Parameter dann unter anderem dieses Timeobjekt und kann mit dessen Daten dann arbeiten. Berechnet wird dieses Objekt aber nur ein mal in der Hauptschleife.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

9

15.03.2013, 13:07

Bei mir sieht es so aus, dass in meiner Hauptschleife mit der Clock Klasse das Timeobjekt berechnet wird. Dieses wird dann an meine Update und meine Render Methode weitergegeben. Die GameStates und alles weitere reichen dieses Timeobjekt so weit wie benötigt durch. Zum Beispiel auch zur Animation. Meine Animationsklasse besitzt nur die Rendermethode. Diese bekommt als Parameter dann unter anderem dieses Timeobjekt und kann mit dessen Daten dann arbeiten. Berechnet wird dieses Objekt aber nur ein mal in der Hauptschleife.


Danke ! :)
So werd ich das in kürze auch erweitern.
Viele Grüße.

Werbeanzeige