//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// Copyright (C)2007 DarkWynter Studios. All rights reserved.
//
//---------------------------------------------------------------------------------------------------------------------------------------------------
// {Contact : darkwynter.com for licensing information
//---------------------------------------------------------------------------------------------------------------------------------------------------
namespace DarkWynter.Game.GameObjects
{
#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.Diagnostics;
using System.Xml;
#endregion
using DarkWynter.Engine.GameObjects;
using DarkWynter.Engine.Globals;
using DarkWynter.Engine.Physics;
using DarkWynter.Engine.ObjectLib;
using GameObjects;
using DarkWynter.Stream;
using DarkWynter.Engine.Init;
///
/// A Bullet
///
public class Bullet : GameObject
{
#region Properties
///
/// Timer used to identify when to recycle the object
///
public Stopwatch dissipationTimer = new Stopwatch();
///
/// Particle-type Enumeration
///
public Enums_Engine.BulletType bulletType;
//private ParticleSounds pSounds = new ParticleSounds();
///
/// A counter for the number of collisions that have occured
///
public int hasCollided = -1;
///
/// Stopwatch for recycling the object after it has collided
///
public Stopwatch hasCollidedTimer = new Stopwatch();
///
/// ID of the player who fired this bullet
///
public int ownerID = -1;
///
/// Boolean check to see if the player was hit by their own bullet
///
public bool hurtOwner = false;
private Stopwatch hurtOwnerTimer = new Stopwatch();
private float waveRadius = 0.0f;
#endregion
#region Construction Methods
///
/// Constructor
///
public Bullet(Load gameObjectLoader)
: base(gameObjectLoader)
{
mass.objectType = Enums_Engine.ObjectType.PARTICLE;
mass.gameObjectPointer = this;
mass.objectHeight = mass.boundingVolume.radius;
mass.isMoving = true;
mass.energy = 1.0f;
waveRadius = 1.0f;
hasCollided = -1;
hurtOwner = false;
hurtOwnerTimer = Stopwatch.StartNew();
collisionWithPlayerResponse = Enums_Engine.CollisionResponses.HEALTHLOSS;
switch (bulletType)
{
case Enums_Engine.BulletType.Earth:
mass.mass = Statics_Engine.ParticleSettings.Earth.EARTH_MASS;
mass.COR = Statics_Engine.ParticleSettings.Earth.EARTH_COLD_COR;
mass.dynamicFrictionCoefficient = Statics_Engine.ParticleSettings.Earth.EARTH_COLD_FRICTION;
break;
case Enums_Engine.BulletType.Water:
mass.mass = Statics_Engine.ParticleSettings.Water.WATER_MASS;
mass.COR = Statics_Engine.ParticleSettings.Water.WATER_COLD_COR;
mass.dynamicFrictionCoefficient = Statics_Engine.ParticleSettings.Water.WATER_COLD_FRICTION;
break;
case Enums_Engine.BulletType.Air:
mass.mass = Statics_Engine.ParticleSettings.Wind.WIND_MASS;
mass.COR = Statics_Engine.ParticleSettings.Wind.WIND_COLD_COR;
mass.dynamicFrictionCoefficient = Statics_Engine.ParticleSettings.Wind.WIND_COLD_FRICTION;
break;
}
}
///
/// Load bullet information from XML
///
/// The bullet's XML node
/// ObjectLibrary
/// True if load was successful, else false
public override bool Load(ObjectLibrary objectLibrary)
{
// Set up Model Manager
bool success = LoadModel(load.node);
// Return unsuccessfully if can't load user supplied XML data
if (!success) { return false; }
draw.drawMethod = Enums_Stream.DrawMethod.BasicGameObject_Draw;
drawBoundingVolume = draw;
draw.technique = "BasicLightingShaderMain";
drawBoundingVolume.technique = "ShieldShaderMain";
// Start Type properties
objectModelName = load.node.Attributes["name"].Value;
drawBoundingVolume.textureList.Add(Statics_Engine.SystemSettings.content.Load("Content/_textures/whitesquare"));
drawBoundingVolume.textureList.Add(Statics_Engine.SystemSettings.content.Load("Content/_textures/Wind"));
mass.scale = new Vector3((float.Parse(load.node.Attributes["maxScale"].Value)));
mass.mass = float.Parse(load.node.Attributes["mass"].Value);
mass.isMoving = false;
isCollectable = bool.Parse(load.node.Attributes["isCollectable"].Value);
isKey = bool.Parse(load.node.Attributes["isKey"].Value);
if (isKey)
{
collisionWithPlayerResponse = Enums_Engine.CollisionResponses.HEALTHBONUS;
}
return true;
}
#endregion
#region Update Methods
///
/// Update
///
/// ObjectLibrary
public override void Update(ref ObjectLibrary objectLibrary)
{
return;
mass.Update();
mass.boundingVolume.UpdateSphere(mass.currentPosition);
//Update COR based on energy level
//mass.COR = Statics.ParticleSettings.Wind.WIND_COLD_COR - ((mass.energy / 2.0f) + 0.5f) * (Statics.ParticleSettings.Wind.WIND_COLD_COR - Statics.ParticleSettings.Wind.WIND_HOT_COR);
//mass.dynamicFrictionCoefficient = Statics.ParticleSettings.Wind.WIND_COLD_FRICTION - ((mass.energy / 2.0f) + 0.5f) * (Statics.ParticleSettings.Wind.WIND_COLD_FRICTION - Statics.ParticleSettings.Wind.WIND_HOT_FRICTION);
mass.Rotate(0.0f, 0.2f);
// Send properties and control signal to Shaders
Vector4 gpu_particleType = new Vector4(0);
if (this.bulletType == Enums_Engine.BulletType.Earth) { gpu_particleType.Y = 0.0f; } // Earth = x0xx
if (this.bulletType == Enums_Engine.BulletType.Water) { gpu_particleType.Y = 1.0f; } // Water = x1xx
if (this.bulletType == Enums_Engine.BulletType.Air) { gpu_particleType.Y = 2.0f; } // Gas = x2xx
gpu_particleType.Z = (mass.energy / 2.0f) + 0.5f; // Fire = xxNx
gpu_particleType.W = waveRadius;
// Instancing buffers
//dynamicObjectValues = new VertexFogBinormalTangent();
//dynamicObjectValues.Fog = new Vector4(mass.scale.Y, gpu_particleType.Y, gpu_particleType.Z, gpu_particleType.W); // Store the scale
//dynamicObjectValues.Binormal = new Vector4(mass.currentRotation.X,
// mass.currentRotation.Y,
// mass.currentRotation.Z,
// mass.currentRotation.W); // Store the quaternion rotation
//dynamicObjectValues.Tangent = new Vector4(mass.currentPosition, 0.0f); // Store the translation
}
#endregion
#region Draw Methods
///
/// Draw the particle object
///
public override Draw Draw()
{
// Calculate ObjectSpace(Rotation) and WorldSpace(Translation) Transformation Matrix
draw.matrix = draw.initialTransform *
Matrix.CreateScale(mass.scale) *
Matrix.CreateFromQuaternion(mass.currentRotation) *
Matrix.CreateTranslation(mass.currentPosition);
return draw;
}
///
/// Function for debugging to compare the size of the bullet with it's bounding volume
///
public void DrawBoundingSphere()
{
drawBoundingVolume.matrix = drawBoundingVolume.initialTransform *
Matrix.CreateScale(mass.boundingVolume.radius) *
Matrix.CreateFromQuaternion(mass.currentRotation) *
Matrix.CreateTranslation(mass.currentPosition);
float[] color = { 1, 1, 1, 1 };
ShaderParameters.DrawFX.materialDiffuse.SetValue(color);
drawBoundingVolume.DoDraw();
}
#endregion
#region CollisionResponse Methods
///
/// Add Particle specific responses to an object to object collision involving this and collidedObject
///
/// Object colliding with this object
/// The resultant force of collision
/// ObjectLibrary
/// True = this object needs to be recycled
public override bool ObjectCollisionResponse(GameObject collidedObject, Vector3 resultantForce, ObjectLibrary objectLibrary)
{
mass.AddForce(resultantForce);
if (collidedObject.mass.objectType == Enums_Engine.ObjectType.PLAYER)
{
// Add Player specific responses to the collided player
// Remove this object
return true;
}
return false;
}
///
/// Add Particle specific responses to an object to terrain collision involving this
///
/// Terrain
public override void TerrainCollisionResponse(Terrain terrain)
{
base.GetObjectHeight(terrain);
// Add Gravity if terrain and player are touching
if (heightDifference < 0.0f)
{
mass.AddForce(mass.mass * Statics_Engine.GameSettings.accelDueToGravity);
}
else if (heightDifference > 0.0f)
{
// Call base first
base.TerrainCollisionResponse(terrain);
if (combinedNormalForce.Y < 0.0f)
{
mass.AddForce(-combinedNormalForce);
}
else
{
mass.AddForce(-velocityNormalComponent);
}
mass.AddForce(heightDifference * surfaceNormal * terrain.particleSurfaceTension * mass.COR);
if (combinedTangentialForce.Length() >= 0.5f)
{
mass.AddForce(mass.mass * -gravityTangentialComponent);
mass.AddFriction(mass.dynamicFrictionCoefficient + terrain.mass.dynamicFrictionCoefficient,
(mass.mass * gravityNormalComponent.Length()) + totalForceNormalComponent.Length(),
combinedTangentialForce);
}
else
{
mass.AddForce(mass.mass * -velocityTangentialComponent / Statics_Engine.SystemSettings.dt);
mass.AddForce(-totalForceTangentialComponent);
}
}
}
#endregion
}
}