Inledning
Denna artikel är en direkt fortsättning på Asteroids - Del 3 . Denna gång gäller det att få rymdskeppet att skjuta. För att hålla koll på hur många skott som flyger på skärmen så ska vi lära oss skriva ut text med hjälp av klassen SpriteFont.
Nya variabler
Okej, vi kommer att behöva en rad nya variabler. Vi behöver grafik till skottet, en font för att rita ut text. Vi kommer också att behöva variabler för att mäta tiden från det att ett skott avlossats till dess att nästa skott kan avlossas. Varje skott behöver en aktuell position och en hastighet för att vi ska kunna rita ut och flytta dem. Till detta använder vi List av typen Vector2.
Ladda hem grafiken till skottet nedan.
Deklarera följande variabler i början av programmet.
//Skott
Texture2D gfx_shot;
SpriteFont font;
List<Vector2> shot_pos = new List<Vector2>();
List<Vector2> shot_speed = new List<Vector2>();
const int shot_delay = 200;
int shot_time;
SpriteFont
För att kunna skriva ut något på skärmen så behövs en SpriteFont. En SpriteFont är liksom en textur en komponent som ska ligga i Content i Solution Explorern. Skillnaden är dock att du kan skapa en ny SpriteFont direkt från Visual Studio genom att högerklicka på Content i Solution Explorern och välja "Add -> New Item...".
Välj alternativet "Sprite Font" och döp filen till myFont.spritefont.
En SpriteFont är egentligen ett XML-dokument som talar om vilket storlek, stil och typsnitt som ska användas när SpriteFont'en ska skapas. Detta betyder bland annat att vi måste göra några ändringar i filen myFont.spritefont. Dubbelklicka på filen i Solution Explorer'n och gör ändringar enligt bilden nedan. Ändra FontName till Verdana och Size till 16.
En SpriteFont-variabel har vi redan deklarerat vid namn font. Inladding sker precis som med texturer i metoden LoadContent(). Vi passar på att ladda grafiken för skottet samtidigt. Placera följande kod där:
gfx_shot = Content.Load<Texture2D>("shot");
font = Content.Load<SpriteFont>("myFont");
Kvar är nu bara uppritning. Count i klassen List (shot_pos) ger oss det aktuella antalet skott som vi har på skärmen. Vi använder oss av metoden DrawString(). Uppritning sker som vanligt i metoden Draw() i vårt projekt. Placera följande kod där:
spriteBatch.DrawString(font, "Shots: " + shot_pos.Count, new Vector2(10, 10), Color.White);
Testa nu ditt projekt! Shots kommer alltid att vara 0 då vi ännu inte avfyrar något.
Skapa skott
I Update() måste vi lägga till en koll för knappen SPACE på tangentbordet. Om det har gått tillräckligt lång tid från föregående skott så ska vi lägga till ett skott i listan shot_pos samt med rätt hastighet i listan shot_speed.
shot_time -= gameTime.ElapsedGameTime.Milliseconds;
if (shot_time < 0)
{
shot_time = 0;
}
if (ks.IsKeyDown(Keys.Space) && shot_time == 0)
{
shot_time = shot_delay;
shot_pos.Add(new Vector2(position.X, position.Y));
shot_speed.Add(new Vector2(5 * (float)Math.Cos(angle), 5 * (float)Math.Sin(angle)));
}
Variabeln shot_time används för att mäta tiden mellan skotten. Varje gång Update()-metoden körs så räknas variabeln ned med den tid i millisekunder som har gått sedan föregående Update(). Variabeln gameTime i Update() innehåller all information om tid.
Om vi trycker SPACE och tiden är mogen för ett nytt skott så skapas två Vector2 för att beskriva skottets position och hastighet. Positionen blir samma som rymdskeppets och hastigheten bygger på skeppets vinkel (angle).
Rita ut skotten
I metoden Draw() behöver vi göra en loop för att rita ut alla skott:
for (int i = 0; i < shot_pos.Count; i++)
{
spriteBatch.Draw(gfx_shot, shot_pos[i], null, Color.White, 0,
new Vector2(gfx_shot.Width / 2, gfx_shot.Height / 2), 1.0f, SpriteEffects.None, 0);
}
Testa nu!
Uppdatera skotten
Som du kanske märkte så rör inte skotten på sig. Vi måste gå igenom alla skott i metoden Update() för att förlytta dem precis som vi gjort med rymdskeppet. Samtidigt kan vi också passa på att städa bort de skott som flygit för långt iväg.
for(int i=0; i < shot_pos.Count; i++)
{
shot_pos[i] += shot_speed[i];
if (shot_pos[i].X < -100 || shot_pos[i].X > graphics.GraphicsDevice.Viewport.Width + 100
|| shot_pos[i].Y < -100 || shot_pos[i].Y > graphics.GraphicsDevice.Viewport.Height + 100)
{
shot_pos.RemoveAt(i);
shot_speed.RemoveAt(i);
continue;
}
}
Det var allt denna gång!