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

20.11.2010, 22:56

[SFML] Selbstebaute Animationsklasse lässt ein Bild aus

Hallo spieleprogrammierer.de

wie die Überschrift schon sagt habe ich mir eine Klasse für Animationen gebastelt leider funktioniert diese noch nicht so ganz sie läst irgendwie immer nach dem letzten Bild eins frei.
Animation.hpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef ANIMATION_HPP_INCLUDED
#define ANIMATION_HPP_INCLUDED

class Animation
{
public:
Animation();
explicit Animation(std::string File, int PicturesOnWidth, int PicturesOnHeight, float FPS);
bool SetActive(bool Active);
bool Draw(sf::RenderWindow &App);
bool SetPosition(int X, int Y);
bool CheckClock();
bool Reset();
bool MoveSubRect();
protected:
// Resourcen
float _FPS; //<FramesPerSecound
int _POW, _POH; // <PicturesOnWidth, PicturesOnHeight
int _WPI, _HPI; //< WidthPerImage, HeightPerImage
int _CPW, _CPH; //<CursorPositionWidth, CursorPositionHeight
sf::Clock _Clock; //<Misst die genau vergangene Zeit
bool _Active; //<Gibt an ob das Elemnt Aktiv ist
sf::Image _Img; //< Image
sf::Sprite _Animation; //< Animationssprite
};

#endif // ANIMATION_HPP_INCLUDED

Animation.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
Animation::Animation()
{

}
Animation::Animation(std::string File, int PicturesOnWidth, int PicturesOnHeight, float FPS)
{
this->_Img.LoadFromFile(File);
this->_Img.SetSmooth(false);
this->_Animation.SetImage(this->_Img);
this->_POW = PicturesOnWidth;
this->_POH = PicturesOnHeight;
sf::Vector2f _WH = this->_Animation.GetSize();
this->_WPI = static_cast<int>( _WH.x )/ this->_POW;
this->_HPI = static_cast<int>( _WH.y )/ this->_POH;
this->_CPW = 0;
this->_CPH = 0;
this->_FPS = FPS;
}
bool Animation::SetActive(bool Active)
{
this->_Active = Active;
return true;
}
bool Animation::Draw(sf::RenderWindow &App)
{
if (this->_Active)
{
if (this->CheckClock())
{
this->MoveSubRect();
this->_Clock.Reset();
}
App.Draw(this->_Animation);
}
else
{
this->Reset();
}
return true;
}
bool Animation::CheckClock()
{
if (this->_Active)
{
if (this->_Clock.GetElapsedTime() > this->_FPS)
{
return true;
}
else
{
return false;
}
}
else
{
this->_Clock.Reset();
return false;
}
}
bool Animation::Reset()
{
this->_Animation.SetSubRect(sf::IntRect(1, 1, this->_WPI, this->_HPI));
this->_CPW = 0;
this->_CPH = 0;
return true;
}
bool Animation::MoveSubRect()
{
if (this->_CPW + 1 <= this->_POW)
{
this->_CPW += 1;
}
else
{
if (this->_CPH + 1 <= this->_POH)
{
this->_CPH += 1;
this->_CPW = 0;
}
else
{
this->Reset();
}
}
this->_Animation.SetSubRect(sf::IntRect(this->_CPW * this->_WPI, this->_CPH * this->_HPI, (this->_CPW + 1) * this->_WPI, (this->_CPH + 1) * this->_HPI));
return true;
}
bool Animation::SetPosition(int X, int Y)
{
this->_Animation.SetPosition(X, Y);
return true;
}


Vielen Dank im Voraus.
MfG Ninjasturm

----------------------------
System: Windows 7 x64
IDE: Visual Studio 2010 Ultimate
Engine: Ogre3D


Favorisierte Programmiersprache: C++
Sonstige Programmiersprachen: AutoIT, PHP, Javascript
Sonstige Auszeichnungsprachen: HTML, CSS
---------------------------

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

2

20.11.2010, 23:39

das image gehört nicht in die spriteklasse!!!
vllt kann dir jemand helfen wenn du die variablennamen ausschreibst und den code hier postest damit die formatierung erhalten bleibt.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

n0_0ne

1x Contest-Sieger

  • Private Nachricht senden

3

21.11.2010, 10:04

Ich geb Nacho recht, was das Image und die Namen angeht. Mit solch "kryptischen" Variablennamen ist der Code nicht wirklich wartbar. Bei heutigen IDEs ist es dank autovervollständigung ja wohl kein Problem mehr, längere, aussagekräftigere Namen zu verwenden...

Meiner Meinung nach ist der Name "FPS" hier auch nicht korrekt verwendet, hier würde eher etwas in der Art wie "SPF", also Seconds per Frame passen. Jedenfalls ergibt nur so die Zeile

if (this->_Clock.GetElapsedTime() > this->_FPS)

einen Sinn.

4

21.11.2010, 23:13

1) Variablennamen
2) const-correctness
3) bool-Rückgabewert, wenns 2 mögliche Ausgänge gibt, bei einem, void.
4) Parameter meist als const-ref übergeben
5) Überprüfe mal ob public und private überall richtig ist. ...
6)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
if (this->_Clock.GetElapsedTime() > this->_FPS)
{
return true;
}
else
{
return false;
}
->

C-/C++-Quelltext

1
return (this->_Clock.GetElapsedTime() > this->_FPS);


und dann rücks mal nochmal ein und poste es dann ;) So ists doch etwas müselig ;)
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

idontknow

unregistriert

5

21.11.2010, 23:15

finde deine klasse total komisch + kompliziert, ist bei mir eigenartigerweise viiiiiiiieeeeeeeeeeeeel simpler..

n0_0ne

1x Contest-Sieger

  • Private Nachricht senden

6

22.11.2010, 06:35

Also ich hab mir deinen Code nicht nochmal genau angesehen. Als Tipp: mach nicht so viele kleine bool methoden. die machen sowas hier eher unleserlich. Ein einfaches if reicht da auch meistens.

Ich hab mal in einem alten SFML code von mir, nach dem Animationsteil geguckt, und der ist bei mir auch sehr viel einfacher. Ich poste ihn mal, sollte eigentlich selbsterklärend sein.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
m_animphase += m_speedAnim * m_frametime;
if (m_animphase >= static_cast<float>(m_numFrames)) {
    m_animphase -= static_cast<float>(m_numFrames);
}

m_column = static_cast<int>(m_animphase) % m_numFramesX;
m_row = static_cast<int>(m_animphase) / m_numFramesX;

m_spriteObject->SetSubRect(sf::IntRect(
    static_cast<int>(m_frameSizeWidth * m_column),
    static_cast<int>(m_frameSizeHeight * m_row),
    static_cast<int>(m_frameSizeWidth * m_column + m_frameSizeWidth),
    static_cast<int>(m_frameSizeHeight * m_row + m_frameSizeHeight)));

idontknow

unregistriert

7

22.11.2010, 15:56

Werd meinen auch mal posten, ist relativ neu und noch stark W.I.P., daher unterstützt der Spaß momentan leider nur eine Animation wird sich aber bald ändern :P. Immerhin bleibdts dadurch sehr simpel!!

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void Animation::Move(float frametime)
{
    m_TimeDelta += frametime;
    if(m_TimeDelta >= m_FrameDuration) // move one frame forward!!!
    {
        m_TimeDelta -= m_FrameDuration;
        m_CurrentFrame++;
    }

    if(m_CurrentFrame > (m_NumFrames - 1))
        if(m_Autorepeat)
            m_CurrentFrame = 0;
        else
            ; // end of animation..

    // calc new subrect!
    m_SubRect.Left = m_Offset.x + m_SubRect.Width * m_CurrentFrame;
    m_Sprite.SetSubRect(m_SubRect);
}

8

22.11.2010, 16:30

Sieht bei idontknow schon mal ganz gut aus.

Kleiner Tipp, auch an Ninjasturm: Häufig kann man es gut gebrauchen wenn eine Animation nicht einfach von Anfang bis Ende abläuft und dann wieder am Anfang beginnt, sondern wenn sie am Ende umkehrt und wieder zurück zum Anfang läuft. Stichwort Pingpong. Das könntet ihr noch einbauen. ;)

Gruß
SaRu_

idontknow

unregistriert

9

22.11.2010, 16:34

Noch kurz zu meiner Klasse: Sofern autorepeat (sprich am Ende angelangt springt die Animation wieder zum ersten Frame) nicht aktiviert ist wird die Animation "ins Leere" laufen sobald der letzte Frame vorbei ist, siehe Zeile 14. Was du dort machen willst bleibt dir überlassen, anbieten würde es sich die Animation zu pausieren. Das habe ich aber noch nicht vollständig implementiert.

Zum Format der Animation: Die Frames muessen schlichtweg von links nach rechts in einer Grafik angegeben werden (kurz: ein vertikaler "Grafikstreifen"). Wenn du mehrere Animationen in einer Grafik haben willst musst du nur die Member ändern, das würde mindestens heißen: m_Offset (linke-obere Ecke des ersten Frames) und m_NumFrames ändern.


Kleiner Tipp, auch an Ninjasturm: Häufig kann man es gut gebrauchen wenn eine Animation nicht einfach von Anfang bis Ende abläuft und dann wieder am Anfang beginnt, sondern wenn sie am Ende umkehrt und wieder zurück zum Anfang läuft. Stichwort Pingpong. Das könntet ihr noch einbauen. ;)

Gruß
SaRu_


Inwiefern macht das Sinn? Ich hatte das urspürnglich eingebaut, aber irgendwie konnte ich mir dann keine anständige Verwendung dafür ausdenken und habs wieder rausgemacht. Notfalls kann man immer noch die Frames zwischen (aber ohne!) Anfang und Ende kopieren und ans Ende setzen und eben die Frame Anzahl erhöhen :). Ist sicherlich nicht die schönste Lößung aber eine^^

Ich kann mir auch nicht ausmalen inwievern man dieses "zurücklaufen" in PingPong brauchen könnte!

10

22.11.2010, 17:16

Notfalls kann man immer noch die Frames zwischen (aber ohne!) Anfang und Ende kopieren und ans Ende setzen und eben die Frame Anzahl erhöhen

Zum Beispiel um genau sowas nicht machen zu müssen wäre das sinnvoll. ;)

Stell dir vor du hast eine Figur die als Animation eine Geh-Bewegung hat. Dann brauchst du nur Frames für die Bewegung von einem Schritt (ein Bein). Der nächste Schritt (anderes Bein) wäre dann die Animation rückwärts. Natürlich kannst du einfach die Frames kopieren, aber ich find das dann doch etwas umständlich und bei vielen Grafiken wird die Datei dann auch entsprechend viel größer. Wenn du das ja schon implementiert hattest, dann weißt du ja, dass es nicht so viel mehr Arbeit ist, sich später aber dann doch auszahlen kann.

Gruß
SaRu_

Werbeanzeige