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.

179 lines
8.1 KiB

  1. using Microsoft.Xna.Framework;
  2. using Microsoft.Xna.Framework.Graphics;
  3. using System;
  4. using System.Collections.Generic;
  5. namespace Jumpy {
  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. Texture2D texture;
  19. Terrain terrain;
  20. Rectangle position;
  21. public Tile(Texture2D texture, Terrain terrain, Rectangle position) {
  22. this.texture = texture;
  23. this.terrain = terrain;
  24. this.position = position;
  25. }
  26. public Rectangle Position { get { return position; } }
  27. public Terrain Terrain { get { return terrain; } }
  28. public void Draw(SpriteBatch spriteBatch, Camera camera) {
  29. int size = World.TileSize;
  30. Vector2 drawPos = new Vector2(position.Left - camera.Left, position.Top);
  31. switch (terrain) {
  32. case Terrain.Grass: {
  33. // TODO: hold these rectangles statically instead of making them anew constantly.
  34. Rectangle source = new Rectangle(3 * size, 0 * size, size, size);
  35. spriteBatch.Draw(texture, drawPos, source, Color.White);
  36. break;
  37. }
  38. case Terrain.GrassL: {
  39. Rectangle source = new Rectangle(2 * size, 0 * size, size, size);
  40. spriteBatch.Draw(texture, drawPos, source, Color.White);
  41. break;
  42. }
  43. case Terrain.GrassR: {
  44. Rectangle source = new Rectangle(4 * size, 0 * size, size, size);
  45. spriteBatch.Draw(texture, drawPos, source, Color.White);
  46. break;
  47. }
  48. case Terrain.Rock: {
  49. Rectangle source = new Rectangle(3 * size, 1 * size, size, size);
  50. spriteBatch.Draw(texture, drawPos, source, Color.White);
  51. break;
  52. }
  53. case Terrain.RockL: {
  54. Rectangle source = new Rectangle(1 * size, 2 * size, size, size);
  55. spriteBatch.Draw(texture, drawPos, source, Color.White);
  56. break;
  57. }
  58. case Terrain.RockR: {
  59. Rectangle source = new Rectangle(5 * size, 2 * size, size, size);
  60. spriteBatch.Draw(texture, drawPos, source, Color.White);
  61. break;
  62. }
  63. case Terrain.Water: {
  64. Rectangle source = new Rectangle(9 * size, 2 * size, size, size);
  65. spriteBatch.Draw(texture, drawPos, source, Color.White);
  66. break;
  67. }
  68. case Terrain.Block: {
  69. Rectangle source = new Rectangle(6 * size, 3 * size, size, size);
  70. spriteBatch.Draw(texture, drawPos, source, Color.White);
  71. break;
  72. }
  73. case Terrain.Empty:
  74. default:
  75. break;
  76. }
  77. }
  78. }
  79. class World {
  80. public const int TileSize = 16;
  81. int width;
  82. int height;
  83. Tile[,] tiles;
  84. public int Width { get; }
  85. public int Height { get; }
  86. string[] worldDesc = new string[] {
  87. " ",
  88. " ",
  89. " ",
  90. " ",
  91. " ",
  92. " X ",
  93. " . ",
  94. " X <======> <==X X <=> <XX> XX . ",
  95. " XXX . ",
  96. " XXXX . ",
  97. " XXXXX . ",
  98. " X <X=X> <> <> <X> = <> X X X X <> X X XX X <=X> XXXXXX . ",
  99. " <> [] [] XX XX XXX XX XXXXXXX . ",
  100. " <> [] [] [] XXX XXX XXXX XXX <> <> XXXXXXXX ",
  101. " []12345678[]123456[]123456789[]1234567890 123456 123456 12345 1234 12345 1234 123XXXX XXXX1234XXXXX XXXX1234[]123 1234567[]XXXXXXXXX12345678 ",
  102. "===========================..========..======..=========..=========> <=============> <==============================================================> <=======..==============..==============================",
  103. "...................................................................] [.............] [..............................................................] [......................................................." };
  104. public World(Texture2D texture) {
  105. // TODO: better error handling for if the string[] isn't rectangular.
  106. width = worldDesc[0].Length;
  107. height = worldDesc.Length;
  108. tiles = new Tile[width, height];
  109. for (int j = 0; j < height; j++) {
  110. for (int i = 0; i < width; i++) {
  111. Terrain terrain;
  112. switch (worldDesc[j][i]) {
  113. case '=':
  114. terrain = Terrain.Grass;
  115. break;
  116. case '<':
  117. terrain = Terrain.GrassL;
  118. break;
  119. case '>':
  120. terrain = Terrain.GrassR;
  121. break;
  122. case '.':
  123. terrain = Terrain.Rock;
  124. break;
  125. case '[':
  126. terrain = Terrain.RockL;
  127. break;
  128. case ']':
  129. terrain = Terrain.RockR;
  130. break;
  131. case '~':
  132. terrain = Terrain.Water;
  133. break;
  134. case 'X':
  135. terrain = Terrain.Block;
  136. break;
  137. case ' ':
  138. default:
  139. terrain = Terrain.Empty;
  140. break;
  141. }
  142. var position = new Rectangle(i * TileSize, j * TileSize, TileSize, TileSize);
  143. tiles[i, j] = new Tile(texture, terrain, position);
  144. }
  145. }
  146. }
  147. public void Draw(SpriteBatch spriteBatch, Camera camera) {
  148. for (int j = 0; j < height; j++) {
  149. for (int i = 0; i < width; i++) {
  150. tiles[i, j].Draw(spriteBatch, camera);
  151. }
  152. }
  153. }
  154. public List<Rectangle> CollisionTargets() {
  155. var result = new List<Rectangle>();
  156. for (int j = 0; j < height; j++) {
  157. for (int i = 0; i < width; i++) {
  158. var t = tiles[i, j];
  159. if (t.Terrain != Terrain.Empty) {
  160. result.Add(t.Position);
  161. }
  162. }
  163. }
  164. return result;
  165. }
  166. }
  167. }