Inledning
Denna artikel är en direkt fortsättning på Asteroids - Del 1 . I denna artikel ser du exempel på hur avläsning av tangentbordet fungerar i XNA samt hur du kan rita ut sprites på ett mer avancerat sätt.
Vi ska få rymdskeppet att rotera när vänster respektive höger piltangent trycks ned.
Roterad uppritning
Rymdskeppet ska nu ha möjlighet att rotera och vi behöver därmed en variabel för att hålla reda på vilken vinkel vi ska rotera med. En float passar bra så vi deklarerar en och kallar den angle.
Texture2D gfx;
Vector2 position;
float angle = 0;
public Game1()
{
//...
Till skillnad från vad du kanske lärt dig på matematiken så mäts inte vinklar i grader särskilt ofta. Ett område där detta är aktuellt är just inom datorvärlden och så också inom programmering. Den enhet vi ska använda för vinklar kallas radianer. Radianer bygger på π och vad som är ett varv, ett halvt varv eller ett fjärdedels varv får andra värden i radianer. Tabellen nedan ger dig en liten överblick.
grader | radianer | värde |
---|---|---|
360° | 2*π | 6.283 |
180° | π | 3.142 |
90° | π/2 | 1.571 |
45° | π/4 | 0.785 |
1° | π/180 | 0.017 |
Vi ska nu använda variabeln angle vid uppritningen. Som nämnts i tidigare artiklar så går det att använda SpriteBatch.Draw() på en rad olika sätt. Vi ändrar från tidigare artikel till att rita ut på följande sätt:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
//spriteBatch.Draw(gfx, position, Color.White);
spriteBatch.Draw(gfx, position, null, Color.White, angle + (float)Math.PI/2,
new Vector2(gfx.Width / 2, gfx.Height / 2), 1.0f, SpriteEffects.None, 0);
spriteBatch.End();
base.Draw(gameTime);
}
De första parametrarna gfx och position anger vilken grafik som ska användas samt var på skärmen vi ska rita ut. Den tredje parametern anger vilken del av gfx som ska användas vid utritningen. Det kan ju vara som så att gfx innehåller mer grafik än bara rymdskeppet. I vårt exempel ska vi använda hela gfx så vi skickar värdet null. null är vårt sätt att tala om att vi inte skickar något värde som tredje parameter. null är ett reserverat ord som används för att tala om att något saknar värde, ej att förväxlas med värdet 0 då det är ett värde.
Fjärde parametern anger med vilken vinkel (i radianer) som spriten ska roteras med. Vi måste kompensera med att lägga till Math.PI/2 då vår grafik är ritad så att skeppet pekar rakt upp.
Vi måste kompensera så att skeppet pekar i den riktning som variabeln angle anger. Koordinatsystemet i XNA (se bild ovan) är roterat så att 0° pekar åt höger. Därmed måste även vårt skepp göra det då angle = 0.
Femte parameterna är en Vector2 som anger var i bilden (gfx) centrum för rotationen ska vara. Normalt brukar centrum av grafiken (bredd / 2, höjd /2) anges. Testa gärna med att ändra parametern till new Vector2(0, 0) för att se skillnad senare.
Sjätte parametern anger om sprite'n ska skalas. Värdet 1.0f anger att ingen skalning ska ske. Ett värde på t.ex 0.5f hade angett en förminskning och ett värde på 2.0f hade angett en förstoring. Detta kan du också testa!
Bokstaven f efter ett värde anger att värdet är angett som en float. Normalt är nämligen att angivna decimala värden är av typen double i C#.
Näst sista parametern ger dig möjlighet att spegla sprite'n vid uppritningen, antingen horisontellt eller vertikalt.
Sista parametern är ett värde mellan 0 och 1.0 som kan användas för att få en automatiskt sorterad uppritning under speciella förhållanden. D v s en sprite som ritas upp senare än en annan sprite kan ändå hamna "bakom" den första.
Hantera tangentbordet
All logik och förflyttning som rör spelet ska ske i metoden Update() i XNA. Vi börjar med koden direkt:
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
KeyboardState ks = Keyboard.GetState();
if (ks.IsKeyDown(Keys.Left))
{
angle -= 0.05f;
}
if (ks.IsKeyDown(Keys.Right))
{
angle += 0.05f;
}
base.Update(gameTime);
}
Statusen på tangnetbordet kan lagras i en variabeltyp kallas KeyboardState. I exemplet ovan så sparar vi statusen på tangentbordet i variabeln ks. Statusen läses av med metoden GetState() som nås via Keyboard.
Med if-satser kan vi nu undersöka om vissa speciella knappar är nedtryckta. Metoden IsKeyDown() finns att använda i variabeltypen KeyboardState. Knapparnas namn finns i strukturen Keys och förbestämda.
Trycker vi vänster pil så minskar vi variabeln angle. Höger pil ökar. På så sätt kontrollerar vi värdet på angle som sedan används vid uppritningen.
Klart för att testa!