Hallo,
Ich habe das Buch "C++ für Spieleprogrammierer" durchgearbeitet und danach auf Youtube einige Tutorials zur Bibliothek "SFML" bearbeitet, und wollte nun mal anfangen, mein erstes kleines Spiel zu programmieren und habe mich für "Snake" entschieden.
Ich speichere die Positionen der einzelnen Segmente der Schlange in einer verketteten Liste, habe mir dafür eine Klasse für Positionen geschrieben und speichere dann Positionsobjekte in der Liste. Die Position des Kopfes der Schlange ist in einer extra Variable gespeichert.
In der update-Funktion der Schlange wird die Position des Kopfes in die aktuelle Richtung um einen Block bewegt, anschließend vorne in die Liste geschoben, und wenn die Größe der Liste größer ist als die Länge der Schlange, dann wird das letzte Element der Liste entfernt.
Dabei tritt jedoch ein seltsames Problem auf, dass ich mir nicht erklären kann. Ich habe mir in der update-Funktion die Koordinate des Schlangenkopfes in der Konsole anzeigen lassen und greife dabei auf das erste Element der Positionsliste zu (mit "front()"), und dabei ist mir aufgefallen, dass zu Beginn der update-Funktion die x-Position der Schlange immer 1 ist, am Ende der update-Funktion jedoch immer den richtigen Wert hat und sich auch verändert.
Dabei habe ich die Schlange nie manuell auf die Position 1 gesetzt (auch nicht beim erstellen über den Konstruktor), und die Startrichtung der Schlange ist auch auf rechts gesetzt, weshalb es merkwürdig ist, dass die Schlange auf einmal weiter links ist als zu Beginn.
Vielleicht tut es auch noch zur Sache, dass die update-Funktion der Schlange nur aufgerufen wird, wenn keine Kollision mit der Wand oder der Schlange selbst auftritt (es wird geprüft, ob der Kopf der Schlange ein anderes Segment der Schlange berührt, Kopf mit Kopf wird dabei aber ausgeschlossen, denn sonst würde ja die ganze Zeit eine Kollision erkannt werden), denn bei einer Kollision soll sich die Schlange ja nicht weiter bewegen. Außerdem wird vorher geprüft, ob der Timer das Zeitlimit erreicht hat, sodass beispielsweise die Schlange sich alle 0.1s um einen Block weiterbewegt. Anschließend wird der Timer wieder zurückgesetzt.
Dies geschieht in der update-Funktion der Game-Klasse, welche bei jedem Schleifendurchgang aufgerufen wird.. Die render-Funktion der Schlange wird ebenfalls bei jedem Schleifendurchgang aufgerufen.
Ich hoffe mir kann jemand helfen, danke schonmal im Voraus.
Hier die Quelltexte:
Positionsklasse Header:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class Position
{
private:
int m_x;
int m_y;
public:
Position (int x, int y);
void move (eDirection direction);
bool operator== (Position &position);
bool operator!= (Position &position);
void setX (int x);
void setY (int y);
int getX ();
int getY ();
};
|
Positionsklasse Konstruktor:
|
C-/C++-Quelltext
|
1
2
3
|
Position::Position (int x, int y)
: m_x (x), m_y (y)
{}
|
Positionsklasse move-Funktion:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
void Position::move (eDirection direction)
{
switch (direction)
{
case RIGHT:
m_x++;
break;
case DOWN:
m_y++;
break;
case LEFT:
m_x--;
break;
case UP:
m_y--;
break;
}
}
|
Schlange Konstruktor:
|
C-/C++-Quelltext
|
1
2
3
4
5
|
Snake::Snake (Position position, eDirection direction, int length)
: m_position (position), m_direction (direction), m_length (length)
{
m_listSegmentPositions.push_front (m_position);
}
|
Schlange: update-Funktion
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
void Snake::update ()
{
// hier ist front() immer 1
std::cout << "Snake Position: " << m_listSegmentPositions.front().getX() << ", " << m_listSegmentPositions.front().getY() << std::endl;
std::cout << "Snake Length: " << m_length << std::endl;
std::cout << "Snake List Size: " << m_listSegmentPositions.size () << std::endl;
m_position.move (m_direction);
m_listSegmentPositions.push_front (m_position);
if (m_listSegmentPositions.size () > static_cast<unsigned>(m_length))
m_listSegmentPositions.pop_back ();
// hier hat front() den richtigen Wert und verändert sich auch
std::cout << "Snake Position: " << m_listSegmentPositions.front().getX() << ", " << m_listSegmentPositions.front().getY() << std::endl;
std::cout << "Snake Length: " << m_length << std::endl;
std::cout << "Snake List Size: " << m_listSegmentPositions.size () << std::endl;
}
|
Schlange: render-Funktion:
|
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
|
void Snake::render (sf::RenderWindow *pWindow)
{
sf::Sprite tempSprite;
for (std::list <Position>::iterator it = m_listSegmentPositions.begin (); it != m_listSegmentPositions.end (); it++)
{
// Kopf
if (*it == m_listSegmentPositions.front ())
tempSprite.setTexture (m_textureFront);
// Schwanzspitze
else if (*it == m_listSegmentPositions.back ())
tempSprite.setTexture (m_textureBack);
// Mittelteil
else
tempSprite.setTexture (m_textureMiddle);
tempSprite.setPosition ((float)(it->getX() * BLOCKSIZE), (float)(it->getY() * BLOCKSIZE));
pWindow->draw (tempSprite);
}
}
|