//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace DarkWynter.Engine { #region Using Statements using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; using System.Net; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; using System.Xml; using System.Windows.Forms; using Audio; using Init; using Menus; using Globals; using Utilities; using Controllers; using ObjectLib; using GameObjects; using Physics; using DarkWynter.Stream; using DarkWynter.Engine.UserInterface; #endregion using Nuclex; // Once we mix XNA with the System.Windows.Forms namespace, some ambiguities will // arise. The following lines create some shortcuts so the can conveniently address // the classes we actually want to use. using XnaColor = Microsoft.Xna.Framework.Graphics.Color; using XnaRectangle = Microsoft.Xna.Framework.Rectangle; using DarkWynter.Engine.EventControl; /// /// Base class for creating a game using the DarkWynter Engine. /// DarkWynterEngine extends object modification to the user through XML. /// DakrWynterEngine extends functionality to the user through overridable objects. /// public class DarkWynterEngine : Nuclex.GameControl { #region Properties /// /// Main User's Heads Up Display /// public static HeadsUpDisplay HUD; /// /// Manage scoring, respawn, and gameover /// private GameLogicController gameRules; /// /// Game Controller /// public static List gameControllers; /// /// Menu Controller /// public static List menuControllers; /// /// List of user-defined game objects /// protected List gameObjectTypes; /// /// A scenegraph/collections class, contains all GameObject instants /// public static ObjectLibrary objectLibrary; /// /// Handles collision detection. /// protected Collision collision; /// /// Renders the scene once for each viewport. /// protected Renderer renderer; /// /// Menu System Componenets /// protected MenuSystem menuSystem; /// /// Interface to GPU Uniform variables /// private ShaderParameters shaderParameters; /// /// FPS - Frames Per Second /// public FPSCounter fps; ///// //// Controller //// //public static Controller playerController; //// //// Controller for the MenuSystem //// //public static Controller menuController; /// /// Screen Saver Shader /// private ScreenSaver screenSaver; /// /// Terrain Mod Singleton /// public static MajikWand majikWand = new MajikWand(); /// /// Supplied from upper layer components that require notification whenever a new Level is loaded. /// /// Controller boolean event arguments public delegate void OnLevelChange(EventArgs args); public static event OnLevelChange onLevelChange; /// /// Supplied from upper layer components that require notification whenever a new Level is loaded. /// /// Controller boolean event arguments public delegate void OnSurveyPretest(object sender, EventArgs args); public static event OnSurveyPretest onSurveyPretest; public static bool launchPreTest = false; /// /// Supplied from upper layer components that require notification whenever a new Level is loaded. /// /// Controller boolean event arguments public delegate void OnSurveyPosttest(object sender, EventArgs args); public static event OnSurveyPosttest onSurveyPosttest; public static bool launchPostTest = false; #endregion #region Methods // --------------- Constructor ----------------- /// /// Main Engine Class. /// Check for Hardware Capabilities. /// Create GraphicsDeviceManager and ContentManager. /// public DarkWynterEngine():base() { // Draw is called as many times as the hardware can handle. // If(IsFixedTimeStep), then Update is called 30x per second. // If(!IsFixedTimeStep), then Update is called as many times as the hardware can handle. // The differrence affects both controller inputs and physics responses in the Virtual Environment. this.IsFixedTimeStep = true; // Set up Global Graphics Device and Content Loader Statics_Stream.RenderSettings.graphics = this.graphics; Statics_Engine.SystemSettings.content = new ContentManager(Services); Statics_Stream.RenderSettings.graphics.SynchronizeWithVerticalRetrace = false; // Check all available adapters on the system for (int i = 0; i < GraphicsAdapter.Adapters.Count; i++) { // Get the capabilities of the hardware device GraphicsDeviceCapabilities caps = GraphicsAdapter.Adapters[i].GetCapabilities(DeviceType.Hardware); if (caps.MaxPixelShaderProfile < ShaderProfile.PS_3_0) { System.Diagnostics.Debug.WriteLine("This adapter does not support Shader Model 3.0."); Statics_Engine.SystemSettings.gameState = Enums_Engine.EngineState.NOT_SUPPORTED; } else { //Yay! They can play Statics_Engine.SystemSettings.gameState = Enums_Engine.EngineState.CREDIT_SCREEN; } } // Initialize Control Docking this.Dock = DockStyle.Fill; this.Focus(); // Set up Mouse to Activate and Deactivate, using Left and Right mouse clicks respectively. this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.OnMouseDown); // Drag/Drop Level Creation this.AllowDrop = true; this.DragEnter += new DragEventHandler(terrain_DragEnter); this.DragDrop += new DragEventHandler(terrain_DragDrop); } // ----------------- Load ---------------------- /// /// Set Up Display Window. /// Create Logging, XML, GameFlow, Renderer, SpriteBatch, /// FontWriter, MenuSystem, Audio, ShaderParameters, ChatClient, /// Frames Per Second Counter, and Screensaver /// protected virtual void Initialize(GameObjectTypes userDefinedTypes) { try { // Load System XML Settings XML.LoadUserPreferences(); DarkWynterEngine.Load_LevelIndex(); DarkWynterEngine.Load_EventIndex(); XML.LoadQuestInfo(); // Load GameObjectTypes - Xml/GameObject Equivalency List XML.gameObjectTypes = new List(); XML.gameObjectTypes.Add(new GameObjectTypes()); XML.gameObjectTypes.Add(userDefinedTypes); if (!XML.contentInstalled) { this.SuspendLayout(); Label installContentLabel = new Label(); installContentLabel.AutoSize = true; installContentLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.00F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold))), System.Drawing.GraphicsUnit.Point, ((byte)(0))); installContentLabel.Location = new System.Drawing.Point(10, 10); installContentLabel.Text = "Content Project could not be found... "; installContentLabel.ForeColor = System.Drawing.Color.Silver; Label installContentLabel2 = new Label(); installContentLabel2.AutoSize = true; installContentLabel2.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.00F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold))), System.Drawing.GraphicsUnit.Point, ((byte)(0))); installContentLabel2.Location = new System.Drawing.Point(10, 50); installContentLabel2.Text = "Please select \"Download Package\" below, to install content from web."; installContentLabel2.ForeColor = System.Drawing.Color.Silver; Panel panel = new Panel(); panel.SuspendLayout(); panel.Dock = DockStyle.Fill; panel.Controls.Add(installContentLabel); panel.Controls.Add(installContentLabel2); panel.ResumeLayout(false); panel.PerformLayout(); this.Controls.Clear(); this.Controls.Add(panel); this.ResumeLayout(false); this.PerformLayout(); } // Menu System menuSystem = new MenuSystem(); XML.LoadAssembly("DWGame.dll"); objectLibrary = new ObjectLibrary(); collision = new Collision(); // Set up display renderer = new Renderer(Statics_Engine.SystemSettings.content); UpdateRendererSettings(); // Set up the renderer draw delegates renderer.drawObjectLibrary = new Renderer.DrawObjectLibrary(objectLibrary.Draw); renderer.drawSprites = new Renderer.DrawSprites(objectLibrary.Draw_Billboards); renderer.drawHUD = new Renderer.DrawHUD(objectLibrary.PostDraw_HUD); renderer.drawObjectOverhead = new Renderer.DrawObjectOverhead(objectLibrary.DrawOverhead); //PUT AN IMPORTANT METHOD CALL HERE // Set up Gpu Shader Handles shaderParameters = new ShaderParameters(Statics_Engine.SystemSettings.content); // Init the audio engine Audio.Audio.Initialize(); Audio.Audio.PlayLevelSong("Theme4"); // ScreenSaver for menuSystem screenSaver = new ScreenSaver(); Statics_Engine.SystemSettings.screenSaverTimer = Stopwatch.StartNew(); // Load the Font class Statics_Stream.Fonts.Arial = Statics_Engine.SystemSettings.content.Load("Content/_fonts/Arial"); Statics_Stream.Fonts.ComicSans = Statics_Engine.SystemSettings.content.Load("Content/_fonts/ComicSansMS"); Statics_Stream.Fonts.ComicSansSmall = Statics_Engine.SystemSettings.content.Load("Content/_fonts/ComicSansSmall"); // Start Logging Logging.setStart(System.DateTime.Now); Logging.G2LLogList.Add(System.DateTime.Now.ToString()); // Create new FPS class fps = new FPSCounter(); // DarkWynterEngine.Deactivate(); // Set up the Game Rules gameRules = new GameLogicController(); // Controller Setup gameControllers = new List(); menuControllers = new List(); ControllerManager.CheckForControllers(objectLibrary); base.Initialize(); } // Catch all loading exceptions and print message to user. catch (Exception e) { Label installContentLabel2 = new Label(); installContentLabel2.AutoSize = true; installContentLabel2.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.00F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold))), System.Drawing.GraphicsUnit.Point, ((byte)(0))); installContentLabel2.Location = new System.Drawing.Point(10, 50); installContentLabel2.Text = "Error Initializing, Prob Due to Content. \n" + e.Message; installContentLabel2.ForeColor = System.Drawing.Color.Silver; Panel panel = new Panel(); panel.SuspendLayout(); panel.Dock = DockStyle.Fill; panel.Controls.Add(installContentLabel2); panel.ResumeLayout(false); panel.PerformLayout(); this.Controls.Clear(); this.Controls.Add(panel); this.ResumeLayout(false); this.PerformLayout(); } } /// /// Loads availible Levels from _Levels.xml and stores them in the LevelInfo list. /// public static void Load_LevelIndex() { string LevelXMLFile = "_xml/LevelEdit/_Levels.xml"; Statics_Engine.levelInfo = new List(); try { // Load physics, music, and fog XmlDocument reader = new XmlDocument(); reader.Load(LevelXMLFile); XmlNodeList allNodes = reader.ChildNodes; foreach (XmlNode levelNode in allNodes) { if (levelNode.Name == "levels") { XmlNodeList levelNodes = levelNode.ChildNodes; foreach (XmlNode node in levelNodes) { if (node.Name == "level") { Statics_Engine.LevelInfo level = new Statics_Engine.LevelInfo(); level.name = node.Attributes["name"].Value; level.filepath = node.Attributes["xmlFile"].Value; level.description = node.Attributes["description"].Value; level.cameraModeEnum_XML = (DarkWynter.Stream.Camera.CameraMode)Enum.Parse(typeof(DarkWynter.Stream.Camera.CameraMode), node.Attributes["CameraModeEnum"].Value, true); Statics_Engine.levelInfo.Add(level); } } } } } catch { XML.contentInstalled = false; System.Diagnostics.Debug.WriteLine("Error reading xml"); //throw new Exception("Error reading XML"); } } public static void Load_EventIndex() { string EventsXMLFile = "_xml/QuestSettings/_Levels.xml"; Statics_Engine.eventsInfo = new List(); try { // Load physics, music, and fog XmlDocument reader = new XmlDocument(); reader.Load(EventsXMLFile); XmlNodeList allNodes = reader.ChildNodes; foreach (XmlNode eventsNode in allNodes) { if (eventsNode.Name == "levels") { XmlNodeList levelNodes = eventsNode.ChildNodes; foreach (XmlNode node in levelNodes) { if (node.Name == "events") { Statics_Engine.EventsInfo eventsInfo = new Statics_Engine.EventsInfo(); eventsInfo.name = node.Attributes["name"].Value; eventsInfo.filepath = node.Attributes["xmlFile"].Value; eventsInfo.description = node.Attributes["description"].Value; Statics_Engine.eventsInfo.Add(eventsInfo); } } } } } catch { XML.contentInstalled = false; System.Diagnostics.Debug.WriteLine("Error reading xml"); //throw new Exception("Error reading XML"); } } /// /// /// public static void Save_LevelIndex() { // Output xml level index to file } /// /// /// public static void Load_Level(string LevelXml_FilePath, string ScriptXml_FilePath) { // Reset load level flag Statics_Engine.GameSettings.LoadLevel = false; if (HUD == null) { HUD = new HeadsUpDisplay(); } // Call Load Sequence objectLibrary.LoadLevel(LevelXml_FilePath); GameEventHandler.LoadEventsXml(ScriptXml_FilePath); // XML.LoadPlayerIndex(); //Statics_Engine.LevelSettings.ViewportSize = new Vector2( // Statics_Stream.RenderSettings.cameraList[0].viewport.Width, // Statics_Stream.RenderSettings.cameraList[0].viewport.Height); Statics_Stream.RenderSettings.cameraList[0].mode = Stream.Camera.CameraMode.FirstPerson; Statics_Stream.RenderSettings.cameraList[0].fixedPosition = new Microsoft.Xna.Framework.Vector3(8000, 6000, 8000); Statics_Stream.RenderSettings.cameraList[0].mode = Statics_Engine.levelInfo[Statics_Engine.levelIndex].cameraModeEnum_XML; // If we only have one player, add a terrain camera for the mini map if (Statics_Stream.RenderSettings.cameraList.Count == 1) { Camera HUDCamera = new Camera(); Statics_Stream.RenderSettings.cameraList.Add(HUDCamera); HUDCamera.mode = Camera.CameraMode.FixedPosition; HUDCamera.lookAtPosition = Vector3.Zero; HUDCamera.cameraPosition = new Vector3(0, 5000, 0); //position HUDCamera.viewport.X = 100; HUDCamera.viewport.Y = 100; //size HUDCamera.viewport.Width = 50; HUDCamera.viewport.Height = 50; } // Switch into Game Mode processing Statics_Engine.SystemSettings.gameState = Enums_Engine.EngineState.GAME_MODE; // Call Level-Loaded Callback delegate to notify upper layers of change. onLevelChange(new EventArgs()); } // --------------- Update --------------------- /// /// Update MenuSystemGame, Audio, FPS. /// Check For Level Loading Request. /// Check For Exit. /// /// XNA GameTime protected override void Update(GameTime gameTime) { // Set current change in time Statics_Engine.SystemSettings.dt = (float)gameTime.ElapsedGameTime.TotalSeconds; // Update renderer settings if changed UpdateRendererSettings(); Statics_Engine.GameSettings.viewport = Statics_Stream.RenderSettings.cameraList[0].viewport; // GameEventHandler.CurrentGameConditions._triggerCoins = 1; // If requested via flag if (Statics_Engine.GameSettings.LoadLevel) { // Load new Level Load_Level( Statics_Engine.levelInfo[Statics_Engine.levelIndex].filepath, Statics_Engine.eventsInfo[Statics_Engine.levelIndex].filepath ); } // If Window is active... if (Statics_Engine.SystemSettings.WINDOW_IN_FOCUS) { // Update all Engine Controllers UpdateControllers(); } // If compiler disabled if (Statics_Engine.SystemSettings.enableCompilerConsole == false) { // If in 3D GameMode if (Statics_Engine.SystemSettings.gameState == Enums_Engine.EngineState.GAME_MODE) { // Update ObjectLibrary objectLibrary.Update(ref objectLibrary, collision); // Update TerrainMod Caps majikWand.Update(objectLibrary); } else { if (Statics_Engine.SystemSettings.WINDOW_IN_FOCUS) { // Update menu system menuSystem.Update(objectLibrary); } } } // Update Frame Rate Counter if (Statics_Engine.SystemSettings.enableFPSDisplay) { fps.Update(); } // Crank the audio engine Audio.Audio.Update(); // Crank the video engine //video.Update(); if (launchPreTest) { if (DarkWynterEngine.onSurveyPretest != null) { DarkWynterEngine.onSurveyPretest(this, new EventArgs()); launchPreTest = false; } } if (launchPostTest) { Logging.writeG2LLog( DarkWynter.Engine.Globals.Statics_Engine.PlayerSettings.studentIDNumber + "-G2Llog.txt", DarkWynter.Engine.Utilities.Logging.G2LLogList ); Logging.writeG2LLog( DarkWynter.Engine.Globals.Statics_Engine.PlayerSettings.studentIDNumber + "-G2LPositionalLog.txt", DarkWynter.Engine.Utilities.Logging.G2LPositionalLog ); if (DarkWynterEngine.onSurveyPosttest != null) { DarkWynterEngine.onSurveyPosttest(this, new EventArgs()); launchPostTest = false; } } // Call XNA Update base.Update(gameTime); } private void UpdateRendererSettings() { // Update renderer settings if changed if (Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.Height != Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT || Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.Width != Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH) { renderer.AutoDetectResolution(); renderer.AutoDetectWindowAndDefaultViewport(/*Window*/); Renderer.ResetViewports(Statics_Engine.SystemSettings.TOTAL_PLAYERS); } } private void UpdateControllers() { // Update Game Mode Controllers if (Statics_Engine.SystemSettings.gameState == Enums_Engine.EngineState.GAME_MODE) { // Update Controllers foreach (GameController gameController in gameControllers) { // Check that the human is alive and hence active in the game if (objectLibrary.humans[gameController.playerNumber].IsAlive()) { gameController.Update(ref objectLibrary, ref menuSystem); } } // Update GameRules gameRules.Update(ref objectLibrary); } // Update Menu Mode Controllers else { // Update all menu controllers foreach (MenuController menuController in menuControllers) { menuController.Update(ref objectLibrary, ref menuSystem); } } } // ----------------- Draw ---------------------- /// /// Draw Game or MenuSystem Screen /// /// XNA GameTime protected override void Draw(GameTime gameTime) { // Clear the device Statics_Engine.SystemSettings.elementalGameTime = gameTime; // If in Game Mode (or paused) call game draw function if (Statics_Engine.SystemSettings.gameState == Enums_Engine.EngineState.GAME_MODE || Statics_Engine.SystemSettings.gameState == Enums_Engine.EngineState.GAME_PAUSE) { renderer.Draw(Statics_Engine.SystemSettings.TOTAL_PLAYERS); //renderer.DrawOverhead(Statics_Stream.RenderSettings.cameraList[1]); } if (Statics_Engine.SystemSettings.gameState != Enums_Engine.EngineState.GAME_MODE) { menuSystem.Draw(renderer.spriteBatch, screenSaver); } fps.Draw(renderer.spriteBatch); // Call XNA Draw base.Draw(gameTime); } // ---------------- Exit ----------------------- /// /// Check to see if user has requested to exit the application. /// protected virtual void CheckExit() { XML.SaveUserPreferences(); //Logging.genReport(System.DateTime.Now); //Logging.saveLog(System.DateTime.Now); Statics_Engine.SystemSettings.enableFPSDisplay = false; //chatClient.CloseConnection(); this.Exit(); } /// /// Unload resources loaded using the content manager /// protected override void UnloadContent() { base.UnloadContent(); Statics_Engine.SystemSettings.content.Unload(); Statics_Engine.SystemSettings.content.Dispose(); } #endregion #region Events protected override void OnResize(EventArgs e) { base.OnResize(e); //if (Statics_Engine.SystemSettings.gameState == Enums_Engine.EngineState.GAME_MODE) { if (HUD != null) { //// Resize based on percentage of FULL screen viewport size HUD.Resize(new Vector2(this.Size.Width, this.Size.Height)); } } } /// /// Copy the new image /// /// /// void terrain_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.Bitmap)) { e.Effect = DragDropEffects.Copy; } else { e.Effect = DragDropEffects.None; } } /// /// Create the new bitmap onto the terrain and add the csobject to the list /// /// /// void terrain_DragDrop(object sender, DragEventArgs e) { //objectLibrary.humans[0].holdingObject = ObjectLibrary.soloObjects[3]; objectLibrary.humans[0].holdingObject.mass.scale = new Vector3(100); //// Create the object and attach to Player //if (tempObj != null) //{ // //if (tempObj is Waypoint) // //{ // //} // //if (tempObj is Actor) // //{ // //} // //if (tempObj is Prop) // //{ // //} //} } /// /// Override XNA function /// Activate Mouse when window gains focus. /// /// /// protected override void OnActivated(object sender, EventArgs args) { //base.OnActivated(sender, args); Statics_Engine.SystemSettings.WINDOW_IN_FOCUS = true; } /// /// Override XNA function. /// Deactivate Mouse when window looses focus. /// /// /// protected override void OnDeactivated(object sender, EventArgs args) { //base.OnDeactivated(sender, args); Statics_Engine.SystemSettings.WINDOW_IN_FOCUS = false; } /// /// Toggle game controllers on/off /// public static void Activate() { Statics_Engine.SystemSettings.WINDOW_IN_FOCUS = true; } /// /// Deactivate Mouse, Controls, and most of the Update Loop. /// public static void Deactivate() { Statics_Engine.SystemSettings.WINDOW_IN_FOCUS = false; } /// /// Activates Mouse, Controller, and unpauses Game when Left-Clicked. /// Deactivates Mouse, Controller and pauses Game when Right-Clicked. /// /// /// protected void OnMouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { DarkWynterEngine.Activate(); } if (e.Button == System.Windows.Forms.MouseButtons.Right) { DarkWynterEngine.Deactivate(); } } /// /// Initiate exit procedure /// public static void DoExit(object sender, FormClosingEventArgs e) { if (MessageBox.Show("Would you like to close the application?", "Allow Close?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) { e.Cancel = true; } else if (Statics_Engine.SystemSettings.gameState == Enums_Engine.EngineState.GAME_MODE) { Statics_Engine.SystemSettings.gameState = Enums_Engine.EngineState.FINALIZE_G2LSTUFF; } else if (Statics_Engine.SystemSettings.gameState == Enums_Engine.EngineState.FINALIZE_G2LSTUFF) { Statics_Engine.SystemSettings.gameState = Enums_Engine.EngineState.GAME_OVER; } else if (Statics_Engine.SystemSettings.gameState == Enums_Engine.EngineState.GAME_OVER) { Statics_Engine.SystemSettings.gameState = Enums_Engine.EngineState.EXIT; } } #endregion } }