/SMLimitless/SMLEngine/SMLEngineSprites/Collections/Level.cs
C# | 443 lines | 329 code | 99 blank | 15 comment | 58 complexity | 205196cb0b4aead8c8aa7f8424426622 MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
-
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Content;
- using Microsoft.Xna.Framework.Graphics;
- using Microsoft.Xna.Framework.Input;
-
- using SmlEngine.Sprites.Base;
- using SmlEngine.Sprites.Camera;
- using SmlEngine.Sprites.Settings;
- using SmlEngine.Sprites.Players;
- using SmlEngine.UI.Input;
- using SmlEngine.UI.Managers;
-
- namespace SmlEngine.Sprites.Collections
- {
- 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)
- {
- bool mode; //Auto-scroll, manual.
-
- #region Properties
-
- public string Name { get; set; }
-
- public InputManager Input { get; set; }
-
- public BackgroundSet Background { get; private set; }
- public IList<Layer> Layers { get; private set; }
- public IList<Player> Players { get; private set; } //May use PlayerCollection
-
- public Camera2D Camera { get; private set; }
-
- public int Section { get; set; }
-
- public int Width { get; set; }
- public int Height { get; set; }
-
- public int Score { get; set; }
-
- public int Time { get; set; }
- public float TimeRemaining { get; set; }
-
- public bool IsRunning { get; set; }
-
- public Axis Wrap { get; set; }
- public Axis Exit { get; set; }
-
- public event LevelClearedEventHandler LevelCleared;
-
- #endregion
-
- #region Methods
-
- #region Constructors
-
- public Level()
- {
- Camera = new Camera2D();
- Background = new BackgroundSet();
- Layers = new List<Layer>(4);
- Players = new List<Player>(4);
- }
-
- public Level(Stream stream)
- : this()
- {
- LevelLoader.ReloadLevel(this, stream);
- }
-
- #endregion
-
- #region Loading
-
- public void Reload(Stream stream)
- {
- LevelLoader.ReloadLevel(this, stream);
- }
-
- public static Level FromFile(Stream stream)
- {
- Level level = new Level();
- LevelLoader.ReloadLevel(level, stream);
- return level;
- }
-
- //Can be refactored
- internal static class LevelLoader
- {
- private static SpriteType type;
- private static Tile tile;
- private static Npc npc;
- private static int layerIndex;
-
- private static int x;
-
- private static bool isLayer;
- private static bool isBackground;
-
- private static Level level;
-
- internal static void ReloadLevel(Level level, Stream stream)
- {
- isLayer = true;
- LevelLoader.level = level;
-
- //Testing
- Player player = new Player(level);
- level.Players.Add(player);
-
- bool reachedBody = false;
- int itemIndex = 0;
- StringBuilder builder = new StringBuilder();
-
- for (int i = 0; i < stream.Length; i++)
- {
- int data = stream.ReadByte();
-
- if (data == -1) //Finished reading stream.
- return;
-
- char character = (char)data;
-
- if (data == '\n' || data == '\r' || data == ' ')
- continue;
-
- bool isSplitter = character == '|';
-
- reachedBody = reachedBody || isSplitter;
-
- if (!reachedBody)
- {
- //Read head data
- if (character == ',')
- {
- ParseHead(level, itemIndex, builder.ToString());
- builder.Clear();
- itemIndex++;
- }
- else
- {
- builder.Append(character);
- }
- }
- else
- {
- if (isSplitter) //Finish reading head data
- {
- ParseHead(level, itemIndex, builder.ToString());
- builder.Clear();
- itemIndex = 0;
- } //Read body data
- else if (character == ':') //Reached next item
- {
- ParseItem(itemIndex, builder.ToString());
-
- if (type == SpriteType.Tile)
- level.Layers[layerIndex].StaticSprites.Add(tile.Clone(), Visibility.Visible);
- else if (type == SpriteType.Npc)
- level.Layers[layerIndex].Sprites.Add(npc, Visibility.Visible);
-
- builder.Clear();
- itemIndex = 0;
- }
- else if (character == ',')
- {
- ParseItem(itemIndex, builder.ToString());
- builder.Clear();
- itemIndex++;
- }
- else
- {
- builder.Append(character);
- }
- }
- }
-
- //Testing
- level.Camera.Position = -new Vector2(level.Width / 2, level.Height / 2);
- }
-
- internal static void ParseHead(Level level, int index, string value)
- {
- switch (index)
- {
- case 0:
- level.Name = value;
- return;
-
- case 1:
- level.Width = Convert.ToInt32(value);
- return;
-
- case 2:
- level.Height = Convert.ToInt32(value);
- return;
-
- default:
-
- if (value[0] == '*')
- {
- if (isLayer)
- {
- isLayer = false;
- isBackground = true;
- }
-
- value = value.Substring(1, value.Length - 1);
- }
-
- if (isLayer)
- {
- Layer layer = new Layer(value);
- layer.Visibility = Visibility.Visible;
- level.Layers.Add(layer);
- return;
- }
- else if (isBackground)
- {
- BackgroundLayer layer = BackgroundSettings.GetBehaviour(Convert.ToInt32(value)).Clone();
- level.Background.Layers.Add(layer);
- return;
- }
- return;
- }
- }
-
- internal static void ParseItem(int index, string value)
- {
- switch (index)
- {
- case 0:
- type = (SpriteType)Convert.ToInt32(value);
- return;
-
- case 1:
- CreateSprite(Convert.ToInt32(value));
- return;
-
- case 2:
- layerIndex = Convert.ToInt32(value);
- return;
-
- case 3:
- x = Convert.ToInt32(value);
- return;
-
- case 4:
- if (type == SpriteType.Tile)
- tile.Collision.Origin += new Vector2(x, Convert.ToInt32(value));
- else
- GetSpriteByType().Position = new Vector2(x, Convert.ToInt32(value));
-
- return;
-
- case 5:
-
- return;
-
- //Load other settings here.
- }
- }
-
- internal static SpriteBase GetSpriteByType()
- {
- switch (type)
- {
- case SpriteType.Tile:
- return tile;
-
- case SpriteType.Npc:
- return npc;
-
- default:
- return null;
- }
- }
-
- internal static void CreateSprite(int index)
- {
- switch (type)
- {
- case SpriteType.Tile:
- tile = TileSettings.GetBehaviour(index);
- tile.Id = index;
- return;
-
- case SpriteType.Npc:
- npc = new Npc(level);
- npc.Id = index;
- return;
- }
- }
- }
-
- #endregion
-
- #region Update and Draw
-
- public void Update(GameTime gameTime)
- {
- if(Input.IsNewKeyMapPress(InputSettings.Cancel))
- IsRunning = !IsRunning;
-
- if (Input.IsNewKeyPress(Keys.X))
- OnLevelCleared(new LevelClearedEventArgs(0)); // temporary
-
- if (IsRunning)
- {
- if (TimeRemaining > 0)
- {
- TimeRemaining -= gameTime.GetElapsedSeconds();
-
- if (TimeRemaining <= 0)
- Timeout();
- }
-
- for (int i = 0; i < Layers.Count; i++)
- {
- Layers[i].Update(gameTime);
- }
-
- for (int i = 0; i < Players.Count; i++)
- {
- Players[i].Update(gameTime);
- }
- }
-
- //Testing code
-
- Vector2 offset = new Vector2();
-
- if (Input.IsNewKeyPress(Keys.R))
- mode = !mode;
-
- //if (Input.IsNewKeyPress(Keys.H))
- //Camera.Zoom *= 1.5f;
-
- //if (Input.IsNewKeyPress(Keys.J))
- //Camera.Zoom /= 1.5f;
-
- if (mode)
- {
- int speed = Input.Current.KeyboardState.IsKeyDown(Keys.LeftShift) ? 10 : 2;
-
- if (Input.Current.KeyboardState.IsKeyDown(Keys.Q))
- offset.X -= speed;
- else if (Input.Current.KeyboardState.IsKeyDown(Keys.D))
- offset.X += speed;
- else if (Input.Current.KeyboardState.IsKeyDown(Keys.W))
- offset.Y -= speed;
- else if (Input.Current.KeyboardState.IsKeyDown(Keys.S))
- offset.Y += speed;
- }
- else
- {
- var player = Players[0];
- offset = player.ProjectedPosition - player.Position;
- }
-
- Scroll(gameTime, offset);
-
- //End of testing code
- }
-
- public void Scroll(GameTime gameTime, Vector2 offset)
- {
- Camera.Move(offset);
- Background.Update(gameTime, offset);
- }
-
- public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
- {
- spriteBatch.End();
-
- Background.Draw(gameTime, spriteBatch, Section);
-
- Matrix transform = Camera.GetTransformation();
-
- spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, transform);
-
- for (int i = 0; i < Layers.Count; i++)
- {
- Layers[i].Draw(gameTime, spriteBatch);
- }
-
- for (int i = 0; i < Players.Count; i++)
- {
- Players[i].Draw(gameTime, spriteBatch);
- }
-
- spriteBatch.End();
-
- spriteBatch.Begin();
- }
-
- #endregion
-
- #region Public Methods
-
- public void Start()
- {
- IsRunning = true;
- }
-
- public void Stop()
- {
- IsRunning = false;
- }
-
- public void Timeout()
- {
-
- }
-
- #endregion
-
- protected virtual void OnLevelCleared(LevelClearedEventArgs e)
- {
- if (LevelCleared != null)
- LevelCleared(this, e);
- }
- #endregion
- }
-
- public sealed class LevelClearedEventArgs : EventArgs
- {
- /// <summary>
- /// Used to indicate which direction the path tiles should reveal on the related overworld.
- /// </summary>
- /// <remarks>If no world or project is associated to this level, than this field will not be used.</remarks>
- public int exitIndex;
-
- public LevelClearedEventArgs(int c_exitIndex)
- {
- exitIndex = c_exitIndex;
- }
- }
-
- public delegate void LevelClearedEventHandler(object sender, LevelClearedEventArgs e);
- }