//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- #define forPC namespace DarkWynter.Engine.ObjectLib { #region Using Statements using System; using System.Collections.Generic; 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.Diagnostics; using System.Threading; #endregion using Audio; using Physics; using Globals; using GameObjects; using EventControl; using DarkWynter.Engine.Init; using DarkWynter.Engine.Utilities; using DarkWynter.Stream.PhysicsGpu; using DarkWynter.Stream; using System.Reflection; using System.ComponentModel; using DarkWynter.Stream.UIInterfacing; /// /// Container and Manager class for GameObjects /// public class ObjectLibrary { #region Attributes // STANDARD OBJECTS ================================================= /// /// Terrain object. /// [EditorAttribute(typeof(ObjectPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] public Terrain terrain { get { return _terrain; } set { _terrain = value; } } public Terrain _terrain; /// /// A list of all Human Players /// [EditorAttribute(typeof(ListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] public List humans { get { return _humans; } set { _humans = value; } } public List _humans; /// /// A list of opponent AI Players /// [EditorAttribute(typeof(ListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] public List bots { get { return _bots; } set { _bots = value; } } public List _bots; // GENERIC OBJECTS ================================================= /// /// Billboards requested by GameObjects /// [EditorAttribute(typeof(ListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] public List billboards { get { return _billboards; } set { _billboards = value; } } public List _billboards; /// /// User Supplied GameObjects /// [EditorAttribute(typeof(ListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] public List gameObjectList { get { return _gameObjectList; } set { _gameObjectList = value; } } public List _gameObjectList; /// /// Cpu-based Props Loaded from XML /// [EditorAttribute(typeof(ListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] public List propLists { get { return _propLists; } set { _propLists = value; } } public List _propLists; /// /// Gpu-based Props Loaded from XML /// [EditorAttribute(typeof(ListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] public List gpuObjectLists { get { return _gpuObjectLists; } set { _gpuObjectLists = value; } } public List _gpuObjectLists; /// /// 3D Visualization of Game Events /// Mostly for debugging... /// [EditorAttribute(typeof(ListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] public List gameEvents { get { return _gameEvents; } set { _gameEvents = value; } } public List _gameEvents; [EditorAttribute(typeof(ListPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] public List _types { get { return types; } set { types = value; } } public static List types; /// /// Drawn on HUD to identify AI at a distance. /// private Texture2D enemyTargetReticle; #endregion /// /// All nodes contained in the currently loaded level xml file /// public static XmlNode levelXmlNode; public static string levelName; public static float vertMapToLocMapRelate; public static float terrainModWidth; private List _objectNames; public List objectNames { get { List names = new List(); if (terrain != null) { names.Add(terrain.name); } for (int i = 0; i < humans.Count; i++) { names.Add(humans[i].name); } for (int i = 0; i < bots.Count; i++) { names.Add(bots[i].name); } for (int i = 0; i < gameObjectList.Count; i++) { names.Add(gameObjectList[i].name); } for (int i = 0; i < propLists.Count; i++) { names.Add(propLists[i].name); } for (int i = 0; i < gpuObjectLists.Count; i++) { names.Add(gpuObjectLists[i].name); } return names; } } /// /// CONSTRUCTOR: /// public ObjectLibrary() { bots = new List(); billboards = new List(); gameObjectList = new List(); propLists = new List(); gpuObjectLists = new List(); gameEvents = new List(); humans = new List(); humans.Add(new Player()); humans[0].playerIndex = 0; ObjectLibrary.LoadAssemblyTypes("DWEngine.dll"); ObjectLibrary.LoadAssemblyTypes("DWStream.dll"); } public static void LoadAssemblyTypes(string assemblyName) { if (types == null) types = new List(); try { string path = System.IO.Directory.GetCurrentDirectory() + "\\"; types.AddRange(Assembly.LoadFile(path + assemblyName).GetTypes()); } catch (Exception e) { Console.WriteLine(e.Message); } } #region Load Methods /// /// Creates an instance of a GameObject using GameObject constructor parameters. /// /// The string-literal class name of the GameObject. EG- "Terrain" /// Constructor parameters, usually empty or using the Load object. /// public static GameObject CreateGameObject(string objectName, object[] parameters) { GameObject gameObject = new GameObject(); for (int i = 0; i < types.Count; i++) { if (types[i].Name == objectName) { try { gameObject = (GameObject)Activator.CreateInstance(types[i], parameters); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } return gameObject; } /// /// Load the Terrain and Skysphere for the Terrain Demo /// public void LoadLevel(string levelXML, string ScriptXml_FilePath) { // Reset load level flag Statics_Engine.GameSettings.LoadLevel = false; humans = new List(); bots = new List(); billboards = new List(); gameObjectList = new List(); propLists = new List(); gpuObjectLists = new List(); // Read the Level File try { XmlDocument reader = new XmlDocument(); String fileLocation = levelXML; reader.Load(fileLocation); // Get all outer nodes (incl xml version info and level) XmlNodeList allNodes = reader.ChildNodes; foreach (XmlNode levelNode in allNodes) { // If level definition if (levelNode.Name == "level") { levelXmlNode = levelNode; // Parse Level Load_Environment(levelNode); // Load Solo Objects Load_SoloObjects(levelNode); // Load Location Map Objects Load_LocationMap(levelNode); } } } catch { System.Diagnostics.Debug.WriteLine("Error reading xml: " + levelXML); // throw new Exception("Error reading XML"); } foreach (PropList propList in propLists) { propList.Load(this); } foreach (GpuObjectList gpuList in gpuObjectLists) { gpuList.Load(this); } #region Old GameObject Creation //// Terrain //if (XML.gameObjectInfo.terrainNode != null) //{ // terrain = new Terrain(); // terrain.Load(XML.gameObjectInfo.terrainNode, this); //} //// Load Audio //if (XML.gameObjectInfo.musicNode != null) //{ // Audio.LoadXML(XML.gameObjectInfo.musicNode); //} //// Game Objects - Single Depth List //gameObjectList = new List(); //if (XML.gameObjectInfo.gameObjectNodes != null) //{ // for(int i=0; i< XML.gameObjectInfo.gameObjectNodes.Count; i++) // { // XmlNode objectNode = XML.gameObjectInfo.gameObjectNodes[i]; // GameObject gameObject = new GameObject(); // if (CreateGameObjectType(objectNode, ref gameObject)) // { // if (gameObject.Load(objectNode, this)) // { // gameObjectList.Add(gameObject); // } // } // } //} //// Props - List of Lists //propLists = new List(); //if (XML.gameObjectInfo.propNode != null) //{ // for (int i = 0; i < XML.gameObjectInfo.propNode.Count; i++) // { // PropList propList = new PropList(); // if (propList.Load(XML.gameObjectInfo.propNode[i], this)) // { // propLists.Add(propList); // } // } //} //// GpuObjects - List of Lists //gpuObjectLists = new List(); //if (XML.gameObjectInfo.gpuObjectNodes != null) //{ // for(int i=0; i< XML.gameObjectInfo.gpuObjectNodes.Count; i++) // { // XmlNode objectNode = XML.gameObjectInfo.gpuObjectNodes[i]; // GpuObjectList gpuObjectList = new GpuObjectList(); // gpuObjectList.Load(objectNode, this); // gpuObjectLists.Add(gpuObjectList); // } //} //// Props Billboards - ( Dynamic GameObject Billboards handled in Draw_Billboards) //billboards = new List(); //if (XML.gameObjectInfo.billboardNode != null) //{ // foreach (XmlNode objectNode in XML.gameObjectInfo.billboardNode.ChildNodes) // { // BillboardList billboardList = new BillboardList(); // billboardList.Load(objectNode, this); // billboards.Add(billboardList); // } //} //// Humans //humans = new List(); //if (XML.gameObjectInfo.humanNodes != null) //{ // for (int i = 0; i < Statics_Engine.SystemSettings.TOTAL_PLAYERS; i++) // { // XmlNode objectNode = XML.gameObjectInfo.humanNodes[i]; // GameObject gameObject = new GameObject(); // if (CreateGameObjectType(objectNode, ref gameObject)) // { // if (gameObject.Load(objectNode, this)) // { // humans.Add((Player)gameObject); // } // } // } //} //// Bots //bots = new List(); //if (XML.gameObjectInfo.botNodes != null) //{ // for (int i = 0; i < Statics_Engine.GameSettings.botCount; i++) // { // XmlNode objectNode = XML.gameObjectInfo.botNodes[i]; // GameObject gameObject = new GameObject(); // if (CreateGameObjectType(objectNode, ref gameObject)) // { // if (gameObject.Load(objectNode, this)) // { // bots.Add((Player)gameObject); // } // } // } //} #endregion // Give life to the humans based on the number of active players selected in Game Setup for (int i = 0; i < humans.Count; i++) { humans[i].health = 100.0f; humans[i].manna = 100.0f; } // Mark each AI with a targeting icons enemyTargetReticle = Statics_Engine.SystemSettings.content.Load("Content/_textures/TargetMarker"); // Start Game Timer Statics_Engine.LevelSettings.gameTimer = new Stopwatch(); Statics_Engine.LevelSettings.gameTimer.Start(); 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); // Switch into Game Mode processing Statics_Engine.SystemSettings.gameState = Enums_Engine.EngineState.GAME_MODE; } private void Load_Environment(XmlNode levelNode) { // Get Level and LocationMap names levelName = levelNode.Attributes["name"].Value; // Cycle through XmlNodes for (int loadCount = 0; loadCount < levelNode.ChildNodes.Count; loadCount++) { XmlNode node = levelNode.ChildNodes[loadCount]; // Terrain Size if (node.Name == "Terrain") { Texture2D terrain = Statics_Engine.SystemSettings.content.Load(node.Attributes["heightmap"].Value); Statics_Engine.TerrainSettings.vertexMapSize = terrain.Width; // Calculate the vertexmap/locationmap ratio for use in the for loop below vertMapToLocMapRelate = Statics_Engine.TerrainSettings.vertexMapSize / float.Parse(levelNode.Attributes["locationMapSize"].Value); // Create a ruler 1 terrain mod long (distance between verticies terrainModWidth = Statics_Engine.TerrainSettings.terrainScaleFactor * vertMapToLocMapRelate; } // Audio if (node.Name == "Music") { Audio.LoadXML(node); } // Dimensions else if (node.Name == "Dimensions") { Statics_Engine.TerrainSettings.terrainScaleFactor = int.Parse(node.Attributes["scale"].Value); } // Physics else if (node.Name == "Physics") { Statics_Engine.GameSettings.accelDueToGravity = new Vector3(0.0f, Statics_Engine.GameSettings.gravityForce, 0.0f); Statics_Engine.GameSettings.gravityForce = float.Parse(node.Attributes["gravity"].Value); Statics_Engine.LevelSettings.TERRAIN_FRICTION = float.Parse(node.Attributes["friction"].Value); } // Fog else if (node.Name == "Fog") { Statics_Engine.LevelSettings.fogDensity = float.Parse(node.Attributes["density"].Value); Statics_Engine.LevelSettings.fogStart = float.Parse(node.Attributes["startfog"].Value); Statics_Engine.LevelSettings.fogEnd = float.Parse(node.Attributes["endfog"].Value); Statics_Engine.LevelSettings.fogColor[0] = float.Parse(node.Attributes["red"].Value); Statics_Engine.LevelSettings.fogColor[1] = float.Parse(node.Attributes["green"].Value); Statics_Engine.LevelSettings.fogColor[2] = float.Parse(node.Attributes["blue"].Value); Statics_Engine.LevelSettings.fogColor[3] = float.Parse(node.Attributes["alpha"].Value); } } } private void Load_SoloObjects(XmlNode levelNode) { List soloObjects = new List(); // Check each Object Node for a match for ( int nodeCount = 0; nodeCount < levelNode.ChildNodes.Count; nodeCount++) { XmlNode node = levelNode.ChildNodes[nodeCount]; // If Node contains x,y,z coordinates if (node.Attributes != null && node.Attributes["x"] != null && node.Attributes["z"] != null) { // Get the Node's location value float x = float.Parse(node.Attributes["x"].Value); float y = 255.0f; float z = float.Parse(node.Attributes["z"].Value); // Create Object or continue GameObject gameObject = ObjectLibrary.CreateGameObject(node.LocalName, new object[] { node, new Vector3(x, y, z) }); // Read by ObjectLibrary::Load soloObjects.Add(gameObject); } } // Load Terrain First for (int i = 0; i < soloObjects.Count; i++) { // Load GameObject GameObject gameObject = soloObjects[i]; if (gameObject is Terrain) { gameObject.Load(this); terrain = gameObject as Terrain; } } // Load Solo Objects for (int i = 0; i < soloObjects.Count; i++) { // Load GameObject GameObject gameObject = soloObjects[i]; // Generic object if (!(gameObject is Terrain)) { // Players gameObject.Load(this); if (gameObject.node.Name == "Human") humans.Add(gameObject as Player); else if (gameObject.node.Name == "Bot") bots.Add(gameObject as Player); else { gameObjectList.Add(gameObject); } } } } private void Load_LocationMap(XmlNode levelNode) { List locationMapObjects = new List(); Random rand = new Random(); // Check each Object Node for a match for (int nodeCount = 0; nodeCount < levelNode.ChildNodes.Count; nodeCount++) { XmlNode node = levelNode.ChildNodes[nodeCount]; // Only get Nodes that contain x,y,z coordinates if (node.Attributes != null && node.Attributes["red"] != null && node.Attributes["green"] != null && node.Attributes["blue"] != null) { // Open Location Map if (node.Attributes["locationMap"] != null) { // Linearize pixels in location map Texture2D locationMap = Statics_Engine.SystemSettings.content.Load(node.Attributes["locationMap"].Value); Color[] pixels = new Color[locationMap.Width * locationMap.Width]; locationMap.GetData(pixels); // Process Pixels from LocationMap for (int pixelCount = 0; pixelCount < pixels.Length; pixelCount++) { Color currentPixel = pixels[pixelCount]; // Skip this pixel if blank, or empty if (currentPixel == Color.Black || currentPixel == Color.White) continue; // Get 2D Position from 1D array // Y is set during GameObject.Load() Vector3 startPosition = new Vector3(((int)pixelCount / locationMap.Width) * Statics_Engine.TerrainSettings.terrainScaleFactor, 0.0f, (pixelCount % locationMap.Width) * Statics_Engine.TerrainSettings.terrainScaleFactor); // Create Object or continue GameObject gameObject = ObjectLibrary.CreateGameObject(node.LocalName, new object[] { node, startPosition }); // Read by ObjectLibrary::Load locationMapObjects.Add(gameObject); } } } } for (int i = 0; i < locationMapObjects.Count; i++) { // Load GameObject GameObject gameObject = locationMapObjects[i]; // Generic Lists if (gameObject is IBillboard) { gameObject.Load(this); //billboards.Add(gameObject as BillboardList); } else if (gameObject is IProp) { gameObject.Load(this); // Randomly orient object (better asthetics) gameObject.mass.Rotate(0, (float)(rand.NextDouble() * Math.PI * 2)); // Check existing prop lists bool found = false; for (int j = 0; j < propLists.Count; j++) { // Add GameObject to existing propList if (gameObject.objectModelName == propLists[j].objectModelName) { propLists[j].AddNewObject(gameObject); found = true; break; } } if (!found) { // Create new prop list for this type PropList propList = new PropList(gameObject.node, gameObject.startPosition); propList.AddNewObject(gameObject); propList.objectModelName = gameObject.objectModelName; propLists.Add(propList); } } else if (gameObject is IGpuObject) { gameObject.Load(this); // Check existing lists bool found = false; for (int j = 0; j < gpuObjectLists.Count; j++) { if (gameObject.objectModelName == gpuObjectLists[j].objectModelName) { gpuObjectLists[j].AddNewObject(gameObject, false); found = true; break; } } if (!found) { GpuObjectList gpuObjectList = new GpuObjectList(gameObject.node, gameObject.startPosition); gpuObjectList.AddNewObject(gameObject, false); gpuObjectList.objectModelName = gameObject.objectModelName; gpuObjectLists.Add(gpuObjectList); } } else if (gameObject is GameObject && !(gameObject is Terrain)) { gameObject.Load(this); gameObjectList.Add(gameObject); } } } #endregion public GameObject GetGameObject(string name) { GameObject gameObject = new GameObject(); if (terrain.name == name) return terrain; for (int i = 0; i < humans.Count; i++) { if (humans[i].name == name) { return humans[i]; } } for (int i = 0; i < bots.Count; i++) { if (bots[i].name == name) { return bots[i]; } } for (int i = 0; i < gameObjectList.Count; i++) { if (gameObjectList[i].name == name) { return gameObjectList[i]; } } for (int i = 0; i < propLists.Count; i++) { if (propLists[i].name == name) { return propLists[i]; } } for (int i = 0; i < gpuObjectLists.Count; i++) { if (gpuObjectLists[i].name == name) { return gpuObjectLists[i]; } } return gameObject; } #region Save Methods /// /// Save the Level. /// /// public XmlDocument ToXml() { // Clear Dirty level node levelXmlNode.RemoveAll(); // Write out Level //levelXmlNode.AppendChild(terrain.ToXml()); for (int i = 0; i < humans.Count; i++) { levelXmlNode.AppendChild(humans[i].ToXml()); } for (int i = 0; i < bots.Count; i++) { levelXmlNode.AppendChild(bots[i].ToXml()); } for (int i = 0; i < gameObjectList.Count; i++) { levelXmlNode.AppendChild(gameObjectList[i].ToXml()); } for (int i = 0; i < propLists.Count; i++) { levelXmlNode.AppendChild(propLists[i].ToXml()); } for (int i = 0; i < gpuObjectLists.Count; i++) { levelXmlNode.AppendChild(gpuObjectLists[i].ToXml()); } // Create Writer XmlDocument xmlDoc = new XmlDocument(); // Append XML declaration to Doc xmlDoc.AppendChild(xmlDoc.CreateNode(XmlNodeType.XmlDeclaration, "", "")); // Create root level element XmlElement xmlRootElement = xmlDoc.CreateElement("", "level", ""); // Append Level GameObjects to root xmlRootElement.AppendChild(levelXmlNode); // Append Root to Doc xmlDoc.AppendChild(xmlRootElement); return xmlDoc; } #endregion #region Update Methods /// /// Call all GameObject Updates to handle gravity and motion /// /// ObjectLibrary /// Collision public void Update(ObjectLibrary objectLibrary, Collision collision) { // TEMP: ============================ // Remove when Scenegraph reinstalled List collisionList = new List(); for (int i = 0; i < gameObjectList.Count; i++) { collisionList.Add(gameObjectList[i].mass); } for (int i = 0; i < humans.Count; i++) { collisionList.Add(humans[i].mass); } for (int i = 0; i < bots.Count; i++) { collisionList.Add(bots[i].mass); } // END TEMP ============================ // Collision Main Entry Point collision.UpdateCollision(ref objectLibrary, collisionList); // GameObject Update (incl Physics) Main Entry terrain.Update(ref objectLibrary); if (Statics_Engine.SystemSettings.WINDOW_IN_FOCUS) { for (int i = 0; i < humans.Count; i++) { humans[i].Update(ref objectLibrary); } } for (int i = 0; i < bots.Count; i++) { bots[i].Update(ref objectLibrary); } for (int i = 0; i < gameObjectList.Count; i++) { gameObjectList[i].Update(ref objectLibrary); } for (int i = 0; i < propLists.Count; i++) { propLists[i].Update(ref objectLibrary); } for (int i = 0; i < gpuObjectLists.Count; i++) { gpuObjectLists[i].Update(this); } DarkWynterEngine._HUD.Update(); } /// /// Remove a Game Object from our list of gameobjects /// /// Game object to be removed public void RemoveGameObject(GameObject gameObject) { gameObjectList.Remove(gameObject); } #endregion #region Attack Methods /// /// Player uses Attack Method to shoot Grenade-like objects onto the board /// /// ID of the player who fired the grenade /// Type of grenade /// Starting position of the grenade /// Normal direction of the grenade /// Mass of grenade /// Thermal value of grenade public void Attack_Grenade(int playerID, Enums_Engine.ParticleType type, Vector3 initialPosition, Vector3 direction) { for (int i = 0; i < levelXmlNode.ChildNodes.Count; i++) { if (levelXmlNode.ChildNodes[i].Name == "Grenade") { GameObject particle = new GameObject(levelXmlNode.ChildNodes[i], Vector3.Zero); particle.Load(this); particle.PrepAttack(playerID, initialPosition, direction); gameObjectList.Add(particle); } } } /// /// Player uses Attack Method to shoot Bullet-like objects onto the board /// /// ID of the player who fired the Bullet /// Type of Bullet /// Starting position of the Bullet /// Normal direction of the Bullet /// Mass of Bullet /// Thermal value of Bullet public void Attack_Bullet(int playerID, Enums_Engine.BulletType type, Vector3 initialPosition, Vector3 direction, int bulletMassValue, int bulletThermalValue) { for (int i = 0; i < levelXmlNode.ChildNodes.Count; i++) { if (levelXmlNode.ChildNodes[i].Name == "Bullet") { GameObject bullet = new GameObject(levelXmlNode.ChildNodes[i], Vector3.Zero); bullet.Load(this); bullet.PrepAttack(playerID, initialPosition, direction); gameObjectList.Add(bullet); } } } /// /// Player uses Attack Method to shoot gpu-based objects onto the board /// /// ID of the player who fired the Swarm /// Starting position of the Swarm /// Normal direction of the Swarm /// Mass of Swarm /// Thermal value of Swarm public void Attack_GpuParticle(int playerID, Vector3 initialPosition, Vector3 direction, int swarmMassValue, int swarmThermalValue) { for (int i = 0; i < levelXmlNode.ChildNodes.Count; i++) { if (levelXmlNode.ChildNodes[i].Name == "GpuObject") { XmlNode node = levelXmlNode.ChildNodes[i]; List burst = new List(); int GPU_BURST_RATE = swarmMassValue; float GPU_BURST_RADIUS = 10.0f; for (int j = 0; j < GPU_BURST_RATE; j++) { GameObject gameObject = ObjectLibrary.CreateGameObject(node.LocalName, new object[] { node, initialPosition }); Random rand = new Random(); Vector3 randomOffset = new Vector3((float)rand.NextDouble() * GPU_BURST_RADIUS, (float)rand.NextDouble() * GPU_BURST_RADIUS, (float)rand.NextDouble() * GPU_BURST_RADIUS); initialPosition += randomOffset; gameObject.Load(this); // Set up Model Manager string type = node.Attributes["name"].Value; // Start Type properties gameObject.mass.gameObjectPointer = gameObject; gameObject.objectModelName = type; // Set Position gameObject.mass.SetPosition(initialPosition + (Statics_Engine.PlayerSettings.PARTICLE_START_DISTANCE * direction), initialPosition + ((Statics_Engine.PlayerSettings.PARTICLE_START_DISTANCE - 10) * direction)); // Init Physics gameObject.mass.boundingVolume = new BoundingVolume(new BoundingSphere(gameObject.mass.currentPosition, 2.0f)); gameObject.mass.velocity = Vector3.Zero; gameObject.mass.acceleration = Vector3.Zero; gameObject.mass.scale = new Vector3((int)(float.Parse(node.Attributes["maxScale"].Value))); gameObject.mass.mass = float.Parse(node.Attributes["mass"].Value); // Add Force gameObject.mass.AddForce(direction * 10000.0f); // Add mass(es) burst.Add(gameObject.mass); } // Add mass(es) if (burst.Count != 0) { // Check existing gpu lists bool found = false; for (int j = 0; j < gpuObjectLists.Count; j++) { if (burst[0].gameObjectPointer.objectModelName == gpuObjectLists[j].objectModelName) { gpuObjectLists[j].AddMass(burst); found = true; break; } } if (!found) { // GPU lists do not contain this object type... so create a new list GpuObjectList gpuObjectList = new GpuObjectList(burst[0].gameObjectPointer.node, burst[0].gameObjectPointer.startPosition); gpuObjectList.AddMass(burst); gpuObjectList.objectModelName = burst[0].gameObjectPointer.objectModelName; gpuObjectLists.Add(gpuObjectList); } } } } } #endregion #region Draw Methods /// /// Draw and Postdrawing /// /// Player for which draw perspective is associated. public List Draw(int playerIndex) { if(Statics_Stream.RenderSettings.cameraList[playerIndex].mode == Camera.CameraMode.FirstPerson) { // Calculate the player's ModelView Matrix Statics_Stream.RenderSettings.matrixView = Statics_Stream.RenderSettings.cameraList[playerIndex].GetViewMatrix(humans[playerIndex].mass.currentPosition, humans[playerIndex].mass.normalVector, humans[playerIndex].mass.upVector, humans[playerIndex].fpvEnabled); } else if (Statics_Stream.RenderSettings.cameraList[playerIndex].mode == Camera.CameraMode.FixedPosition) { Vector3 position = Statics_Stream.RenderSettings.cameraList[playerIndex].fixedPosition; Vector3 normal = new Vector3(Statics_Engine.TerrainSettings.collisionMapSize/2, 0.0f,Statics_Engine.TerrainSettings.collisionMapSize/2) - position; normal.Normalize(); Vector3 perpVec = new Vector3(-normal.Z, 0.0f, normal.X); perpVec.Normalize(); Vector3 upVector = Vector3.Cross(perpVec, normal); upVector.Normalize(); // Calculate the player's ModelView Matrix Statics_Stream.RenderSettings.matrixView = Statics_Stream.RenderSettings.cameraList[playerIndex].GetViewMatrix( position,normal,upVector,humans[playerIndex].fpvEnabled); } // Calculate the player's Projection Matrix Statics_Stream.RenderSettings.matrixProjection = Statics_Stream.RenderSettings.cameraList[playerIndex].GetProjectionMatrix(); // Pass Matricies to Shader ShaderParameters.DrawFX.ViewProj.SetValue(Statics_Stream.RenderSettings.matrixView * Statics_Stream.RenderSettings.matrixProjection); ShaderParameters.DrawFX.EyePostion.SetValue(Matrix.Invert(Statics_Stream.RenderSettings.matrixView)); // Send Lighting to the Shader ShaderParameters.DrawFX.lightPosition0.SetValue(Statics_Engine.LevelSettings.lightPosition1); ShaderParameters.DrawFX.lightAmbient0.SetValue(Statics_Engine.LevelSettings.lightAmbient1); ShaderParameters.DrawFX.lightDiffuse0.SetValue(Statics_Engine.LevelSettings.lightDiffuse1); ShaderParameters.DrawFX.lightSpecular0.SetValue(Statics_Engine.LevelSettings.lightSpecular1); if (Statics_Engine.SystemSettings.singleLightSource) { ShaderParameters.DrawFX.lightPosition1.SetValue(Statics_Engine.LevelSettings.lightPosition1); ShaderParameters.DrawFX.lightAmbient1.SetValue(Statics_Engine.LevelSettings.lightAmbient1); ShaderParameters.DrawFX.lightDiffuse1.SetValue(Statics_Engine.LevelSettings.lightDiffuse1); ShaderParameters.DrawFX.lightSpecular1.SetValue(Statics_Engine.LevelSettings.lightSpecular1); } else { ShaderParameters.DrawFX.lightPosition1.SetValue(Statics_Engine.LevelSettings.lightPosition2); ShaderParameters.DrawFX.lightAmbient1.SetValue(Statics_Engine.LevelSettings.lightAmbient2); ShaderParameters.DrawFX.lightDiffuse1.SetValue(Statics_Engine.LevelSettings.lightDiffuse2); ShaderParameters.DrawFX.lightSpecular1.SetValue(Statics_Engine.LevelSettings.lightSpecular2); } ShaderParameters.DrawFX.fogEnd.SetValue(Statics_Engine.LevelSettings.fogEnd); ShaderParameters.DrawFX.fogStart.SetValue(Statics_Engine.LevelSettings.fogStart); // TerrainLOD and TerrainMod Shader Requisits Statics_Engine.PlayerSettings.playerPosition = humans[playerIndex].mass.currentPosition; Statics_Engine.PlayerSettings.playerLookVector = new Vector2(humans[playerIndex].mass.normalVector.X, humans[playerIndex].mass.normalVector.Z); Statics_Engine.PlayerSettings.playerRotation = humans[playerIndex].mass.currentRotation; Statics_Engine.TerrainSettings.terrainLookAtPoint = humans[playerIndex].lookAtPoint; Statics_Engine.TerrainSettings.terrainModRange = (int)(humans[playerIndex].attackMagnitude / 25); Statics_Engine.TerrainSettings.terrainModEnabled = humans[playerIndex].terrainModEnabled; List drawList = new List(); // Draw the terrain drawList.Add(terrain.Draw()); // Draw Cpu Based Object Lists for (int i = 0; i < propLists.Count; i++) { drawList.Add(propLists[i].Draw()); } // Draw Gpu Based Object Lists for (int i = 0; i < gpuObjectLists.Count; i++) { drawList.Add(gpuObjectLists[i].Draw()); } // Draw AI foreach (Player player in bots) { drawList.Add(player.Draw()); } //// Draw Humans //foreach (Player human in humans) //{ // if (human.fpvEnabled && human == humans[playerIndex] && Camera.offset == Vector3.Zero) // { // continue; // } // drawList.Add(human.Draw()); //} // Draw User Defined Game Objects for (int i = 0; i < gameObjectList.Count; i++) { drawList.Add(gameObjectList[i].Draw()); } // Draw Events for (int i = 0; i < gameEvents.Count; i++) { List draw = gameEvents[i].Draw(); if (draw != null) { drawList.AddRange(draw); } } // Draw AI Shields (NOTE: draw 2nd to last for transparency reasons) foreach (Player player in bots) { if (player.IsAlive()) { drawList.Add(player.DrawShield()); } } // Draw Human Shields (NOTE: draw last for transparency reasons) foreach (Player player in humans) { if (player.IsAlive()) { drawList.Add(player.DrawShield()); } } return drawList; } /// /// Pass a Billboard List to GameObjects so they can add GameObject-relative Billboards. /// This does not effect the Prop Billboards. /// /// Billboards are oriented towards the Player we are drawing them for. public List Draw_Billboards(int playerIndex) { // Calculate the player's ModelView Matrix Statics_Stream.RenderSettings.matrixView = Matrix.CreateLookAt(humans[playerIndex].mass.currentPosition, humans[playerIndex].mass.currentPosition + humans[playerIndex].mass.normalVector, humans[playerIndex].mass.upVector); // Calculate the player's Projection Matrix Statics_Stream.RenderSettings.matrixProjection = Matrix.CreatePerspectiveFieldOfView((float)Math.PI / 4, Statics_Stream.RenderSettings.cameraList[playerIndex].viewport.Width / Statics_Stream.RenderSettings.cameraList[playerIndex].viewport.Height, 0.3f, 100000f); // Create Empty List BillboardList dynamicBillboards = new BillboardList(); // Draw the terrain terrain.Draw_Billboards(this, dynamicBillboards); //// Draw Cpu Based Object Lists //for (int i = 0; i < propLists.Count; i++) //{ // propLists[i].Draw_Billboards(this, ref gameObjectBillboards); //} //// Draw Gpu Based Object Lists //for (int i = 0; i < gpuObjectLists.Count; i++) //{ // gpuObjectLists[i].Draw_Billboards(this, ref gameObjectBillboards); //} // Draw User Defined Game Objects for (int i = 0; i < gameObjectList.Count; i++) { // gameObjectList[i].Draw_Billboards(this, dynamicBillboards); } // Draw Humans foreach (Player human in humans) { human.Draw_Billboards(this, dynamicBillboards); } // Draw AI foreach (Player player in bots) { player.Draw_Billboards(this, dynamicBillboards); } // Draw all GameObject Billboards return dynamicBillboards.Draw_Billboards(this, playerIndex); } /// /// Draw AI vision /// /// AI's index public void DrawAIVision(Vector3 aiCurrentPosition) { for (int i = 0; i < humans.Count; i++) { if (humans[i].IsAlive()) { ShaderParameters.DrawFX.playerIndex.SetValue((i + 1) / 14.0f); humans[i].DrawAIVision(); } } terrain.DrawAIVision(aiCurrentPosition); } /// /// Let each GameObject draw it's own Sprites /// /// Current player's index /// SpriteBatch used to draw public void PostDraw_HUD(int currentPlayerIndex, SpriteBatch spriteBatch) { // Calculate the player's ModelView Matrix Statics_Stream.RenderSettings.matrixView = Statics_Stream.RenderSettings.cameraList[currentPlayerIndex].GetViewMatrix(humans[currentPlayerIndex].mass.currentPosition, humans[currentPlayerIndex].mass.normalVector, humans[currentPlayerIndex].mass.upVector, humans[currentPlayerIndex].fpvEnabled); Statics_Stream.RenderSettings.matrixProjection = Statics_Stream.RenderSettings.cameraList[currentPlayerIndex].GetProjectionMatrix(); // Post Draw HUD DarkWynterEngine._HUD.Draw(spriteBatch); // Mark Other Players // -The further away the enemy is, the smaller and fainter the icon // -scale range: 0.25-1.0, alpha range: 50-200 float distance = 0.0f; float distRatio = 0.0f; float totalScale = 0.25f; Vector3 position = new Vector3(); // Draw AI bots foreach (Player bot in bots) { if (bot.IsAlive()) { // DrawEnemyTargets(currentPlayerIndex, spriteBatch, ref position, ref distance, ref distRatio, totalScale, bot); } } // Draw Humans foreach (Player player in humans) { if (player.IsAlive() && player != humans[currentPlayerIndex]) { //DrawEnemyTargets(currentPlayerIndex, spriteBatch, ref position, ref distance, ref distRatio, totalScale, player); } } } private void DrawEnemyTargets(int currentPlayerIndex, SpriteBatch spriteBatch, ref Vector3 position, ref float distance, ref float distRatio, float totalScale, Player player) { distance = Vector3.Distance(player.mass.currentPosition, humans[currentPlayerIndex].mass.currentPosition); if (distance > Statics_Engine.PlayerSettings.ENEMY_MARKER_MIN_DISTANCE) { position = Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.Project(player.mass.currentPosition, Statics_Stream.RenderSettings.matrixProjection, Statics_Stream.RenderSettings.matrixView, Matrix.Identity); if (position.Z < 1) { position.X -= Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.X; position.Y -= Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.Y; if (position.X >= 0 && position.X < Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.Width && position.Y >= 0 && position.Y < Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.Height) { distRatio = 1.0f - (distance / Statics_Engine.PlayerSettings.ENEMY_MARKER_MAX_DISTANCE); //if negative they are too far away if (distRatio < 0) { distRatio = 0; } spriteBatch.Draw(enemyTargetReticle, new Rectangle((int)(position.X - (enemyTargetReticle.Width * distRatio * totalScale) / 2), (int)(position.Y - (enemyTargetReticle.Height * distRatio * totalScale)), (int)(enemyTargetReticle.Width * distRatio * totalScale), (int)(enemyTargetReticle.Height * distRatio * totalScale)), new Color(255, 255, 255, (byte)(200 * distRatio))); } } } } #endregion } } #region Legacy Code /* /// /// Function to reset our list of human players /// public void DeinitializeHumans() { //be warned.. MUST call Statics.CheckForControllers after this!! foreach (Human human in humans) { human.playerController.playerControllerType = Enums_Engine.ControllerType.NONE; human.health = 0; human.manna = 0; } } public void GetDrawObjects() { for (int i = 0; i < humans.Count; i++) { if (humans[i].IsAlive()) { lookupMap.GetDrawObjects(humans[i].mass, drawList[i]); } } } // Test Function to update energy distribution public void UpdateHeatDissipation(ObjectLibrary objectLibrary, float dt) { List newParticlesToAddToList = new List(); foreach (Particle particle in particles) { particle.mass.UpdatePosition(dt); } // Iterate through dynamic particles for (int i = 0; i < particles.Count; i++) { Particle particle = particles[i]; // List to store the pointers to neighboring particles List neighboringParticleList = new List(); // Used to calculate the average value of all neighboring particles float averageEnergy = particle.mass.energy; // Get the list of neighboring particle pointers neighboringParticleList = GetSurroundingParticles(particle.mass.currentPosition, objectLibrary); // Calculate their total energy foreach (Particle neigborParticle in neighboringParticleList) { averageEnergy += neigborParticle.mass.energy; } // Find the average averageEnergy /= neighboringParticleList.Count + 1; // If the average value is not equal to zero then we have some heat dissipation to do if (averageEnergy != particle.mass.energy && neighboringParticleList.Count != 0) { // Iterate through neighboring particles foreach (Particle neigborParticle in neighboringParticleList) { // If their value is not equal to the average set it and set the flag if (neigborParticle.mass.energy != averageEnergy) { neigborParticle.mass.SetEnergy(averageEnergy); if (!neigborParticle.mass.isChanging) { neigborParticle.mass.isChanging = true; newParticlesToAddToList.Add(neigborParticle); } } } // Set the starting particle's energy to average value as well particle.mass.SetEnergy(averageEnergy); } else if (particle.mass.energy != 0.0f) { DissipateHeat(particle); } else { // The particle and it's neighbors are in equilibrium so remove it from the list particle.mass.isChanging = false; if (!particle.mass.isMoving) { // Particle needs to be put back into the static list MoveParticle(particles, particles, particle); } else { particles.Remove(particle); } i--; } } foreach (Particle newParticle in newParticlesToAddToList) { if (particles.Contains(newParticle)) { continue; } if (newParticle.mass.isMoving) { CopyParticle(particles, particles, newParticle); } else { MoveParticle(particles, particles, newParticle); } } } public void StateChange(ObjectLibrary objectLibrary, float elementUse, GameObject gameObject) { Particle particle = (Particle)gameObject; gameObject.mass.ChangeEnergy(elementUse / 2.0f); if (gameObject.mass.isChanging) { return; } else if (gameObject.mass.isMoving) { // Particle is in the dynamic list so we need to copy it to the Thermal list switch (particle.particleType) { case Particle.ParticleType.Air: { objectLibrary.particleManager.air.CopyParticle(objectLibrary.particleManager.air.dynamicParticles, objectLibrary.particleManager.air.thermalParticles, particle); break; } case Particle.ParticleType.Water: { objectLibrary.particleManager.water.CopyParticle(objectLibrary.particleManager.water.dynamicParticles, objectLibrary.particleManager.water.thermalParticles, particle); break; } case Particle.ParticleType.Earth: { objectLibrary.particleManager.earth.CopyParticle(objectLibrary.particleManager.earth.dynamicParticles, objectLibrary.particleManager.earth.thermalParticles, particle); break; } } gameObject.mass.isChanging = true; } else { // It's in the static list, so move the particle to the dynamic list switch (particle.particleType) { case Particle.ParticleType.Air: { objectLibrary.particleManager.air.MoveParticle(objectLibrary.particleManager.air.staticParticles, objectLibrary.particleManager.air.thermalParticles, particle); break; } case Particle.ParticleType.Water: { objectLibrary.particleManager.water.MoveParticle(objectLibrary.particleManager.water.staticParticles, objectLibrary.particleManager.water.thermalParticles, particle); break; } case Particle.ParticleType.Earth: { objectLibrary.particleManager.earth.MoveParticle(objectLibrary.particleManager.earth.staticParticles, objectLibrary.particleManager.earth.thermalParticles, particle); break; } } gameObject.mass.isChanging = true; } } public void UpdateLightPosition() { // Light goes 180 degrees back and forth (never below) //if (Math.Abs(lightMoveAngle1) > Math.PI / 2.0f) //{ // LIGHT_MOVE_SPEED1 = -LIGHT_MOVE_SPEED1; //} // Light goes full 360 degrees // Update light source position if (lightMoveAngle1 < 0) { //reset to 2PI lightMoveAngle1 = Math.PI * 2.0f; } else if (lightMoveAngle1 > Math.PI * 2.0f) { //reset to zero lightMoveAngle1 = 0.0f; } // Update the angle of the light lightMoveAngle1 += LIGHT_MOVE_SPEED1; //Calculate the X and Y based on the angle float dx = (float)(lightDistance1 * Math.Sin(lightMoveAngle1)); float dz = (float)(lightDistance1 * Math.Cos(lightMoveAngle1)); lightInfo1.M11 = dx + (Statics.TerrainSettings.collisionMapSize / 2.0f); lightInfo1.M13 = dz +(Statics.TerrainSettings.collisionMapSize / 2.0f); } */ #endregion