PageRenderTime 59ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/SMLimitless/SMLEngine/SMLEngineSprites/Collections/Level.cs

#
C# | 443 lines | 329 code | 99 blank | 15 comment | 58 complexity | 205196cb0b4aead8c8aa7f8424426622 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Text;
  5. using Microsoft.Xna.Framework;
  6. using Microsoft.Xna.Framework.Content;
  7. using Microsoft.Xna.Framework.Graphics;
  8. using Microsoft.Xna.Framework.Input;
  9. using SmlEngine.Sprites.Base;
  10. using SmlEngine.Sprites.Camera;
  11. using SmlEngine.Sprites.Settings;
  12. using SmlEngine.Sprites.Players;
  13. using SmlEngine.UI.Input;
  14. using SmlEngine.UI.Managers;
  15. namespace SmlEngine.Sprites.Collections
  16. {
  17. public class Level : IName // (cel) Needed to remove sealed modifier since events don't play well with sealed classes (got this compiler error: http://msdn.microsoft.com/en-us/library/exaxze9s(v=vs.71).aspx)
  18. {
  19. bool mode; //Auto-scroll, manual.
  20. #region Properties
  21. public string Name { get; set; }
  22. public InputManager Input { get; set; }
  23. public BackgroundSet Background { get; private set; }
  24. public IList<Layer> Layers { get; private set; }
  25. public IList<Player> Players { get; private set; } //May use PlayerCollection
  26. public Camera2D Camera { get; private set; }
  27. public int Section { get; set; }
  28. public int Width { get; set; }
  29. public int Height { get; set; }
  30. public int Score { get; set; }
  31. public int Time { get; set; }
  32. public float TimeRemaining { get; set; }
  33. public bool IsRunning { get; set; }
  34. public Axis Wrap { get; set; }
  35. public Axis Exit { get; set; }
  36. public event LevelClearedEventHandler LevelCleared;
  37. #endregion
  38. #region Methods
  39. #region Constructors
  40. public Level()
  41. {
  42. Camera = new Camera2D();
  43. Background = new BackgroundSet();
  44. Layers = new List<Layer>(4);
  45. Players = new List<Player>(4);
  46. }
  47. public Level(Stream stream)
  48. : this()
  49. {
  50. LevelLoader.ReloadLevel(this, stream);
  51. }
  52. #endregion
  53. #region Loading
  54. public void Reload(Stream stream)
  55. {
  56. LevelLoader.ReloadLevel(this, stream);
  57. }
  58. public static Level FromFile(Stream stream)
  59. {
  60. Level level = new Level();
  61. LevelLoader.ReloadLevel(level, stream);
  62. return level;
  63. }
  64. //Can be refactored
  65. internal static class LevelLoader
  66. {
  67. private static SpriteType type;
  68. private static Tile tile;
  69. private static Npc npc;
  70. private static int layerIndex;
  71. private static int x;
  72. private static bool isLayer;
  73. private static bool isBackground;
  74. private static Level level;
  75. internal static void ReloadLevel(Level level, Stream stream)
  76. {
  77. isLayer = true;
  78. LevelLoader.level = level;
  79. //Testing
  80. Player player = new Player(level);
  81. level.Players.Add(player);
  82. bool reachedBody = false;
  83. int itemIndex = 0;
  84. StringBuilder builder = new StringBuilder();
  85. for (int i = 0; i < stream.Length; i++)
  86. {
  87. int data = stream.ReadByte();
  88. if (data == -1) //Finished reading stream.
  89. return;
  90. char character = (char)data;
  91. if (data == '\n' || data == '\r' || data == ' ')
  92. continue;
  93. bool isSplitter = character == '|';
  94. reachedBody = reachedBody || isSplitter;
  95. if (!reachedBody)
  96. {
  97. //Read head data
  98. if (character == ',')
  99. {
  100. ParseHead(level, itemIndex, builder.ToString());
  101. builder.Clear();
  102. itemIndex++;
  103. }
  104. else
  105. {
  106. builder.Append(character);
  107. }
  108. }
  109. else
  110. {
  111. if (isSplitter) //Finish reading head data
  112. {
  113. ParseHead(level, itemIndex, builder.ToString());
  114. builder.Clear();
  115. itemIndex = 0;
  116. } //Read body data
  117. else if (character == ':') //Reached next item
  118. {
  119. ParseItem(itemIndex, builder.ToString());
  120. if (type == SpriteType.Tile)
  121. level.Layers[layerIndex].StaticSprites.Add(tile.Clone(), Visibility.Visible);
  122. else if (type == SpriteType.Npc)
  123. level.Layers[layerIndex].Sprites.Add(npc, Visibility.Visible);
  124. builder.Clear();
  125. itemIndex = 0;
  126. }
  127. else if (character == ',')
  128. {
  129. ParseItem(itemIndex, builder.ToString());
  130. builder.Clear();
  131. itemIndex++;
  132. }
  133. else
  134. {
  135. builder.Append(character);
  136. }
  137. }
  138. }
  139. //Testing
  140. level.Camera.Position = -new Vector2(level.Width / 2, level.Height / 2);
  141. }
  142. internal static void ParseHead(Level level, int index, string value)
  143. {
  144. switch (index)
  145. {
  146. case 0:
  147. level.Name = value;
  148. return;
  149. case 1:
  150. level.Width = Convert.ToInt32(value);
  151. return;
  152. case 2:
  153. level.Height = Convert.ToInt32(value);
  154. return;
  155. default:
  156. if (value[0] == '*')
  157. {
  158. if (isLayer)
  159. {
  160. isLayer = false;
  161. isBackground = true;
  162. }
  163. value = value.Substring(1, value.Length - 1);
  164. }
  165. if (isLayer)
  166. {
  167. Layer layer = new Layer(value);
  168. layer.Visibility = Visibility.Visible;
  169. level.Layers.Add(layer);
  170. return;
  171. }
  172. else if (isBackground)
  173. {
  174. BackgroundLayer layer = BackgroundSettings.GetBehaviour(Convert.ToInt32(value)).Clone();
  175. level.Background.Layers.Add(layer);
  176. return;
  177. }
  178. return;
  179. }
  180. }
  181. internal static void ParseItem(int index, string value)
  182. {
  183. switch (index)
  184. {
  185. case 0:
  186. type = (SpriteType)Convert.ToInt32(value);
  187. return;
  188. case 1:
  189. CreateSprite(Convert.ToInt32(value));
  190. return;
  191. case 2:
  192. layerIndex = Convert.ToInt32(value);
  193. return;
  194. case 3:
  195. x = Convert.ToInt32(value);
  196. return;
  197. case 4:
  198. if (type == SpriteType.Tile)
  199. tile.Collision.Origin += new Vector2(x, Convert.ToInt32(value));
  200. else
  201. GetSpriteByType().Position = new Vector2(x, Convert.ToInt32(value));
  202. return;
  203. case 5:
  204. return;
  205. //Load other settings here.
  206. }
  207. }
  208. internal static SpriteBase GetSpriteByType()
  209. {
  210. switch (type)
  211. {
  212. case SpriteType.Tile:
  213. return tile;
  214. case SpriteType.Npc:
  215. return npc;
  216. default:
  217. return null;
  218. }
  219. }
  220. internal static void CreateSprite(int index)
  221. {
  222. switch (type)
  223. {
  224. case SpriteType.Tile:
  225. tile = TileSettings.GetBehaviour(index);
  226. tile.Id = index;
  227. return;
  228. case SpriteType.Npc:
  229. npc = new Npc(level);
  230. npc.Id = index;
  231. return;
  232. }
  233. }
  234. }
  235. #endregion
  236. #region Update and Draw
  237. public void Update(GameTime gameTime)
  238. {
  239. if(Input.IsNewKeyMapPress(InputSettings.Cancel))
  240. IsRunning = !IsRunning;
  241. if (Input.IsNewKeyPress(Keys.X))
  242. OnLevelCleared(new LevelClearedEventArgs(0)); // temporary
  243. if (IsRunning)
  244. {
  245. if (TimeRemaining > 0)
  246. {
  247. TimeRemaining -= gameTime.GetElapsedSeconds();
  248. if (TimeRemaining <= 0)
  249. Timeout();
  250. }
  251. for (int i = 0; i < Layers.Count; i++)
  252. {
  253. Layers[i].Update(gameTime);
  254. }
  255. for (int i = 0; i < Players.Count; i++)
  256. {
  257. Players[i].Update(gameTime);
  258. }
  259. }
  260. //Testing code
  261. Vector2 offset = new Vector2();
  262. if (Input.IsNewKeyPress(Keys.R))
  263. mode = !mode;
  264. //if (Input.IsNewKeyPress(Keys.H))
  265. //Camera.Zoom *= 1.5f;
  266. //if (Input.IsNewKeyPress(Keys.J))
  267. //Camera.Zoom /= 1.5f;
  268. if (mode)
  269. {
  270. int speed = Input.Current.KeyboardState.IsKeyDown(Keys.LeftShift) ? 10 : 2;
  271. if (Input.Current.KeyboardState.IsKeyDown(Keys.Q))
  272. offset.X -= speed;
  273. else if (Input.Current.KeyboardState.IsKeyDown(Keys.D))
  274. offset.X += speed;
  275. else if (Input.Current.KeyboardState.IsKeyDown(Keys.W))
  276. offset.Y -= speed;
  277. else if (Input.Current.KeyboardState.IsKeyDown(Keys.S))
  278. offset.Y += speed;
  279. }
  280. else
  281. {
  282. var player = Players[0];
  283. offset = player.ProjectedPosition - player.Position;
  284. }
  285. Scroll(gameTime, offset);
  286. //End of testing code
  287. }
  288. public void Scroll(GameTime gameTime, Vector2 offset)
  289. {
  290. Camera.Move(offset);
  291. Background.Update(gameTime, offset);
  292. }
  293. public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
  294. {
  295. spriteBatch.End();
  296. Background.Draw(gameTime, spriteBatch, Section);
  297. Matrix transform = Camera.GetTransformation();
  298. spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, transform);
  299. for (int i = 0; i < Layers.Count; i++)
  300. {
  301. Layers[i].Draw(gameTime, spriteBatch);
  302. }
  303. for (int i = 0; i < Players.Count; i++)
  304. {
  305. Players[i].Draw(gameTime, spriteBatch);
  306. }
  307. spriteBatch.End();
  308. spriteBatch.Begin();
  309. }
  310. #endregion
  311. #region Public Methods
  312. public void Start()
  313. {
  314. IsRunning = true;
  315. }
  316. public void Stop()
  317. {
  318. IsRunning = false;
  319. }
  320. public void Timeout()
  321. {
  322. }
  323. #endregion
  324. protected virtual void OnLevelCleared(LevelClearedEventArgs e)
  325. {
  326. if (LevelCleared != null)
  327. LevelCleared(this, e);
  328. }
  329. #endregion
  330. }
  331. public sealed class LevelClearedEventArgs : EventArgs
  332. {
  333. /// <summary>
  334. /// Used to indicate which direction the path tiles should reveal on the related overworld.
  335. /// </summary>
  336. /// <remarks>If no world or project is associated to this level, than this field will not be used.</remarks>
  337. public int exitIndex;
  338. public LevelClearedEventArgs(int c_exitIndex)
  339. {
  340. exitIndex = c_exitIndex;
  341. }
  342. }
  343. public delegate void LevelClearedEventHandler(object sender, LevelClearedEventArgs e);
  344. }