Du bist nicht angemeldet.

Werbeanzeige

1

26.04.2011, 15:00

Schussanimation in SFML

Hallo Leute,

Meine Klasse CProjectilebesitzt eine Update Methode, die mir die Projektilbewegung simuliert:

C-/C++-Quelltext

1
2
3
4
5
void CProjectile::Update(sf::RenderWindow &app)
{
if (app.GetInput().IsKeyDown(sf::Key::Space))
    m_sprite.Move(m_speed * app.GetFrameTime(), 0);
};


Nur muss ich Space gedrückt halten, damit sich das Projektil bewegt. Das ist natürlich nicht gewollt.
Könnte mir bitte jemand einen Tipp geben, wie man so etwas löst, ich habe grad ne totale Blockade :cursing:.

Achso: Ich glaub ich habe schonmal einen ähnlichen Thread gelesen, finde ihn aber leider nicht mehr...

Gruß NEUMee

Werwofl

Treue Seele

Beiträge: 100

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

2

26.04.2011, 15:12

Das bewegen des Schuss darf nicht vom Tastendruck abhängen, nur der Schuss selbst, also das initieren der Animation darf vom Tastendruck abhängig sein.

Phalax

Frischling

Beiträge: 82

Beruf: Student Media Systems

  • Private Nachricht senden

3

26.04.2011, 15:30

Nimm doch einfach ein bool z.B. m_bAlive, welcher bei Tastendruck auf true gesetzt wird. Dann updatest du das Projektil nur wenn m_bAlive true ist. Sollte das Projektil dann irgendwo gegenkommen oder halt anders verschwinden, musst du nur noch m_bAlive auf false setzen und das Projektil löschen.

Also etwa so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
bool m_bAlive;

if(app.GetInput().IsKeyDown(sf::Key::Space))
m_bAlive = true;
...
if(m_bAlive)
{
   // Update Schüsse
   // Wenn der Schuss weg ist, setzte m_bAlive auf false und lösche den Schuss 
}

Schorsch

Supermoderator

Beiträge: 4 961

Wohnort: Wickede

Beruf: Student

  • Private Nachricht senden

4

26.04.2011, 17:38

Ich gehe davon aus, du hast irgendwo eine Liste oder eine andere Datenstruktur in der du deine Projektile hältst. An irgend einer Stelle im Code fragst du die Tasten ab. Dann würdest du etwa sowas schreiben:

C-/C++-Quelltext

1
2
if(app.GetInput().IsKeyDown(sf::Key::Space))
{    ProjektilListe.add(new Schuss(Position, Richtung));}



Das ProjektilListe.add...... musst du dann natürlich gegen deine Datenstruktur austauschen. Vielleicht benutzt du da ja einfach ein Array oder irgendwas ganz anderes.
Jeden Frame gehst du nun einfach alle Projektile durch und Updatest diese. Dabei wird halt eine neue Position geprüft und noch auf Kollision geachtet.
„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.“

5

26.04.2011, 19:09

Ich danke euch Allen. Das hilft mir weiter.

6

29.04.2011, 17:34

Hallo,

ich komme mit meiner Schussanimation nicht weiter.

Ich habe zwar keine Projektilliste, aber ein einzelnes Projektil müsste ja auch animiert werden, oder?

main.cpp

C-/C++-Quelltext

1
2
3
4
5
if(App.GetInput().IsKeyDown(sf::Key::Space))
{
      CProjectile laser(ImageProjectile, 1000, fighter.getXShip()+142, fighter.getYShip()+38, 500);
      laser.Fire(App);
}



projectile.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void CProjectile::Update(sf::RenderWindow &app)
{
if(m_isFired and m_sprite.GetPosition().x < m_startX + m_range)
{
    m_sprite.Move(m_speed * app.GetFrameTime(), 0);
}
};

void CProjectile::Draw(sf::RenderWindow &app)
{
Update(app);
app.Draw(m_sprite);
};

void CProjectile::Fire(sf::RenderWindow &app)
{
m_isFired = true;
this->Draw(app);
};


Das Problem ist, dass das Projektil gezeichnet aber nicht bewegt wird. Habe es auch schon mit einem dyn. Array von CProjectile gemacht, der Fehler bleibt jedoch der gleiche.
Was mache ich falsch?

Hier liegt das gesamte Projektzum Download: http://darkgdk.kilu.de/SFML_Starship.rar

Gruß, NEUMee...

7

29.04.2011, 18:26

if(App.GetInput().IsKeyDown(sf::Key::Space))
{
CProjectile laser(ImageProjectile, 1000, fighter.getXShip()+142, fighter.getYShip()+38, 500);
laser.Fire(App);
}
Dein Projektil wird nach beenden des Codeblocks wieder gelöscht. Deshalb wird er nur einmal gezeichnet. Hältst du space gedrückt wird jeden Frame ein neues Projektil erstellt und einmal gezeichnet, bis es wieder gelöscht wird

8

05.05.2011, 23:06

So geschafft, mein Fighter schiesst jetzt, allerdings immer nur ein Projektil. Wenn ich wieder Space drücke, wird das Projektil neu erstellt und das vorige verschwindet, bevor es seine max. Reichweite erreicht hat.

Ich benötige also einen Container für meine Projektilobjekte.
Ich habe versucht es mit einem dyn. Array zu lösen, das hat aber nicht geklappt.

Vielleicht könnt ihr mir noch Tipps geben, ich habe versucht meine Vorgehensweise zu kommentieren.

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
#include <SFML/Graphics.hpp>
#include "starship.h"
#include "projectile.h"

int main()
{
    sf::RenderWindow App(sf::VideoMode(800, 600, 32), "SFML-Type");
    sf::Image ImageFighter;
    ImageFighter.LoadFromFile("fighter.png");

    sf::Image ImageProjectile;
    ImageProjectile.LoadFromFile("bullet.png");

    CStarship fighter(ImageFighter, 180, 10, (App.GetHeight()-ImageFighter.GetHeight())/2);

    //Hier wird ein Projektil, namens laser, erzeugt
    CProjectile laser(ImageProjectile, 800, 500);

    //Hier wird ein Array mit 10 Projektilen erzeugt
    //CProjectile *arr = new CProjectile[10];

    //Hier wird das Array mit Projektilen, namens laser, gefüllt
    /*
    for(int i=0; i<10; ++i)
    {
        arr[i] = laser;
    }
    */

    while(App.IsOpened())
    {
        sf::Event mainEvent;
        while(App.GetEvent(mainEvent))
        {
            if(mainEvent.Type == sf::Event::Closed)
            {
                App.Close();
            }
        }

        App.Clear(sf::Color(0,0,0));
        fighter.Draw(App);

        //ab hier müsste irgendwie laser mit arr[i] ersetzt werden, und i bei jedem
        //Betätigen der Space-Taste hochgezählt werden (bis i=10)
        if(App.GetInput().IsKeyDown(sf::Key::Space))
        {
            laser.setStartPosition(fighter.getXShip()+142, fighter.getYShip()+38);
            laser.Fire(App);
        }
        laser.Update(App);
        laser.Draw(App);
        //bis hierhin laser mit arr[i] ersetzen

        App.Display();
    }

    //Hier wird das Array wieder gelöscht
    //delete[] arr;

    return 0;
}


Gruß, NEUMee...

NachoMan

Community-Fossil

Beiträge: 3 892

Wohnort: Berlin

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

  • Private Nachricht senden

9

05.05.2011, 23:11

Du musst alle Laser im Array zeichnen und Updaten. Schau dir mal std::List an. Damit ist es etwas einfacher.
Wieder Grundlagen...
"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?

Fred

Supermoderator

Beiträge: 2 134

Beruf: Softwareentwickler

  • Private Nachricht senden

10

06.05.2011, 01:03

std::list oder std::vector sind quasi prädestiniert für diese Aufgabe. Denn du weißt ja nicht, wie viele Projektile der Spieler abschießen will und brauchst deshalb ein Array unbestimmter Größe und dafür bieten sich eben die STL-Container an.
Um zu zeichnen dann eben einfach alle Elemente der Liste durchgehen und die Draw-Methode aufrufen.

Werbeanzeige