Download presentation
Presentation is loading. Please wait.
1
Sprite Sheets, Game States
Arjan Egges & Paul Bergervoet
2
Overzicht
3
Sprite sheets Strips vs. Sheets Strip is handiger met tekenen
Soms is een strip te breed om in het videogeheugen te passen Sheet kan meer sprites bevatten dan strip Sheet is wat onhandiger om te tekenen
4
Sprite strip tekenen in Jewel Jam
public override void Draw(GameTime gameTime, SpriteBatch s) { if (!visible) return; Rectangle source = new Rectangle(variation * sprite.Height, 0, sprite.Height, sprite.Height); s.Draw(sprite, GlobalPosition, source, Color.White); glitters.Draw(gameTime, spriteBatch); }
5
Nieuwe klasse SpriteSheet
SpriteSheet heeft een aantal rijen en kolommen Er is een ‘sheet index’ die aangeeft welk element van de sheet we willen tekenen. 4 kolommen 1 2 3 4 5 6 7 2 rijen
6
SpriteSheet class SpriteSheet { protected Texture2D sprite;
protected int sheetIndex; protected int sheetColumns; protected int sheetRows; protected bool mirror; public SpriteSheet(string assetname, int sheetIndex = 0) ... }
7
Sprite sheet instellingen
Bij het laden van een asset zijn er dan drie mogelijkheden: Het is een enkele sprite Het is een sprite strip Het is een sprite sheet Trucje: encodering in de filenaam! spr_help.jpg
8
String ‘ontleden’ in de constructor
sprite = PenguinPairs.AssetManager.getSprite(assetname); this.sheetIndex = sheetIndex; this.sheetColumns = 1; this.sheetRows = 1; string[] assetSplit = if (assetSplit.Length <= 1) return; string sheetNrData = assetSplit[assetSplit.Length - 1]; string[] colrow = sheetNrData.Split('x'); this.sheetColumns = int.Parse(colrow[0]); if (colrow.Length == 2) this.sheetRows = int.Parse(colrow[1]); Levert een array op van strings. Blijkbaar is het geen strip of sheet. sheet (rijen en kolommen)
9
Properties public int Width { get return sprite.Width / sheetColumns;
} public int Height return sprite.Height / sheetRows; Deel door het aantal kolommen voor de juiste breedte. Deel door het aantal rijen voor de juiste hoogte.
10
Meer properties public int NumberSheetElements {
get { return this.sheetColumns * this.sheetRows; } } public int SheetIndex get { return this.sheetIndex; } set if (value < NumberSheetElements && value >= 0) this.sheetIndex = value; = totaal aantal elementen Alleen toekennen als het mag.
11
SpriteSheet tekenen public override void Draw(SpriteBatch spriteBatch, Vector2 position, Vector2 origin) { int columnIndex = sheetIndex % sheetColumns; int rowIndex = sheetIndex / sheetColumns; Rectangle spritePart = new Rectangle(columnIndex * this.Width, rowIndex * this.Height, this.Width, this.Height); SpriteEffects spriteEffects = SpriteEffects.None; if (mirror) spriteEffects = SpriteEffects.FlipHorizontally; spriteBatch.Draw(sprite, position, spritePart, Color.White, 0.0f, origin, 1.0f, spriteEffects, 0.0f); } Bereken de juiste rij/kolom waarden.
12
SpriteGameObject klasse
protected SpriteSheet sprite; protected Vector2 origin; public SpriteGameObject(string assetname, int layer = 0, string id = "", int sheetIndex = 0) : base(layer, id) { if (assetname != "") sprite = new SpriteSheet(assetname, sheetIndex); else sprite = null; } public override void Draw(GameTime gameTime, SpriteBatch s) { if (!visible || sprite == null) return; sprite.Draw(spriteBatch, this.GlobalPosition, origin);
13
SpriteGameObject gebruiken
protected override void LoadContent() { ... gameWorld = new GameObjectList(); gameWorld.Add( new SpriteGameObject("spr_background_levelselect")); SpriteGameObject penguin = new 1, "penguin"); penguin.Position = new Vector2(500, 420); gameWorld.Add(penguin); }
14
SpriteGameObject gebruiken
protected void HandleInput() { inputHelper.Update(); if (inputHelper.KeyPressed(Keys.Escape)) this.Exit(); if (inputHelper.KeyPressed(Keys.F5)) SetFullScreen(!graphics.IsFullScreen); gameWorld.HandleInput(inputHelper); SpriteGameObject penguin; penguin = gameWorld.Find("penguin") as SpriteGameObject; if (inputHelper.KeyPressed(Keys.Left)) penguin.SheetIndex--; else if (inputHelper.KeyPressed(Keys.Right)) penguin.SheetIndex++; }
15
Menu’s Tekst Aan/uit knop Slider
16
TextGameObject class TextGameObject : GameObject {
protected SpriteFont spriteFont; protected Color color; protected string text; public TextGameObject(string assetname, int layer = 0, string id = "") : base(layer, id) spriteFont = PenguinPairs.AssetManager.Content.Load<SpriteFont>(assetname); color = Color.White; } ...
17
TextGameObject public override void Draw(GameTime gameTime, SpriteBatch s) { if (visible) spriteBatch.DrawString(spriteFont, text, this.GlobalPosition, color); } public Color Color get { return color; } set { color = value; } public string Text get { return text; } set { text = value; }
18
Knoppen: muisklik detecteren
Hoe weten we of op een knop geklikt wordt? Muisknop ingedrukt Muis is binnen de rechthoek die de knop omsluit BoundingBox property toevoegen aan SpriteGameObject: public override Rectangle BoundingBox { get int left = (int)(GlobalPosition.X - origin.X); int top = (int)(GlobalPosition.Y - origin.Y); return new Rectangle(left, top, Width, Height); }
19
Eenvoudige knop class Button : SpriteGameObject {
protected bool pressed; public Button(string imageAsset, int layer = 0, string id = "") : base(imageAsset, layer, id) { } public override void HandleInput(InputHelper inputHelper) { pressed = inputHelper.MouseLeftButtonPressed() && BoundingBox.Contains((int)inputHelper.MousePosition.X, (int)inputHelper.MousePosition.Y); } public bool Pressed { get { return pressed; } }
20
Aan/uit knop (toggle) class OnOffButton : SpriteGameObject {
public OnOffButton(string imageAsset, int layer = 0, string id = "") : base(imageAsset, layer, id, 0) } public override void HandleInput(InputHelper inputHelper) if (inputHelper.MouseLeftButtonPressed() && BoundingBox.Contains((int)inputHelper.MousePosition.X, (int)inputHelper.MousePosition.Y)) sheetIndex = (sheetIndex + 1) % 2; ...
21
Aan/uit knop (toggle) public bool On { get
return sprite.SheetIndex == 1; } set if (value) sprite.SheetIndex = 1; else sprite.SheetIndex = 0;
22
Slider class Slider : GameObjectList {
protected SpriteGameObject back, front; protected bool dragging; protected int leftmargin, rightmargin; public Slider(string sliderback, string sliderfront, int layer = 0, string id = "") : base(layer, id) } ...
23
Slider public Slider(string sliderback, string sliderfront, int layer = 0, string id = "") : base(layer, id) { leftmargin = 5; rightmargin = 7; back = new SpriteGameObject(sliderback, 0); this.Add(back); front = new SpriteGameObject(sliderfront, 1); front.Position = new Vector2(leftmargin, 8); this.Add(front); dragging = false; }
24
Slider public override void HandleInput(InputHelper inputHelper) {
if (inputHelper.MouseLeftButtonDown()) { if (back.BoundingBox.Contains((int)inputHelper.MousePosition.X, (int)inputHelper.MousePosition.Y) || dragging) float newxpos = MathHelper.Clamp(inputHelper.MousePosition.X - back.GlobalPosition.X - front.Width / 2, back.Position.X + leftmargin, back.Position.X + back.Width - front.Width - rightmargin); front.Position = new Vector2(newxpos, front.Position.Y); dragging = true; } else dragging = false;
25
Slider public float Value { get
return (front.Position.X - back.Position.X - leftmargin) / (back.Width - leftmargin - rightmargin - front.Width); } set float newxpos = value * (back.Width - leftmargin - rightmargin – front.Width) + back.Position.X + leftmargin; front.Position = new Vector2(newxpos, front.Position.Y);
26
Game states Veel games hebben verschillende game toestanden Hoofdmenu
Optiemenu Helpmenu Aan het spelen Game over Highscore …
27
goede klassenstructuur!
Game states Noemen we ook wel: Game states Hoe representeren we die toestanden? Hoe wisselen we tussen toestanden? Maak gebruik van een goede klassenstructuur!
28
Ad hoc manier in Jewel Jam
public override void HandleInput(InputHelper inputHelper) { if (title.Visible) { if (inputHelper.KeyPressed(Keys.Space)) title.Visible = false; } else if (this.GameOver) this.Reset(); else ... Per game state andere invoer afhandelen.
29
Ad hoc manier in Jewel Jam
Zelfde idee in Update. public override void Update(GameTime gameTime) { if (this.GameOver && !gameover.Visible) gameover.Visible = true; JewelJam.AssetManager.playSound("snd_gameover"); } else if (!helpFrame.Visible && !title.Visible) base.Update(gameTime); Kan tot verwarring leiden!
30
Algemeen game loop object
Definieer een interface met daarin alle belangrijke game loop methoden. interface IGameLoopObject { void HandleInput(InputHelper inputHelper); void Update(GameTime gameTime); void Draw(GameTime gameTime, SpriteBatch spriteBatch); void Reset(); }
31
Klassen implementeren de interface
Ook de GameObject klasse! class GameObject : IGameLoopObject { protected GameObject parent; protected Vector2 position, velocity; protected int layer; protected string id; protected bool visible; ... }
32
Game state manager class GameStateManager : IGameLoopObject {
protected Dictionary<string, IGameLoopObject> gameStates; protected IGameLoopObject currentGameState; public GameStateManager() gameStates = new Dictionary<string, IGameLoopObject>(); currentGameState = null; } ...
33
Game state manager public void AddGameState(string name, IGameLoopObject state) { gameStates[name] = state; } public IGameLoopObject GetGameState(string name) return gameStates[name]; public IGameLoopObject CurrentGameState get return currentGameState;
34
public void SwitchTo(string name)
{ if (gameStates.ContainsKey(name)) currentGameState = gameStates[name]; }
35
Game state manager public void HandleInput(InputHelper inputHelper) {
if (currentGameState != null) currentGameState.HandleInput(inputHelper); } public void Update(GameTime gameTime) { currentGameState.Update(gameTime); public void Draw(GameTime gameTime, SpriteBatch spriteBatch) { currentGameState.Draw(gameTime, spriteBatch); ...
36
In PenguinPairs Static membervariabele: Met property:
protected static GameStateManager gameStateManager; public static GameStateManager GameStateManager { get { return gameStateManager; } }
37
class TitleMenuState : GameObjectList {
protected Button playButton, optionButton, helpButton; public TitleMenuState() { // create the game objects... } public override void HandleInput(InputHelper inputHelper) { base.HandleInput(inputHelper); if (playButton.Pressed) PenguinPairs.GameStateManager.SwitchTo("levelMenu"); else if (optionButton.Pressed) PenguinPairs.GameStateManager.SwitchTo("optionsMenu"); else if (helpButton.Pressed) PenguinPairs.GameStateManager.SwitchTo("helpState");
38
class OptionsMenuState : GameObjectList {
protected Button backButton; protected Slider musicVolumeSlider; protected OnOffButton onOffButton; public override void HandleInput(InputHelper inputHelper) { base.HandleInput(inputHelper); if (backButton.Pressed) PenguinPairs.GameStateManager.SwitchTo("titleMenu"); } public override void Update(GameTime gameTime) { base.Update(gameTime); MediaPlayer.Volume = musicVolumeSlider.Value; ...
39
In PenguinPairs protected override void LoadContent() {
spriteBatch = new SpriteBatch(GraphicsDevice); screen = new Point(1200, 900); this.SetFullScreen(false); gameStateManager.AddGameState("titleMenu", new TitleMenuState()); gameStateManager.AddGameState("optionsMenu", new OptionsMenuState()); gameStateManager.AddGameState("levelMenu", new LevelMenuState()); gameStateManager.AddGameState("helpState", new HelpState()); gameStateManager.SwitchTo("titleMenu"); }
40
In PenguinPairs protected void HandleInput() { inputHelper.Update();
if (inputHelper.KeyPressed(Keys.Escape)) this.Exit(); if (inputHelper.KeyPressed(Keys.F5)) SetFullScreen(!graphics.IsFullScreen); gameStateManager.HandleInput(inputHelper); }
41
In PenguinPairs protected override void Update(GameTime gameTime) {
HandleInput(); gameStateManager.Update(gameTime); } protected override void Draw(GameTime gameTime) GraphicsDevice.Clear(Color.Black); spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, spriteScale); gameStateManager.Draw(gameTime, spriteBatch); spriteBatch.End();
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.