This article has been localized into German by the community.
In this article series, we're building a complete Snake game from scratch. It makes sense to start with the Introduction and then work your way through the articles one by one, to get the full understanding.
If you want to get the complete source code for the game at once, to get started modifying and learning from it right now, consider downloading all our samples!
Hinzufügen vom Futter für die Schlange
In dieser Phase der SnakeWPF-Artikelserie haben wir jetzt einen Schachbretthintergrund als Spielfeld sowie eine hübsch aussehende grüne Schlange, die sich darauf bewegt. Wie in der Einleitung erwähnt, ist der Zweck des Spiels, dass die Schlange etwas zu essen bekommt - in unserer Version sind es rote Äpfel!
Jetzt ist es an der Zeit, dem Spielfeld etwas Futter hinzuzufügen. Wir werden es tun, indem wir einen roten Kreis zufällig irgendwo innerhalb der Grenzen des GameArea Canvas einfügen, aber wir müssen sicherstellen, dass wir ihn nicht auf einem der Quadrate platzieren, die bereits von der ständig wachsenden Schlange besetzt sind. Mit anderen Worten, einer der wichtigsten Aspekte beim Platzieren eines Apfels auf dem Spielfeld ist der Code, der über die nächste Position entscheidet. Hier ist der Code, mit dem wir genau das machen:
private Point GetNextFoodPosition()
{
int maxX = (int)(GameArea.ActualWidth / SnakeSquareSize);
int maxY = (int)(GameArea.ActualHeight / SnakeSquareSize);
int foodX = rnd.Next(0, maxX) * SnakeSquareSize;
int foodY = rnd.Next(0, maxY) * SnakeSquareSize;
foreach(SnakePart snakePart in snakeParts)
{
if((snakePart.Position.X == foodX) && (snakePart.Position.Y == foodY))
return GetNextFoodPosition();
}
return new Point(foodX, foodY);
}
Stellen Sie sicher, dass Sie diese Zeile zusammen mit den übrigen Feldern/Konstanten auch oben in der Window-Klassendeklaration einfügen:
public partial class SnakeWPFSample : Window
{
private Random rnd = new Random();
......
Um den Code schnell zu erklären: Wir verwenden erneut die SnakeSquareSize -Konstante, um die nächste Position für unser Essen in Kombination mit der Random-Klasse zu berechnen, die uns eine zufällige X- und Y-Position gibt . Sobald wir es haben, durchlaufen wir alle aktuellen Schlangenteile und prüfen, ob ihre Position mit den X- und Y-Koordinaten übereinstimmt, die wir gerade erstellt haben. Wenn dies der Fall ist, bedeutet dies, dass wir einen Bereich getroffen haben, der momentan von der Schlange besetzt ist, und danach fragen wir eine neue Position durch einfaches erneutes Aufrufen der Methode (dies ist eine rekursive Methode).
Dies bedeutet auch, dass diese Methode sich unbegrenzt oft selbst aufrufen und theoretisch zu einer Endlosschleife führen kann. Wir könnten das überprüfen, aber es sollte nicht nötig sein, da es erforderlich wäre, dass die Schlange so lang ist, dass kein leerer Raum mehr frei bleibt. Ich wette, dass das Spiel beendet sein wird, bevor dies passiert.
Nachdem dies geschehen ist, können Sie den Code hinzufügen, mit dem das Lebensmittel an der neu berechneten Position hinzugefügt wird. Dies erfolgt mit der Methode DrawSnakeFood(). Dank all der Arbeit, die bereits von GetNextFoodPosition() erledigt wurde, ist es ziemlich einfach, aber deklarieren Sie zunächst das Feld, in dem ein Verweis auf das Lebensmittel gespeichert wurde, sowie den SolidColorBrush, der zum Zeichnen des Apfel, zusammen mit den anderen Feld-/Konstantendeklarationen:
public partial class SnakeWPFSample : Window
{
private UIElement snakeFood = null;
private SolidColorBrush foodBrush = Brushes.Red;
......
Hier ist die Implementierung der Methode:
private void DrawSnakeFood()
{
Point foodPosition = GetNextFoodPosition();
snakeFood = new Ellipse()
{
Width = SnakeSquareSize,
Height = SnakeSquareSize,
Fill = foodBrush
};
GameArea.Children.Add(snakeFood);
Canvas.SetTop(snakeFood, foodPosition.Y);
Canvas.SetLeft(snakeFood, foodPosition.X);
}
Wie versprochen ist es sehr einfach - sobald wir die Position haben, erstellen wir einfach eine neue Ellipse-Instanz und verwenden erneut die Konstante SnakeSquareSize, um sicherzustellen, dass sie dieselbe Größe wie die Hintergrundkacheln hat sowie jeder Schlangenteil. Wir speichern einen Verweis auf die Ellipse-Instanz im Feld snakeFood, da wir ihn später benötigen.
In diesem Fall müssen wir nur die DrawSnakeFood() -Methode aufrufen, um das Ergebnis unserer Arbeit zu sehen. Dies geschieht in zwei Situationen: Zu Beginn des Spiels und wenn die Schlange das Futter "frisst" (dazu später mehr). Lassen Sie uns vorerst einen Aufruf in unserer StartNewGame() -Methode hinzufügen:
private void StartNewGame()
{
snakeLength = SnakeStartLength;
snakeDirection = SnakeDirection.Right;
snakeParts.Add(new SnakePart() { Position = new Point(SnakeSquareSize * 5, SnakeSquareSize * 5) });
gameTickTimer.Interval = TimeSpan.FromMilliseconds(SnakeStartSpeed);
// Draw the snake and the snake food
DrawSnake();
DrawSnakeFood();
// Go!
gameTickTimer.IsEnabled = true;
}
Das ist es! Wenn Sie das Spiel jetzt starten, sollten Sie sehen, dass die Schlange endlich etwas zu fressen hat:
Ziemlich viel Arbeit, um einen roten Punkt auf dem Bildschirm zu platzieren, oder?
Zusammenfassung
In diesem Artikel haben wir endlich etwas Futter auf den Tisch gelegt, damit die Schlange es fangen kann, aber es bleibt noch viel zu tun: Wir müssen die Schlange kontrollieren können und wissen, wann sie auf etwas stößt (eine Wand, seinen eigenen Schwanz oder das Essen). Mehr dazu im nächsten Artikel.