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

rid_

Frischling

  • »rid_« ist der Autor dieses Themas
  • Private Nachricht senden

1

28.02.2012, 11:33

[Snake] Steuerung der Schlange

Hey

ich sitze momentan an einem kleinen Snake Clone um mich wieder einmal in sfml einzuarbeiten. Bisweilen funktionieren einfache Richtungsänderungen. Dabei steuert man natürlich nur den Kopf der Schlange. Anschließend ziehe ich beim Richtungswechsel das 2. Element direkt zum Kopf, danach werden die restlichen Elemente um eine Position nach vorn geschoben usw. . Dadurch ergibt sich die typische Snake Bewegung. Leider funktioniert mein Code nicht für mehrmalige Richtungswechsel, d.h. wenn der Schwanz der Schlange noch in eine andere Richtung zeigt als der Körper .
Hier mal etwas Code (WIP!) :

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
switch(direction)
    {
        case 1: //left
        
            for (int i=1; i<length; i++)
            {   
                if ((rect[i-1]->GetPosition().x - rect[i]->GetPosition().x) <(-12))
                {
                    rect[i]->SetPosition(rect[i-1]->GetPosition().x + 12, rect[i-1]->GetPosition().y);
                }
                for (int e=i+1; e<length; e++)
                {   
                    if ((rect[e-1]->GetPosition().y - rect[e]->GetPosition().y) < (-i*12))
                    {
                        rect[e]->SetPosition( rect[e]->GetPosition().x, rect[e]->GetPosition().y - 12 );
                    }
                    if ((rect[e-1]->GetPosition().y - rect[e]->GetPosition().y) > (i*12))
                    {
                        rect[e]->SetPosition( rect[e]->GetPosition().x, rect[e]->GetPosition().y + 12 );
                    }
                }
            }
            
            break;
        case 2: //right
        
            break;
        case 3: //up
            for (int i=1; i<length; i++)
            {

                if ((rect[i-1]->GetPosition().y - rect[i]->GetPosition().y) < (-12))
                {
                    rect[i]->SetPosition(rect[i-1]->GetPosition().x, rect[i-1]->GetPosition().y + 12);
                }
                for (int e=i+1; e<length; e++)
                {   
                    if ((rect[e-1]->GetPosition().x - rect[e]->GetPosition().x) < (-i*12))
                    {
                        rect[e]->SetPosition( rect[e]->GetPosition().x-12, rect[e]->GetPosition().y );
                    }
                }
                
            }
            break;
        case 4: //down
            for (int i=1; i<length; i++)
            {   
                if ((rect[i-1]->GetPosition().y - rect[i]->GetPosition().y) > (12))
                {
                    rect[i]->SetPosition(rect[i-1]->GetPosition().x, rect[i-1]->GetPosition().y - 12);
                }
                for (int e=i+1; e<length; e++)
                {
                    if ((rect[e-1]->GetPosition().x - rect[e]->GetPosition().x) < (-i*12))
                    {
                        rect[e]->SetPosition( rect[e]->GetPosition().x-12, rect[e]->GetPosition().y );
                    }
                }
            }

            break;
    }


Die Variable Direction spiegelt die jeweilige Richtung wieder, die momentan gedrückt wird - und sich die Schlange letztendlich bewegt
rect[] - beinhaltet sf::RectangleShape - demzufolge ein Quadrat

Für die jeweiligen Richtungswechsel überprüfe ich ggf. die x / y Koordinaten um festzustellen, ob das erste Element nach links/rechts/oben/ unten bewegt wird
Hat jemand eine Idee wie man die mehrmaligen Richtungswechsel richtig programmiert ?
Vielen Dank für die Denkanstöße

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

2

28.02.2012, 11:39

Ich hab bei meinem Snakeklon die Schlangenparts in einer Liste gespeichert. Bei jeder Bewegung habe ich vorne ein neues Stück an gehangen und das letzte gelöscht. Als andere Möglichkeit könnte jedes Schlangenstück seinen Vorgänger kennen und jeden Schritt auf ihn zugehen.
„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.“

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

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

  • Private Nachricht senden

3

28.02.2012, 13:14

Wobei Schorschs erste Variante einfacher zu implementieren und, besonders bei sehr langen Schlangen, wesentlich effektiver ist. Du wirst den Performanceunterschied zwar nie merken(es sei denn du hast ein paar tausend Teile...) aber du solltest dir über solche Datenstrukturen schon gedanken machen, weil sie bei komplexeren Spielen immer wichtiger werden. :thumbsup:

Wenn du die Schlange verlängerst musst du bei der Bewegung vorn nur ein neues Körperteil hinzufügen ohne hinten eins wegzunehmen.

Achja, willkommen im Forum.
"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?

rid_

Frischling

  • »rid_« ist der Autor dieses Themas
  • Private Nachricht senden

4

28.02.2012, 15:16

Vielen dank für die erste Hilfe. Ich habe nun erstmal in meinem Code einiges umgeschrieben. Wie empfohlen wurde eine Liste erstellt, die die Positionen der einzelnen Körperteile der Schlange speichert. Bei einem Richtungswechsel wird nun die letzte Position in der Liste gelöscht und an den Anfang der Liste kommt die neue Position, die sich aus der neuen Richtung ergibt, soweit so gut.

C-/C++-Quelltext

1
2
3
4
5
6
for (int i=1; i<length; i++)
{
    liste.pop_back();
    pos = new sf::Vector2f(rect.GetPosition().x + i*12, rect.GetPosition().y);
    liste.push_front(*pos);
}


ich habe das mit den i*12 drin, weil ich keine durchgängige Linie erstelle sondern Quadrate im gleichen Abstand zu einander haben möchte.
Ok, jetzt kommt wieder das Problem der Verzögerung. Ich habe an dieser Stelle einen kleinen Timer erstellt , so das nach 150ms immer ein Objekt gelöscht und vorn angehangen wird. Das ergibt aber eine Ruckelbewegung. Früher habe ich das immer mit Überprüfung von Koordinaten geregelt.
Einen Tipp?

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

5

28.02.2012, 15:18

Warum soll die zweite Variante langsamer sein? Wenn ich jedes mal vorne ein Tile erzeuge und hinten eins lösche kann das auch Overhead erzeugen. Das könnte man dann zwar auffangen indem man das letzte Tile einfach vorn anhängt aber an sich ist das alles Quatsch. In solchen Fällen sollte man die Lösung nehmen, die man selbst am verständlichsten hält. Man wird nie so große Schlangen bekommen, dass man dort wirklich etwas merken würde. Und selbst wenn, gibt es sicherlich genug andere Punkte an denen man anfangen kann;)
„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.“

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

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

  • Private Nachricht senden

6

28.02.2012, 15:28

Das könnte man dann zwar auffangen indem man das letzte Tile einfach vorn anhängt aber an sich ist das alles Quatsch.

Wieso ist es Quatsch?

Ich gehe hier natürlich vom klassischen Snake aus, in dem sich die Schlange Tile für Tile bewegt. Wenn du es "modern" haben willst... solltest du dir überlegen ob du schon so weit für eine solche Übung bist.
"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?

Werbeanzeige