<Compile Include="Program.cs" />\r
<Compile Include="Script.cs" />\r
<Compile Include="Timer.cs" />\r
+ <Compile Include="Trigger.cs" />\r
<Compile Include="XnaGame.cs" />\r
<Compile Include="ScreenManager.cs" />\r
</ItemGroup>\r
</Compile>\r
</ItemGroup>\r
<ItemGroup>\r
- <Compile Include="Maps\stable.cfmap">\r
- <Name>stable</Name>\r
+ <Compile Include="Maps\level1.cfmap">\r
+ <Name>level1</Name>\r
<Importer>MapImporter</Importer>\r
<Processor>PassThroughProcessor</Processor>\r
</Compile>\r
-; This map should load and function just fine.\r
-\r
[metadata]\r
author = Chaz McGarvey\r
levelname = Stable\r
speed = 10\r
path = [16,8] [20,6] wait(5) [56,9] [71,17] [75,2] [11,13]\r
\r
+[T]\r
+ type = Trigger\r
+ condition = Print("Trigger tested.") False()\r
+ event = Print("Trigger fired!")\r
+\r
[maptable]\r
+------------------------------------------------------------------------------+\r
-| |\r
+|T |\r
| 1 |\r
-| |\r
+| M |\r
| 2 +---- |\r
-| | |\r
+| | M |\r
| 3 | |\r
| |------------------------------------------ |\r
| 4 | | |\r
public Map Map;\r
public List<IEntity> Entities = new List<IEntity>();\r
public List<Projectile> mProjectiles = new List<Projectile>();\r
- public Player[] mCharacters = new Player[4];\r
+ public Player[] mCharacters;\r
public Display mDisplay;\r
\r
#endregion\r
mNumberOfPlayers = numPlayers;\r
mFrameNumber = 0;\r
\r
+ mCharacters = new Player[numPlayers];\r
+\r
mIsGameOver = new bool[numPlayers];\r
mIsTerminated = new bool[numPlayers];\r
\r
foreach (IEntity entity in State.Entities)\r
{\r
Point coordinates = entity.Coordinates;\r
- grid[coordinates.X, coordinates.Y] = true;\r
+ if (State.Map.IsCellOpen(coordinates)) grid[coordinates.X, coordinates.Y] = false;\r
}\r
return grid;\r
}\r
\r
\r
#region Public Methods\r
- public bool IsCellOpen(Point point)\r
+\r
+ public IEntity GetEntityAtCoordinates(Point point)\r
{\r
- if (!State.Map.IsCellOpen(point)) return false;\r
foreach (IEntity entity in State.Entities)\r
{\r
- if (entity.Coordinates == point) return false;\r
+ if (entity.Coordinates == point) return entity;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public Player GetPlayerAtCoordinates(Point point)\r
+ {\r
+ foreach (Player player in State.mCharacters)\r
+ {\r
+ if (player != null && player.Coordinates == point) return player;\r
}\r
+ return null;\r
+ }\r
+\r
+ public bool IsCellOpen(Point point)\r
+ {\r
+ if (!State.Map.IsCellOpen(point)) return false;\r
+ if (GetEntityAtCoordinates(point) != null) return false;\r
return true;\r
}\r
\r
State.mDisplay = new Display(this);\r
State.mDisplay.LoadContent(mContentManager);\r
\r
- State.Map = mContentManager.Load<Map>("Maps/stable");\r
+ State.Map = mContentManager.Load<Map>("Maps/level1");\r
State.Entities = State.Map.GetAllEntities(this);\r
Map.DefaultTile = mContentManager.Load<Texture2D>("default");\r
\r
/// Parses a function.\r
/// </summary>\r
/// <param name="atom">Text.</param>\r
- /// <returns>An array two strings containing the function name and\r
+ /// <returns>An array with two strings containing the function name and\r
/// parameter-list, in that order, or null if parsing failed.</returns>\r
public static string[] Function(string atom)\r
{\r
List<Point> list = new List<Point>();\r
\r
cell = cell.Parent;\r
- while (cell.Point != start)\r
+ while (cell != null && cell.Point != start)\r
{\r
list.Add(cell.Point);\r
cell = cell.Parent;\r
PathFinder pathFinder = new PathFinder(mGame.Grid);\r
mPath = new List<Point>(32);\r
mPath.Add(Coordinates);\r
- mPath.AddRange(pathFinder.GetPath(mMotion.Coordinates, mIdlePath[mIdlePathIndex]));\r
- mPath.Add(mIdlePath[mIdlePathIndex]);\r
+ List<Point> path = pathFinder.GetPath(mMotion.Coordinates, mIdlePath[mIdlePathIndex]);\r
+ if (path != null)\r
+ {\r
+ mPath.AddRange(path);\r
+ mPath.Add(mIdlePath[mIdlePathIndex]);\r
+ }\r
mPathIndex = 0;\r
}\r
\r
PathFinder pathFinder = new PathFinder(mGame.Grid);\r
mPath = new List<Point>(32);\r
mPath.Add(Coordinates);\r
- mPath.AddRange(pathFinder.GetPath(mMotion.Coordinates, mIdlePath[mIdlePathIndex % mIdlePath.Count]));\r
- mPath.Add(mIdlePath[mIdlePathIndex % mIdlePath.Count]);\r
+ List<Point> path = pathFinder.GetPath(mMotion.Coordinates, mIdlePath[mIdlePathIndex % mIdlePath.Count]);\r
+ if (path != null)\r
+ {\r
+ mPath.AddRange(path);\r
+ mPath.Add(mIdlePath[mIdlePathIndex % mIdlePath.Count]);\r
+ }\r
mPathIndex = 0;\r
}\r
\r
using System.Collections.Generic;\r
using System.Linq;\r
using System.Text;\r
+using System.Reflection;\r
+using System.Diagnostics;\r
\r
namespace CarFire\r
{\r
public class Script\r
{\r
- #region Public Types\r
+ #region Public Properties\r
\r
- public enum Status\r
+ public bool IsRunning { get { return mIsRunning; } }\r
+\r
+ #endregion\r
+\r
+\r
+ #region Public Methods\r
+\r
+ public Script(string code, Game game)\r
{\r
- Waiting,\r
- Done,\r
+ mGame = game;\r
+\r
+ string[] functions = Parse.List(code);\r
+ if (functions != null)\r
+ {\r
+ foreach (string function in functions)\r
+ {\r
+ string[] parts = Parse.Function(function);\r
+ if (parts != null)\r
+ {\r
+ string[] args = Parse.List(parts[1]);\r
+ if (args != null)\r
+ {\r
+ Function func = new Function(parts[0], args);\r
+ mFunctions.Add(func);\r
+ }\r
+ else throw new Exception("Arguments could not be parsed: " + parts[1]);\r
+ }\r
+ else throw new Exception("Function could not be parsed: " + function);\r
+ }\r
+ }\r
+ else throw new Exception("Script could not be parsed: " + code);\r
}\r
\r
- public enum Function\r
+ public bool Run(Player player)\r
{\r
- Create,\r
- Has,\r
- Play,\r
- Remove,\r
- UseUp,\r
- Wait,\r
+ bool result = false;\r
+\r
+ if (!mIsRunning)\r
+ {\r
+ mIsRunning = true;\r
+ mRunningIndex = 0;\r
+ }\r
+\r
+ for (; mRunningIndex < mFunctions.Count; mRunningIndex++)\r
+ {\r
+ result = Call(mRunningIndex, player);\r
+ if (!result) break;\r
+ }\r
+\r
+ if (mRunningIndex >= mFunctions.Count - 1) mIsRunning = false;\r
+ return result;\r
}\r
\r
#endregion\r
\r
\r
- #region Public Methods\r
+ #region Private Methods\r
\r
- public Script(string code)\r
+ bool Call(int index, Player player)\r
{\r
+ Debug.Assert(0 <= index && index < mFunctions.Count);\r
+ try\r
+ {\r
+ object[] args = new object[2];\r
+ args[0] = player;\r
+ args[1] = mFunctions[index].Arguments;\r
+ return (bool)typeof(Impl).InvokeMember(mFunctions[index].Name, BindingFlags.InvokeMethod, null, null, args);\r
+ }\r
+#pragma warning disable 0168\r
+ catch (System.MissingMethodException ex)\r
+#pragma warning restore 0168\r
+ {\r
+ throw new Exception("Function could not be found: " + mFunctions[index].Name);\r
+ }\r
}\r
\r
- public Status Run()\r
+ #endregion\r
+\r
+\r
+ #region Private Types\r
+\r
+ class Impl\r
{\r
- return Status.Done;\r
+ public static bool True(Player player, string[] args)\r
+ {\r
+ return true;\r
+ }\r
+\r
+ public static bool False(Player player, string[] args)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ public static bool Has(Player player, string[] args)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ public static bool Print(Player player, string[] args)\r
+ {\r
+ foreach (string arg in args)\r
+ {\r
+ string line = Parse.String(arg);\r
+ if (line != null) Console.WriteLine(line);\r
+ }\r
+ return true;\r
+ }\r
}\r
\r
- public Status Evaluate(out bool value)\r
+ class Function\r
{\r
- value = true;\r
- return Status.Done;\r
+ public string Name { get { return mName; } }\r
+ public string[] Arguments { get { return mArgs; } }\r
+\r
+ public Function(string name, string[] args)\r
+ {\r
+ mName = name;\r
+ mArgs = args;\r
+ }\r
+\r
+ string mName;\r
+ string[] mArgs;\r
}\r
\r
#endregion\r
+\r
+\r
+ #region Private Variables\r
+\r
+ Game mGame;\r
+ List<Function> mFunctions = new List<Function>();\r
+ bool mIsRunning;\r
+ int mRunningIndex;\r
+ Impl mImpl = new Impl();\r
+\r
+ #endregion\r
}\r
}\r
--- /dev/null
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using Microsoft.Xna.Framework;\r
+using Microsoft.Xna.Framework.Graphics;\r
+using Microsoft.Xna.Framework.Content;\r
+\r
+namespace CarFire\r
+{\r
+ /// <summary>\r
+ /// A trigger is an invisible entity whose only purpose is\r
+ /// to check a condition and run a script when the condition\r
+ /// is right.\r
+ /// </summary>\r
+ public class Trigger : IEntity\r
+ {\r
+ #region Public Methods\r
+\r
+ public Trigger(char identifier, Point position, Dictionary<string, string> info, Game game)\r
+ {\r
+ mGame = game;\r
+ mPrevCondition = false;\r
+ mCoordinates = position;\r
+\r
+ string condition;\r
+ if (info.TryGetValue("condition", out condition))\r
+ {\r
+ mCondition = new Script(condition, game);\r
+ }\r
+ else throw new Exception("Triggers must define a condition script.");\r
+\r
+ string eventt;\r
+ if (info.TryGetValue("event", out eventt))\r
+ {\r
+ mEvent = new Script(eventt, game);\r
+ }\r
+ else throw new Exception("Triggers must define an event script.");\r
+ }\r
+\r
+ public void Update(TimeSpan timeSpan)\r
+ {\r
+ Player player = mGame.GetPlayerAtCoordinates(mCoordinates);\r
+ if (player != null)\r
+ {\r
+ bool condition = mCondition.Run(player);\r
+ if (condition && condition != mPrevCondition)\r
+ {\r
+ mEvent.Run(player);\r
+ }\r
+ mPrevCondition = condition;\r
+ }\r
+ else\r
+ {\r
+ mPrevCondition = false;\r
+ }\r
+ }\r
+\r
+ public void LoadContent(ContentManager contentManager)\r
+ {\r
+ // No implementation needed.\r
+ }\r
+\r
+ public void Draw(SpriteBatch spriteBatch)\r
+ {\r
+ // No implementation needed.\r
+ }\r
+\r
+ public Vector2 Position\r
+ {\r
+ get { return Vector2.Zero; }\r
+ }\r
+\r
+ public Point Coordinates\r
+ {\r
+ get { return new Point(-1, -1); }\r
+ }\r
+\r
+ #endregion\r
+\r
+\r
+ #region Private Variables\r
+\r
+ Script mCondition;\r
+ Script mEvent;\r
+ Game mGame;\r
+ bool mPrevCondition;\r
+ Point mCoordinates;\r
+\r
+ #endregion\r
+ }\r
+}\r