--- /dev/null
+\r
+Microsoft Visual Studio Solution File, Format Version 10.00\r
+# Visual Studio 2008\r
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CS 3505 Project 06", "CS 3505 Project 06\CS 3505 Project 06.csproj", "{0C08A79E-3951-4C7F-A554-32468808F00D}"\r
+EndProject\r
+Global\r
+ GlobalSection(SubversionScc) = preSolution\r
+ Svn-Managed = True\r
+ Manager = AnkhSVN - Subversion Support for Visual Studio\r
+ EndGlobalSection\r
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+ Debug|x86 = Debug|x86\r
+ Release|x86 = Release|x86\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {0C08A79E-3951-4C7F-A554-32468808F00D}.Debug|x86.ActiveCfg = Debug|x86\r
+ {0C08A79E-3951-4C7F-A554-32468808F00D}.Debug|x86.Build.0 = Debug|x86\r
+ {0C08A79E-3951-4C7F-A554-32468808F00D}.Release|x86.ActiveCfg = Release|x86\r
+ {0C08A79E-3951-4C7F-A554-32468808F00D}.Release|x86.Build.0 = Release|x86\r
+ {56086477-A1FB-4593-8868-2B41D8719294}.Debug|x86.ActiveCfg = Debug|x86\r
+ {56086477-A1FB-4593-8868-2B41D8719294}.Release|x86.ActiveCfg = Release|x86\r
+ EndGlobalSection\r
+ GlobalSection(SolutionProperties) = preSolution\r
+ HideSolutionNode = FALSE\r
+ EndGlobalSection\r
+EndGlobal\r
--- /dev/null
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">\r
+ <PropertyGroup>\r
+ <ProjectGuid>{0C08A79E-3951-4C7F-A554-32468808F00D}</ProjectGuid>\r
+ <ProjectTypeGuids>{6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>\r
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>\r
+ <OutputType>WinExe</OutputType>\r
+ <AppDesignerFolder>Properties</AppDesignerFolder>\r
+ <RootNamespace>CS_3505_Project_06</RootNamespace>\r
+ <AssemblyName>CS 3505 Project 06</AssemblyName>\r
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>\r
+ <XnaFrameworkVersion>v3.0</XnaFrameworkVersion>\r
+ <XnaPlatform>Windows</XnaPlatform>\r
+ <XnaCrossPlatformGroupID>4c8ffe57-5280-4c98-91c6-e0b1fcc90362</XnaCrossPlatformGroupID>\r
+ <ApplicationIcon>Game.ico</ApplicationIcon>\r
+ <Thumbnail>GameThumbnail.png</Thumbnail>\r
+ <PublishUrl>publish\</PublishUrl>\r
+ <Install>true</Install>\r
+ <InstallFrom>Disk</InstallFrom>\r
+ <UpdateEnabled>false</UpdateEnabled>\r
+ <UpdateMode>Foreground</UpdateMode>\r
+ <UpdateInterval>7</UpdateInterval>\r
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>\r
+ <UpdatePeriodically>false</UpdatePeriodically>\r
+ <UpdateRequired>false</UpdateRequired>\r
+ <MapFileExtensions>true</MapFileExtensions>\r
+ <ApplicationRevision>0</ApplicationRevision>\r
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>\r
+ <IsWebBootstrapper>false</IsWebBootstrapper>\r
+ <UseApplicationTrust>false</UseApplicationTrust>\r
+ <BootstrapperEnabled>true</BootstrapperEnabled>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">\r
+ <DebugSymbols>true</DebugSymbols>\r
+ <DebugType>full</DebugType>\r
+ <Optimize>false</Optimize>\r
+ <OutputPath>bin\x86\Debug</OutputPath>\r
+ <DefineConstants>DEBUG;TRACE;WINDOWS</DefineConstants>\r
+ <ErrorReport>prompt</ErrorReport>\r
+ <WarningLevel>4</WarningLevel>\r
+ <NoStdLib>true</NoStdLib>\r
+ <UseVSHostingProcess>false</UseVSHostingProcess>\r
+ <PlatformTarget>x86</PlatformTarget>\r
+ <XnaCompressContent>false</XnaCompressContent>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">\r
+ <DebugType>pdbonly</DebugType>\r
+ <Optimize>true</Optimize>\r
+ <OutputPath>bin\x86\Release</OutputPath>\r
+ <DefineConstants>TRACE;WINDOWS</DefineConstants>\r
+ <ErrorReport>prompt</ErrorReport>\r
+ <WarningLevel>4</WarningLevel>\r
+ <NoStdLib>true</NoStdLib>\r
+ <UseVSHostingProcess>false</UseVSHostingProcess>\r
+ <PlatformTarget>x86</PlatformTarget>\r
+ <XnaCompressContent>true</XnaCompressContent>\r
+ </PropertyGroup>\r
+ <ItemGroup>\r
+ <Reference Include="Microsoft.Xna.Framework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=x86">\r
+ <Private>False</Private>\r
+ <SpecificVersion>True</SpecificVersion>\r
+ </Reference>\r
+ <Reference Include="Microsoft.Xna.Framework.Game, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=MSIL">\r
+ <Private>False</Private>\r
+ <SpecificVersion>True</SpecificVersion>\r
+ </Reference>\r
+ <Reference Include="mscorlib">\r
+ <Private>False</Private>\r
+ </Reference>\r
+ <Reference Include="System">\r
+ <Private>False</Private>\r
+ </Reference>\r
+ <Reference Include="System.Data" />\r
+ <Reference Include="System.Xml">\r
+ <Private>False</Private>\r
+ </Reference>\r
+ <Reference Include="System.Core">\r
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>\r
+ <Private>False</Private>\r
+ </Reference>\r
+ <Reference Include="System.Xml.Linq">\r
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>\r
+ <Private>False</Private>\r
+ </Reference>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <Compile Include="CS 3505\IDeterministicGame.cs" />\r
+ <Compile Include="CS 3505\TestHarness.cs" />\r
+ <Compile Include="Properties\AssemblyInfo.cs" />\r
+ <Compile Include="Program.cs" />\r
+ <Compile Include="Game06.cs" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <Content Include="Game.ico" />\r
+ <Content Include="GameThumbnail.png" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <NestedContentProject Include="Content\Content.contentproj">\r
+ <Project>56086477-a1fb-4593-8868-2b41d8719294</Project>\r
+ <Visible>False</Visible>\r
+ </NestedContentProject>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">\r
+ <Visible>False</Visible>\r
+ <ProductName>.NET Framework Client Profile</ProductName>\r
+ <Install>false</Install>\r
+ </BootstrapperPackage>\r
+ <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">\r
+ <Visible>False</Visible>\r
+ <ProductName>.NET Framework 2.0 %28x86%29</ProductName>\r
+ <Install>false</Install>\r
+ </BootstrapperPackage>\r
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">\r
+ <Visible>False</Visible>\r
+ <ProductName>.NET Framework 3.0 %28x86%29</ProductName>\r
+ <Install>false</Install>\r
+ </BootstrapperPackage>\r
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">\r
+ <Visible>False</Visible>\r
+ <ProductName>.NET Framework 3.5</ProductName>\r
+ <Install>false</Install>\r
+ </BootstrapperPackage>\r
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">\r
+ <Visible>False</Visible>\r
+ <ProductName>.NET Framework 3.5 SP1</ProductName>\r
+ <Install>true</Install>\r
+ </BootstrapperPackage>\r
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">\r
+ <Visible>False</Visible>\r
+ <ProductName>Windows Installer 3.1</ProductName>\r
+ <Install>true</Install>\r
+ </BootstrapperPackage>\r
+ <BootstrapperPackage Include="Microsoft.Xna.Framework.3.0">\r
+ <Visible>False</Visible>\r
+ <ProductName>Microsoft XNA Framework Redistributable 3.0</ProductName>\r
+ <Install>true</Install>\r
+ </BootstrapperPackage>\r
+ </ItemGroup>\r
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />\r
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.targets" />\r
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
+ Other similar extension points exist, see Microsoft.Common.targets.\r
+ <Target Name="BeforeBuild">\r
+ </Target>\r
+ <Target Name="AfterBuild">\r
+ </Target>\r
+ -->\r
+</Project>
\ No newline at end of file
--- /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.Input;\r
+using Microsoft.Xna.Framework.Content;\r
+\r
+namespace CS_3505_Project_06\r
+{\r
+ /// <summary>\r
+ /// A DeterministicGame object is a full XNA game, except that it does not\r
+ /// extend the Microsoft.Xna.Framework.Game class. It supports content loading\r
+ /// and unloading, as well as modified Update and Draw functionality.\r
+ /// \r
+ /// DeterministicGame objects are intented to be incorporated inside of an \r
+ /// existing game. By simply calling update and draw at the appropriate times,\r
+ /// and by supplying user inputs, the game will play just like any other game.\r
+ /// \r
+ /// It is intended that a DeterministicGame be a multiplayer game, and support for\r
+ /// this is listed in the interface below. Each player is identified by a unique object\r
+ /// reference (of the caller's choice, not a struct). The game supports the notion of a\r
+ /// current 'frame', or state. The enclosing code supplies the user inputs for the\r
+ /// next frame by calling methods. The enclosing code then should call the update\r
+ /// method to advance the game to the next frame. Finally, the enclosing code\r
+ /// calls the draw method to render the game state. Note that the game state can\r
+ /// be drawn multiple times without updating the game, thus allowing the game\r
+ /// to be paused or stalled.\r
+ /// </summary>\r
+ public interface IDeterministicGame\r
+ {\r
+ /// <summary>\r
+ /// Call this method to give the game a chance to load its content.\r
+ /// </summary>\r
+ /// <param name="contentManager">A valid content manager pointing to the root of the content tree</param>\r
+ void LoadContent (ContentManager contentManager);\r
+\r
+ /// <summary>\r
+ /// Call this method to give the game a chance to unload its content.\r
+ /// </summary>\r
+ void UnloadContent();\r
+\r
+ /// <summary>\r
+ /// Returns the preferred screen size for this game.\r
+ /// </summary>\r
+ /// <returns></returns>\r
+ Vector2 PreferredScreenSize { get; }\r
+\r
+ /// <summary>\r
+ /// Returns the minimum number of players this game can support.\r
+ /// </summary>\r
+ /// <returns>the minimum player count</returns>\r
+ int MinimumSupportedPlayers { get; }\r
+\r
+ /// <summary>\r
+ /// Returns the maximum number of players this game can support.\r
+ /// </summary>\r
+ /// <returns>the maximum player count</returns>\r
+ int MaximumSupportedPlayers { get; }\r
+\r
+ /// <summary>\r
+ /// Call this method to reset the game state, to set the current frame at 0, and\r
+ /// to supply identifiers for each player in the game. Player identifiers should\r
+ /// be unique object references (not structs) that the caller will use later\r
+ /// to identify each player. (It is important that these not be 'boxed' object\r
+ /// references or the reference will not be preserved.)\r
+ /// \r
+ /// Since, in theory, there will be four copies of the game running, a second\r
+ /// parameter identifies the player that is running this copy of the game.\r
+ /// </summary>\r
+ /// <param name="playerIdentifiers">An array of objects (references) that will identify each player</param>\r
+ /// <param name="playerIdentifiers">An object identifier for the player whose machine is displaying this game</param>\r
+ void ResetGame(Object[] playerIdentifiers, Object thisPlayer);\r
+\r
+ /// <summary>\r
+ /// Returns the current frame number. This corresponds to the current state\r
+ /// of the game world.\r
+ /// </summary>\r
+ /// <returns>the current frame number</returns>\r
+ long CurrentFrameNumber { get; }\r
+\r
+ /// <summary>\r
+ /// Returns a checksum of all of the game world state. This checksum can be used\r
+ /// to ensure that multiple players at some frame all share the same state. It is\r
+ /// guaranteed that identical states will produce identical checksums.\r
+ /// </summary>\r
+ /// <returns>the current game state checksum</returns>\r
+ long CurrentChecksum { get; }\r
+\r
+ /// <summary>\r
+ /// Call this method to report changes in keypresses to the game. You should call this method\r
+ /// to report any changes in keyboard state for a player. The keyboard state will be\r
+ /// applied to the next game state (not the current state).\r
+ /// </summary>\r
+ /// <param name="playerIdentifier">An object (reference) that was registered for a player in the game</param>\r
+ /// <param name="key">A key identifier</param>\r
+ /// <param name="isKeyPressed">The key state - true means pressed, false means released</param>\r
+ void ApplyKeyInput (Object playerIdentifier, Keys key, bool isKeyPressed);\r
+\r
+ /// <summary>\r
+ /// Call this method to report changes in mouse locations to the game. You should call this method\r
+ /// any time the mouse coordinates for a player changes. The mouse information will\r
+ /// be applied to the next game state (not the current state).\r
+ /// </summary>\r
+ /// <param name="playerIdentifier">an object (reference) that was registered for a player in the game</param>\r
+ /// <param name="x">the mouse x location</param>\r
+ /// <param name="y">the mouse y location</param>\r
+ void ApplyMouseLocationInput (Object playerIdentifier, int x, int y);\r
+\r
+ /// <summary>\r
+ /// Call this method to report changes in mouse button state to the game. Note that only one\r
+ /// mouse button is supported in game. You should call this method to report any\r
+ /// changes in mouse button state for a player. The mouse button state will be\r
+ /// applied to the next game state (not the current state).\r
+ /// </summary>\r
+ /// <param name="playerIdentifier">an object (reference) that was registered for a player in the game</param>\r
+ /// <param name="isButtonPressed">the mouse button state</param>\r
+ void ApplyMouseButtonInput (Object playerIdentifier, bool isButtonPressed);\r
+\r
+ /// <summary>\r
+ /// Returns true if the specified player's game is over. They can be safely disconnected from the game\r
+ /// when this flag is true, their inputs do not affect game state. (You can continue to report inputs,\r
+ /// to allow the player to view a game over screen, but no game state action is taken.)\r
+ /// </summary>\r
+ /// <param name="playerIdentifier">an object (reference) that was registered for a player in the game</param>\r
+ /// <returns>true if the game is over</returns>\r
+ bool IsGameOver(Object playerIdentifier);\r
+\r
+ /// <summary>\r
+ /// Returns true if the specified player's game is over, and the player has clicked on something indicating\r
+ /// they wish to leave the game over screen. (This only becomes true if inputs are reported\r
+ /// even after the game is over.)\r
+ /// </summary>\r
+ /// <param name="playerIdentifier">an object (reference) that was registered for a player in the game</param>\r
+ /// <returns>true if the player has terminated the game</returns>\r
+ bool IsTerminated(Object playerIdentifier);\r
+\r
+ /// <summary>\r
+ /// Call this method to advance the game state. Previously sent inputs are applied\r
+ /// to the game state and the frame number is advanced and returned. Caution should be used when\r
+ /// supplying the seconds parameter - it can affect game state. All players in a game\r
+ /// should advance their game time by the same amount.\r
+ /// </summary>\r
+ /// <param name="timespan">The elapsed game time</param>\r
+ /// <returns>the frame number of the new game state (now the current state)</returns>\r
+ long Update(TimeSpan timespan);\r
+\r
+ /// <summary>\r
+ /// Draws the current game state. This does not affect the game state - it may be called\r
+ /// repeatedly to redraw the current game state if needed.\r
+ /// </summary>\r
+ /// <param name="spriteBatch">a SpriteBatch object that has begun a batch</param>\r
+ /// <returns>the current game state frame number</returns>\r
+ long Draw(SpriteBatch spriteBatch);\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.Content;\r
+using Microsoft.Xna.Framework.Input;\r
+using Microsoft.Xna.Framework;\r
+using Microsoft.Xna.Framework.Graphics;\r
+\r
+namespace CS_3505_Project_06.CS_3505\r
+{\r
+ // Everything in objects built from this class represent the critical game state\r
+ public class GameState\r
+ {\r
+ public long frameNumber;\r
+\r
+ private long checksum;\r
+ public long Checksum { get { return checksum; } }\r
+\r
+ public bool[] isGameOver;\r
+ public bool[] isTerminated;\r
+\r
+ // Since this is not a game, I'll just keep track of the user inputs as the game state.\r
+\r
+ public int[] mouseLocationX;\r
+ public int[] mouseLocationY;\r
+ public bool[] mouseButton;\r
+ public List<Keys>[] keysDown;\r
+ public int[] keypressCount;\r
+\r
+ public long elapsedTime;\r
+\r
+ /* Constructor */\r
+ public GameState()\r
+ {\r
+ frameNumber = 0;\r
+ checksum = 0;\r
+\r
+ isGameOver = new bool[4];\r
+ isTerminated = new bool[4];\r
+\r
+ mouseLocationX = new int[4];\r
+ mouseLocationY = new int[4];\r
+ mouseButton = new bool[4];\r
+ keysDown = new List<Keys>[4];\r
+ for (int i = 0; i < 4; i++)\r
+ keysDown[i] = new List<Keys>();\r
+ keypressCount = new int[4];\r
+\r
+ elapsedTime = 0;\r
+\r
+ checksum = 0;\r
+ }\r
+\r
+ /* The game engine! */\r
+ public void advanceFrame(NextInputs inputs, long milliseconds)\r
+ {\r
+ // Advance frame number\r
+ frameNumber++;\r
+\r
+ // Advance game - for the test harness, just record statistics and input states.\r
+\r
+ elapsedTime += milliseconds;\r
+\r
+ for (int player = 0; player < 4; player++)\r
+ {\r
+ if (isGameOver[player])\r
+ continue;\r
+\r
+ if (inputs.mousePressedChanged[player])\r
+ mouseButton[player] = inputs.mousePressed[player];\r
+\r
+ if (inputs.mouseLocationChanged[player])\r
+ {\r
+ mouseLocationX[player] = inputs.mouseLocationX[player];\r
+ mouseLocationY[player] = inputs.mouseLocationY[player];\r
+ }\r
+\r
+ foreach (Keys k in inputs.keysPressed[player])\r
+ if (!keysDown[player].Contains(k))\r
+ {\r
+ keysDown[player].Add(k);\r
+ keypressCount[player]++;\r
+ }\r
+\r
+ foreach (Keys k in inputs.keysReleased[player])\r
+ keysDown[player].Remove(k); \r
+\r
+ // If the mouse was pressed for a certain player, activate game over or terminated states as appropriate\r
+\r
+ if (inputs.mousePressed[player])\r
+ for (int p = 0; p < 4; p++)\r
+ {\r
+ int x = 200 * p + 10;\r
+ int y = 220;\r
+\r
+ if (mouseLocationX[player] >= x && mouseLocationY[player] >= y &&\r
+ mouseLocationX[player] < x + 25 && mouseLocationY[player] < y + 25)\r
+ {\r
+ isGameOver[p] = true;\r
+ }\r
+ y += 25;\r
+ if (mouseLocationX[player] >= x && mouseLocationY[player] >= y &&\r
+ mouseLocationX[player] < x + 25 && mouseLocationY[player] < y + 25)\r
+ {\r
+ isGameOver[p] = true;\r
+ isTerminated[p] = true;\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ // Advance the checksum.\r
+\r
+ computeChecksum();\r
+ \r
+ }\r
+\r
+ /* Just hash the values */\r
+ private long computeChecksum()\r
+ {\r
+ checksum += frameNumber;\r
+ for (int i = 0; i < 4; i++)\r
+ {\r
+ checksum = checksum + keypressCount[i];\r
+ checksum = checksum * 3 + (isGameOver[i] ? 1 : 2);\r
+ checksum = checksum * 3 + (isTerminated[i] ? 1 : 2);\r
+ foreach (Keys k in keysDown[i])\r
+ checksum = checksum * 257 + (int) k;\r
+ checksum = checksum * 25789 + mouseLocationX[i] * 259 + mouseLocationY[i] + 375;\r
+ checksum = checksum * 3 + (mouseButton[i] ? 1 : 2);\r
+\r
+ }\r
+ checksum += elapsedTime;\r
+\r
+ return checksum;\r
+ }\r
+ }\r
+\r
+ // This class encapsulates inputs from the players.\r
+ public class NextInputs\r
+ {\r
+ public List<Keys>[] keysPressed;\r
+ public List<Keys>[] keysReleased;\r
+ public int[] mouseLocationX;\r
+ public int[] mouseLocationY;\r
+ public bool[] mouseLocationChanged;\r
+ public bool[] mousePressed;\r
+ public bool[] mousePressedChanged;\r
+\r
+ public NextInputs()\r
+ {\r
+ keysPressed = new List<Keys>[4];\r
+ keysReleased = new List<Keys>[4];\r
+ mouseLocationX = new int[4];\r
+ mouseLocationY = new int[4];\r
+ mouseLocationChanged = new bool[4];\r
+ mousePressed = new bool[4];\r
+ mousePressedChanged = new bool[4];\r
+ for (int i = 0; i < 4; i++)\r
+ keysPressed[i] = new List<Keys>();\r
+ for (int i = 0; i < 4; i++)\r
+ keysReleased[i] = new List<Keys>();\r
+ }\r
+ }\r
+\r
+ public class TestHarness : IDeterministicGame\r
+ {\r
+ GameState state;\r
+ NextInputs inputs;\r
+ Object[] playerIdentifiers;\r
+ int thisPlayerID;\r
+\r
+ // Instance variables here contribute to the display, but not the game state\r
+\r
+ Texture2D crosshair;\r
+ SpriteFont font;\r
+\r
+ // Constructor\r
+\r
+ public TestHarness()\r
+ {\r
+ playerIdentifiers = new Object[4];\r
+ }\r
+\r
+ // Helper methods\r
+\r
+ private int idPlayer(Object playerIdentifier)\r
+ {\r
+ for (int i = 0; i < playerIdentifiers.Length; i++)\r
+ if (playerIdentifiers[i] == playerIdentifier)\r
+ return i;\r
+ throw new Exception("Illegal player identifier" + playerIdentifier);\r
+ }\r
+\r
+ // Implementation of the DeterministicGame interface\r
+ #region IDeterministicGame Members\r
+\r
+ public void LoadContent(ContentManager contentManager)\r
+ {\r
+ crosshair = contentManager.Load<Texture2D>("CS 3505/Crosshair");\r
+ font = contentManager.Load<SpriteFont>("CS 3505/GameFont");\r
+ }\r
+\r
+ public void UnloadContent()\r
+ {\r
+ // Nothing to do - the content manager will take care of it.\r
+ }\r
+\r
+ public Vector2 PreferredScreenSize\r
+ {\r
+ get { return new Vector2(800, 600); }\r
+ }\r
+\r
+ public int MinimumSupportedPlayers\r
+ {\r
+ get { return 4; }\r
+ }\r
+\r
+ public int MaximumSupportedPlayers\r
+ {\r
+ get { return 4; }\r
+ }\r
+\r
+ public void ResetGame(Object[] playerIdentifiers, Object thisPlayer)\r
+ {\r
+ if (playerIdentifiers.Length != 4)\r
+ throw new Exception("This game requires four players.");\r
+\r
+ // Copy the player identifiers - do not rely on the array parameter not changing.\r
+\r
+ for (int i = 0; i < 4; i++)\r
+ this.playerIdentifiers[i] = playerIdentifiers[i];\r
+\r
+ // Create new game state and inputs objects.\r
+\r
+ state = new GameState();\r
+ inputs = new NextInputs();\r
+\r
+ // Record 'this' player.\r
+\r
+ this.thisPlayerID = idPlayer(thisPlayer);\r
+ }\r
+\r
+ public long CurrentFrameNumber\r
+ {\r
+ get { return state.frameNumber; }\r
+ }\r
+\r
+ public long CurrentChecksum\r
+ {\r
+ get { return state.Checksum; }\r
+ }\r
+\r
+ public void ApplyKeyInput(Object playerIdentifier, Keys key, bool isKeyPressed)\r
+ {\r
+ int player = idPlayer(playerIdentifier);\r
+\r
+ if (isKeyPressed && !inputs.keysPressed[player].Contains(key))\r
+ inputs.keysPressed[player].Add(key);\r
+\r
+ if (!isKeyPressed && !inputs.keysReleased[player].Contains(key))\r
+ inputs.keysReleased[player].Add(key);\r
+ }\r
+\r
+ public void ApplyMouseLocationInput(Object playerIdentifier, int x, int y)\r
+ {\r
+ int player = idPlayer(playerIdentifier);\r
+ inputs.mouseLocationX[player] = x;\r
+ inputs.mouseLocationY[player] = y;\r
+ inputs.mouseLocationChanged[player] = true;\r
+ }\r
+\r
+ public void ApplyMouseButtonInput(Object playerIdentifier, bool isButtonPressed)\r
+ {\r
+ int player = idPlayer(playerIdentifier);\r
+ inputs.mousePressed[player] = isButtonPressed;\r
+ inputs.mousePressedChanged[player] = true;\r
+ }\r
+\r
+ public bool IsGameOver(Object playerIdentifier)\r
+ {\r
+ int player = idPlayer(playerIdentifier);\r
+ return state.isGameOver[player] ;\r
+ }\r
+\r
+ public bool IsTerminated(object playerIdentifier)\r
+ {\r
+ int player = idPlayer(playerIdentifier);\r
+ return state.isTerminated[player];\r
+ }\r
+\r
+ public long Update(TimeSpan elapsedTime)\r
+ {\r
+ state.advanceFrame(inputs, elapsedTime.Milliseconds); // Apply the inputs, advance game state.\r
+\r
+ inputs = new NextInputs(); // Start with inputs cleared on the next frame.\r
+\r
+ return state.frameNumber;\r
+ }\r
+\r
+ public long Draw(SpriteBatch spriteBatch)\r
+ {\r
+ centerString(spriteBatch, Color.White, "CS 3505 - Software Practice 2", 0, 800, 0);\r
+ centerString(spriteBatch, Color.White, "Test Harness", 0, 800, 25);\r
+ centerString(spriteBatch, Color.White, "Debug output", 0, 800, 50);\r
+\r
+ nameIntPair(spriteBatch, Color.White, "Frame:", state.frameNumber, 10, 150, 100);\r
+ nameHexPair(spriteBatch, Color.White, "Checksum:", state.Checksum, 215, 515, 100);\r
+ nameDecPair(spriteBatch, Color.White, "Elapsed Time:", state.elapsedTime / 1000.0f, 570, 790, 100);\r
+\r
+ printPlayer(spriteBatch, Color.Turquoise, 0, 10, 190, 170);\r
+ printPlayer(spriteBatch, Color.Wheat, 1, 210, 390, 170);\r
+ printPlayer(spriteBatch, Color.Tomato, 2, 410, 590, 170);\r
+ printPlayer(spriteBatch, Color.Violet, 3, 610, 790, 170);\r
+\r
+ if (!state.isGameOver[0])\r
+ spriteBatch.Draw(crosshair, new Vector2(state.mouseLocationX[0] - 5, state.mouseLocationY[0] - 5), Color.Turquoise);\r
+ if (!state.isGameOver[1])\r
+ spriteBatch.Draw(crosshair, new Vector2(state.mouseLocationX[1] - 5, state.mouseLocationY[1] - 5), Color.Wheat);\r
+ if (!state.isGameOver[2])\r
+ spriteBatch.Draw(crosshair, new Vector2(state.mouseLocationX[2] - 5, state.mouseLocationY[2] - 5), Color.Tomato);\r
+ if (!state.isGameOver[3])\r
+ spriteBatch.Draw(crosshair, new Vector2(state.mouseLocationX[3] - 5, state.mouseLocationY[3] - 5), Color.Violet);\r
+\r
+ spriteBatch.Draw(crosshair, new Vector2(Mouse.GetState().X - 5, Mouse.GetState().Y - 5), Color.White);\r
+\r
+ return state.frameNumber;\r
+ }\r
+\r
+ #endregion\r
+\r
+ void printPlayer(SpriteBatch spriteBatch, Color c, int player, float left, float right, float top)\r
+ {\r
+ leftJustify(spriteBatch, c, String.Format("Player {0}", player+1), left, top);\r
+ top += 10;\r
+ leftJustify(spriteBatch, c, "_________", left, top);\r
+ top += 40;\r
+ nameIntPair(spriteBatch, c, "[X] Game Over", state.isGameOver[player]?1:0, left, right, top);\r
+ top += 25;\r
+ nameIntPair(spriteBatch, c, "[X] Terminated", state.isTerminated[player] ? 1 : 0, left, right, top);\r
+ top += 40;\r
+ nameIntPair(spriteBatch, c, "Mouse X", (int)state.mouseLocationX[player], left, right, top);\r
+ top += 25;\r
+ nameIntPair(spriteBatch, c, "Mouse Y", (int)state.mouseLocationY[player], left, right, top);\r
+ top += 40;\r
+ leftJustify(spriteBatch, c, "Mouse", left, top);\r
+ rightJustify(spriteBatch, c, state.mouseButton[player]?"Pressed":"Released", right, top);\r
+ top += 40;\r
+ nameIntPair(spriteBatch, c, "Key count", (int)state.keypressCount[player], left, right, top);\r
+ top += 25;\r
+ leftJustify(spriteBatch, c, "Keys", left, top);\r
+ if (state.keysDown[player].Count == 0)\r
+ rightJustify(spriteBatch, c, "None", right, top);\r
+ else\r
+ foreach (Keys k in state.keysDown[player])\r
+ {\r
+ rightJustify(spriteBatch, c, k.ToString(), right, top);\r
+ top += 25;\r
+ }\r
+\r
+ }\r
+\r
+ void centerString(SpriteBatch spriteBatch, Color c, String s, float left, float right, float top)\r
+ {\r
+ Vector2 v = font.MeasureString(s);\r
+ float x = left + (right-left - v.X) / 2;\r
+ float y = top;\r
+ spriteBatch.DrawString(font, s, new Vector2(x, y), c);\r
+ }\r
+\r
+ void centerString(SpriteBatch spriteBatch, Color c, String s, Rectangle r)\r
+ {\r
+ Vector2 v = font.MeasureString(s);\r
+ float x = r.Left + (r.Width - v.X) / 2;\r
+ float y = r.Top + (r.Height - v.Y) / 2;\r
+ spriteBatch.DrawString(font, s, new Vector2(x, y), c);\r
+ }\r
+\r
+ void leftJustify(SpriteBatch spriteBatch, Color c, String s, float left, float top)\r
+ {\r
+ float x = left;\r
+ float y = top;\r
+ spriteBatch.DrawString(font, s, new Vector2(x, y), c);\r
+ }\r
+\r
+ void rightJustify(SpriteBatch spriteBatch, Color c, String s, float right, float top)\r
+ {\r
+ Vector2 v = font.MeasureString(s);\r
+ float x = right - v.X;\r
+ float y = top;\r
+ spriteBatch.DrawString(font, s, new Vector2(x, y), c);\r
+ }\r
+\r
+ void nameDecPair(SpriteBatch spriteBatch, Color c, String name, float number, float left, float right, float top)\r
+ {\r
+ String num = String.Format("{0:.00}", number);\r
+ leftJustify(spriteBatch, c, name, left, top);\r
+ rightJustify(spriteBatch, c, num, right, top);\r
+ }\r
+\r
+ void nameIntPair(SpriteBatch spriteBatch, Color c, String name, long number, float left, float right, float top)\r
+ {\r
+ String num = String.Format("{0}", number);\r
+ leftJustify(spriteBatch, c, name, left, top);\r
+ rightJustify(spriteBatch, c, num, right, top);\r
+ }\r
+\r
+ void nameHexPair(SpriteBatch spriteBatch, Color c, String name, long number, float left, float right, float top)\r
+ {\r
+ String num = String.Format("{0:x}", number);\r
+ leftJustify(spriteBatch, c, name, left, top);\r
+ rightJustify(spriteBatch, c, num, right, top);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<!--\r
+This file contains an xml description of a font, and will be read by the XNA\r
+Framework Content Pipeline. Follow the comments to customize the appearance\r
+of the font in your game, and to change the characters which are available to draw\r
+with.\r
+-->\r
+<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">\r
+ <Asset Type="Graphics:FontDescription">\r
+\r
+ <!--\r
+ Modify this string to change the font that will be imported.\r
+ -->\r
+ <FontName>Kootenay</FontName>\r
+\r
+ <!--\r
+ Size is a float value, measured in points. Modify this value to change\r
+ the size of the font.\r
+ -->\r
+ <Size>16</Size>\r
+\r
+ <!--\r
+ Spacing is a float value, measured in pixels. Modify this value to change\r
+ the amount of spacing in between characters.\r
+ -->\r
+ <Spacing>0</Spacing>\r
+\r
+ <!--\r
+ UseKerning controls the layout of the font. If this value is true, kerning information\r
+ will be used when placing characters.\r
+ -->\r
+ <UseKerning>true</UseKerning>\r
+\r
+ <!--\r
+ Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",\r
+ and "Bold, Italic", and are case sensitive.\r
+ -->\r
+ <Style>Regular</Style>\r
+\r
+ <!--\r
+ If you uncomment this line, the default character will be substituted if you draw\r
+ or measure text that contains characters which were not included in the font.\r
+ -->\r
+ <!-- <DefaultCharacter>*</DefaultCharacter> -->\r
+\r
+ <!--\r
+ CharacterRegions control what letters are available in the font. Every\r
+ character from Start to End will be built and made available for drawing. The\r
+ default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin\r
+ character set. The characters are ordered according to the Unicode standard.\r
+ See the documentation for more information.\r
+ -->\r
+ <CharacterRegions>\r
+ <CharacterRegion>\r
+ <Start> </Start>\r
+ <End>~</End>\r
+ </CharacterRegion>\r
+ </CharacterRegions>\r
+ </Asset>\r
+</XnaContent>\r
--- /dev/null
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">\r
+ <PropertyGroup>\r
+ <ProjectGuid>56086477-a1fb-4593-8868-2b41d8719294</ProjectGuid>\r
+ <ProjectTypeGuids>{96E2B04D-8817-42c6-938A-82C39BA4D311};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>\r
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>\r
+ <OutputType>Library</OutputType>\r
+ <AppDesignerFolder>Properties</AppDesignerFolder>\r
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>\r
+ <XnaFrameworkVersion>v3.0</XnaFrameworkVersion>\r
+ <PlatformTarget>x86</PlatformTarget>\r
+ <OutputPath>bin\$(Platform)\$(Configuration)</OutputPath>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">\r
+ <XnaPlatform>Windows</XnaPlatform>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">\r
+ <XnaPlatform>Windows</XnaPlatform>\r
+ </PropertyGroup>\r
+ <ItemGroup>\r
+ <Reference Include="Microsoft.Xna.Framework.Content.Pipeline.EffectImporter, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=MSIL">\r
+ <Private>False</Private>\r
+ </Reference>\r
+ <Reference Include="Microsoft.Xna.Framework.Content.Pipeline.FBXImporter, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=MSIL">\r
+ <Private>False</Private>\r
+ </Reference>\r
+ <Reference Include="Microsoft.Xna.Framework.Content.Pipeline.TextureImporter, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=MSIL">\r
+ <Private>False</Private>\r
+ </Reference>\r
+ <Reference Include="Microsoft.Xna.Framework.Content.Pipeline.XImporter, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=MSIL">\r
+ <Private>False</Private>\r
+ </Reference>\r
+ <Reference Include="Microsoft.Xna.Framework.Content.Pipeline.AudioImporters, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=MSIL">\r
+ <Private>False</Private>\r
+ </Reference>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <Compile Include="CS 3505\GameFont.spritefont">\r
+ <Name>GameFont</Name>\r
+ <Importer>FontDescriptionImporter</Importer>\r
+ <Processor>FontDescriptionProcessor</Processor>\r
+ </Compile>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <Compile Include="CS 3505\Crosshair.png">\r
+ <Name>Crosshair</Name>\r
+ <Importer>TextureImporter</Importer>\r
+ <Processor>TextureProcessor</Processor>\r
+ </Compile>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <Compile Include="InstructionFont.spritefont">\r
+ <Name>InstructionFont</Name>\r
+ <Importer>FontDescriptionImporter</Importer>\r
+ <Processor>FontDescriptionProcessor</Processor>\r
+ </Compile>\r
+ </ItemGroup>\r
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\v3.0\Microsoft.Xna.GameStudio.ContentPipeline.targets" />\r
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
+ Other similar extension points exist, see Microsoft.Common.targets.\r
+ <Target Name="BeforeBuild">\r
+ </Target>\r
+ <Target Name="AfterBuild">\r
+ </Target>\r
+ -->\r
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<!--\r
+This file contains an xml description of a font, and will be read by the XNA\r
+Framework Content Pipeline. Follow the comments to customize the appearance\r
+of the font in your game, and to change the characters which are available to draw\r
+with.\r
+-->\r
+<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">\r
+ <Asset Type="Graphics:FontDescription">\r
+\r
+ <!--\r
+ Modify this string to change the font that will be imported.\r
+ -->\r
+ <FontName>Pescadero</FontName>\r
+\r
+ <!--\r
+ Size is a float value, measured in points. Modify this value to change\r
+ the size of the font.\r
+ -->\r
+ <Size>14</Size>\r
+\r
+ <!--\r
+ Spacing is a float value, measured in pixels. Modify this value to change\r
+ the amount of spacing in between characters.\r
+ -->\r
+ <Spacing>0</Spacing>\r
+\r
+ <!--\r
+ UseKerning controls the layout of the font. If this value is true, kerning information\r
+ will be used when placing characters.\r
+ -->\r
+ <UseKerning>true</UseKerning>\r
+\r
+ <!--\r
+ Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",\r
+ and "Bold, Italic", and are case sensitive.\r
+ -->\r
+ <Style>Regular</Style>\r
+\r
+ <!--\r
+ If you uncomment this line, the default character will be substituted if you draw\r
+ or measure text that contains characters which were not included in the font.\r
+ -->\r
+ <!-- <DefaultCharacter>*</DefaultCharacter> -->\r
+\r
+ <!--\r
+ CharacterRegions control what letters are available in the font. Every\r
+ character from Start to End will be built and made available for drawing. The\r
+ default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin\r
+ character set. The characters are ordered according to the Unicode standard.\r
+ See the documentation for more information.\r
+ -->\r
+ <CharacterRegions>\r
+ <CharacterRegion>\r
+ <Start> </Start>\r
+ <End>~</End>\r
+ </CharacterRegion>\r
+ </CharacterRegions>\r
+ </Asset>\r
+</XnaContent>\r
--- /dev/null
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using Microsoft.Xna.Framework;\r
+using Microsoft.Xna.Framework.Audio;\r
+using Microsoft.Xna.Framework.Content;\r
+using Microsoft.Xna.Framework.GamerServices;\r
+using Microsoft.Xna.Framework.Graphics;\r
+using Microsoft.Xna.Framework.Input;\r
+using Microsoft.Xna.Framework.Media;\r
+using Microsoft.Xna.Framework.Net;\r
+using Microsoft.Xna.Framework.Storage;\r
+using CS_3505_Project_06.CS_3505;\r
+\r
+namespace CS_3505_Project_06\r
+{\r
+ /// <summary>\r
+ /// A game outline for testing network communications\r
+ /// </summary>\r
+ public class Game06 : Microsoft.Xna.Framework.Game\r
+ {\r
+ GraphicsDeviceManager graphics;\r
+ SpriteBatch spriteBatch;\r
+ SpriteFont font;\r
+ \r
+ IDeterministicGame deterministicGame;\r
+ TimeSpan targetTimeSpan;\r
+ Object[] playerIdentifiers = { "One", "Two", "Three", "Four" }; // Any objects will do, strings are easy to debug.\r
+\r
+ // For debugging\r
+\r
+ List<Keys> lastPressedKeys;\r
+ bool lastButtonPressed;\r
+ Object activePlayer;\r
+ bool paused;\r
+ long lastAutoPause;\r
+\r
+ // Constructor\r
+\r
+ public Game06()\r
+ {\r
+ graphics = new GraphicsDeviceManager(this);\r
+ Content.RootDirectory = "Content";\r
+\r
+ // Make the game object. The game is currently called 'testHarness'.\r
+\r
+ deterministicGame = new TestHarness();\r
+ \r
+ // Debugging setup\r
+\r
+ lastPressedKeys = new List<Keys>();\r
+ activePlayer = playerIdentifiers[0];\r
+ paused = false;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Allows the game to perform any initialization it needs to before starting to run.\r
+ /// This is where it can query for any required services and load any non-graphic\r
+ /// related content. Calling base.Initialize will enumerate through any components\r
+ /// and initialize them as well.\r
+ /// </summary>\r
+ protected override void Initialize()\r
+ {\r
+ // Set a fixed time span of 1/60th of a second.\r
+\r
+ targetTimeSpan = new TimeSpan(166666); // In 100 nanosecond units = 16 666 600 nanoseconds\r
+ IsFixedTimeStep = true;\r
+ TargetElapsedTime = targetTimeSpan;\r
+\r
+ // Reset the game - indicate that player #1 (player 0) owns this instance of the game.\r
+\r
+ deterministicGame.ResetGame(playerIdentifiers, playerIdentifiers[0]);\r
+\r
+ // For debugging - reset the mouse position to the center of the window.\r
+\r
+ Mouse.SetPosition(400, 300);\r
+\r
+ // Allow the base class to initialize.\r
+\r
+ base.Initialize();\r
+ }\r
+\r
+ /// <summary>\r
+ /// LoadContent will be called once per game and is the place to load\r
+ /// all of your content.\r
+ /// </summary>\r
+ protected override void LoadContent()\r
+ {\r
+ // Create a new SpriteBatch, which can be used to draw textures.\r
+\r
+ spriteBatch = new SpriteBatch(GraphicsDevice);\r
+\r
+ // Let the game load its content.\r
+\r
+ font = Content.Load<SpriteFont>("InstructionFont");\r
+\r
+ deterministicGame.LoadContent(Content);\r
+ }\r
+\r
+ /// <summary>\r
+ /// UnloadContent will be called once per game and is the place to unload\r
+ /// all content.\r
+ /// </summary>\r
+ protected override void UnloadContent()\r
+ {\r
+ deterministicGame.UnloadContent();\r
+ }\r
+\r
+ /// <summary>\r
+ /// Allows the game to run logic such as updating the world,\r
+ /// checking for collisions, gathering input, and playing audio.\r
+ /// </summary>\r
+ /// <param name="gameTime">Provides a snapshot of timing values.</param>\r
+ protected override void Update(GameTime gameTime)\r
+ {\r
+ // Get user's input state.\r
+\r
+ KeyboardState keyState = Keyboard.GetState();\r
+ MouseState mouseState = Mouse.GetState();\r
+\r
+ // Make a list of the keys pressed or released this frame.\r
+\r
+ List<Keys> pressedKeys = new List<Keys>();\r
+ List<Keys> releasedKeys = new List<Keys>();\r
+\r
+ Keys[] pressedKeysArray = keyState.GetPressedKeys();\r
+ foreach (Keys k in pressedKeysArray)\r
+ if (!lastPressedKeys.Contains(k))\r
+ pressedKeys.Add(k);\r
+ else\r
+ lastPressedKeys.Remove(k);\r
+\r
+ releasedKeys = lastPressedKeys;\r
+ lastPressedKeys = new List<Keys>(pressedKeysArray);\r
+\r
+ // Get mouse button state.\r
+\r
+ bool buttonPressed = mouseState.LeftButton == ButtonState.Pressed;\r
+\r
+ /***** Begining of game logic. *****/\r
+\r
+ // Debug - allow user to exit.\r
+\r
+ if (pressedKeys.Contains(Keys.Escape))\r
+ this.Exit();\r
+\r
+ // Debug - allow user on this machine to direct input to any player's state in the game.\r
+\r
+ if (pressedKeys.Contains(Keys.F1)) activePlayer = playerIdentifiers[0];\r
+ if (pressedKeys.Contains(Keys.F2)) activePlayer = playerIdentifiers[1];\r
+ if (pressedKeys.Contains(Keys.F3)) activePlayer = playerIdentifiers[2];\r
+ if (pressedKeys.Contains(Keys.F4)) activePlayer = playerIdentifiers[3];\r
+\r
+ // Debug - allow user on this machine to pause/resume game state advances.\r
+\r
+ if (pressedKeys.Contains(Keys.F12) ||\r
+ pressedKeys.Contains(Keys.P) && (keyState.IsKeyDown(Keys.LeftControl) || keyState.IsKeyDown(Keys.RightControl)))\r
+ {\r
+ paused = !paused;\r
+ return; // Don't update on pause start or stop\r
+ }\r
+\r
+ // Debug - automatically pause every 1000 frames.\r
+\r
+ if (deterministicGame.CurrentFrameNumber % 1000 == 0 && deterministicGame.CurrentFrameNumber != lastAutoPause)\r
+ {\r
+ paused = true;\r
+ lastAutoPause = deterministicGame.CurrentFrameNumber;\r
+ }\r
+\r
+ // Game update\r
+\r
+ // Direct inputs to the game engine - only report changes.\r
+\r
+ foreach (Keys k in pressedKeys)\r
+ deterministicGame.ApplyKeyInput(activePlayer, k, true);\r
+\r
+ foreach (Keys k in releasedKeys)\r
+ deterministicGame.ApplyKeyInput(activePlayer, k, false);\r
+\r
+ deterministicGame.ApplyMouseLocationInput(activePlayer, mouseState.X, mouseState.Y);\r
+\r
+ if (lastButtonPressed != buttonPressed)\r
+ deterministicGame.ApplyMouseButtonInput(activePlayer, buttonPressed);\r
+\r
+ lastButtonPressed = buttonPressed;\r
+\r
+ if (!paused)\r
+ {\r
+ // Advance the game engine.\r
+\r
+ deterministicGame.Update(targetTimeSpan);\r
+ }\r
+\r
+ /***** End of game logic. *****/\r
+\r
+ // Allow the superclass to do any needed updates (unknown purpose).\r
+\r
+ base.Update(gameTime);\r
+ }\r
+\r
+ /// <summary>\r
+ /// This is called when the game should draw itself.\r
+ /// </summary>\r
+ /// <param name="gameTime">Provides a snapshot of timing values.</param>\r
+ protected override void Draw(GameTime gameTime)\r
+ {\r
+ GraphicsDevice.Clear(new Color(16, 16, 16, 255)); // Needed by the test harness, should be removed for the real game.\r
+\r
+ spriteBatch.Begin();\r
+\r
+ // Draw a few instructions.\r
+\r
+ if (paused && gameTime.TotalRealTime.Milliseconds < 500)\r
+ spriteBatch.DrawString(font, "-=> Paused <=-", new Vector2(10, 130), Color.White);\r
+\r
+ spriteBatch.DrawString(font, "Press [F1]...[F4] to simulate input for each player. Click X's to end game or terminate player.", new Vector2(10, 540), Color.White);\r
+ spriteBatch.DrawString(font, "Press [ESC] to exit and [F12] to pause/unpause. Game auto-pauses every 1000 frames.", new Vector2(10, 570), Color.White);\r
+\r
+ // Let the game draw itself.\r
+\r
+ deterministicGame.Draw(spriteBatch);\r
+ \r
+\r
+ spriteBatch.End();\r
+\r
+ base.Draw(gameTime);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using System;\r
+\r
+namespace CS_3505_Project_06\r
+{\r
+ static class Program\r
+ {\r
+ /// <summary>\r
+ /// The main entry point for the application.\r
+ /// </summary>\r
+ static void Main(string[] args)\r
+ {\r
+ using (Game06 game = new Game06())\r
+ {\r
+ game.Run();\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
--- /dev/null
+using System.Reflection;\r
+using System.Runtime.CompilerServices;\r
+using System.Runtime.InteropServices;\r
+\r
+// General Information about an assembly is controlled through the following \r
+// set of attributes. Change these attribute values to modify the information\r
+// associated with an assembly.\r
+[assembly: AssemblyTitle("CS 3505 Project 06")]\r
+[assembly: AssemblyProduct("CS 3505 Project 06")]\r
+[assembly: AssemblyDescription("")]\r
+[assembly: AssemblyCompany("Microsoft")]\r
+\r
+[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]\r
+[assembly: AssemblyTrademark("")]\r
+[assembly: AssemblyCulture("")]\r
+\r
+// Setting ComVisible to false makes the types in this assembly not visible \r
+// to COM components. If you need to access a type in this assembly from \r
+// COM, set the ComVisible attribute to true on that type.\r
+[assembly: ComVisible(false)]\r
+\r
+// The following GUID is for the ID of the typelib if this project is exposed to COM\r
+[assembly: Guid("654b7ae7-964e-40c4-b040-f46b7bec42bb")]\r
+\r
+\r
+// Version information for an assembly consists of the following four values:\r
+//\r
+// Major Version\r
+// Minor Version \r
+// Build Number\r
+// Revision\r
+//\r
+[assembly: AssemblyVersion("1.0.0.0")]\r