XNA är en högkonjunktur för skapande av spel för Microsoft-enheter, inklusive Windows-datorer, Xbox 360 och det helt nya Windows Phone 7-operativsystemet. I en tidigare handledning täckte vi grunderna i XNA-ramverket, inklusive hanteringsinmatning och visning av sprites. I den här artikeln lär du dig att kombinera dessa färdigheter med en egen spelide för att skapa något roligt att spela och enkelt att hämta.
I denna handledning kommer du att skapa ett enkelt Tic-Tac-Toe-spel som kan spelas med vänner. Tic-Tac-Toe är ett enkelt spel där två spelare tar växlande svängar placera tecken på ett tre i tre rutor. Den första spelaren använder en O och den andra spelaren använder en X. För att vinna spelet måste en spelare ordna tre av sina karaktärer i en rad, kolumn eller diagonal.
Medan det här spelet är enkelt krävs det ett par olika färdigheter att bygga. Först använder du XNA och dess grafikfunktioner för att bygga ditt spel. Som sådan måste du vara bekant med att visa sprites. För det andra behöver du veta hur man hanterar beröring på telefonens pekpanel. Lyckligtvis tillhandahåller XNA ett högt API för att komma åt dessa berör. Slutligen måste du tillämpa lite programmering och logisk know-how för att bestämma vinnaren. För denna handledning kommer mycket av det att ges till dig. När du bygger spel i framtiden måste du komma med dina egna idéer och logik.
För att börja, se till att du har installerat de senaste utvecklingsverktygen för Windows Phone 7. Om du inte har uppdaterat dina verktyg sedan den senaste WP7-handledningen på MobileTuts, bör du besöka Microsoft Download Center och få RTW-versionen. Den senaste versionen kommer med den slutliga emulatorn som visar hur dina appar ska fungera för att släppa ut daghårdvara.
När du har visat att dina verktyg är uppdaterade öppnar du Visual Studio 2010 och klickar på länken "Ny projekt ..." i vänster sidofält. I dialogrutan som dyker upp väljer du "XNA Game Studio 4" i den vänstra kolumnen och kontrollerar att "Windows Phone Game (4.0)" mallen är vald till höger. Ge ditt projekt ett lämpligt namn som "TicTacToe" och bekräfta att kryssrutan "Skapa katalog för lösning" är markerad. Om du har gjort allt detta korrekt bör din dialogruta matcha följande bild:
Klicka på "OK" för att skapa ditt nya projekt. Visual Studio 2010 kommer att generera nödvändiga filer i din angivna katalog och öppna Game1.cs
för redigering.
Eftersom du använder sprites för all spelgrafik i det här projektet måste du importera de nödvändiga objekten till ditt projekt. I nedladdningen som följer med denna handledning hittar du en Media
katalog som innehåller en mängd bilder. I lösningsutforskaren på höger sida av skärmen, leta reda på innehållsprojektet (kallat TicTacToeContent) och högerklicka på det. Från snabbmenyn väljer du "Lägg till> Befintlig föremål ...". När dialogrutan öppnas, bläddra till Media
mapp som du släpper ut från handledningen och väljer alla bilder som finns i den. Du bör kunna berätta från bildnamnen exakt vad varje objekt innehåller.
Efter att ha importerat ditt media ska din lösningsutforskare likna följande:
Nu när dina medier har importerats till innehållsprojektet som bifogas din lösning måste du ladda varje bild som en separat textur. Eftersom du använder dessa texturer i hela ditt spel kommer du att lagra dem i fält inuti din spelklass. Öppna filen Game1.cs och lägg till följande fält högst upp i din klassdeklaration:
Texture2D gridTexture; Rektangel gridRectangle; Texture2D resetButton; Rektangel resetButtonPosition; Texture2D oPiece; Texture2D xPiece; Texture2D oWinner; Texture2D xWinner; Texture2D noWinner; Texture2D oTurn; Texture2D xTurn;
Du ser att alla bilder du importerat har ett fält för att säkerhetskopiera det. Dessutom har det huvudsakliga spelruten och återställningsknappens textur fält av typ Rektangel
som kommer att användas för att placera dessa objekt. Dessa lagras som fält eftersom de inte kommer att förändras under spelet.
Nu när du har rätt fält skapade är det dags att instansera Texture2D
och Rektangel
objekt som tilldelas fälten. Bläddra ner till din Game1.cs
filen tills du når LoadContent
metod. Inuti denna metod, sätt in följande kod efter den linje som läser spriteBatch = ny SpriteBatch (GraphicsDevice);
:
gridTexture = Content.Load( "TicTacToe_Grid"); gridRectangle = ny rektangel (0, 0, spriteBatch.GraphicsDevice.Viewport.Width, spriteBatch.GraphicsDevice.Viewport.Height); oPiece = Content.Load ( "TicTacToe_O"); xPiece = Content.Load ( "TicTacToe_X"); resetButton = Content.Load ( "TicTacToe_Reset"); resetButtonPosition = ny rektangel (spriteBatch.GraphicsDevice.Viewport.Width / 2 - (resetButton.Width / 2), spriteBatch.GraphicsDevice.Viewport.Height - 95, resetButton.Width, resetButton.Height); oWinner = Content.Load ( "TicTacToe_O_Winner"); xWinner = Content.Load ( "TicTacToe_X_Winner"); noWinner = Content.Load ( "TicTacToe_Draw"); oTurn = Content.Load ( "TicTacToe_O_Turn"); xTurn = Content.Load ( "TicTacToe_X_Turn");
Efter att ha laddat sprites som kommer att användas av spelet, måste du komma överens med det arbetsflöde som spelet kommer att springa på. För Tic-Tac-Toe är det här ganska enkelt och ser något ut som följande:
Som du säkert kan berätta, faller dessa steg i en av två grundläggande kategorier, Draw eller Update. Skanna igenom Game1.cs
filen ser du att du har två metoder, Dra
och Uppdatering
Det är de perfekta behållarna för koden som krävs för att beskriva arbetsflödet.
Om man tittar på arbetsflödet kan man skilja att det finns fyra olika saker att hålla reda på för att hantera spelstaten. Först måste du spåra tillståndet för varje rutnät på spelplanen. Du gör detta med hjälp av en anpassad uppräkning och en mångdimensionell matris. Därefter måste du hålla reda på om spelet har vunnits och av vem. För det tredje måste du spåra vars vänd det är. Slutligen måste du spåra är om spelet är winnable. Denna artikel initialiseras som Sann
och omräknas efter varje spelare har en tur. När alla rutor är fyllda ändras detta till falsk
.
Du börjar med att definiera den anpassade uppräkningen som beskriver en spelare för ditt spel. Överst i din klassfil, ovanför din klassdeklaration, lägg till följande kod:
allmänhet TicTacToePlayer Ingen, PlayerO, PlayerX
Denna uppräkning avgränsar tre spelare (Ingen, PlayerO och PlayerX) och kommer att användas för att spåra både nätstatus och spelvinnaren. Lägg nu till instansvariablerna som hjälper dig att spåra spelets tillstånd. Dessa objekt ska läggas högst upp i din klassdeklaration:
bool winnable; TicTacToePlayer vinnare; TicTacToePlayer current; TicTacToePlayer [,] rutnät;
Du lagrar fyra saker här. Först avgränsar du om spelet fortfarande är winnable. För det andra förklarar du vinnaren. Om vinnaren är Ingen, fortsätter spelningen. Därefter lagrar du den aktuella spelaren. Slutligen lagrar du rutnätet. Vid denna tidpunkt behöver du fortfarande initiera alla dessa variabler. Tänk på att du vet att du måste återinitiera dem när någon klickar på Återställ-knappen och som sådan kan vi skapa en ny metod som hanterar den initialiseringen. Lägg till den nya metoden i din klass under initiera
metod enligt följande:
privat tomt återställning () winnable = true; vinnare = TicTacToePlayer.None; rutnät = nytt TicTacToePlayer [3, 3]; för (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) grid[i, j] = TicTacToePlayer.None;
Nu, ring den här nya metoden från initiera
metod genom att ändra den för att läsa enligt följande:
skyddad åsidosättningsfel Initialisera () Reset (); base.Initialize ();
Vid denna tidpunkt lagrar du all information du behöver, så det borde vara enkelt att börja granska gränssnittet.
Innan du börjar skriva något måste du ange önskad bredd och höjd för din enhet. Du gör det här inuti game1
konstruktör. Ändra det för att läsa enligt följande:
offentliga Game1 () graphics = new GraphicsDeviceManager (this); Content.RootDirectory = "Innehåll"; graphics.PreferredBackBufferWidth = 480; graphics.PreferredBackBufferHeight = 800; // Ramhastighet är 30 fps som standard för Windows Phone. TargetElapsedTime = TimeSpan.FromTicks (333333);
Du har lagt till uttalanden som anger att du vill att bakbuffertbredden ska vara 480 pixlar och höjden ska vara 800 pixlar. Detta underlättar väldigt att dra resten av komponenterna till spelet.
För att hålla sakerna enkla, ska du utföra varje ritningssteg inuti en separat metod. Dessa metoder kommer då att ringas från basen Dra
metod som redan finns. Låt oss börja med att tänka på några bra namn för var och en av arbetsflödet, skapa metoder för det namnet och lägga till samtal till dessa methos från Dra
. Enligt min mening beskriver följande metodnamn tillräckligt både vad de ska göra och de arbetsflödessteg som omfattas:
Skapa dessa metoder nu genom att infoga följande kod under din Dra
metod:
private void DrawGrid () privat void DrawPieces () privat void DrawStatus () privat void DrawResetButton ()
Du skriver koden för dessa metoder på ett ögonblick, men för tillfället måste du lägga till dem i din Dra
metod genom att ändra den för att läsa enligt följande:
skyddad åsidosätt rubbning (GameTime gameTime) GraphicsDevice.Clear (Color.Black); spriteBatch.Begin (); DrawGrid (); DrawPieces (); DrawStatus (); DrawResetButton (); spriteBatch.End (); base.Draw (gametime);
Du kommer märka att du har omringat samtalen till dina hjälpmetoder med samtal till spriteBatch
objekt Börja
och Slutet
metoder. Du gör det här eftersom dina hjälpar metoder kommer alla att dra sprites och det är mycket effektivare att ringa Börja
och Slutet
par en gång inuti Dra
snarare än inuti varje hjälparmetod.
Nu, låt oss arbeta med att få spelningsnätet att dyka upp. Spelningsnätet är en 480 pixlar bred vid 800 pixlar lång bild med en genomskinlig bakgrund och ett vitt rutnät av kvadrater 150 pixlar bred i mitten. Du importerade det tidigare. Att dra det till telefonens skärm kunde inte vara enklare. Du tar den textur du laddat och lagrade i gridTexture
variabel och rita den genom att placera den med hjälp av prevoiusly instantiated gridRectangle
variabel, passerar båda objekten till spriteBatch
objekt Dra
metod. Ändra din DrawGrid
metod att läsa enligt följande:
privat tomt DrawGrid () spriteBatch.Draw (gridTexture, gridRectangle, Color.White);
Spara filen du arbetar med och klicka på F5 för att kompilera och köra ditt projekt. Windows Phone 7 Emulator ska dyka upp och visa ditt Tic-Tac-Toe-rutnät på en svart bakgrund precis som följande bild:
Nu när gallret är på plats, låt oss rita spelbitarna. Vid denna tidpunkt kan vi tillämpa en enkel logik för att visa bitarna men ingenting kommer att visas tills vi lägger till koden för att faktiskt hantera berör och spela spelet. Ändra din DrawPieces
metod enligt följande:
private void DrawPieces () for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) if (grid[i, j] != TicTacToePlayer.None) Texture2D texture = grid[i, j] == TicTacToePlayer.PlayerO ? oPiece : xPiece; Rectangle position = GetGridSpace(i, j, texture.Width, texture.Height); spriteBatch.Draw(texture, position, Color.White);
Om du har ett skarpt öga (eller mer sannolikt visar Visual Studio dig röda squiggly linjer) ser du att GetGridSpace
metod saknas. GetGridSpace
är en bekväm metod som hjälper till att hålla lite kod ut ur DrawPieces
metod och kommer också att vara till nytta när man försöker hantera beröring senare. Lägg till det i slutet av din klassdeklaration enligt följande:
privat rektangel GetGridSpace (int kolumn, int rad, int bredd, int höjd) int centerX = spriteBatch.GraphicsDevice.Viewport.Width / 2; int centerY = spriteBatch.GraphicsDevice.Viewport.Height / 2; int x = centerX + ((kolumn - 1) * 150) - (bredd / 2); int y = centerY + ((rad - 1) * 150) - (höjd / 2); returnera ny rektangel (x, y, bredd, höjd);
Nu ska vi titta på resten av DrawPieces
. Denna metod är lite mer komplicerad än DrawGrid
men det borde fortfarande vara ganska lätt att förstå. Du repeterar över varje rad och kolumn i spelplanen, lagrad i rutnät
variabel och kolla för att se tillståndet för det nätutrymmet. Om rutnätet innehåller en annan spelare än "Ingen" än att rita rätt textur. Du använder den ternära operatören för att ta tag i rätt textur baserat på rutnätets tillstånd och dra sedan det med rektangeln som erhållits från GetGridSpace
.
Nästa problem att hantera drar nuvarande status. Statusen visar vars tur det är, vem vann spelet, eller om spelet är oavgjort. Fyll i metoden enligt följande:
privat tomt DrawStatus () Texture2D texture; om (vinnare! = TicTacToePlayer.None) textur = vinnare == TicTacToePlayer.PlayerO? oWinner: xWinner; annars om (! winnable) texture = noWinner; else texture = current == TicTacToePlayer.PlayerO? oTurn: xTurn; Rektangelposition = ny rektangel (spriteBatch.GraphicsDevice.Viewport.Width / 2 - (texture.Width / 2), 15, texture.Width, texture.Hight); spriteBatch.Draw (textur, position, Color.White);
Denna metod skiljer sig inte mycket från de andra ritningsmetoderna du hittills har skapat. Du har en konsistens och en position och behöver rita texturen på skärmen. Den intressanta delen av denna metod är att bestämma vilken textur som ska ritas. Du först kontrollera om det finns en vinnare. Om det finns, väljer du rätt vinnare textur och ritar det. Därefter kontrollerar du om alla rutnät är upptagna och spelet är inte längre winnable. Om så är fallet väljer du ingen vinnare textur och ritar den. Om ingen av dessa villkor är sanna, kontrollera vilken spelarens tur det är, välj rätt svängtextur och dra den. Om du sammanställer och kör ditt projekt vid denna tidpunkt (genom att trycka på F5) ser du att gränssnittet visar att det är O: s tur:
Slutligen kommer du att skapa koden som drar återställningsknappen. Detta är ganska enkelt. Om det finns en vinnare eller spelet inte längre är winnable, drar du återställningsknappens textur. Ändra DrawResetButton
metod så det lyder som följer:
privat tomt DrawResetButton () om (vinnare! = TicTacToePlayer.None ||! winnable) spriteBatch.Draw (resetButton, resetButtonPosition, Color.White);
Vid denna tidpunkt har du skapat all kod som behövs för att rita ditt gränssnitt och alla dess delar. Nu behöver du bara hantera uppdateringen av ditt spel baserat på beröring från spelarna.
Om du följde den sista handledningen på XNA kommer mycket av följande kod att bli bekant. Hantering av beröring på skärmen är något som är ganska vanligt och det är bara inuti den beröringshanteringskod som du har din spellogik. För att börja, låt oss sätta den grundläggande beröringshanteringskoden i Uppdatering
metod. Hitta Uppdatering
i din game1
klass och ändra det för att läsa enligt följande:
Uppdaterad skyddad överstyrning (GameTime gameTime) if (GamePad.GetState (PlayerIndex.One) .Buttons.Back == ButtonState.Pressed) this.Exit (); TouchCollection berör = TouchPanel.GetState (); om (! rörande && berör.Count> 0) touching = true; TouchLocation touch = touches.First (); HandleBoardTouch (touch); HandleResetTouch (touch); annars om (berör.Count == 0) touching = false; base.Update (gameTime);
Det finns några saker i denna metod att uppmärksamma. Först märker du ett nytt rörande
variabel som inte existerar. Denna variabel lagrar om spelaren berörde styrelsen på föregående Uppdatering
ring och förhindrar att ett långvarigt finger spelas flera gånger utan att släppa från skärmen. Lägg till rörande
som en instansvariabel överst i din klassdeklaration.
bool rörande;
Du märker också att du gör två metalsamtal inom Uppdatering
metod för metoder som inte existerar än. Lägg till dessa metoder i din klassdeklaration direkt under Uppdatering
metod:
privat tomt HandleBoardTouch (TouchLocation touch) privat void HandleResetTouch (TouchLocation touch)
Nu går vi igenom Uppdatering
metod du ser att du söker efter aktuella berör på skärmen. Om det rör sig om och spelaren inte rörde på skärmen tidigare, tar du den första kontakten och skickar den till de metoder som hanterar styrelsen berör och återställer handen. Om spelaren inte rör skärmen och de var tidigare uppdaterar du rörande
variabel till false.
Låt oss nu fylla i HandleBoardTouch
och HandleResetTouch
metoder. Dessa motsvarar arbetsflödet steg 5 respektive 6.
När en användare röra på skärmen måste spelet göra några saker:
Uppdatera HandleBoardTouch
att läsa enligt följande, hantera alla ovanstående steg:
privat void HandleBoardTouch (TouchLocation touch) om (vinnare == TicTacToePlayer.None) for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) Rectangle box = GetGridSpace(i, j, 150, 150); if (grid[i, j] == TicTacToePlayer.None && box.Contains((int)touch.Position.X, (int)touch.Position.Y)) grid[i, j] = current; CheckForWin(current); CheckForWinnable(); current = current == TicTacToePlayer.PlayerO ? TicTacToePlayer.PlayerX : TicTacToePlayer.PlayerO;
Som du kan se följer den här metoden den grundläggande konturen ovan. Om det inte finns en vinnare, det itereras över varje rutnät, kontrollerar om kontakten är i det utrymmet, kontrollerar om utrymmet är öppet och lägger sedan en bit där. Att kontrollera om en vinnare och se till att spelet fortfarande är winnable hanteras med andra metoder. Låt oss stubba ut dessa metoder nu. Under HandleBoardTouch
metod, lägg till följande kod:
privat tomt CheckForWin (TicTacToePlayer-spelare) privat tomt CheckForWinnable ()
Förlåt nu dessa metoder tomma och kompilera och kör ditt spel. Försök vidröra styrelsen genom att klicka på emulatorn och titta på statusmeddelandet och spela upp spelningsstyckena. Du är väl på väg till ett komplett spel nu!
Vid denna tidpunkt kommer du till det riktiga köttet i spelet, den vinnande logiken. Som diskuterats tidigare uppträder ett vinnande tillstånd när en spelares bitar upptar en av raderna, en av kolumnerna eller en av de två diagonalerna. Spelet blir oanvändbart när det inte finns någon vinnare deklarerat och det finns inga lediga platser kvar. För detta spel använder vi en multidimensionell array för att lagra nätets tillstånd och ut ur rutan C # tillhandahåller inte metoder för att kolla rader, kolumner eller diagonaler. Lyckligtvis stöder språket en fantastisk funktion som kallas förlängningsmetoder som du använder här för att göra din kod lite renare.
För att skapa förlängningsmetoder måste du först skapa en ny klass. Klicka på projektets namn i Solution Explorer och klicka på "Add> Class ...". Namn på din klass MultiDimensionalArrayExtensions och klicka på "Add". När din nya fil öppnas för redigering, ändra den så att din klassdeklaration ser ut som följande:
offentliga statiska klass MultiDimensionalArrayExtensions
Du ser att du har lagt till modifierarna offentlig
och statisk
till klassdeklarationen. Detta behövs för att skapa förlängningsmetoder. Nu ska vi skapa ett par metoder som vi behöver, var och en returnerar en IEnumerable
för enkel fråga:
Ändra din klass igen och lägg till metoderna enligt följande:
offentliga statiska klass MultiDimensionalArrayExtensions public static IEnumerableRad (denna T [,] array, int rad) var columnLower = array.GetLowerBound (1); var columnUpper = array.GetUpperBound (1); för (int i = columnLower; i <= columnUpper; i++) yield return array[row, i]; public static IEnumerable Kolumn (denna T [,] array, int kolumn) var rowLower = array.GetLowerBound (0); var rowUpper = array.GetUpperBound (0); för (int i = rowLower; i <= rowUpper; i++) yield return array[i, column]; public static IEnumerable Diagonal (denna T [,] array, DiagonalDirection riktning) var rowLower = array.GetLowerBound (0); var rowUpper = array.GetUpperBound (0); var columnLower = array.GetLowerBound (1); var columnUpper = array.GetUpperBound (1); för (int rad = rowLower, column = columnLower; row <= rowUpper && column <= columnUpper; row++, column++) int realColumn = column; if (direction == DiagonalDirection.DownLeft) realColumn = columnUpper - columnLower - column; yield return array[row, realColumn]; public enum DiagonalDirection DownRight, DownLeft public static IEnumerable Allt (denna T [,] array) var rowLower = array.GetLowerBound (0); var rowUpper = array.GetUpperBound (0); var columnLower = array.GetLowerBound (1); var columnUpper = array.GetUpperBound (1); för (int rad = rowLower; row <= rowUpper; row++) for (int column = columnLower; column <= columnUpper; column++) yield return array[row, column];
Du kan se att det inte finns så mycket med dessa metoder. För var och en av dem är en viss del av den flerdimensionella gruppen itererad över och den delen av matrisen returneras som en del av en IEnumerable
. Den enda riktigt knepiga delen kan vara användningen av avkastning
nyckelord. En förklaring av beteendet för det sökordet ligger utanför ramen för den här artikeln, men referensen C # på MSDN för avkastningsordet kan vara till hjälp om du vill lära dig mer. Som en sidotal tas mycket av arbetet med dessa förlängningsmetoder från ett användarbidrag på StackOverflow som du kan hitta här
Nu när de nödvändiga utvidgningsmetoderna genomförs, bör det vara ganska enkelt att genomföra win logiken. Låt oss gå tillbaka till CheckForWin
metod och implementera det. Uppdatera metoden för att läsa enligt följande:
privat tomt CheckForWin (TicTacToePlayer-spelare) FunccheckWinner = b => b == spelare; om (grid.Row (0) .All (checkWinner) || grid.Row (1) .All (checkWinner) || grid.Row (2) .All (checkWinner) || grid.Column (0) .All checkWinner) || grid.Column (1) .All (checkWinner) || grid.Column (2) .All (checkWinner) || grid.Diagonal (MultiDimensionalArrayExtensions.DiagonalDirection.DownRight) .All (checkWinner) || grid.Diagonal (MultiDimensionalArrayExtensions.DiagonalDirection.DownLeft) .Alla (checkWinner)) vinnare = spelare;
Med tanke på vad du redan vet från att skapa förlängningsmetoder, borde det vara ganska enkelt att dechiffrera. Du skapar först en "Func": http: //msdn.microsoft.com/en-us/library/bb549151.aspx
objekt som agerar en delegat och låter dig använda ett lambda uttalande (det b => b == spelare
del) för att fråga en IEnumerable
(som de som returneras från förlängningsmetoden) och returnera a bool
. Du tillämpar sedan detta Func
objekt över varje rad, kolumn och diagonal med hjälp av IEnumerable.All
metod. Om något av dessa fall är sant, tilldelar du vinnare
instansvariabel till spelare
parameter. Om inget av dessa fall är sant så händer ingenting.
Ändra nu din CheckForWinnable
metod:
privat tomt CheckForWinnable () om (vinnare == TicTacToePlayer.None) FunccheckNone = b => b == TicTacToePlayer.None; om (! grid.All () .Varje (checkNone)) winnable = false;
Denna metod liknar mycket CheckForWin
. Först kontrollerar du för att se om spelet har en vinnare. Om det inte gör det skapar du en Func
objekt som kommer att kontrollera om ett objekt är lika med TicTacToePlayer
Ingen
. Du tillämpar sedan detta Func
mot alla utrymmen i rutnätet och kontrollerar om någon av utrymmena är obesluten. Om ingen är, är spelet inte längre winnable, och du växlar instansvariabeln winnable
.
Vid denna tidpunkt är ditt spel redo att gå. Du kan kompilera och köra ditt projekt genom att slå F5 och börja spela (antingen själv eller med en partner). Vänd om att placera bitar på brädet, titta på statusmeddelandet och se vad som händer när du vinner. När du vinner eller ritar, klicka på återställningsknappen och titta på spelet återgå till sin ursprungliga status.
Vid denna tidpunkt finns det en mängd olika saker du kan göra. Du kan genomföra ett vinnande räkning som visar hur många olika tider varje spelare har vunnit. Du kan ändra hur stycken visar, eller lägg till en cool animation när en vinnare förklaras. Du kan tema spelet för att göra det lite mer intressant, kanske genom att pitta Rebel Alliance mot Galactic Empire?
Vid denna tidpunkt är det allt upp till dig att expandera och utveckla vad du vill. Jag hoppas att du njöt av att följa denna handledning så mycket som jag tyckte om att skriva det och ser fram emot att höra dina kommentarer.