TOC

This article is currently in the process of being translated into Italian (~98% done).

Creare un gioco: SnakeWPF:
Chapter introduction:

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!

Aggiungere cibo per the Snake

Finora abbiamo uno sfondo a scacchiera come area di gioco, oltre a un adorabile serpente verde che si muove attorno ad esso. Tuttavia, come menzionato nell'introduzione, lo scopo del gioco è che il serpente mangi del cibo: nella nostra versione saranno mele rosse!

Quindi ora è il momento di iniziare ad aggiungere del cibo nell'area di gioco. Lo faremo aggiungendo casualmente un cerchio rosso da qualche parte entro i confini della tela GameArea, ma dobbiamo assicurarci di non posizionarlo in uno dei quadrati già occupati dal serpente in costante crescita. In altre parole, uno degli aspetti più importanti del posizionamento di una mela nell'area di gioco è il codice che decide la posizione successiva. Ecco il codice che useremo per fare proprio questo:

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);
}

Metti anche questa riga nella parte superiore della dichiarazione della classe Window, insieme al resto dei campi / costanti:

public partial class SnakeWPFSample : Window
{
    private Random rnd = new Random();
    ......

Spiego rapidamente il codice: utilizziamo ancora una volta la costante SnakeSquareSize per aiutarci a calcolare la posizione successiva per il nostro cibo, in combinazione con la classe random, che ci darà una posizione X e Y casuale . Una volta che abbiamo la posizione, cicliamo su tutte le parti attuali del serpente e controlliamo se la loro posizione corrisponde alle coordinate X e Y che abbiamo appena creato - se corrisponde, significa che abbiamo scelto un'area attualmente occupata dal serpente e quindi chiediamo una nuova posizione semplicemente richiamando il metodo (metodo ricorsivo).

Ciò significa anche che questo metodo può essere chiamato un numero illimitato di volte e, in teoria, può provocare un ciclo infinito. Potremmo fare qualche controllo, ma non dovrebbe essere necessario, dal momento che richiederebbe che il serpente fosse così lungo da non lasciare spazio vuoto - la mia scommessa è che il gioco sarà finito prima che ciò accada.

In questo modo, siamo pronti ad definire il codice che aggiungerà il cibo nella posizione appena calcolata - lo faremo da un metodo chiamato DrawSnakeFood () . Grazie a tutto il lavoro già gestito da GetNextFoodPosition () , è piuttosto semplice, ma prima si deve dichiarare il campo utilizzato per salvare un riferimento al cibo e un SolidColorBrush utilizzato per disegnare la mela:

public partial class SnakeWPFSample : Window  
{  
    private UIElement snakeFood = null;  
    private SolidColorBrush foodBrush = Brushes.Red;
    ......

Ecco l'implementazione del metodo:

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);
}

Come promesso, è molto semplice: appena abbiamo la posizione, creiamo semplicemente una nuova istanza di Ellipse e ancora una volta utilizziamo la costante SnakeSquareSize per assicurarci che abbia le stesse dimensioni delle tessere di sfondo così come ogni parte del serpente. Salviamo un riferimento all'istanza di Ellipse nel campo snakeFood , perché ne abbiamo bisogno in seguito.

Ora dobbiamo solo chiamare il metodo DrawSnakeFood () per vedere il risultato del nostro lavoro. Ciò avverrà in due situazioni: all'inizio del gioco e quando il serpente "mangia" il cibo (ne parleremo più avanti). Per ora, aggiungiamo una chiamata al nostro metodo StartNewGame () :

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;
}

Questo è tutto! Se esegui il gioco ora, dovresti vedere che il serpente ha finalmente del cibo da inseguire:

Un po' di lavoro per posizionare un punto rosso sullo schermo, giusto?

Summary

In questo articolo, abbiamo finalmente aggiunto del cibo al tavolo per la cattura del serpente, ma c'è ancora del lavoro da fare: dobbiamo essere in grado di controllare il serpente e dobbiamo sapere quando colpisce qualcosa (un muro, la propria coda o il cibo). Maggiori informazioni su questo nel prossimo articolo.

This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!