Hoorcollege 4 Objecten en methoden
Eigen methode toevoegen class Painter : Game { public void HandleInput() { … } protected override void Update(GameTime gameTime) { HandleInput(); … } Eigen bedachte methode!
De ‘HandleInput’ methode public void HandleInput() { prevMS = currMS; prevKS = currKS; currMS = Mouse.GetState(); currKS = Keyboard.GetState(); if (currKS.IsKeyDown(Keys.R) && prevKS.IsKeyUp(Keys.R)) cannonColor = Color.Red; else if (currKS.IsKeyDown(Keys.G) && prevKS.IsKeyUp(Keys.G)) cannonColor = Color.Green; else if (currKS.IsKeyDown(Keys.B) && prevKS.IsKeyUp(Keys.B)) cannonColor = Color.Blue; }
Verschillende soorten methoden Methoden met een resultaat object: Methoden zonder een resultaat object: Methoden met parameters: Methoden zonder parameters: currMS = Mouse.GetState(); GraphicsDevice.Clear(Color.Olive); currKS.IsKeyDown(Keys.G) spriteBatch.Begin()
Verschillende soorten methoden Sommige methoden bewerken objecten Sommige methoden bewerken geen objecten (maar horen wel bij een klasse) – Deze methoden noemen we static In de methode header kun je zien wat voor soort methode het is! spriteBatch.Begin() Console.WriteLine("Hallo");
Methode headers public static void Main() { … } public void HandleInput() { … } protected override void Update(GameTime gameTime) { … } static methode (bewerkt geen object)methode zonder resultaatobject methode zonder parameters methode met 1 parameter
Methoden met resultaat public float CalculateSquare(float x) { return x*x; } Vergelijkbaar met wiskundige functie – f(x) = x 2 ; In het gebruik: We stoppen er een float in......en we leveren een float op. Met return geven we aan wat opgeleverd wordt. float f = CalculateSquare(10.0f);
Methoden met resultaat Na een return stopt de methode Daar kunnen we gebruik van maken! public int SomeMethod() { return 12; int tmp = 45; } Wordt nooit uitgevoerd! public float SquareRoot(float f) { if (f < 0.0f) return 0.0f; // Hier weten we nu zeker dat altijd geldt dat f >= 0 }
Methoden met resultaat Return waarde kunnen we in een variabele bewaren: Maar dat hoeft niet! float f = CalculateSquare(10.0f); if (CalculateSquare(10.0f) != 100.0f) Console.WriteLine("Your processor is broken");
Tekenen of opleveren? Console.Writeline (x,...) spriteBatch.Draw(cannon, Vector2.Zero,...) return x; resultaat komt meteen op het scherm resultaat wordt teruggegeven aan de aanroeper, die zelf kan beslissen wat hij ermee doet
Declaraties vs. parameters Lijken erg op elkaar protected override void Update(GameTime gameTime) { int red; red = gameTime.TotalGameTime.Milliseconds; … } public float SquareRoot(float f) { if (f < 0.0f) return 0.0f; … } Gebruiken we als locale variabele Locale variabele
Methoden Hoe meer parameters, des te flexibeler de methode public void Draw(Texture2D sprite, Vector2 position, Color col, float rotation, float scale, bool mirror, float transparency, Rectangle part, Vector2 origin, Rectangle destination, …) { … en des te lastiger aan te roepen...
Flexibiliteit Veel parameters: Nu lastig om te programmeren In de toekomst misschien gemakkelijk uit te breiden Weinig parameters: Nu gemakkelijk om te programmeren In de toekomst misschien lastig te onderhouden
Programma en geheugen opdrachten methoden klasse variabelen objecten klasse zijn gegroepeerd in hebben als type veranderen bewerken
Objecten en geheugen Built-in types in het geheugen - Numerieke typen (int, double,...) - Tekst (strings) - Waarheidswaarden int i = 12; double pi = 3.14; 12 i 3.14 pi string s = "hallo, "; s += "Arjan"; "hallo, " s "hallo, Arjan" bool b = true; b = !b; true b false
Objecten en geheugen Gevolg: public void keerTwee(int i) { i *= 2; } int i = 3; keerTwee(i); // wat is nu de waarde van i? public void keerTwee(int getal) { getal *= 2; } Nog steeds 3, want de waarde wordt gekopieerd bij het doorgeven aan de keerTwee methode!
Objecten en geheugen Typen die gebaseerd zijn op een klasse werken anders cannonBarrel Texture2D … … … width height data … verwijzing!
Waarom verwijzingen? Bij een aanroep van een methode wordt niet het hele geheugen gekopieerd, alleen de verwijzing Objecten kunnen worden doorgegeven tussen methoden
Verwijzingen Built-in types (int, double, float) – Values – Speciaal geval: string “non-mutable” Object-typen gedefinieerd door klassen – References (verwijzingen) Object-typen gedefinieerd door structs – Values (!) – Wordt gebruikt voor simpele datastructuren – Voorbeelden: Vector2, Point, Color…
Creatie van objecten Opbouw van object is gespecificeerd in de klasse class Painter { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D background, cannonBarrel; Vector2 barrelPosition, barrelOrigin; float angle; // methoden... : Game } Painter IsMouseVisible Content GraphicsDevice game Overgeërfd uit de Game-klasse spriteBatch barrelPosition barrelOrigin backgroundcannonBarrel graphics angle
game Painter geërfd van Game zelf gedeclareerd
game Painter spriteBatch background SpriteBatch Texture2D graphics GraphicsDeviceManager Texture2D cannonBarrel barrelPosition barrelOrigin 34 angle 0
De Cannon klasse Groepeer alle member variabelen die bij het kannon horen in een klasse Cannon class Cannon { Texture2D cannonBarrel; Texture2D colorRed, colorGreen, colorBlue; Texture2D currentColor; Vector2 position; Vector2 barrelOrigin, colorOrigin; Color color; float angle; // methoden worden nog toegevoegd. }
x Declaratie Declaratie reserveert geheugenruimte Voor een object-verwijzing int x; x = 5; 5 s zoals be- schreven in klasse SpriteBatch Voor een object-waarde SpriteBatch s; s = new SpriteBatch(…); Vector2 p; p = new Vector2(10,20); Y0 X zoals be- schreven in struct Vector2 Voor een primitieve waarde p
Constructie van nieuw object Geheugenruimte klaarzetten Constructormethode aanroepen new-expressie doet twee dingen: waarde is pijl naar het nieuwe object cannon die je kunt opslaan cannon = new Cannon (…) ; position cannonBarrel Cannon color … Texture2D 0 255
public Cannon(ContentManager Content) { this.cannonBarrel = Content.Load ("spr_cannon_barrel"); this.colorRed = Content.Load ("spr_cannon_red"); this.colorGreen = Content.Load ("spr_cannon_green"); this.colorBlue = Content.Load ("spr_cannon_blue"); this.currentColor = colorBlue; color = Color.Blue; barrelOrigin = new Vector2(cannonBarrel.Height, cannonBarrel.Height) / 2; colorOrigin = new Vector2(currentColor.Width, currentColor.Height) / 2; position = new Vector2(72, 405); } Parameter(s) van de constructormethode Member- variabelen krijgen een waarde. Geen return type!
Constructie van een nieuw object class Painter : Game {... Cannon cannon;... protected override LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); background = Content.Load ("spr_background"); }... } cannon = new Cannon(Content); Informatie doorgeven via parameters! Membervariabele
null Als een variabele nog nergens naar wijst, dan zeggen we dat de variabele null is: Dit kunnen we zelfs in condities gebruiken: Of korter: Cannon cannon; if (cannon == null) cannon = new Cannon(Content); if (!cannon) cannon = new Cannon(Content); null mapt naar de booleanwaarde false
Objecten Object: groepje variabelen dat bij elkaar hoort 255 r g 0 b 100 w 20 h 3 aantal prijs hallo!
Objecten Om een object te gebruiken, hoef je niet te weten uit welke variabelen het object bestaat Je hoeft alleen te weten - welke methoden er zijn - welke properties er zijn "vraag niet hoe het kan... " "maar profiteer ervan! "
Game objecten ontwerpen Wat doet een game object? – Invoer van de speler afhandelen – Zichzelf bijwerken (update) – Zichzelf tekenen (draw) Bijbehorende methoden: – HandleInput – Update – Draw Daarnaast: – Reset
Methoden in Cannon public void Draw(GameTime gameTime, SpriteBatch spriteBatch) { spriteBatch.Draw(cannonBarrel, position, null, Color.White, angle, barrelOrigin, 1f, SpriteEffects.None, 0); spriteBatch.Draw(currentColor, position, null, Color.White, 0f, colorOrigin, 1f, SpriteEffects.None, 0); } public void Reset() { currentColor = colorBlue; color = Color.Blue; angle = 0.0f; }
Property voor lezen positie public Vector2 Position { get { return position; } Type van de property Naam van de property Property lezen Zo gebruiken we de property: Vector2 cannonPos = cannon.Position;
public Color Color { get { return color; } set { if (value != Color.Red && value != Color.Green && value != Color.Blue) return; color = value; if (color == Color.Red) currentColor = colorRed; else if (color == Color.Green) currentColor = colorGreen; else if (color == Color.Blue) currentColor = colorBlue; } } Property lezen Property schrijven Controleren of het wel mag. value bevat de rechterkant van de toekenning
Properties Sommige properties mag je alleen lezen – String.Length – Viewport.Width Sommige properties mag je ook schrijven – Vector2.X – Content.RootDirectory – Cannon.Color
Properties Properties hoeven niet altijd direct met een waarde van een membervariabele te corresponderen, bijv.: public Vector2 Center { get { return new Vector2(sprite.Width, sprite.Height) / 2; }
Spelerinvoer afhandelen Spelerinvoer afhandelen is nogal omslachtig momenteel: 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 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
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 public bool MouseLeftButtonPressed() { return currMS.LeftButton == ButtonState.Pressed && prevMS.LeftButton == ButtonState.Released; } public bool KeyPressed(Keys k) { return currKS.IsKeyDown(k) && prevKS.IsKeyUp(k); } = deze methode mag in een andere klasse aangeroepen worden.
InputHelper gebruiken protected override void Update(GameTime gameTime) { inputHelper.Update(); HandleInput(inputHelper); // hier nog de game wereld bijwerken }
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!
GameWorld klasse class GameWorld { Texture2D background; Cannon cannon; public GameWorld(ContentManager Content) { background = Content.Load ("spr_background"); cannon = new Cannon(Content); } public void HandleInput(InputHelper inputHelper) { cannon.HandleInput(inputHelper); }... Game wereld bestaat uit alle game objecten
... public void Update(GameTime gameTime) { } public void Draw(GameTime gameTime, SpriteBatch spriteBatch) { spriteBatch.Begin(); spriteBatch.Draw(background, Vector2.Zero, Color.White); cannon.Draw(gameTime, spriteBatch); spriteBatch.End(); } public Cannon Cannon { get { return cannon; } }
class Painter : Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; InputHelper inputHelper; static GameWorld gameWorld; … protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); gameWorld = new GameWorld(Content); } … public static GameWorld GameWorld { get { return gameWorld; } } Static member variabele Static property om erbij te kunnen Constructie van de game wereld
protected override void Update(GameTime gameTime) { inputHelper.Update(); gameWorld.HandleInput(inputHelper); gameWorld.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.White); gameWorld.Draw(gameTime, spriteBatch); }
Overzicht programma-constructies Declaratie Lokale variabele voor tijdelijk gebruik Membervariabele permanent deel van het object Parameter om waarden door te spelen aan methoden Type Primitief type – int – double – bool, enz. Object-type – Color, Vector2 enz. – Game, SpriteBatch, enz. geeft het type van variabelen waarde-verzameling van een expressie
De volgende keer… Hoofdstukken 8 & 9 uit het boek – Willekeurigheid in games – Game object interactie – …meer game objecten! Let’s add these bad boys…