From f1b71ca87dc91d93e8594fb5a3a95a365beda0e3 Mon Sep 17 00:00:00 2001 From: Colin McMillen Date: Thu, 20 Feb 2020 12:25:46 -0500 Subject: [PATCH] Tiles can now be obstacles (in the foreground) or decorations (in the background). Updated Levels to show off some of these. GitOrigin-RevId: d8d04410c15dd36218d5a1504dd842827082180f --- Shared/Levels.cs | 18 ++++---- Shared/Scene.cs | 12 +++--- Shared/World.cs | 109 ++++++++++++++++++++++++++++------------------- 3 files changed, 79 insertions(+), 60 deletions(-) diff --git a/Shared/Levels.cs b/Shared/Levels.cs index e6b29ce..31eedcf 100644 --- a/Shared/Levels.cs +++ b/Shared/Levels.cs @@ -12,15 +12,15 @@ 5 6 7 -8 <===X===> <======================> -9 -0 -1 -2 -3 dfffxfffxfffb -===================> <=============> <================================================================================================ -...................] [..............^^^^................................................................................................. -....................~`~`...................................................................................................................."; +8 <=X=X=X=> <=============> (__________) +9 / \ +0 | | +1 | | +2 | | +3 dfffxfffxfffb dfffxfffxfffb v v +=================> <=============> <================================================================================================ +..................~`~`~`...............^^^^................................................................................................. +..................======...................................................................................................................."; public const string ROCKS = @" diff --git a/Shared/Scene.cs b/Shared/Scene.cs index f67b431..be1e778 100644 --- a/Shared/Scene.cs +++ b/Shared/Scene.cs @@ -76,17 +76,17 @@ namespace SemiColinGames { // Set up transformation matrix for drawing world objects. Matrix transform = Matrix.CreateTranslation(-camera.Left, -camera.Top, 0); - - // Draw player. spriteBatch.Begin( SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null, null, transform); + + // Draw background tiles. + world.DrawBackground(spriteBatch); + + // Draw player. player.Draw(spriteBatch); - spriteBatch.End(); // Draw foreground tiles. - spriteBatch.Begin( - SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null, null, transform); - world.Draw(spriteBatch); + world.DrawForeground(spriteBatch); spriteBatch.End(); // Draw debug rects & lines on top. diff --git a/Shared/World.cs b/Shared/World.cs index 5e29725..8bab157 100644 --- a/Shared/World.cs +++ b/Shared/World.cs @@ -5,25 +5,49 @@ using System.Collections.Generic; using System.Linq; namespace SemiColinGames { - enum Terrain { - Grass, - GrassL, - GrassR, - Rock, - RockL, - RockR, - WaterL, - WaterR, - Block, - Spike, - Wood, - WoodL, - WoodR, - WoodVert, - FenceL, - Fence, - FencePost, - FenceR, + class Terrain { + + public static Terrain FromSymbol(char symbol) { + if (mapping.ContainsKey(symbol)) { + return mapping[symbol]; + } else { + return null; + } + } + + private static Dictionary mapping = new Dictionary(); + + public static Terrain Grass = new Terrain('=', true); + public static Terrain GrassL = new Terrain('<', true); + public static Terrain GrassR = new Terrain('>', true); + public static Terrain Rock = new Terrain('.', true); + public static Terrain RockL = new Terrain('[', true); + public static Terrain RockR = new Terrain(']', true); + public static Terrain WaterL = new Terrain('~', false); + public static Terrain WaterR = new Terrain('`', false); + public static Terrain Block = new Terrain('X', true); + public static Terrain Spike = new Terrain('^', true); + public static Terrain Wood = new Terrain('_', true); + public static Terrain WoodL = new Terrain('(', true); + public static Terrain WoodR = new Terrain(')', true); + public static Terrain WoodVert = new Terrain('|', false); + public static Terrain WoodVertL = new Terrain('/', false); + public static Terrain WoodVertR = new Terrain('\\', false); + public static Terrain WoodBottom = new Terrain('v', false); + public static Terrain FenceL = new Terrain('d', false); + public static Terrain Fence = new Terrain('f', false); + public static Terrain FencePost = new Terrain('x', false); + public static Terrain FenceR = new Terrain('b', false); + + public bool IsObstacle { get; private set; } + + private Terrain(char symbol, bool isObstacle) { + if (mapping.ContainsKey(symbol)) { + throw new ArgumentException("already have a terrain with symbol " + symbol); + } + IsObstacle = isObstacle; + mapping[symbol] = this; + } } class TileFactory { @@ -56,6 +80,9 @@ namespace SemiColinGames { { Terrain.WoodL, GetTextureSource(Textures.Grassland, 9, 3) }, { Terrain.WoodR, GetTextureSource(Textures.Grassland, 12, 3) }, { Terrain.WoodVert, GetTextureSource(Textures.Grassland, 9, 5) }, + { Terrain.WoodVertL, GetTextureSource(Textures.Grassland, 9, 4) }, + { Terrain.WoodVertR, GetTextureSource(Textures.Grassland, 12, 4) }, + { Terrain.WoodBottom, GetTextureSource(Textures.Grassland, 10, 5) }, { Terrain.FenceL, GetTextureSource(Textures.Grassland, 5, 4) }, { Terrain.Fence, GetTextureSource(Textures.Grassland, 6, 4) }, { Terrain.FencePost, GetTextureSource(Textures.Grassland, 7, 4) }, @@ -98,6 +125,7 @@ namespace SemiColinGames { public const int TileSize = 16; readonly Tile[] tiles; + readonly Tile[] decorations; // Size of World in terms of tile grid. private readonly int tileWidth; @@ -112,31 +140,10 @@ namespace SemiColinGames { get { return tileHeight * TileSize; } } - private static readonly Dictionary charToTerrain = - new Dictionary() { - { '=', Terrain.Grass }, - { '<', Terrain.GrassL }, - { '>', Terrain.GrassR }, - { '.', Terrain.Rock }, - { '[', Terrain.RockL }, - { ']', Terrain.RockR }, - { '~', Terrain.WaterL }, - { '`', Terrain.WaterR }, - { 'X', Terrain.Block }, - { '^', Terrain.Spike }, - { '_', Terrain.Wood }, - { '(', Terrain.WoodL }, - { ')', Terrain.WoodR }, - { '|', Terrain.WoodVert }, - { 'd', Terrain.FenceL }, - { 'f', Terrain.Fence }, - { 'x', Terrain.FencePost }, - { 'b', Terrain.FenceR }, - }; - public World(string levelSpecification) { TileFactory factory = new TileFactory(); var tilesList = new List(); + var decorationsList = new List(); string[] worldDesc = levelSpecification.Split('\n'); tileWidth = worldDesc.AsQueryable().Max(a => a.Length); tileHeight = worldDesc.Length; @@ -145,15 +152,21 @@ namespace SemiColinGames { for (int j = 0; j < tileHeight; j++) { if (i < worldDesc[j].Length) { char key = worldDesc[j][i]; - if (charToTerrain.ContainsKey(key)) { - Terrain terrain = charToTerrain[key]; + Terrain terrain = Terrain.FromSymbol(key); + if (terrain != null) { var position = new Rectangle(i * TileSize, j * TileSize, TileSize, TileSize); - tilesList.Add(factory.MakeTile(terrain, position)); + Tile tile = factory.MakeTile(terrain, position); + if (tile.Terrain.IsObstacle) { + tilesList.Add(tile); + } else { + decorationsList.Add(tile); + } } } } } tiles = tilesList.ToArray(); + decorations = decorationsList.ToArray(); // Because we added tiles from left to right, the CollisionTargets are sorted by x-position. // We maintain this invariant so that it's possible to efficiently find CollisionTargets that @@ -176,7 +189,13 @@ namespace SemiColinGames { new Vector2(Width + 1, 0), new Vector2(1, float.MaxValue)); } - public void Draw(SpriteBatch spriteBatch) { + public void DrawBackground(SpriteBatch spriteBatch) { + foreach (Tile t in decorations) { + t.Draw(spriteBatch); + } + } + + public void DrawForeground(SpriteBatch spriteBatch) { foreach (Tile t in tiles) { t.Draw(spriteBatch); }