Gameprogrammeren: Player input in Painter Arjan Egges Paul Bergervoet Wouter van Toll
Onderwerpen in dit voorbeeld Sprites tekenen Variabelen Input handling Methoden (Klassen)
De Painter-game Screenshot: Heeft een kanon dat de muispointer volgt
Roterend kanon Membervariabelen in de Painter-klasse: GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D background, cannonBarrel; Vector2 barrelPosition, barrelOrigin; float angle;
Roterend kanon LoadContent-methode protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); background = Content.Load<Texture2D>("spr_background"); cannonBarrel = Content.Load<Texture2D>("spr_cannon_barrel"); barrelPosition = new Vector2(72, 405); barrelOrigin = new Vector2(cannonBarrel.Height, cannonBarrel.Height) / 2; } Height
Roterend kanon Hoek uitrekenen in de Update-methode: protected override void Update(GameTime gameTime) { MouseState mouse = Mouse.GetState(); double opposite = mouse.Y - barrelPosition.Y; double adjacent = mouse.X - barrelPosition.X; angle = (float)Math.Atan2(opposite, adjacent); }
Roterend kanon Alles tekenen protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.White); spriteBatch.Begin(); spriteBatch.Draw(background, Vector2.Zero, Color.White); spriteBatch.Draw(cannonBarrel, barrelPosition, null, Color.White, angle, barrelOrigin, 1.0f, SpriteEffects.None, 0); spriteBatch.End(); } De hoek geven we mee als parameter
Als de muisknop is ingedrukt (maar niet per se wordt) Roterend kanon Hoek kanon alleen aanpassen nadat je geklikt hebt protected override void Update(GameTime gameTime) { MouseState mouse = Mouse.GetState(); if (mouse.LeftButton == ButtonState.Pressed) double opposite = mouse.Y - barrelPosition.Y; double adjacent = mouse.X - barrelPosition.X; angle = (float)Math.Atan2(opposite, adjacent); } Als de muisknop is ingedrukt (maar niet per se wordt)
Toggling/wisselen Actie eenmalig uitvoeren als de speler de muisknop indrukt Wanneer drukt de speler op een knop? 1: als de speler de vorige keer de muisknop nog niet had ingedrukt 2: als de speler nu de muisknop wel ingedrukt heeft
Vorige + huidige status Twee MouseState membervariabelen: In de Update-methode: MouseState current, previous; protected override void Update(GameTime gameTime) { previous = current; current = Mouse.GetState(); // doe iets… }
Vorige + huidige status Muisklik afhandelen: protected override void Update(GameTime gameTime) { previous = current; current = Mouse.GetState(); if (current.LeftButton == ButtonState.Pressed && previous.LeftButton == ButtonState.Released) double opposite = current.Y - barrelPosition.Y; double adjacent = current.X - barrelPosition.X; angle = (float)Math.Atan2(opposite, adjacent); }
Alternatief met toetsenbord protected override void Update(GameTime gameTime) { KeyboardState k = Keyboard.GetState(); if (k.isKeyDown(Keys.K)) double opposite = mouse.Y - barrelPosition.Y; double adjacent = mouse.X - barrelPosition.X; angle = (float)Math.Atan2(opposite, adjacent); } Wordt alleen uitgevoerd als de K-toets ingedrukt is!
Spelerinvoer afhandelen Wordt omslachtig door previous/current states… previousMS = currentMS; previousKS = currentKS; currentMS = Mouse.GetState(); currentKS = Keyboard.GetState(); if (currentKS.IsKeyDown(Keys.R) && previousKS.IsKeyUp(Keys.R)) cannon.Color = Color.Red; else if (currentKS.IsKeyDown(Keys.G) && previousKS.IsKeyUp(Keys.G)) cannon.Color = Color.Green; else if (currentKS.IsKeyDown(Keys.B) && previousKS.IsKeyUp(Keys.B)) cannon.Color = Color.Blue; ... Veel dubbele code, dus je maakt snel fouten!
De InputHelper-klasse We maken een hulpklasse: class InputHelper { MouseState currMS, prevMS; KeyboardState currKS, prevKS; // methoden en properties } Deze informatie wordt bewaard in een InputHelper object De klasse InputHelper beschrijft hoe een object van het type InputHelper eruit ziet!
class Painter : Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; InputHelper inputHelper; … static void Main() { Painter game = new Painter(); game.Run(); } public Painter() { Content.RootDirectory = "Content"; graphics = new GraphicsDeviceManager(this); inputHelper = new InputHelper(); Declaratie Toekenning en maken van een instantie
bijwerken in zijn eigen Handige methoden class InputHelper { MouseState currMS, prevMS; KeyboardState currKS, prevKS; public void Update() prevMS = currMS; prevKS = currKS; currMS = Mouse.GetState(); currKS = Keyboard.GetState(); } … InputHelper object bijwerken in zijn eigen Update methode
Handige methoden = deze methode mag in een andere klasse aangeroepen worden. public bool IsMouseLeftButtonPressed() { return currMS.LeftButton == ButtonState.Pressed && prevMS.LeftButton == ButtonState.Released; } public bool IsKeyPressed(Keys k) return currKS.IsKeyDown(k) && prevKS.IsKeyUp(k);
InputHelper gebruiken in de game protected override void Update(GameTime gameTime) { inputHelper.Update(); HandleInput(inputHelper); // hier nog de game wereld bijwerken } Sla het verschil in keyboard/mouse state op Doe er iets mee
Cannon krijgt zijn eigen HandleInput public void HandleInput(InputHelper inputHelper) { if (inputHelper.KeyPressed(Keys.R)) Color = Color.Red; else if (inputHelper.KeyPressed(Keys.G)) Color = Color.Green; else if (inputHelper.KeyPressed(Keys.B)) Color = Color.Blue; double opposite = inputHelper.MousePosition.Y - position.Y; double adjacent = inputHelper.MousePosition.X - position.X; angle = (float)Math.Atan2(opposite, adjacent); } Veel korter en veel overzichtelijker!