//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// Copyright (C)2007 DarkWynter Studios. All rights reserved.
//
//---------------------------------------------------------------------------------------------------------------------------------------------------
// {Contact : darkwynter.com for licensing information
//---------------------------------------------------------------------------------------------------------------------------------------------------
namespace DarkWynterEngine.GameObjects
{
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Xml;
using Physics;
using Globals;
using ObjectLib;
#endregion
///
/// Used to pass instance data to shaders through existing gpu pipelines.
///
/// Location and orientation variables are stored as follows:
/// Fog = GameObject scale
/// Binormal = GameObject rotation
/// Tangent = GameObject position
///
public struct VertexFogBinormalTangent
{
///
/// scale
///
public Vector4 Fog;
///
/// rotation
///
public Vector4 Binormal;
///
/// position
///
public Vector4 Tangent;
}
///
/// Used to pass instance data to shaders through existing gpu pipelines.
///
/// World matrix values are stored as follows:
/// Fog = World.M11, World.M12, World.M13, World.M14
/// Binormal = World.M21, World.M22, World.M23, World.M24
/// Tangent = World.M31, World.M32, World.M33, World.M34
/// Weight = World.M41, World.M42, World.M43, World.M44
///
public struct VertexFogBinormalTangentWeight
{
///
/// World.M11, World.M12, World.M13, World.M14
///
public Vector4 Fog;
///
/// World.M21, World.M22, World.M23, World.M24
///
public Vector4 Binormal;
///
/// World.M31, World.M32, World.M33, World.M34
///
public Vector4 Tangent;
///
/// World.M41, World.M42, World.M43, World.M44
///
public Vector4 BlendWeight;
}
///
/// Methods of GameObject follow the GameFlow pattern to ensure quick and efficient loading and unloading procedures.
/// Additional properties are included in GameObject and are used by Renderer and Update to manipulate the GameObject.
/// Each object specifies its draw and update procedures internally and is passed to Physics for in game motion and rotation.
///
public class GameObject
{
#region GameObject Interface Properties
private Mass _mass;
private Model _model;
private Matrix _matrix;
private XmlNode _xml;
private List _textureList = new List();
private string _objectModelName;
private bool _isCollectable;
private bool _isKey;
///
/// Mass object, handles physics of GameObject.
///
public Mass mass { get { return _mass; } set { _mass = value; } }
///
/// Model used by this GameObject.
///
public Model model { get { return _model; } set { _model = value; } }
///
/// Location and orientation matrix passed to shaders.
///
public Matrix matrix { get { return _matrix; } set { _matrix = value; } }
///
/// Xml data associated with this object.
///
public XmlNode xml { get { return _xml; } set { _xml = value; } }
///
/// Textures associated with this object.
///
public List textureList { get { return _textureList; } set { _textureList = value; } }
///
/// Text identifier for model name.
///
public string objectModelName { get { return _objectModelName; } set { _objectModelName = value; } }
///
/// Defines if this object is collectable by players.
///
public bool isCollectable { get { return _isCollectable; } set { _isCollectable = value; } }
///
/// Defines if this object is a Key object collected to pass the level.
///
public bool isKey { get { return _isKey; } set { _isKey = value; } }
///
/// Buffer to store vertices
///
public VertexBuffer vertexBuffer;
///
/// Array to store vertex Position, Normal and Texture information
///
public VertexPositionNormalTexture[] vertices;
///
/// Vertex Declaration.
///
public VertexDeclaration vertexDeclaration;
///
/// Used to pass instance data to shader.
///
public VertexFogBinormalTangent objectValues;
///
/// Tangential component of force calculations.
///
public Vector3 tangentialComponent = new Vector3();
///
/// Normal component of force calculations.
///
public Vector3 normalComponent = new Vector3();
///
/// Used in collision; surface normal calculation.
///
public Vector3 surfaceNormal;
///
/// Used in collision; gravity normal calculation.
///
public Vector3 gravityNormalComponent;
///
/// Used in collision; tangential gravity-force calculation.
///
public Vector3 gravityTangentialComponent;
///
/// Used in collision; normal velocity-force calculation.
///
public Vector3 velocityNormalComponent;
///
/// Used in collision; tangential velocity-force calculation.
///
public Vector3 velocityTangentialComponent;
///
/// Used in collision; normal totalForce calculation.
///
public Vector3 totalForceNormalComponent;
///
/// Used in collision; tangential totalForce calculation.
///
public Vector3 totalForceTangentialComponent;
///
/// Used in collision; combined velocity and totalForce normal calculation.
///
public Vector3 combinedNormalForce;
///
/// Used in collision; combined velocity and totalForce tangential calculation.
///
public Vector3 combinedTangentialForce;
///
/// Difference between object height and terrain at it's x/z location.
/// HeightDifference is positive when object is below the terrain.
///
public float heightDifference;
///
/// Terrain height at object's x/z location.
///
public float localTerrainHeight;
///
/// Defines what kind of collision response this GameObject should have.
///
public Enums.CollisionResponses collisionWithPlayerResponse = Enums.CollisionResponses.NONE;
///
/// Defines the scale of damage or health an object bestows.
///
public float collisionMultiplier = 0.001f;
#endregion
#region Methods
///
/// Game object constructor.
/// Gets a pre-initialized mass object from the Statics.LevelSettings.darkMatter list.
///
public GameObject()
{
mass = Statics.LevelSettings.darkMatter[Statics.LevelSettings.darkMatterIterator++];
mass.gameObjectPointer = this;
}
///
/// Load object data from Xml.
///
/// The Level xml node corresponding to this object
/// ObjectLibrary that this object belongs to.
public virtual bool Load(XmlNode node, ObjectLibrary objectLibrary)
{
// Set up Model Manager
bool success = objectLibrary.modelManager.AddNewModel(node.Attributes["type"].Value,
node.Attributes["model"].Value,
node.Attributes["texture"].Value,
node.Attributes["bumpTexture"].Value);
// Return unsuccessfully if can't load user supplied XML data
if (!success) { return true; } // WE SHOULD RETURN FALSE HERE... OTHERWISE WE'RE SAYING "YES, IT LOADED" WHEN IT DIDN'T
// Get the Location Map
Texture2D locationMap = Statics.SystemSettings.content.Load(node.Attributes["locationMap"].Value);
int length = locationMap.Width * locationMap.Width;
Color[] locationColorValues = new Color[length];
locationMap.GetData(locationColorValues);
Random rand = new Random();
// Precalculate the vertexmap/locationmap ratio for use in the for loop below
float vertexmapToObjectmapRelationship = Statics.TerrainSettings.vertexMapSize / locationMap.Width;
// Create a ruler 1 terrain mod long (distance between verticies
float terrainModWidth = Statics.TerrainSettings.terrainScaleFactor * vertexmapToObjectmapRelationship;
// Get the color value of the node
int mapColorR = int.Parse(node.Attributes["red"].Value);
int mapColorG = int.Parse(node.Attributes["green"].Value);
int mapColorB = int.Parse(node.Attributes["blue"].Value);
// For each pixel of the treeMap
for (int l = 0; l < length; l++)
{
// If the color matches create a prop
if (locationColorValues[l].R == mapColorR && locationColorValues[l].G == mapColorG && locationColorValues[l].B == mapColorB)
{
// Get the 2D location from 1D array
int h = l % locationMap.Width;
int w = (int)l / locationMap.Width;
// Start Type properties
//gameObject.mass.objectType = objectType;
mass.gameObjectPointer = this;
objectModelName = node.Attributes["type"].Value;
// Get terrain height at position
float yPosition = objectLibrary.terrain.GetTerrainHeight(w * vertexmapToObjectmapRelationship,
h * vertexmapToObjectmapRelationship);
// Set the object world properties
Vector3 locpos = new Vector3(w * terrainModWidth, yPosition, h * terrainModWidth);
Vector3 refpos = new Vector3(w * terrainModWidth, yPosition, h * terrainModWidth - 1);
mass.SetPosition(locpos, refpos);
mass.Rotate(0.0f, 0.0f);
mass.scale = new Vector3((float.Parse(node.Attributes["maxScale"].Value)));
mass.mass = float.Parse(node.Attributes["mass"].Value);
mass.isMoving = false;
isCollectable = bool.Parse(node.Attributes["isCollectable"].Value);
isKey = bool.Parse(node.Attributes["isKey"].Value);
if (isKey)
{
collisionWithPlayerResponse = Enums.CollisionResponses.HEALTHBONUS;
}
objectValues = new VertexFogBinormalTangent();
objectValues.Fog = new Vector4(mass.scale, 0.0f); // Store the scale
objectValues.Binormal = new Vector4(mass.currentRotation.X,
mass.currentRotation.Y,
mass.currentRotation.Z,
mass.currentRotation.W); // Store the quaternion rotation
objectValues.Tangent = new Vector4(mass.currentPosition, 0.0f);
}
}
return true;
}
///
/// Update this object
///
/// ObjectLibrary
public virtual void Update(ref ObjectLibrary objectLibrary)
{
mass.UpdatePosition();
mass.boundingVolume.UpdateSphere(mass.currentPosition);
objectValues = new VertexFogBinormalTangent();
objectValues.Fog = new Vector4(mass.scale, 0.0f); // Store the scale
objectValues.Binormal = new Vector4(mass.currentRotation.X,
mass.currentRotation.Y,
mass.currentRotation.Z,
mass.currentRotation.W); // Store the quaternion rotation
objectValues.Tangent = new Vector4(mass.currentPosition, 0.0f); // Store the translation
}
///
/// Default behavior applies force based physics for rebound.
/// Override to supplement behavior.
/// Return true if collidedObject is absorbed or destroyed, else false.
///
/// GameObject that collided with this GameObject.
/// The force applied by the colliding GameObject to this GameObject
/// ObjectLibrary that this object belongs to.
/// True = this object has to be recycled
public virtual bool ObjectCollisionResponse(GameObject collidedObject, Vector3 resultantForce, ObjectLibrary objectLibrary)
{
mass.numberOfCollision++;
mass.isMoving = true;
return false;
}
///
/// Default behavior applies force based physics for rebound.
/// Override to supplement or replace behavior.
///
/// A copy of the terrain, provided for overrides
public virtual void TerrainCollisionResponse(Terrain terrain)
{
CalculateVectorComponents(surfaceNormal, Statics.GameSettings.accelDueToGravity);
gravityNormalComponent = normalComponent + Vector3.Zero;
gravityTangentialComponent = tangentialComponent + Vector3.Zero;
// Calculate the components of velocity with reference to the surface normal
CalculateVectorComponents(surfaceNormal, mass.velocity);
velocityNormalComponent = normalComponent + Vector3.Zero;
velocityTangentialComponent = tangentialComponent + Vector3.Zero;
// Calculate the components of totalForce with reference to the surface normal
CalculateVectorComponents(surfaceNormal, mass.totalForce);
totalForceNormalComponent = normalComponent + Vector3.Zero;
totalForceTangentialComponent = tangentialComponent + Vector3.Zero;
// Calculate normal and tangential forces with reference to the their components
combinedNormalForce = (mass.mass * velocityNormalComponent / Statics.SystemSettings.dt) + totalForceNormalComponent;
combinedTangentialForce = (mass.mass * velocityTangentialComponent / Statics.SystemSettings.dt) +
totalForceTangentialComponent +
(mass.mass * gravityTangentialComponent);
mass.numberOfCollision++;
}
///
/// Calculate components of collision.
///
/// Normal of surface that is being collided against.
/// Velocity of this GameObject.
private void CalculateVectorComponents(Vector3 surfaceNormal, Vector3 objectVelocity)
{
float vectorToNormalAngle, vectorToSurfaceAngle;
float normalComponentOfVector;
if (objectVelocity.Length() >= 0.01f || !float.IsInfinity(objectVelocity.Length()))
{
normalComponent = Vector3.Dot(objectVelocity, surfaceNormal) * surfaceNormal;
tangentialComponent = objectVelocity - normalComponent;
/*
// Based on vector dot product to get the angle between the two vectors
vectorToNormalAngle = (float)Math.Acos(Vector3.Dot(surfaceNormal, objectVelocity) / objectVelocity.Length());
// Stupid check required due to XNA's inaccuracy
if (float.IsNaN(vectorToNormalAngle))
{
vectorToNormalAngle = 0.0f;
}
// The angle between the ground and the vector is pi/2 - previous angle
vectorToSurfaceAngle = (float)Math.PI / 2.0f - vectorToNormalAngle;
// Scalar component of the vector in the the normal direction
normalComponentOfVector = objectVelocity.Length() * (float)Math.Sin(vectorToSurfaceAngle);
if (float.IsNaN(normalComponentOfVector))
{
//if objectVelocity.Length gives an invalid value
normalComponentOfVector = 0.0f;
}
// Above scalar component multiplied by the surface normal gives us the normal component of the vector
normalComponent = normalComponentOfVector * surfaceNormal;
// The vector plus the negative normalComponent will give us the tangential component in the reverse direction
tangentialComponent = -(objectVelocity + (-normalComponent));
*/
}
else
{
// Object velocity is equal to zero so set both components to zero
normalComponent = Vector3.Zero;
tangentialComponent = Vector3.Zero;
}
}
///
/// Sets the heightDifference parameter for this GameObject.
/// HeightDifference is positive when object is below the terrain.
///
/// Terrain object to determine height difference with.
public void GetObjectHeight(Terrain terrain)
{
// Used to calculate the average terrain height around the player
localTerrainHeight = 0;
// Error check
mass.EnforceBoundary();
// Get X and Z positions
int posX = (int)mass.currentPosition.X;
int posZ = (int)mass.currentPosition.Z;
// Add up all neighboring terrain points
localTerrainHeight = terrain.GetTerrainHeight(posX / Statics.TerrainSettings.terrainScaleFactor, posZ / Statics.TerrainSettings.terrainScaleFactor);
surfaceNormal = terrain.GetTerrainNormal(posX / Statics.TerrainSettings.terrainScaleFactor, posZ / Statics.TerrainSettings.terrainScaleFactor, mass.velocity);
// Average all the neighboring terrain points
float newHeight = localTerrainHeight + (mass.objectHeight / 2);
// Get difference between average and player
heightDifference = newHeight - mass.currentPosition.Y;
}
///
/// Draws a stand alone model with no instancing or triangle stripping.
/// Uses model stored in ModelManager and referenced by objectModelName.
///
/// ModelManager containing this object's model file.
/// Shader technique to draw model with.
public virtual void Draw(ModelManager modelManager, string technique)
{
// Calculate ObjectSpace(Rotation) and WorldSpace(Translation) Transformation Matrix
matrix = Matrix.CreateScale(mass.scale) *
Matrix.CreateFromQuaternion(mass.currentRotation) *
Matrix.CreateTranslation(mass.currentPosition);
// Matricies
ShaderParameters.World.SetValue(matrix);
// Lighting
ShaderParameters.shininess.SetValue(7000.0f);
// Load resources for that catagory
ModelInfo modelInfo = modelManager.GetModelInfo(objectModelName);
ShaderParameters.modelTexture1.SetValue(modelInfo.currentTexture);
ShaderParameters.bumpTexture1.SetValue(modelInfo.bumpTexture);
foreach (ModelMesh mesh in modelInfo.model.Meshes)
{
Statics.SystemSettings.graphics.GraphicsDevice.Indices = mesh.IndexBuffer;
foreach (ModelMeshPart part in mesh.MeshParts)
{
Statics.SystemSettings.graphics.GraphicsDevice.VertexDeclaration = part.VertexDeclaration;
Statics.SystemSettings.graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, part.StreamOffset, part.VertexStride);
part.Effect.CurrentTechnique = part.Effect.Techniques[technique];
part.Effect.Begin();
for (int k = 0; k < part.Effect.CurrentTechnique.Passes.Count; k++)
{
EffectPass pass = part.Effect.CurrentTechnique.Passes[k];
pass.Begin();
Statics.SystemSettings.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
part.BaseVertex,
0,
part.NumVertices,
part.StartIndex,
part.PrimitiveCount);
pass.End();
}
part.Effect.End();
}
}
}
///
/// Draws a stand alone model with no instancing or triangle stripping.
/// Uses model passed in from invoking function call.
///
/// Model to draw.
/// Shader technique to draw model with.
public void DrawBasic(Model model, string technique)
{
// Calculate ObjectSpace(Rotation) and WorldSpace(Translation) Transformation Matrix
matrix = Matrix.CreateScale(mass.scale) *
Matrix.CreateFromQuaternion(mass.currentRotation) *
Matrix.CreateTranslation(mass.currentPosition);
// Matricies
ShaderParameters.World.SetValue(matrix);
// Lighting
ShaderParameters.shininess.SetValue(7000.0f);
foreach (ModelMesh mesh in model.Meshes)
{
Statics.SystemSettings.graphics.GraphicsDevice.Indices = mesh.IndexBuffer;
foreach (ModelMeshPart part in mesh.MeshParts)
{
Statics.SystemSettings.graphics.GraphicsDevice.VertexDeclaration = part.VertexDeclaration;
Statics.SystemSettings.graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, part.StreamOffset, part.VertexStride);
part.Effect.CurrentTechnique = part.Effect.Techniques[technique];
part.Effect.Begin();
for (int k = 0; k < part.Effect.CurrentTechnique.Passes.Count; k++)
{
EffectPass pass = part.Effect.CurrentTechnique.Passes[k];
pass.Begin();
Statics.SystemSettings.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
part.BaseVertex,
0,
part.NumVertices,
part.StartIndex,
part.PrimitiveCount);
pass.End();
}
part.Effect.End();
}
}
}
///
/// Draws a stand alone model that uses the triangle-strip content processor for loading.
///
/// Model to draw.
/// Shader technique to draw model with.
public void DrawTriStrips(Model model, string technique)
{
foreach (ModelMesh mesh in model.Meshes)
{
Statics.SystemSettings.graphics.GraphicsDevice.Indices = mesh.IndexBuffer;
foreach (ModelMeshPart part in mesh.MeshParts)
{
part.Effect.CurrentTechnique = part.Effect.Techniques[technique];
Statics.SystemSettings.graphics.GraphicsDevice.VertexDeclaration = part.VertexDeclaration;
Statics.SystemSettings.graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, part.StreamOffset, part.VertexStride);
int numPrimitives;
if (mesh.IndexBuffer.IndexElementSize == IndexElementSize.SixteenBits)
{
numPrimitives = mesh.IndexBuffer.SizeInBytes / sizeof(ushort);
}
else
{
numPrimitives = mesh.IndexBuffer.SizeInBytes / sizeof(int);
}
numPrimitives -= 2;
part.Effect.Begin();
foreach (EffectPass pass in part.Effect.CurrentTechnique.Passes)
{
pass.Begin();
Statics.SystemSettings.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleStrip,
part.BaseVertex,
0,
part.NumVertices,
part.StartIndex,
numPrimitives);
pass.End();
}
part.Effect.End();
}
}
}
///
/// Draws an instanced model that uses the standard content processor.
///
/// Model to draw.
/// Shader technique to draw model with.
/// The number of bits between verticies. Use "vertexDeclaration.GetVertexStrideSize()" to find this.
public void DrawInstancedBasic(Model model, string technique, int vertexStride)
{
foreach (ModelMesh mesh in model.Meshes)
{
// Set the index buffer
Statics.SystemSettings.graphics.GraphicsDevice.Indices = mesh.IndexBuffer;
// Tell the GPU how many times to run through the vertex data and set the stream.
Statics.SystemSettings.graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, 0, vertexStride);
foreach (ModelMeshPart part in mesh.MeshParts)
{
part.Effect.CurrentTechnique = part.Effect.Techniques[technique];
part.Effect.Begin();
for (int k = 0; k < part.Effect.CurrentTechnique.Passes.Count; k++)
{
EffectPass pass = part.Effect.CurrentTechnique.Passes[k];
pass.Begin();
Statics.SystemSettings.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
part.BaseVertex,
0,
part.NumVertices,
part.StartIndex,
part.PrimitiveCount);
pass.End();
}
part.Effect.End();
}
}
}
///
/// Draws an instanced model that uses the triangle-strip content processor.
///
/// Model to draw.
/// Shader technique to draw model with.
/// The number of bits between verticies. Use "vertexDeclaration.GetVertexStrideSize()" to find this.
public void DrawInstancedTriStrips(Model model, string technique, int vertexStride)
{
foreach (ModelMesh mesh in model.Meshes)
{
// Set the index buffer
Statics.SystemSettings.graphics.GraphicsDevice.Indices = mesh.IndexBuffer;
int numPrimitives;
if (mesh.IndexBuffer.IndexElementSize == IndexElementSize.SixteenBits)
{
numPrimitives = mesh.IndexBuffer.SizeInBytes / sizeof(ushort);
}
else
{
numPrimitives = mesh.IndexBuffer.SizeInBytes / sizeof(int);
}
numPrimitives -= 2;
// Tell the GPU how many times to run through the vertex data and set the stream.
Statics.SystemSettings.graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, 0, vertexStride);
foreach (ModelMeshPart part in mesh.MeshParts)
{
part.Effect.CurrentTechnique = part.Effect.Techniques[technique];
part.Effect.Begin();
for (int k = 0; k < part.Effect.CurrentTechnique.Passes.Count; k++)
{
EffectPass pass = part.Effect.CurrentTechnique.Passes[k];
pass.Begin();
Statics.SystemSettings.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleStrip,
part.BaseVertex,
0,
part.NumVertices,
part.StartIndex,
numPrimitives);
pass.End();
}
part.Effect.End();
}
}
}
///
/// Called after Draw method.
/// Allows GameObjects to add Billboards to be drawn.
/// List is cleared each pass, or frame.
///
/// ObjectLibrary that this object belongs to.
/// Dynamic Billboard list.
public virtual void Draw_Billboards(ObjectLibrary objectLibrary, BillboardList gameObjectBillboards)
{
//do stuff later
}
#endregion
}
}
#region Legacy Code - Heat dissipation and State Change
/* Legacy Code
// 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;
}
}
*/
#endregion