Bookmark and Share

Svårighetsgrad
Svårighetsgrad
Betyg (7 röster)
BetygBetygBetygBetygBetyg
 

Space Race - Del 3

Inledning

UPPDATERING: Artikeln har uppdaterats till XNA 4.0.

Läs mer om ändringar från XNA 3.1 till 4.0 under sista rubriken.

Eftersom detta är del 3 i en artikelserie så behöver du läsa del 1 och 2 först om du inte redan gjort det.

I denna artikel ska vi försöka färdigställa projektet och börja få en mer färdig produkt. Trots detta så kommer det finnas utrymme kvar för förbättringar både vad det gäller grafik, kod och spelidé. Det som tas upp i denna artikel är hantering av "game states", tidberäkning, ljud, byte av banor och mer grafik bl.a. ett GUI.

Alla steg i koden kommer inte att beskrivas utan vi fokuserar på att beskriva de viktigaste bitarna för att du skall förstå helheten och koden som du laddar hem. I slutet av artikeln kan du ladda hem och testa projektet.

Game states

I enklare spel räcker det oftast a definiera olika tillstånd (states) som spelet kan befinna sig i. I detta fall, med en spelidé som att ta sig från punkt A till punkt B så snabbt som möjligt med begränsad mängd bränsle, så tänker vi oss följande tillstånd:

Dessa tillstånd behövs för att kunna presentera viktig information för spelaren. För att hålla reda på de olika tillstånden så skapar vi en enum. En enum är en speciell konstruktion som innehåller namngivna element. En enum kan sedan bara ha ett värde som redan finns som namnmgivet element. Varje element får en unik siffra. En stor fördel med enum är att koden blir mer lättläst och begriplig.

Av de tillstånd som beskrivits gör vi följande enum och döper varje tillstånd till engelska. Exemplet nedan visar var du kan placera enumdeklarationen.

Vi deklarerar variabeln gameState och börjar med att försätta spelet i tillståndet READY. Tillståndsvariabeln gameState använder vi sedan för att påverka vad som sker i spelets Update och Draw. Vi gör detta genom att använda switch-satser för varje tillstånd enligt exemplet nedan:

I Update väntar tillstånden WON, GAMEOVER och READY egentligen bara på rätt förutsättningar för att gå över till PLAYING. I alla fallen handlar det om att trycka på SPACE för att gå vidare.

I Draw så visas det speciell grafik om gameState är i WON, GAMEOVER eller READY, då spelet ej pågår. Den speciella grafiken är det som kallas "overlays". För tillståndet READY ser det ut som bilden nedan:

bild

Tidräkning

Tiden för att klara av en bana är helt enkelt satt till 2 minuter. Detta är givetvis något som borde anpassas efter hur banan är konstruerad. I koden löses detta med en TimeSpan sruktur kallad levelTime. Det finns också en TimeSpan kallad warningTime som användas för att signalera att tiden närmar sig att ta slut. warningTime är satt till 30 sekunder.

Vid varje Update räknas levelTime ned med den tid som passerat tills dess att levelTime når noll. När detta inträffar tar spelet slut (GAMEOVER).

Ljudeffekter

Den teknik som vi använder för att spela bakgrundsmusik och ljudeffekter beskrivs i artikeln "Ljud i XNA" så vi nöjer oss med att beskriva vilka ljud vi använder.

Händelse Ljud
Bakgrundsmusik music.mp3
Sköldarna når 0 explosion.wav
Skeppet landra i mål win.wav
Skeppet accelererar throttle.wav

Byte av banor

Banorna lagras som bilder i PNG-format. Det betyder att det bara krävs ett enkelt ritprogram för att skapa nya utmanande banor. För att underlätta bytet av banor så har vi helt enkelt namngett banorna som Level01.png, Level02.png, etc. Med variabeln levelIndex håller vi reda på vilken bana vi är på. För att byta bana ökar vi levelIndex och letar i Content om det finns en bild som heter "Level" + levelIndex + ".xnb". XNB är det format som XNA konverterar all Content till. För att lägga till fler banor behövs endast fler LevelXX.xnb filer i Contentkatalogen.

Vi tar en titt på metoden som laddar nästa bana.

Skulle inte "nästa bana" hittas så återgår levelIndex till 1, dvs. första banan laddas igen.

LoadNextLevel återställer skeppets startposition och all tidräkning. Därmed anropas även LoadNextLevel när en bana skall laddas om vid t.ex. tidsbrist eller att skeppet kraschar. Villkoren för att klara av banan och komma till nästa är följande:

CheckCollision har modifierats till att returnerar true om skeppet landat på mål, pekar uppåt och har låg hastighet. "Pekar uppåt" betyder en vinkelavvikelse på max 10 grader åt höger eller vänster vilket löses med metoden PointingUp.

Explosion

När skeppets sköldar når 0 p.g.a. kollisioner så har vi lagt in en liten animation av en explosion. Tekniken för detta beskriv i artikeln Animationer.

Nya mätare

Nivån på skeppets sköld samt den tid som är kvar för att hinna klara av banan visas med en vanlig SpriteFont. Vi gör ett enkelt trick för att få skuggning på utskriften (outline). Tricket går ut på att skriva ut samma text fast svart med någon pixels förskjutning innan texten skrivs ut. Tyvärr finns det inte inställning för "outline" i en SpriteFont.

bild

Vi har lagt lite med tid på att skapa en rolig mätare för bränslenivån. Tanken är att den skall likna en analog mätare som finns i t.ex. bilar. Här finns också rum för förbättringar.

bild

Man skulle kunna kalla detta för ett enkelt GUI (graphical user interface) eller HUD (heads-up display)

Avslutning

I denna sista del av Space Race presenterar vi mer ett färdigt resultat än en guide. Här nedan kan du ladda hem hela projektet med ljudeffekter och allt. Vill du vidareutveckla spelet så är det upp till dig. För privat bruk får du göra vad du vill med koden och grafiken men om du tänker publicera dina resultat av en vidareutveckling så var noga med att ange källan (csharpskolan.se). Helst av allt vill vi bli informerade i förväg.

Som nämnts innan så finns det många förbättringar at göra, har listar vi några förslag:

Listan kan göras ännu längre.

Färdigt projekt

Projekten innehåller all "content" både rå och kompilerad.

Uppgradering till XNA 4.0

Ljudeffekterna (XACT) behövdes uppgraderas. Detta gjordes enkelt genom att kompilera om xap-filen i XACT.

StorageContainer.TitleLocation har försvunnit så sökvägen till banorna fick redigeras lite.

En märklig sag var att ordningen på pixeldatan i texturerna som laddades in har ändrats. Tidagare var ordningen ARGB (alpha, red, green, blue) men verkar numera vara i ordningen #ABGR. Det betyder att färgen röd tidigare definerades som 0xFFFF0000 nu definieras som 0xFF0000FF.

Kommentarer

2 inlägg