Gameprogrammeren

advertisement
Objecten en Methoden
Arjan Egges & Paul Bergervoet
Eigen methode toevoegen
class Painter : Game
{
public void HandleInput()
{
…
}
Eigen bedachte methode!
protected override void Update(GameTime gameTime)
{
HandleInput();
…
}
}
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:
currMS = Mouse.GetState();
• Methoden zonder een resultaat object:
GraphicsDevice.Clear(Color.Olive);
• Methoden met parameters:
currKS.IsKeyDown(Keys.G)
• Methoden zonder parameters:
spriteBatch.Begin()
Verschillende soorten methoden
• Sommige methoden bewerken objecten
spriteBatch.Begin()
• Sommige methoden bewerken geen objecten
(maar horen wel bij een klasse)
– Deze methoden noemen we static
Console.WriteLine("Hallo");
• In de methode header kun je zien wat voor
soort methode het is!
Methode headers
public static void Main()
{
static methode (bewerkt geen object)
…
}
public void HandleInput()
methode zonder parameters
{
… methode zonder resultaatobject
}
protected override void Update(GameTime gameTime)
{
…
methode met 1 parameter
}
Methoden met resultaat
We stoppen er een float in...
...en we leveren een float op.
public float CalculateSquare(float x)
{
Met return geven we aan
return x*x;
wat opgeleverd wordt.
}
• Vergelijkbaar met wiskundige functie
– f(x) = x2;
• In het gebruik:
float f = CalculateSquare(10.0f);
Methoden met resultaat
• Na een return stopt de methode
public int SomeMethod()
{
return 12;
int tmp = 45;
Wordt nooit uitgevoerd!
}
• Daar kunnen we gebruik van maken!
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:
float f = CalculateSquare(10.0f);
• Maar dat hoeft niet!
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
public float SquareRoot(float f)
{
Gebruiken we als locale variabele
if (f < 0.0f)
return 0.0f;
…
}
protected override void Update(GameTime gameTime)
{
Locale variabele
int red;
red = gameTime.TotalGameTime.Milliseconds;
…
}
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
veranderen
zijn gegroepeerd in
methoden
zijn gegroepeerd in
bewerken
zijn gegroepeerd in
klasse
variabelen
objecten
hebben als type
klasse
klasse
Objecten en geheugen
• Built-in types in het geheugen
- Numerieke typen (int, double, ...)
int i = 12;
double pi = 3.14;
- Tekst (strings)
string s = "hallo, ";
s += "Arjan";
i
s
12
b
3.14
"hallo,
"hallo,
Arjan"
"
- Waarheidswaarden
bool b = true;
b = !b;
pi
false
true
Objecten en geheugen
• Gevolg:
public void keerTwee(int getal)
i)
{
i *= 2;*= 2;
getal
}
int i = 3;
keerTwee(i);
// wat is nu de waarde van i?
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
verwijzing!
Texture2D
cannonBarrel
width
height
data
…
…
…
…
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
Painter
game
class Painter : Game
{ GraphicsDeviceManager
graphics;
SpriteBatch spriteBatch;
Texture2D background,
cannonBarrel;
Vector2 barrelPosition,
barrelOrigin;
float angle;
// methoden...
Overgeërfd uit
de Game-klasse
GraphicsDevice IsMouseVisible Content
barrelPosition
angle
barrelOrigin
graphics
}
spriteBatch
background cannonBarrel
game
Painter
geërfd van Game
zelf gedeclareerd
game
GraphicsDeviceManager
Painter
SpriteBatch
graphics
spriteBatch
background
barrelPosition
72
405
angle
0
barrelOrigin
34
34
Texture2D
cannonBarrel
Texture2D
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.
}
Declaratie
Declaratie reserveert geheugenruimte
• Voor een primitieve waarde
int x;
x = 5;
zoals beschreven
in struct
Vector2
5
x
• Voor een object-waarde
Vector2 p;
p = new Vector2(10,20);
p
X
Y
• Voor een object-verwijzing
SpriteBatch s;
s = new SpriteBatch(…);
s
10
0
0
20
zoals beschreven
in klasse
SpriteBatch
Constructie van nieuw object
new-expressie doet twee dingen:
cannon = new Cannon (…) ;
• Geheugenruimte
klaarzetten
cannon
position
72
405
Texture2D
• Constructormethode
aanroepen
waarde is pijl naar het nieuwe object
die je kunt opslaan
color
cannonBarrel
…
Cannon
0
0
255
Geen return type!
Parameter(s) van de
constructormethode
public Cannon(ContentManager Content)
{
this.cannonBarrel = Content.Load<Texture2D>("spr_cannon_barrel");
this.colorRed = Content.Load<Texture2D>("spr_cannon_red");
this.colorGreen = Content.Load<Texture2D>("spr_cannon_green");
this.colorBlue = Content.Load<Texture2D>("spr_cannon_blue");
this.currentColor = colorBlue;
color = Color.Blue;
MemberbarrelOrigin = new Vector2(cannonBarrel.Height,
cannonBarrel.Height) / 2; variabelen
krijgen een
colorOrigin = new Vector2(currentColor.Width,
waarde.
currentColor.Height) / 2;
position = new Vector2(72, 405);
}
Constructie van een nieuw object
class Painter : Game
{ ...
Cannon cannon;
...
Membervariabele
protected override LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
background = Content.Load<Texture2D>("spr_background");
cannon = new Cannon(Content);
}
Informatie doorgeven
...
via parameters!
}
null
• Als een variabele nog nergens naar wijst, dan
zeggen we dat de variabele null is:
Cannon cannon;
• Dit kunnen we zelfs in condities gebruiken:
if (cannon == null)
cannon = new Cannon(Content);
• Of korter:
null mapt naar de
booleanwaarde false
if (!cannon)
cannon = new Cannon(Content);
Objecten
• Object: groepje variabelen
dat bij elkaar hoort
r
255
g
255
b
0
w
100
h
20
aantal
prijs
ha l l o !
3
199.95
Objecten
"vraag niet hoe het kan... "
• Om een object te gebruiken,
hoef je niet te weten
uit welke variabelen het object bestaat
"maar profiteer ervan! "
• Je hoeft alleen te weten
- welke methoden er zijn
- welke properties er zijn
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
Type van de property
Naam van de property
public Vector2 Position
{
get
Property lezen
{
return position;
}
}
• Zo gebruiken we de property:
Vector2 cannonPos = cannon.Position;
public Color Color
Property lezen
{
get { return color; }
Controleren of
set
het wel mag.
Property schrijven
{
if (value != Color.Red && value != Color.Green
&& value != Color.Blue)
return;
color = value;
value bevat de
if (color == Color.Red)
rechterkant van de
currentColor = colorRed;
toekenning
else if (color == Color.Green)
currentColor = colorGreen;
else if (color == Color.Blue)
currentColor = colorBlue;
}
}
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();
Veel dubbele code,
dus je maakt snel fouten!
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;
...
De InputHelper klasse
class InputHelper
{
MouseState currMS, prevMS;
KeyboardState currKS, prevKS;
Deze informatie wordt bewaard
in een InputHelper object
// methoden en properties
}
De klasse InputHelper beschrijft
hoe een object van het
type InputHelper eruit ziet!
class Painter : Game
{ GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Declaratie
InputHelper inputHelper;
…
static void Main()
{ Painter game = new Painter();
game.Run();
}
public Painter()
{ Content.RootDirectory = "Content";
graphics = new GraphicsDeviceManager(this);
inputHelper = new InputHelper();
Toekenning en maken
}
van een instantie
…
Handige methoden
class InputHelper
{
MouseState currMS, prevMS;
KeyboardState currKS, prevKS;
InputHelper object
public void Update()
bijwerken in zijn eigen
{
Update methode
prevMS = currMS;
prevKS = currKS;
currMS = Mouse.GetState();
currKS = Keyboard.GetState();
}
…
Handige methoden
= deze methode mag
in een andere klasse
aangeroepen worden.
public bool MouseLeftButtonPressed()
{
return currMS.LeftButton == ButtonState.Pressed &&
prevMS.LeftButton == ButtonState.Released;
}
public bool KeyPressed(Keys k)
{
return currKS.IsKeyDown(k) && prevKS.IsKeyUp(k);
}
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;
Veel korter en veel
else if (inputHelper.KeyPressed(Keys.G))
overzichtelijker!
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);
}
GameWorld klasse
class GameWorld
{
Texture2D background;
Cannon cannon;
Game wereld bestaat
uit alle game objecten
public GameWorld(ContentManager Content)
{
background = Content.Load<Texture2D>("spr_background");
cannon = new Cannon(Content);
}
public void HandleInput(InputHelper inputHelper)
{
cannon.HandleInput(inputHelper);
}
...
...
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;
Static member variabele
InputHelper inputHelper;
static GameWorld gameWorld;
…
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
gameWorld = new GameWorld(Content);
}
Constructie van de game wereld
…
public static GameWorld GameWorld
{
Static property om
get { return gameWorld; }
erbij te kunnen
}
}
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
geeft het type
van variabelen Type
Declaratie
• Lokale variabele
voor tijdelijk gebruik
• Membervariabele
permanent deel van
het object
• Parameter
om waarden door
te spelen aan methoden
waarde-verzameling
van een expressie
• Primitief type
– int
– double
– bool, enz.
• Object-type
– Color, Vector2 enz.
– Game, SpriteBatch, enz.
Download