Advertisement
smc_gamer

World.cs

Dec 22nd, 2012
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 53.79 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. using System.Linq;
  7.  
  8. using Microsoft.Xna.Framework;
  9. using Microsoft.Xna.Framework.Content;
  10. using Microsoft.Xna.Framework.Graphics;
  11. using Microsoft.Xna.Framework.Input;
  12. using Microsoft.Xna.Framework.Audio;
  13. using Microsoft.Xna.Framework.Media;
  14.  
  15. using SmlEngine.Sprites.Base;
  16. using SmlEngine.Sprites.Camera;
  17. using SmlEngine.Sprites.Collections;
  18. using SmlEngine.Sprites.Settings;
  19. using SmlEngine.Graphics;
  20. using SmlEngine.UI.Managers;
  21. using SmlEngine.Sprites.Base.WorldMap;
  22. using SmlEngine.Extensions;
  23. using SmlEngine.IO;
  24.  
  25. namespace SmlEngine.Sprites.Collections
  26. {
  27.     /// <summary>
  28.     /// An overhead map to signify levels.
  29.     /// </summary>
  30.     public class World : IName
  31.     {
  32.         #region Properties and Fields
  33.  
  34.         public string Name { get; set; }
  35.  
  36.         public InputManager Input { get; set; }
  37.  
  38.         public IList<Layer> Layers { get; private set; } // unused
  39.         public List<WorldPlayer> Players { get; private set; }
  40.  
  41.         public Camera2D Camera { get; private set; }
  42.         public int Score { get; set; }
  43.         public bool IsRunning { get; set; }
  44.         public bool HandleInput { get; set; } // Set to false to stop handling input, useful when fading
  45.         private bool isContentLoaded;
  46.  
  47.         private Vector2 windowSize;
  48.  
  49.         public WorldPlayer ActivePlayer
  50.         {
  51.             get;
  52.             private set;
  53.         }
  54.  
  55.         public int ActivePlayerIndex
  56.         {
  57.             get
  58.             {
  59.                 if (ActivePlayer == null) return -1;
  60.                 return Players.IndexOf(ActivePlayer);
  61.             }
  62.         }
  63.  
  64.         public bool IsLoaded { get; private set; }
  65.  
  66.         private SpriteFont testFont;
  67.  
  68.         private Song worldMusic; // temporary
  69.         private SoundEffect jumpSound; // temporary
  70.  
  71.         #region World Settings
  72.         public string worldName { get; private set; }
  73.         public string worldAuthor { get; private set; }
  74.         // public object Project <-- will be implemented later
  75.         public Vector2 worldOrigin { get; private set; }
  76.         public Vector2 worldSize { get; private set; }
  77.         public string worldFolder { get; private set; }
  78.         #endregion
  79.  
  80.         #region Jumping
  81.         private bool IsJumping = false;
  82.         private Vector2 jumpDistancePerFrame;
  83.         private int jumpedFor = 0;
  84.         #endregion
  85.  
  86.         #region Object Lists
  87.         public QuadTree<WorldMapTile> staticTiles = new QuadTree<WorldMapTile>(new Vector2(64, 64));
  88.         public QuadTree<WorldAnimatedTile> animatedTiles = new QuadTree<WorldAnimatedTile>(new Vector2(64, 64));
  89.         public QuadTree<PathTile> pathTiles = new QuadTree<PathTile>(new Vector2(64, 64));
  90.         public QuadTree<LevelTile> levelTiles = new QuadTree<LevelTile>(new Vector2(64, 64));
  91.         public QuadTree<PipeTile> pipeTiles = new QuadTree<PipeTile>(new Vector2(64, 64));
  92.         #endregion
  93.  
  94.         #region Section Data
  95.         public bool isCameraLocked;  
  96.         public int Section { get; set; }
  97.         public string FileName { get; private set; }
  98.         #endregion
  99.  
  100.         #region Preloaded Custom Tile Lists
  101.         private Dictionary<string, WorldMapTile> loadedCustomTiles = new Dictionary<string, WorldMapTile>();
  102.         private Dictionary<string, WorldAnimatedTile> loadedCustomAnimTiles = new Dictionary<string, WorldAnimatedTile>();
  103.         private Dictionary<string, LevelTile> loadedCustomLevelTiles = new Dictionary<string, LevelTile>();
  104.         private Dictionary<string, PathTile> loadedCustomPathTiles = new Dictionary<string, PathTile>();
  105.         #endregion
  106.  
  107.         #region Exit Settings
  108.         private int exitIndex; // how many exits are loaded
  109.         private Dictionary<int, List<PathTile>> pathsByExit = new Dictionary<int,List<PathTile>>(); // stores references to path tiles by exit number
  110.         private int revealingExitIndex = -3; // which exit is being revealed, -3 is the code for no exit is being revealed
  111.         private int revealingTileIndex = -1; // which tile in the exit is being revealed
  112.         private LevelTile currentLevel; // which level tile is currently entered
  113.         private bool unlockCurrentTile; // whether we should unlock the current tile
  114.         #endregion
  115.  
  116.         #region Border Text
  117.         public string LevelDisplayText = "";
  118.         public string CoinDisplayText
  119.         {
  120.             get
  121.             {
  122.                 if (ActivePlayer == null) return "";
  123.                 return ActivePlayer.Coins.ToString();
  124.             }
  125.         }
  126.         public string LivesDisplayText
  127.         {
  128.             get
  129.             {
  130.                 if (ActivePlayer == null) return "";
  131.                 return ActivePlayer.Lives.ToString();
  132.             }
  133.         }
  134.         #endregion
  135.  
  136.         #region Pipes and Section Switching
  137.         public event LevelEnteredEventHandler LevelEntered;
  138.         private LevelTile tileEntering;
  139.         public PipeTile pipeEntering;
  140.         #endregion
  141.  
  142.         #endregion
  143.  
  144.         #region Methods
  145.  
  146.         #region Constructors
  147.  
  148.         public World(Vector2 c_windowSize)
  149.         {
  150.             Camera = new Camera2D();
  151.             Layers = new List<Layer>();
  152.             Players = new List<WorldPlayer>();
  153.             windowSize = c_windowSize;
  154.             this.IsRunning = false;
  155.             this.HandleInput = true;
  156.         }
  157.        
  158.         #endregion
  159.  
  160.         #region Loading
  161.         public void Load(string world_path)
  162.         {
  163.             System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
  164.             stopWatch.Start();
  165.             if (IsLoaded) return;
  166.             if (File.Exists(world_path))
  167.             {
  168.                 this.FileName = world_path;
  169.                 worldFolder = world_path.Substring(0, world_path.LastIndexOf(@"\"));
  170.                 DataReader dataReader = new DataReader(world_path);
  171.                 if (!dataReader.SectionExists("[world]")) { throw new Exception("The world file at " + world_path + " is corrupt."); }
  172.  
  173.                 LoadHeader(dataReader);
  174.                 LoadStaticTiles(dataReader);
  175.                 LoadAnimatedTiles(dataReader);
  176.                 LoadPathTiles(dataReader);
  177.                 LoadWorldPlayers(dataReader);
  178.                 LoadLevelTiles(dataReader);
  179.                 LoadPipeTiles(dataReader);
  180.  
  181.                 IsLoaded = true;
  182.             }
  183.             else
  184.             {
  185.                 throw new FileNotFoundException(string.Format("The world file at {0} could not be found.", world_path));
  186.             }
  187.             stopWatch.Stop();
  188.             System.Diagnostics.Trace.WriteLine("World load: " + stopWatch.ElapsedMilliseconds);
  189.         }
  190.  
  191.         private void LoadHeader(DataReader dataReader)
  192.         {
  193.             var header = dataReader.ReadFullSection("[world]");
  194.             if (header == null) throw new Exception(string.Format("The world file at {0} is corrupt or invalid.", dataReader.FilePath));
  195.  
  196.             worldName = header["name"];
  197.             worldAuthor = header["author"];
  198.             // worldProject = <-- will be implemented later
  199.             worldOrigin = GetVector(header["start"]);
  200.             worldSize = GetVector(header["size"]);
  201.         }
  202.  
  203.         private void LoadStaticTiles(DataReader dataReader)
  204.         {
  205.             string[] tile_entries = dataReader.ReadAllLinesInSection("[static]");
  206.             string[] tile_entry;
  207.             int tile_id;
  208.             string tile_filePath = "";
  209.             int tileX;
  210.             int tileY;
  211.             Vector2 quadTreePos;
  212.  
  213.             foreach (string tile in tile_entries)
  214.             {
  215.                 tile_entry = tile.Split(',');
  216.                 if (!Int32.TryParse(tile_entry[0], out tile_id)) // If this tile is custom
  217.                 {
  218.                     tile_filePath = String.Concat(worldFolder, @"\", tile_entry[1]);
  219.                     tile_id = -1;
  220.                 }
  221.                 tileX = int.Parse(tile_entry[1]);
  222.                 tileY = int.Parse(tile_entry[2]);
  223.  
  224.                 WorldMapTile lt, t;
  225.                 if (tile_id != -1)
  226.                 {
  227.                     t = WorldObjectSet.LoadWorldMapTile(tile_id);
  228.                 }
  229.                 else
  230.                 {
  231.                     // Custom tile
  232.                     if (!IsCustomTileLoaded(tile_filePath))
  233.                     {
  234.                         // All custom tiles are preloaded, and then cloned as necessary.
  235.                         lt = WorldObjectSet.LoadCustomStaticTile(worldFolder, tile_filePath);
  236.                         loadedCustomTiles.Add(tile_filePath, lt);
  237.                     }
  238.                     t = (WorldMapTile)loadedCustomTiles[tile_filePath].Clone();
  239.                 }
  240.                 t.Position = new Vector2(tileX, tileY);
  241.                 staticTiles.Add(t);
  242.             }
  243.  
  244.  
  245.             // Clearing out the (pre-)loaded tiles
  246.             loadedCustomTiles.Clear();
  247.         }
  248.  
  249.         private void LoadAnimatedTiles(DataReader dataReader)
  250.         {
  251.             dataReader.SetIndexToSection("[anim]");
  252.             string[] atile_entry;
  253.             int atile_id;
  254.             int atileX;
  255.             int atileY;
  256.             string a_filePath = "";
  257.             Vector2 quadTreePos;
  258.  
  259.             while ((atile_entry = dataReader.ReadNextEntry()) != null)
  260.             {
  261.                 if (!Int32.TryParse(atile_entry[0], out atile_id)) // Custom tile
  262.                 {
  263.                     a_filePath = String.Concat(worldFolder, @"\", atile_entry[1]);
  264.                     atile_id = -1;
  265.                 }
  266.                 atileX = int.Parse(atile_entry[1]);
  267.                 atileY = int.Parse(atile_entry[2]);
  268.  
  269.                 WorldAnimatedTile a = null, la;
  270.                 if (atile_id >= 0)
  271.                 {
  272.                     a = WorldObjectSet.LoadWorldAnimatedTile(atile_id);
  273.                 }
  274.                 else
  275.                 {
  276.                     if (!IsCustomAnimatedTileLoaded(a_filePath))
  277.                     {
  278.                         la = WorldObjectSet.LoadCustomAnimatedTile(worldFolder, a_filePath);
  279.                         loadedCustomAnimTiles.Add(a_filePath, la);
  280.                     }
  281.                     a = (WorldAnimatedTile)loadedCustomAnimTiles[a_filePath].Clone();
  282.                 }
  283.  
  284.                 a.SetData(new Vector2(atileX, atileY));
  285.                 quadTreePos = a.Position.FloorDivide(64);
  286.                 animatedTiles.Add(a);
  287.             }
  288.             loadedCustomAnimTiles.Clear();
  289.         }
  290.  
  291.         private void LoadPathTiles(DataReader dataReader)
  292.         {
  293.             string[] path_entry;
  294.             int path_id;
  295.             string path_cconfig = "";
  296.             int path_X = 0;
  297.             int path_Y = 0;
  298.             int path_exitNumber = 0;
  299.             Vector2 p_quadTreePos;
  300.  
  301.             dataReader.SetIndexToSection("[path]");
  302.             while ((path_entry = dataReader.ReadNextEntry()) != null)
  303.             {
  304.                 path_exitNumber = 0;
  305.                 if (!Int32.TryParse(path_entry[0], out path_id))
  306.                 {
  307.                     path_cconfig = worldFolder + @"\" + path_entry[2];
  308.                     path_id = -1;
  309.                 }
  310.  
  311.                 path_X = Int32.Parse(path_entry[1]);
  312.                 path_Y = Int32.Parse(path_entry[2]);
  313.                 path_exitNumber = Int32.Parse(path_entry[3]);
  314.  
  315.                 PathTile p = null, lp;
  316.                 if (path_id != -1)
  317.                 {
  318.                     p = WorldObjectSet.LoadPathTile(path_id);
  319.                 }
  320.                 else
  321.                 {
  322.                     if (!IsCustomPathTileLoaded(path_cconfig))
  323.                     {
  324.                         lp = WorldObjectSet.LoadCustomPathTile(worldFolder, path_cconfig);
  325.                         loadedCustomPathTiles.Add(path_cconfig, lp);
  326.                     }
  327.                     p = (PathTile)loadedCustomPathTiles[path_cconfig].Clone();
  328.                 }
  329.                 p.SetData(new Vector2(path_X, path_Y), path_exitNumber);
  330.                 p_quadTreePos = p.Position.FloorDivide(64);
  331.                 pathTiles.Add(p);
  332.                 if (!pathsByExit.ContainsKey(path_exitNumber)) { pathsByExit.Add(path_exitNumber, new List<PathTile>()); }
  333.                 pathsByExit[path_exitNumber].Add(p);
  334.             }
  335.         }
  336.  
  337.         private void LoadLevelTiles(DataReader dataReader)
  338.         {
  339.             var tiles = dataReader.ReadFullMultiSection("[level]");
  340.             if (tiles != null)
  341.             {
  342.                 foreach (var tile in tiles)
  343.                 {
  344.                     #region Data Loading
  345.                     int id;
  346.                     string configPath = "";
  347.                     Vector2 position;
  348.                     bool revealed;
  349.                     string filePath;
  350.                     string displayName;
  351.                     int exitNumber;
  352.                     string[] exitData;
  353.                     List<Exit> level_exits = new List<Exit>();
  354.                     int revealOn;
  355.  
  356.                     bool isSMB3Style = false;
  357.  
  358.                     if (!Int32.TryParse(tile["id"], out id))
  359.                     {
  360.                         configPath = worldFolder + @"\" + tile["id"];
  361.                         id = -1;
  362.                     }
  363.                     position = GetVector(tile["position"]);
  364.                     revealed = tile["reveal"] == "yes" ? true : false;
  365.                     filePath = tile["path"];
  366.                     displayName = tile["display"];
  367.                     exitNumber = Int32.Parse(tile["exits"]);
  368.                     if (tile["exitdata"] != "smb3")
  369.                     {
  370.                         exitData = tile["exitdata"].Split(',');
  371.                         if (exitData.Length > 4) throw new Exception(string.Format("There were too many defined exits for this level tile (level tile #{0})", tiles.IndexOf(tile)));
  372.                         foreach (string s in exitData)
  373.                         {
  374.                             level_exits.Add(new Exit(s));
  375.                         }
  376.                     }
  377.                     else
  378.                     {
  379.                         isSMB3Style = true;
  380.                     }
  381.                     revealOn = int.Parse(tile["revealOn"]);
  382.                     #endregion
  383.                     LevelTile l = null;
  384.                     if (id >= 0)
  385.                     {
  386.                         l = WorldObjectSet.LoadLevelTile(id);
  387.                     }
  388.                     else
  389.                     {
  390.                         if (!IsCustomLevelTileLoaded(configPath))
  391.                         {
  392.                             if (!isSMB3Style)
  393.                             {
  394.                                 loadedCustomLevelTiles.Add(configPath, WorldObjectSet.LoadCustomLevelTile(worldFolder, configPath));
  395.                             }
  396.                             else
  397.                             {
  398.                                 loadedCustomLevelTiles.Add(configPath, WorldObjectSet.LoadCustomSMB3LevelTile(worldFolder, configPath));
  399.                             }
  400.                             l = (LevelTile)loadedCustomLevelTiles[configPath].Clone();
  401.                         }
  402.                     }
  403.                     if (!isSMB3Style)
  404.                     {
  405.                         l.SetData(position, "", filePath, level_exits);
  406.                         l.SetData(revealOn);
  407.                     }
  408.                     else
  409.                     {
  410.                         (l as SMB3LevelTile).SetData(position, "", filePath);
  411.                     }
  412.                     l.LevelName = displayName;
  413.                     Vector2 quadtreePos = l.Position.FloorDivide(64);
  414.                     levelTiles.Add(l);
  415.                     if (!pathsByExit.ContainsKey(revealOn)) pathsByExit.Add(revealOn, new List<PathTile>());
  416.                     pathsByExit[revealOn].Add(l);
  417.                 }
  418.             }
  419.         }
  420.  
  421.         private void LoadWorldPlayers(DataReader dataReader)
  422.         {
  423.             dataReader.SetIndexToSection("[player]");
  424.             string[] player_entry;
  425.             int player_ID;
  426.             string config_path = "";
  427.             int player_X;
  428.             int player_Y;
  429.             while ((player_entry = dataReader.ReadNextEntry()) != null)
  430.             {
  431.                 if (!Int32.TryParse(player_entry[0], out player_ID)) // custom player
  432.                 {
  433.                     config_path = player_entry[0];
  434.                     player_ID = -1;
  435.                 }
  436.                 player_X = Int32.Parse(player_entry[1]);
  437.                 player_Y = Int32.Parse(player_entry[2]);
  438.  
  439.                 WorldPlayer p = null;
  440.                 if (player_ID >= 0)
  441.                 {
  442.                     p = WorldObjectSet.LoadWorldPlayer(player_ID);
  443.                 }
  444.                 else
  445.                 {
  446.                     p = WorldObjectSet.LoadCustomWorldPlayer(worldFolder, config_path);
  447.                 }
  448.                 p.Position = new Vector2(player_X, player_Y);
  449.                 Players.Add(p);
  450.                 if (ActivePlayer == null) ActivePlayer = p;
  451.             }
  452.         }
  453.  
  454.         private void LoadPipeTiles(DataReader dataReader)
  455.         {
  456.             var pipes = dataReader.ReadFullMultiSection("[pipe]");
  457.             if (pipes != null)
  458.             {
  459.                 int pipeID;
  460.                 string pipeCustomConfigPath = "";
  461.                 Vector2 pipePosition;
  462.                 string pipeDisplayName;
  463.                 int pipeDestinationSection = -1;
  464.                 string pipeDestinationFileName = "";
  465.                 Vector2 pipeDestinationPosition;
  466.                 int pipeRevealOnExit;
  467.  
  468.                 foreach (var pipe in pipes)
  469.                 {
  470.                     if (!int.TryParse(pipe["id"], out pipeID))
  471.                     {
  472.                         pipeCustomConfigPath = pipe["id"];
  473.                         pipeID = -1;
  474.                     }
  475.                     pipePosition = GetVector(pipe["position"]);
  476.                     pipeDisplayName = pipe["display"];
  477.                     pipeDestinationPosition = GetVector(pipe["destination"]);
  478.                     pipeRevealOnExit = int.Parse(pipe["revealOn"]);
  479.                    
  480.                     // load the destination section/filename
  481.                     if (pipe.ContainsKey("section"))
  482.                     {
  483.                         pipeDestinationSection = Int32.Parse(pipe["section"]);
  484.                     }
  485.                     else if (pipe.ContainsKey("filename"))
  486.                     {
  487.                         pipeDestinationFileName = string.Concat(worldFolder, pipe["filename"]);
  488.                         pipeDestinationSection = -1;
  489.                     }
  490.  
  491.                     PipeTile p = null;
  492.                     if (pipeID >= 0)
  493.                     {
  494.                         p = WorldObjectSet.LoadPipeTile(pipeID);
  495.                     }
  496.                     else
  497.                     {
  498.                         p = WorldObjectSet.LoadCustomPipeTile(worldFolder, pipeCustomConfigPath);
  499.                     }
  500.  
  501.                     p.SetData(pipePosition, pipeRevealOnExit);
  502.                     p.DisplayName = pipeDisplayName;
  503.                     p.DestinationWorldSection = pipeDestinationSection;
  504.                     p.DestinationFileName = pipeDestinationFileName;
  505.                     p.DestinationPosition = pipeDestinationPosition;
  506.  
  507.                     pipeTiles.Add(p);
  508.                     if (!pathsByExit.ContainsKey(p.exitNumber))
  509.                     {
  510.                         pathsByExit.Add(p.exitNumber, new List<PathTile>());
  511.                     }
  512.                     pathsByExit[p.exitNumber].Add(p);
  513.                 }
  514.             }
  515.         }
  516.  
  517.         public void LoadContent(ContentManager Content, GraphicsDevice Graphics)
  518.         {
  519.             System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
  520.             stopWatch.Start();
  521.             if (!isContentLoaded)
  522.             {
  523.                 foreach (WorldMapTile t in staticTiles)
  524.                 {
  525.                     t.LoadContent(Content, Graphics);
  526.                 }
  527.                 foreach (WorldAnimatedTile a in animatedTiles)
  528.                 {
  529.                     a.LoadContent(Content, Graphics);
  530.                 }
  531.                 foreach (var path in pathTiles)
  532.                 {
  533.                     path.LoadContent(Content, Graphics);
  534.                 }
  535.                 foreach (LevelTile l in levelTiles)
  536.                 {
  537.                     if (l is SMB3LevelTile)
  538.                     {
  539.                         (l as SMB3LevelTile).LoadContent(Graphics, Content);
  540.                     }
  541.                     else
  542.                     {
  543.                         l.LoadContent(Graphics, Content);
  544.                     }
  545.                 }
  546.                 foreach (var i in pipeTiles)
  547.                 {
  548.                     i.LoadContent(Content, Graphics);
  549.                 }
  550.                 foreach (WorldPlayer player in Players)
  551.                 {
  552.                     player.LoadContent(Graphics, Content);
  553.                 }
  554.  
  555.                 testFont = Content.Load<SpriteFont>(@"world\testFont");
  556.                 worldMusic = Content.Load<Song>(@"sound_test\music");
  557.                 jumpSound = Content.Load<SoundEffect>(@"sound_test\smw_scroll");
  558.                 MediaPlayer.Volume = 0.5f;
  559.                 MediaPlayer.Play(worldMusic);
  560.                 isContentLoaded = true;
  561.  
  562.                 stopWatch.Stop();
  563.                 System.Diagnostics.Trace.WriteLine("World load content: " + stopWatch.ElapsedMilliseconds);
  564.             }
  565.         }
  566.  
  567.         private string GetValue(string input)
  568.         {
  569.             return input.Split('=')[1].TrimStart();
  570.         }
  571.  
  572.         //private object GetMatchingObjectByIndex(object[] inputs, object[] outputs, string input)
  573.         //{
  574.         //    if (inputs.Length != outputs.Length) throw new ArgumentException("Could not get matching object by index, parameters were not the same length.");
  575.         //    int index = Array.IndexOf(inputs, input);
  576.         //    if (index == -1) return null;
  577.         //    return outputs[index];
  578.         //}
  579.  
  580.         private static Vector2 GetVector(string input)
  581.         {
  582.             String[] v = input.Split(',');
  583.             v[0] = v[0].Trim();
  584.             return new Vector2(float.Parse(v[0]), float.Parse(v[1]));
  585.         }
  586.  
  587.         private bool IsCustomTileLoaded(string file_path)
  588.         {
  589.             return loadedCustomAnimTiles.ContainsKey(file_path);
  590.         }
  591.  
  592.         private bool IsCustomAnimatedTileLoaded(string file_path)
  593.         {
  594.             return loadedCustomAnimTiles.ContainsKey(file_path);
  595.         }
  596.  
  597.         private bool IsCustomPathTileLoaded(string path)
  598.         {
  599.             return loadedCustomPathTiles.ContainsKey(path);
  600.         }
  601.  
  602.         private bool IsCustomLevelTileLoaded(string path)
  603.         {
  604.             return loadedCustomLevelTiles.ContainsKey(path);
  605.         }
  606.  
  607.         #endregion
  608.  
  609.         #region Update and Draw
  610.         public void UpdateCamera()
  611.         {
  612.             if (!isCameraLocked && ActivePlayer != null)
  613.             {
  614.                 if (IsJumping)
  615.                 {
  616.                     if (jumpedFor == 30)
  617.                     {
  618.                         IsJumping = false;
  619.                         jumpDistancePerFrame = Vector2.Zero;
  620.                         jumpedFor = 0;
  621.                     }
  622.                     Camera.Position += jumpDistancePerFrame;
  623.                     jumpedFor++;
  624.                 }
  625.                 else
  626.                 {
  627.                     Vector2 halfPlayer = new Vector2(ActivePlayer.Size.X / 2, ActivePlayer.Size.Y / 2);
  628.                     Vector2 halfWindow = windowSize / 2;
  629.                     Camera.Position = ActivePlayer.Position + halfPlayer;
  630.                     Camera.Position = new Vector2(Camera.Position.X - halfWindow.X, Camera.Position.Y - halfWindow.Y);
  631.                 }
  632.             }
  633.         }
  634.  
  635.         public void Update(GameTime gameTime)
  636.         {
  637.             if (!this.IsRunning) return;
  638.  
  639.             UpdateCamera();
  640.  
  641.             #region Fading Checks
  642.             //if (fadeStep < 0) // fade in
  643.             //{
  644.             //    if (fadeLevel > 0) fadeLevel += fadeStep;
  645.             //    else
  646.             //    {
  647.             //        fadeStep = 0;
  648.             //        tileEntering = null;
  649.             //        if (revealingExitIndex >= 0)
  650.             //        {
  651.             //            internalStartReveal(revealingExitIndex);
  652.             //        }
  653.             //        if (unlockCurrentTile)
  654.             //        {
  655.             //            internalUnlockTile();
  656.             //            unlockCurrentTile = false;
  657.             //        }
  658.             //        //OnFadeCompleted(new FadeCompletedEventArgs(FadeType.In));
  659.             //    }
  660.             //}
  661.             //else if (fadeStep > 0) // fade out
  662.             //{
  663.             //    if (fadeLevel < 60) fadeLevel += fadeStep;
  664.             //    else
  665.             //    {
  666.             //        fadeStep = 0;
  667.             //        if (tileEntering != null) OnLevelEntered(tileEntering);
  668.             //        //OnFadeCompleted(new FadeCompletedEventArgs(FadeType.Out));
  669.             //    }
  670.             //}
  671.             #endregion
  672.  
  673.             #region Reveal Checks
  674.                 if (revealingExitIndex != -3 && revealingTileIndex >= 0) // if we're revealing
  675.                 {
  676.                     if (pathsByExit[revealingExitIndex][revealingTileIndex].IsRevealed) // if this tile is done revealing and we're not at the end of the list
  677.                     {
  678.                         revealingTileIndex++;
  679.                         pathsByExit[revealingExitIndex][revealingTileIndex].Reveal();
  680.                     }
  681.                     else if (revealingTileIndex == pathsByExit[revealingExitIndex].Count - 1)
  682.                     {
  683.                         revealingExitIndex = -3;
  684.                         revealingTileIndex = -1;
  685.                     }
  686.                 }
  687.             #endregion
  688.  
  689.             #region Tile Updating
  690.             pathTiles.Update(gameTime);
  691.             levelTiles.Update(gameTime);
  692.             pipeTiles.Update(gameTime);
  693.             #endregion
  694.  
  695.             if (ActivePlayer != null)
  696.             {
  697.                 PathTile currentPath = GetPath(ActivePlayer.tilePosition);
  698.                 if (LevelDisplayText == "" && (currentPath != null && currentPath is LevelTile))
  699.                 {
  700.                     LevelDisplayText = (currentPath as LevelTile).LevelName;
  701.                 }
  702.                 else if (LevelDisplayText == "" && (currentPath != null && currentPath is PipeTile))
  703.                 {
  704.                     LevelDisplayText = (currentPath as PipeTile).DisplayName;
  705.                 }
  706.                 else if (currentPath == null || ((!(currentPath is LevelTile)) && (!(currentPath is PipeTile))))
  707.                 {
  708.                     LevelDisplayText = "";
  709.                 }
  710.             }
  711.  
  712.             #region Input Handling
  713.             //if (!Players.Any() || ActivePlayer == null) return;
  714.             if (HandleInput)
  715.             {
  716.                 if (!ActivePlayer.IsMoving && !IsJumping && revealingExitIndex == -3)
  717.                 {
  718.                     var keymap = Input.Current.KeyboardState;
  719.                     Vector2 tilePos = ActivePlayer.tilePosition;
  720.                     Vector2 distance = Vector2.Zero;
  721.  
  722.                     if (keymap.IsKeyDown(Keys.Up)) { distance = GetDistanceToNextPathStop(ActivePlayer.tilePosition, Direction.Top); ActivePlayer.Move(distance); }
  723.                     else if (keymap.IsKeyDown(Keys.Down)) { distance = GetDistanceToNextPathStop(ActivePlayer.tilePosition, Direction.Bottom); ActivePlayer.Move(distance); }
  724.                     else if (keymap.IsKeyDown(Keys.Left)) { distance = GetDistanceToNextPathStop(ActivePlayer.tilePosition, Direction.Left); ActivePlayer.Move(distance); }
  725.                     else if (keymap.IsKeyDown(Keys.Right)) { distance = GetDistanceToNextPathStop(ActivePlayer.tilePosition, Direction.Right); ActivePlayer.Move(distance); }
  726.  
  727.                     if (Input.IsNewKeyPress(Keys.J) && !IsJumping) Jump();
  728.                     if (Input.IsNewKeyPress(Keys.Q)) internalStartReveal(0); // temporary
  729.                 }
  730.  
  731.                 if (Input.IsNewKeyPress(Keys.X) && !IsJumping)
  732.                 {
  733.                     PathTile p = GetPath(ActivePlayer.tilePosition);
  734.                     if (p is LevelTile)
  735.                     {
  736.                         OnLevelEntered((LevelTile)p);
  737.                     }
  738.                     else if (p is PipeTile && !ActivePlayer.IsMoving)
  739.                     {
  740.                         PipeTile pipe = (PipeTile)p;
  741.                         int section = pipe.DestinationWorldSection;
  742.                         string filename = pipe.DestinationFileName;
  743.                         if ((section == this.Section || section == -1) && filename == this.FileName) // same world
  744.                         {
  745.                             Vector2 oldPosition = ActivePlayer.Position;
  746.                             ActivePlayer.Position = pipe.DestinationPosition;
  747.                             Jump(oldPosition, ActivePlayer.Position);
  748.                         }
  749.                         else
  750.                         {
  751.                             pipe.PlayerToSend = ActivePlayer;
  752.                             pipeEntering = pipe;
  753.                         }
  754.                     }
  755.                 }
  756.             }
  757.             foreach (WorldPlayer p in Players) p.Update(gameTime);
  758.             #endregion
  759.         }
  760.  
  761.         public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
  762.         {
  763.             if (!this.IsRunning) return;
  764.  
  765.             spriteBatch.End();
  766.             spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null, Camera.GetTransformation());
  767.  
  768.             staticTiles.Draw(gameTime, spriteBatch);
  769.             animatedTiles.Draw(gameTime, spriteBatch);
  770.             pathTiles.Draw(gameTime, spriteBatch);
  771.             levelTiles.Draw(gameTime, spriteBatch);
  772.             pipeTiles.Draw(gameTime, spriteBatch);
  773.  
  774.             if (!unlockCurrentTile)
  775.             {
  776.                 foreach (WorldPlayer p in Players)
  777.                 {
  778.                     p.Draw(gameTime, spriteBatch);
  779.                 }
  780.             }
  781.             //spriteBatch.DrawRectangle(GetScreenBounds(), (Color.Black * (fadeLevel * 0.01667f)));
  782.             //spriteBatch.DrawString(testFont, "Now opening: New Pipe Network", new Vector2(30, 30) + Camera.Position, Color.White);
  783.             spriteBatch.End();
  784.             spriteBatch.Begin();
  785.         }
  786.  
  787.         #endregion
  788.  
  789.         #region Public Methods
  790.  
  791.         public void Start()
  792.         {
  793.             IsRunning = true;
  794.         }
  795.  
  796.         public void Stop()
  797.         {
  798.             IsRunning = false;
  799.         }
  800.  
  801.         public void Jump(int playerIndex)
  802.         {
  803.             if (playerIndex < 0 || playerIndex > Players.Count - 1)
  804.             {
  805.                 throw new ArgumentOutOfRangeException("playerIndex", string.Format("The world tried to focus a player that did not exist ({0})", playerIndex));
  806.             }
  807.  
  808.             if (ActivePlayer.Position == Players[playerIndex].Position)
  809.             {
  810.                 return;
  811.             }
  812.  
  813.             IsJumping = true;
  814.             Vector2 v1 = ActivePlayer.Position;
  815.             Vector2 v2 = Players[playerIndex].Position;
  816.             jumpDistancePerFrame = ((v2 - v1) / 30);
  817.             ActivePlayer = Players[playerIndex];
  818.  
  819.             Players.ForEach(p => p.Velocity = Vector2.Zero);
  820.             jumpSound.Play();
  821.         }
  822.  
  823.         public void Jump(Vector2 a, Vector2 b)
  824.         {
  825.             if (a == b) return;
  826.             IsJumping = true;
  827.             jumpDistancePerFrame = ((b - a) / 30);
  828.         }
  829.  
  830.         public void Jump()
  831.         {
  832.             if (Players.Count == 1) return;
  833.             if (ActivePlayerIndex == Players.Count - 1) Jump(0);
  834.             else Jump(ActivePlayerIndex + 1);
  835.         }
  836.  
  837.         public void StartReveal(int exitIndex)
  838.         {
  839.             revealingExitIndex = exitIndex;
  840.         }
  841.  
  842.         private void internalStartReveal(int exitIndex)
  843.         {
  844.             if (exitIndex >= 0 && exitIndex < pathsByExit.Count)
  845.             {
  846.                 revealingExitIndex = exitIndex;
  847.                 if (pathsByExit[exitIndex].Any())
  848.                 {
  849.                     int i;
  850.                     LevelTile l = GetLevelTileByExit(exitIndex, out i);
  851.                     if (l != null && l.Exits[i].Cleared == false)
  852.                     {
  853.                         l.Exits[i] = new Exit(exitIndex, l.Exits[i].ExitDirection, true);
  854.                         revealingTileIndex = 0;
  855.                         pathsByExit[exitIndex][0].Reveal();
  856.                     }
  857.                     else
  858.                     {
  859.                         revealingExitIndex = -3;
  860.                         revealingTileIndex = -1;
  861.                     }
  862.                 }
  863.             }
  864.         }
  865.  
  866.         public void UnlockTile()
  867.         {
  868.             unlockCurrentTile = true;
  869.         }
  870.  
  871.         private void internalUnlockTile()
  872.         {
  873.             if (currentLevel != null && currentLevel is SMB3LevelTile)
  874.             {
  875.                 (currentLevel as SMB3LevelTile).Unlock();
  876.             }
  877.         }
  878.  
  879.         public WorldPlayer GetPlayer(int index)
  880.         {
  881.             if (index < Players.Count)
  882.             {
  883.                 return Players[index];
  884.             }
  885.             return null;
  886.         }
  887.  
  888.         public void AddPlayer(WorldPlayer player, Vector2 position)
  889.         {
  890.             player.Position = position;
  891.             Players.Add(player);
  892.             ActivePlayer = player;
  893.         }
  894.  
  895.         public void ClearSwap()
  896.         {
  897.             pipeEntering = null;
  898.         }
  899.  
  900.         public void ReloadContent(GraphicsDevice gd, ContentManager cm)
  901.         {
  902.             UnloadContent();
  903.             foreach (WorldMapTile t in staticTiles)
  904.             {
  905.                 t.LoadContent(cm, gd);
  906.             }
  907.             foreach (WorldAnimatedTile va in animatedTiles) va.LoadContent(cm, gd);
  908.             foreach (var p in pathTiles) p.LoadContent(cm, gd);
  909.             foreach (var l in levelTiles)
  910.             {
  911.                 if (l is SMB3LevelTile) (l as SMB3LevelTile).LoadContent(cm, gd);
  912.                 else l.LoadContent(cm, gd);
  913.             }
  914.             foreach (var p in pipeTiles) p.LoadContent(cm, gd);
  915.             Players.ForEach(pl => pl.LoadContent(gd, cm));
  916.         }
  917.  
  918.         public void UnloadContent()
  919.         {
  920.             foreach (WorldMapTile t in staticTiles) t.UnloadContent();
  921.             foreach (WorldAnimatedTile a in animatedTiles) a.UnloadContent();
  922.             foreach (var v in pathTiles) v.UnloadContent();
  923.             foreach (var v in levelTiles) v.UnloadContent();
  924.             foreach (var v in pipeTiles) v.UnloadContent();
  925.             Players.ForEach(pl => pl.UnloadContent());
  926.         }
  927.         #endregion
  928.  
  929.         #region Section and Pipe Methods
  930.         //private void SetSectionToSwap(int newSectionIndex, Vector2 newDestination, int playerSwapIndex)
  931.         //{
  932.         //    SwapSectionIndex = newSectionIndex;
  933.         //    SwapDestination = newDestination;
  934.         //    SwapWorldPlayerIndex = playerSwapIndex;
  935.         //}
  936.  
  937.         //public void FinishSwap()
  938.         //{
  939.         //    SwapSectionIndex = -1;
  940.         //    SwapWorldPlayerIndex = -1;
  941.         //}
  942.  
  943.         //public void FadeIn()
  944.         //{
  945.         //    if (fadeLevel != 0)
  946.         //    {
  947.         //        fadeStep = -1;
  948.         //    }
  949.         //}
  950.  
  951.         //public void FadeOut()
  952.         //{
  953.         //    if (fadeLevel != 60)
  954.         //    {
  955.         //        fadeStep = 1;
  956.         //    }
  957.         //}
  958.  
  959.         public void UpdateFocusedPlayer()
  960.         {
  961.             //if (focusedPlayer >= Players.Count)
  962.             //{
  963.             //    focusedPlayer = Players.Count - 1;
  964.             //}
  965.         }
  966.         #endregion
  967.  
  968.         #region Helper Methods
  969.         public PathTile GetPath(Vector2 tileLocation)
  970.         {
  971.             // TODO: only check rect intersections with bottom center point of WorldPlayer hitbox (prevents multiple tiles registered)
  972.             Vector2 quadTreePos = tileLocation.FloorDivide(4);
  973.             if (pathTiles.ContainsCell(quadTreePos))
  974.             {
  975.                 foreach (PathTile p in pathTiles[quadTreePos])
  976.                 {
  977.                     if (p.tilePosition == tileLocation) return p;
  978.                     else if (!p.Size.ComparePoint(ActivePlayer.Size) && p.Area.GetIntersectionDepth(ActivePlayer.Area) != Vector2.Zero) return p;
  979.                 }
  980.             }
  981.             if (levelTiles.ContainsCell(quadTreePos))
  982.             {
  983.                 foreach (LevelTile l in levelTiles[quadTreePos])
  984.                 {
  985.                     if (l.tilePosition == tileLocation) return l;
  986.                     else if (!l.Size.ComparePoint(ActivePlayer.Size) && l.Area.GetIntersectionDepth(ActivePlayer.Area) != Vector2.Zero) return l;
  987.                 }
  988.             }
  989.             if (pipeTiles.ContainsCell(quadTreePos))
  990.             {
  991.                 foreach (PipeTile p in pipeTiles[quadTreePos])
  992.                 {
  993.                     if (p.tilePosition == tileLocation) return p;
  994.                     else if (!p.Size.ComparePoint(ActivePlayer.Size) && p.Area.GetIntersectionDepth(ActivePlayer.Area) != Vector2.Zero) return p;
  995.                 }
  996.             }
  997.             return null;
  998.         }
  999.  
  1000.         private WorldPlayer GetWorldPlayer(Vector2 tileLocation)
  1001.         {
  1002.             foreach (var player in Players)
  1003.             {
  1004.                 if (player.tilePosition == tileLocation) return player;
  1005.             }
  1006.             return null;
  1007.         }
  1008.  
  1009.         private Vector2 GetDistanceToNextPathStop(Vector2 startPathTilePosition, Direction direction)
  1010.         {
  1011.             Vector2 offset = Vector2.Zero; // the number of tiles to go by
  1012.             Vector2 iteratorPosition = Vector2.Zero;
  1013.             PathTile p;
  1014.  
  1015.             // first, check if the player is on an SMB3LevelTile, and see if it can move
  1016.             if ((p = GetPath(startPathTilePosition)) != null)
  1017.             {
  1018.                 if (p is SMB3LevelTile && (p as SMB3LevelTile).LockState == LockedState.Locked)
  1019.                 {
  1020.                     WorldPlayer player = GetWorldPlayer(startPathTilePosition);
  1021.                     if (player != null && player.InvertDirection(player.LastMoveDirection) != direction)
  1022.                     {
  1023.                         return Vector2.Zero;
  1024.                     }
  1025.                 }
  1026.             }
  1027.             else return Vector2.Zero; // no path tile
  1028.  
  1029.             switch (direction)
  1030.             {
  1031.                 case Direction.Top: // up (Y decreases)
  1032.                     if (p.Direction == PathType.Horizontal) // || p.Direction == PathType.CornerTopLeft || p.Direction == PathType.CornerTopRight || p.Direction == PathType.TIntersectionFromBottom)
  1033.                     {
  1034.                         return Vector2.Zero;
  1035.                     }
  1036.                     iteratorPosition = new Vector2(startPathTilePosition.X, startPathTilePosition.Y - 1);
  1037.                     p = GetPath(iteratorPosition);
  1038.                     while (p != null)
  1039.                     {
  1040.                         if (p.IsNode)
  1041.                         {
  1042.                             offset.Y -= p.Size.Y;
  1043.                             return offset;
  1044.                         }
  1045.                         if (p is SMB3LevelTile)
  1046.                         {
  1047.                             offset.Y -= p.Size.Y;
  1048.                             return offset;
  1049.                         }
  1050.                         if (!p.IsRevealed)
  1051.                         {
  1052.                             return offset;
  1053.                         }
  1054.                         iteratorPosition.Y--;
  1055.                         offset.Y -= p.Size.Y;
  1056.                         p = GetPath(iteratorPosition);
  1057.                     }
  1058.                     break;
  1059.                 case Direction.Bottom: // down (Y increases)
  1060.                     if (p.Direction == PathType.Horizontal) // || p.Direction == PathType.CornerBottomLeft || p.Direction == PathType.CornerBottomRight || p.Direction == PathType.TIntersectionFromTop)
  1061.                     {
  1062.                         return Vector2.Zero;
  1063.                     }
  1064.                     iteratorPosition = new Vector2(startPathTilePosition.X, startPathTilePosition.Y + 1);
  1065.                     p = GetPath(iteratorPosition);
  1066.                     while (p != null)
  1067.                     {
  1068.                         if (p.IsNode)
  1069.                         {
  1070.                             offset.Y += p.Size.Y;
  1071.                             return offset;
  1072.                         }
  1073.                         if (p is SMB3LevelTile)
  1074.                         {
  1075.                             offset.Y += p.Size.Y;
  1076.                             return offset;
  1077.                         }
  1078.                         if (!p.IsRevealed)
  1079.                         {
  1080.                             return offset;
  1081.                         }
  1082.                         iteratorPosition.Y++;
  1083.                         offset.Y += p.Size.Y;
  1084.                         p = GetPath(iteratorPosition);
  1085.                     }
  1086.                     break;
  1087.                 case Direction.Left: // left (X decreases)
  1088.                     if (p.Direction == PathType.Vertical) // || p.Direction == PathType.CornerBottomLeft || p.Direction == PathType.CornerTopLeft || p.Direction == PathType.TIntersectionFromRight)
  1089.                     {
  1090.                         return Vector2.Zero;
  1091.                     }
  1092.                     iteratorPosition = new Vector2(startPathTilePosition.X - 1, startPathTilePosition.Y);
  1093.                     p = GetPath(iteratorPosition);
  1094.                     while (p != null)
  1095.                     {
  1096.                         if (p.IsNode)
  1097.                         {
  1098.                             offset.X -= p.Size.X;
  1099.                             return offset;
  1100.                         }
  1101.                         if (p is SMB3LevelTile)
  1102.                         {
  1103.                             offset.X -= p.Size.X;
  1104.                             return offset;
  1105.                         }
  1106.                         if (!p.IsRevealed)
  1107.                         {
  1108.                             return offset;
  1109.                         }
  1110.                         iteratorPosition.X--;
  1111.                         offset.X -= p.Size.X;
  1112.                         p = GetPath(iteratorPosition);
  1113.                     }
  1114.                     break;
  1115.                 case Direction.Right: // right (X increases)
  1116.                     if (p.Direction == PathType.Vertical) //|| p.Direction == PathType.CornerBottomRight || p.Direction == PathType.CornerTopRight || p.Direction == PathType.TIntersectionFromLeft)
  1117.                     {
  1118.                         return Vector2.Zero;
  1119.                     }
  1120.                     iteratorPosition = new Vector2(startPathTilePosition.X + 1, startPathTilePosition.Y);
  1121.                     p = GetPath(iteratorPosition);
  1122.                     while (p != null)
  1123.                     {
  1124.                         if (p.IsNode)
  1125.                         {
  1126.                             offset.X += p.Size.X;
  1127.                             return offset;
  1128.                         }
  1129.                         if (p is SMB3LevelTile)
  1130.                         {
  1131.                             offset.X += p.Size.X;
  1132.                             return offset;
  1133.                         }
  1134.                         if (!p.IsRevealed)
  1135.                         {
  1136.                             return offset;
  1137.                         }
  1138.                         iteratorPosition.X++;
  1139.                         offset.X += p.Size.X;
  1140.                         p = GetPath(iteratorPosition);
  1141.                     }
  1142.                     break;
  1143.             }
  1144.  
  1145.             return offset;
  1146.         }
  1147.  
  1148.         private Rectangle GetScreenBounds()
  1149.         {
  1150.             return new Rectangle((int)Camera.Position.X, (int)Camera.Position.Y, (int)windowSize.X, (int)windowSize.Y);
  1151.         }
  1152.  
  1153.         private Vector2? CheckForPathTile(Vector2 position, Direction dir)
  1154.         {
  1155.             Vector2 startTileSize = GetPath(position.FloorDivide(16)).Size;
  1156.             Rectangle r = new Rectangle((int)position.X, (int)position.Y, 1, 1);
  1157.             if (dir == Direction.Top) r.Y--;
  1158.             else if (dir == Direction.Bottom) r.Y++;
  1159.             else if (dir == Direction.Left) r.X--;
  1160.             else if (dir == Direction.Right) r.X++;
  1161.             Vector2 colRectCell = new Vector2(r.X, r.Y).FloorDivide(64);
  1162.             foreach (PathTile p in pathTiles[colRectCell])
  1163.             {
  1164.                 Rectangle pRect = p.Position.ToRectangle(p.Size);
  1165.                 Vector2 depth = r.GetIntersectionDepth(pRect);
  1166.                 if (depth != Vector2.Zero) return p.Position;
  1167.             }
  1168.             foreach (LevelTile l in levelTiles[colRectCell])
  1169.             {
  1170.                 Rectangle pRect = l.Position.ToRectangle(l.Size);
  1171.                 Vector2 depth = r.GetIntersectionDepth(pRect);
  1172.                 if (depth != Vector2.Zero) return l.Position;
  1173.             }
  1174.             return null;
  1175.         }
  1176.  
  1177.         protected virtual void OnLevelEntered(LevelTile e)
  1178.         {
  1179.             if (LevelEntered != null)
  1180.                 LevelEntered(this, e);
  1181.         }
  1182.         #endregion
  1183.  
  1184.         #region Path Methods
  1185.  
  1186.         public void AssignPathToExitByBorder(PathTile p)
  1187.         {
  1188.             #region Field Initialization
  1189.             Dictionary<Direction, Vector2> offset = new Dictionary<Direction, Vector2>();
  1190.             offset.Add(Direction.Top, new Vector2(0, -1));
  1191.             offset.Add(Direction.Bottom, new Vector2(0, 1));
  1192.             offset.Add(Direction.Left, new Vector2(-1, 0));
  1193.             offset.Add(Direction.Right, new Vector2(1, 0));
  1194.  
  1195.             Dictionary<Direction, List<PathType>> movable_types = new Dictionary<Direction, List<PathType>>();
  1196.             movable_types.Add(Direction.Top, new List<PathType>() { PathType.CornerTopLeft, PathType.CornerTopRight, PathType.FourWayIntersection,
  1197.                 PathType.TIntersectionFromBottom, PathType.TIntersectionFromLeft, PathType.TIntersectionFromRight, PathType.Vertical});
  1198.             movable_types.Add(Direction.Bottom, new List<PathType>() { PathType.CornerBottomLeft, PathType.CornerBottomRight, PathType.FourWayIntersection,
  1199.                 PathType.TIntersectionFromLeft, PathType.TIntersectionFromRight, PathType.TIntersectionFromTop, PathType.Vertical});
  1200.             movable_types.Add(Direction.Left, new List<PathType>() { PathType.CornerBottomLeft, PathType.CornerTopLeft, PathType.FourWayIntersection,
  1201.                 PathType.Horizontal, PathType.TIntersectionFromBottom, PathType.TIntersectionFromRight, PathType.TIntersectionFromTop});
  1202.             movable_types.Add(Direction.Right, new List<PathType>() { PathType.CornerBottomRight, PathType.CornerTopRight, PathType.FourWayIntersection,
  1203.                 PathType.Horizontal, PathType.TIntersectionFromBottom, PathType.TIntersectionFromLeft, PathType.TIntersectionFromTop});
  1204.  
  1205.             Dictionary<PathType, List<Direction>> searchDirections = new Dictionary<PathType, List<Direction>>();
  1206.             searchDirections.Add(PathType.CornerBottomLeft, new List<Direction>() { Direction.Top, Direction.Right });
  1207.             searchDirections.Add(PathType.CornerBottomRight, new List<Direction>() { Direction.Top, Direction.Left });
  1208.             searchDirections.Add(PathType.CornerTopLeft, new List<Direction>() { Direction.Bottom, Direction.Right });
  1209.             searchDirections.Add(PathType.CornerTopRight, new List<Direction>() { Direction.Bottom, Direction.Left });
  1210.             searchDirections.Add(PathType.FourWayIntersection, new List<Direction>() { Direction.Top, Direction.Bottom, Direction.Left, Direction.Right });
  1211.             searchDirections.Add(PathType.Horizontal, new List<Direction>() { Direction.Left, Direction.Right });
  1212.             searchDirections.Add(PathType.TIntersectionFromBottom, new List<Direction>() { Direction.Bottom, Direction.Left, Direction.Right });
  1213.             searchDirections.Add(PathType.TIntersectionFromLeft, new List<Direction>() { Direction.Left, Direction.Top, Direction.Bottom });
  1214.             searchDirections.Add(PathType.TIntersectionFromRight, new List<Direction>() { Direction.Right, Direction.Top, Direction.Bottom });
  1215.             searchDirections.Add(PathType.TIntersectionFromTop, new List<Direction>() { Direction.Top, Direction.Left, Direction.Right });
  1216.             searchDirections.Add(PathType.Vertical, new List<Direction>() { Direction.Top, Direction.Bottom });
  1217.             #endregion
  1218.             foreach (Direction d in Enum.GetValues(typeof(Direction)))
  1219.             {
  1220.                 if (searchDirections[p.Direction].Contains(d))
  1221.                 {
  1222.                     PathTile check_tile = GetPath(p.tilePosition + offset[d]);
  1223.                     if (check_tile != null && movable_types[d].Contains(check_tile.Direction))
  1224.                     {
  1225.                         p.SetData(check_tile.exitNumber);
  1226.                         if (!pathsByExit.ContainsKey(p.exitNumber)) pathsByExit.Add(p.exitNumber, new List<PathTile>());
  1227.                         pathsByExit[p.exitNumber].Add(p);
  1228.                     }
  1229.                 }
  1230.             }
  1231.         }
  1232.  
  1233.         public List<PathTile> AssignBorderPathsToExit(PathTile p)
  1234.         {
  1235.             #region Field Initialization
  1236.             Dictionary<Direction, Vector2> offset = new Dictionary<Direction, Vector2>();
  1237.             offset.Add(Direction.Top, new Vector2(0, -1));
  1238.             offset.Add(Direction.Bottom, new Vector2(0, 1));
  1239.             offset.Add(Direction.Left, new Vector2(-1, 0));
  1240.             offset.Add(Direction.Right, new Vector2(1, 0));
  1241.  
  1242.             Dictionary<Direction, List<PathType>> movable_types = new Dictionary<Direction, List<PathType>>();
  1243.             movable_types.Add(Direction.Top, new List<PathType>() { PathType.CornerTopLeft, PathType.CornerTopRight, PathType.FourWayIntersection,
  1244.                 PathType.TIntersectionFromBottom, PathType.TIntersectionFromLeft, PathType.TIntersectionFromRight, PathType.Vertical});
  1245.             movable_types.Add(Direction.Bottom, new List<PathType>() { PathType.CornerBottomLeft, PathType.CornerBottomRight, PathType.FourWayIntersection,
  1246.                 PathType.TIntersectionFromLeft, PathType.TIntersectionFromRight, PathType.TIntersectionFromTop, PathType.Vertical});
  1247.             movable_types.Add(Direction.Left, new List<PathType>() { PathType.CornerBottomLeft, PathType.CornerTopLeft, PathType.FourWayIntersection,
  1248.                 PathType.Horizontal, PathType.TIntersectionFromBottom, PathType.TIntersectionFromRight, PathType.TIntersectionFromTop});
  1249.             movable_types.Add(Direction.Right, new List<PathType>() { PathType.CornerBottomRight, PathType.CornerTopRight, PathType.FourWayIntersection,
  1250.                 PathType.Horizontal, PathType.TIntersectionFromBottom, PathType.TIntersectionFromLeft, PathType.TIntersectionFromTop});
  1251.  
  1252.             Dictionary<PathType, List<Direction>> searchDirections = new Dictionary<PathType, List<Direction>>();
  1253.             searchDirections.Add(PathType.CornerBottomLeft, new List<Direction>() { Direction.Top, Direction.Right });
  1254.             searchDirections.Add(PathType.CornerBottomRight, new List<Direction>() { Direction.Top, Direction.Left });
  1255.             searchDirections.Add(PathType.CornerTopLeft, new List<Direction>() { Direction.Bottom, Direction.Right });
  1256.             searchDirections.Add(PathType.CornerTopRight, new List<Direction>() { Direction.Bottom, Direction.Left });
  1257.             searchDirections.Add(PathType.FourWayIntersection, new List<Direction>() { Direction.Top, Direction.Bottom, Direction.Left, Direction.Right });
  1258.             searchDirections.Add(PathType.Horizontal, new List<Direction>() { Direction.Left, Direction.Right });
  1259.             searchDirections.Add(PathType.TIntersectionFromBottom, new List<Direction>() { Direction.Bottom, Direction.Left, Direction.Right });
  1260.             searchDirections.Add(PathType.TIntersectionFromLeft, new List<Direction>() { Direction.Left, Direction.Top, Direction.Bottom });
  1261.             searchDirections.Add(PathType.TIntersectionFromRight, new List<Direction>() { Direction.Right, Direction.Top, Direction.Bottom });
  1262.             searchDirections.Add(PathType.TIntersectionFromTop, new List<Direction>() { Direction.Top, Direction.Left, Direction.Right });
  1263.             searchDirections.Add(PathType.Vertical, new List<Direction>() { Direction.Top, Direction.Bottom });
  1264.             #endregion
  1265.             List<PathTile> result = new List<PathTile>();
  1266.             foreach (Direction d in Enum.GetValues(typeof(Direction)))
  1267.             {
  1268.                 if (searchDirections[p.Direction].Contains(d))
  1269.                 {
  1270.                     PathTile check_tile = GetPath(p.tilePosition + offset[d]);
  1271.                     if (check_tile != null && movable_types[d].Contains(check_tile.Direction))
  1272.                     {
  1273.                         check_tile.SetData(p.exitNumber);
  1274.                         if (!pathsByExit.ContainsKey(p.exitNumber)) pathsByExit.Add(p.exitNumber, new List<PathTile>());
  1275.                         pathsByExit[p.exitNumber].Add(check_tile);
  1276.                         result.Add(check_tile);
  1277.                     }
  1278.                 }
  1279.             }
  1280.             return result;
  1281.         }
  1282.  
  1283.         public void RebuildExitTree()
  1284.         {
  1285.             throw new NotImplementedException();
  1286.         }
  1287.  
  1288.         private LevelTile GetLevelTileByExit(int exitNumber, out int exitNumberinList)
  1289.         {
  1290.             foreach (LevelTile l in levelTiles)
  1291.             {
  1292.                 foreach (Exit e in l.Exits)
  1293.                 {
  1294.                     if (e.Index == exitNumber) { exitNumberinList = l.Exits.IndexOf(e); return l; }
  1295.                 }
  1296.             }
  1297.             exitNumberinList = -1;
  1298.             return null;
  1299.         }
  1300.  
  1301.         #endregion
  1302.  
  1303.         #endregion
  1304.     }
  1305.  
  1306.     public delegate void LevelEnteredEventHandler(object sender, LevelTile e);
  1307. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement