Gameprogrammeren: Overerving in Painter Arjan Egges Paul Bergervoet Wouter van Toll
Onderwerpen in dit voorbeeld Klassen en objecten Overerving (Abstracte klassen)
Een object uitbreiden Voorbeeld: Painter-klasse als subklasse van Game Variabelen toevoegen (spriteBatch, …) Methodes toevoegen (HandleInput) Methodes vervangen (Update, Draw, …) Ander voorbeeld: ThreeColorGameObject-klasse als basis voor alle game-objecten in Painter (Ball, PaintCan, Cannon)
de constructormethode class ThreeColorGameObject { protected Texture2D colorRed, colorGreen, colorBlue; protected Texture2D currentColor; protected Vector2 position, velocity; protected Color color; public ThreeColorGameObject(Texture2D colorRed, Texture2D colorGreen, Texture2D colorBlue) this.colorRed = colorRed; this.colorGreen = colorGreen; this.colorBlue = colorBlue; Color = Color.Blue; position = Vector2.Zero; velocity = Vector2.Zero; } … Toegang verlenen aan subklassen Parameters van de constructormethode
class ThreeColorGameObject { ... { ... public virtual void HandleInput(InputHelper inputHelper) { } public virtual void Update(GameTime gameTime) position += velocity * (float)gameTime.ElapsedGameTime.TotalSeconds; public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch) spriteBatch.Draw(currentColor, position, Color.White); = de methode mag vervangen worden in een subklasse Handige methoden voor game-objecten!
De klasse ThreeColorGameObject class ThreeColorGameObject { ... public Vector2 Center { get { return new Vector2(currentColor.Width, currentColor.Height) / 2; } public Vector2 Position { get { return position; } public Color Color... Handige properties voor game-objecten!
De nieuwe Ball-klasse class Ball : ThreeColorGameObject { bool shooting; public Ball(ContentManager Content) : base(Content.Load<Texture2D>("spr_ball_red"), Content.Load<Texture2D>("spr_ball_green"), Content.Load<Texture2D>("spr_ball_blue")) } … Speciale versie van ThreeColorGameObject… … namelijk met een extra membervariabele! Informatie doorgeven aan constructormethode van ThreeColorGameObject base wijst naar het huidige object alsof hij het type van de superklasse heeft!
Ball overschrijft HandleInput Vervang de originele versie public override void HandleInput(InputHelper inputHelper) { if (inputHelper.MouseLeftButtonPressed() && !shooting) shooting = true; velocity = (inputHelper.MousePosition - position) * 1.2f; }
Andere methoden in de Ball-klasse public override void Reset() { base.Reset(); position = new Vector2(65, 390); velocity = Vector2.Zero; shooting = false; } Roep de originele versie aan
Andere methoden in de Ball-klasse public override void Update(GameTime gameTime) { if (shooting) { velocity.X *= 0.99f; velocity.Y += 6; } else { Color = Painter.GameWorld.Cannon.Color; position = Painter.GameWorld.Cannon.BallPosition - Center; if (Painter.GameWorld.IsOutsideWorld(position)) Reset(); base.Update(gameTime); Welke versie wordt hier aangeroepen?
Omgaan met ‘game over’ Membervariabelen in de GameWorld-klasse: Texture2D background, gameover; Ball ball; PaintCan can1, can2, can3; Cannon cannon; int lives; Texture2D livesSprite; Game over overlay Bijhouden en tekenen aantal levens
GameWorld: HandleInput public void HandleInput(InputHelper inputHelper) { if (lives > 0) cannon.HandleInput(inputHelper); ball.HandleInput(inputHelper); } else if (inputHelper.KeyPressed(Keys.Space)) Reset(); Ander gedrag afhankelijk van het aantal overgebleven levens
GameWorld: Update public void Update(GameTime gameTime) { if (lives > 0) ball.Update(gameTime); can1.Update(gameTime); can2.Update(gameTime); can3.Update(gameTime); } Objecten alleen updaten indien speler nog levens heeft
Teken ‘game over’-overlay public void Draw(GameTime gameTime, SpriteBatch spriteBatch) { spriteBatch.Begin(); spriteBatch.Draw(background, Vector2.Zero, Color.White); ball.Draw(gameTime, spriteBatch); cannon.Draw(gameTime, spriteBatch); can1.Draw(gameTime, spriteBatch); can2.Draw(gameTime, spriteBatch); can3.Draw(gameTime, spriteBatch); for (int i = 0; i < lives; i++) spriteBatch.Draw(livesSprite, new Vector2(i * livesSprite.Width + 15, 20), Color.White); if (lives <= 0) spriteBatch.Draw(gameover, new Vector2(Painter.Screen.X – gameover.Width, Painter.Screen.Y - gameover.Height) / 2, Color.White); spriteBatch.End(); } Teken ‘game over’-overlay
Geluidseffecten (finishing touch) In de Ball-klasse: Membervariabele toevoegen: Effect laden in constructor: Afspelen bij afschieten: protected SoundEffect ballShot; ballShot = Content.Load<SoundEffect>("snd_shoot_paint"); if (inputHelper.MouseLeftButtonPressed() && !shooting) { shooting = true; velocity = (inputHelper.MousePosition - position) * 1.2f; ballShot.Play(); }
Abstracte klasse? ThreeColorGameObject mag abstract zijn Je maakt altijd een Ball, PaintCain, etc., en nooit een “gewone” ThreeColorGameObject Met abstract class ThreeColorGameObject { ... } kun je dit afdwingen