A stealth-based 2D platformer where you don't have to kill anyone unless you want to. https://www.semicolin.games
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
7.9 KiB

  1. using Microsoft.Xna.Framework;
  2. using Microsoft.Xna.Framework.Graphics;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. namespace SemiColinGames {
  6. enum Terrain {
  7. Empty,
  8. Grass,
  9. GrassL,
  10. GrassR,
  11. Rock,
  12. RockL,
  13. RockR,
  14. Water,
  15. Block
  16. }
  17. class Tile {
  18. readonly Texture2D texture;
  19. public Tile(Texture2D texture, Terrain terrain, Rectangle position) {
  20. this.texture = texture;
  21. Terrain = terrain;
  22. Position = position;
  23. }
  24. public Rectangle Position { get; private set; }
  25. public Terrain Terrain { get; private set; }
  26. public void Draw(SpriteBatch spriteBatch, Camera camera) {
  27. int size = World.TileSize;
  28. Vector2 drawPos = new Vector2(Position.Left - camera.Left, Position.Top);
  29. switch (Terrain) {
  30. case Terrain.Grass: {
  31. Rectangle source = new Rectangle(3 * size, 0 * size, size, size);
  32. spriteBatch.Draw(texture, drawPos, source, Color.White);
  33. break;
  34. }
  35. case Terrain.GrassL: {
  36. Rectangle source = new Rectangle(2 * size, 0 * size, size, size);
  37. spriteBatch.Draw(texture, drawPos, source, Color.White);
  38. break;
  39. }
  40. case Terrain.GrassR: {
  41. Rectangle source = new Rectangle(4 * size, 0 * size, size, size);
  42. spriteBatch.Draw(texture, drawPos, source, Color.White);
  43. break;
  44. }
  45. case Terrain.Rock: {
  46. Rectangle source = new Rectangle(3 * size, 1 * size, size, size);
  47. spriteBatch.Draw(texture, drawPos, source, Color.White);
  48. break;
  49. }
  50. case Terrain.RockL: {
  51. Rectangle source = new Rectangle(1 * size, 2 * size, size, size);
  52. spriteBatch.Draw(texture, drawPos, source, Color.White);
  53. break;
  54. }
  55. case Terrain.RockR: {
  56. Rectangle source = new Rectangle(5 * size, 2 * size, size, size);
  57. spriteBatch.Draw(texture, drawPos, source, Color.White);
  58. break;
  59. }
  60. case Terrain.Water: {
  61. Rectangle source = new Rectangle(9 * size, 2 * size, size, size);
  62. spriteBatch.Draw(texture, drawPos, source, Color.White);
  63. break;
  64. }
  65. case Terrain.Block: {
  66. Rectangle source = new Rectangle(6 * size, 3 * size, size, size);
  67. spriteBatch.Draw(texture, drawPos, source, Color.White);
  68. break;
  69. }
  70. case Terrain.Empty:
  71. default:
  72. break;
  73. }
  74. }
  75. }
  76. class World {
  77. public const int TileSize = 16;
  78. readonly Tile[] tiles;
  79. readonly Rectangle[] collisionTargets;
  80. public int Width { get; private set; }
  81. public int Height { get; private set; }
  82. readonly string worldString = @"
  83. X
  84. .
  85. X <======> <==X X <=> <XX> XX .
  86. XXX .
  87. XXXX .
  88. XXXXX .
  89. X <X=X> <> <> <X> = <> X X X X <> X X XX X <=X> XXXXXX .
  90. <> [] [] XX XX XXX XX XXXXXXX .
  91. <> [] [] [] XXX XXX XXXX XXX <> <> XXXXXXXX
  92. []12345678[]123456[]123456789[]1234567890 123456 123456 12345 1234 12345 1234 123XXXX XXXX1234XXXXX XXXX1234[]123 1234567[]XXXXXXXXX12345678
  93. ====================> <====..========..======..=========..=========> <=============> <==============================================================> <=======..==============..==============================
  94. ....................] [............................................] [.............] [..............................................................] [.......................................................";
  95. public World(Texture2D texture) {
  96. var tilesList = new List<Tile>();
  97. string[] worldDesc = worldString.Split('\n');
  98. Width = worldDesc.AsQueryable().Max(a => a.Length);
  99. Height = worldDesc.Length;
  100. Debug.WriteLine("world size: {0}x{1}", Width, Height);
  101. for (int i = 0; i < Width; i++) {
  102. for (int j = 0; j < Height; j++) {
  103. Terrain terrain = Terrain.Empty;
  104. if (i < worldDesc[j].Length) {
  105. switch (worldDesc[j][i]) {
  106. case '=':
  107. terrain = Terrain.Grass;
  108. break;
  109. case '<':
  110. terrain = Terrain.GrassL;
  111. break;
  112. case '>':
  113. terrain = Terrain.GrassR;
  114. break;
  115. case '.':
  116. terrain = Terrain.Rock;
  117. break;
  118. case '[':
  119. terrain = Terrain.RockL;
  120. break;
  121. case ']':
  122. terrain = Terrain.RockR;
  123. break;
  124. case '~':
  125. terrain = Terrain.Water;
  126. break;
  127. case 'X':
  128. terrain = Terrain.Block;
  129. break;
  130. default:
  131. terrain = Terrain.Empty;
  132. break;
  133. }
  134. }
  135. if (terrain != Terrain.Empty) {
  136. var position = new Rectangle(i * TileSize, j * TileSize, TileSize, TileSize);
  137. tilesList.Add(new Tile(texture, terrain, position));
  138. }
  139. }
  140. }
  141. tiles = tilesList.ToArray();
  142. collisionTargets = new Rectangle[tiles.Length];
  143. for (int i = 0; i < tiles.Length; i++) {
  144. collisionTargets[i] = tiles[i].Position;
  145. }
  146. }
  147. public void Draw(SpriteBatch spriteBatch, Camera camera) {
  148. foreach (Tile t in tiles) {
  149. t.Draw(spriteBatch, camera);
  150. }
  151. }
  152. public Rectangle[] CollisionTargets {
  153. get { return collisionTargets; }
  154. }
  155. }
  156. }