#region File Description
//-----------------------------------------------------------------------------
// SceneItem.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
#endregion
namespace Spacewar
{
///
/// SceneItem is any item that can be in a scenegraph
///
public class SceneItem : List
{
///
/// Collision Radius of this item
///
protected float radius;
///
/// Should this item be deleted?
///
protected bool delete;
///
/// Simulation paused for this items, nothing will update
///
private bool paused;
///
/// The root SceneItem
///
protected SceneItem Root;
///
/// The parent SceneItem
///
protected SceneItem Parent;
///
/// Shape is the actual renderable object
///
protected Shape shape;
///
/// The position of this item
///
protected Vector3 position;
///
/// The velocity of this item
///
protected Vector3 velocity;
///
/// The acceleration of the item
///
protected Vector3 acceleration;
///
/// The current rotation of this item
///
protected Vector3 rotation;
///
/// The scaling transformation for this object
///
protected Vector3 scale = new Vector3(1f, 1f, 1f);
///
/// The center of rotation and scaling
///
protected Vector3 center;
private Game game;
#region Properties
public bool Delete
{
get
{
return delete;
}
set
{
delete = value;
}
}
public float Radius
{
get
{
return radius;
}
set
{
radius = value;
}
}
public Shape ShapeItem
{
get
{
return shape;
}
set
{
shape = value;
}
}
public bool Paused
{
get
{
return paused;
}
set
{
paused = value;
}
}
public Vector3 Acceleration
{
get
{
return acceleration;
}
}
public Vector3 Velocity
{
get
{
return velocity;
}
set
{
velocity = value;
}
}
public Vector3 Position
{
get
{
return position;
}
set
{
position = value;
}
}
public Vector3 Rotation
{
get
{
return rotation;
}
set
{
rotation = value;
}
}
public Vector3 Center
{
get
{
return center;
}
set
{
center = value;
}
}
public Vector3 Scale
{
get
{
return scale;
}
set
{
scale = value;
}
}
protected Game GameInstance
{
get
{
return game;
}
}
#endregion
///
/// Default constructor, does nothing special
///
public SceneItem(Game game)
{
this.game = game;
}
///
/// Creates a SceneItem with a shape to be rendered at an initial position
///
/// The shape to be rendered for this item
/// The initial position of the item
public SceneItem(Game game, Shape shape, Vector3 initialPosition)
{
this.shape = shape;
this.position = initialPosition;
this.game = game;
}
///
/// Creates a SceneItem with a shape to be rendered
///
/// The shape to be rendered for this item
public SceneItem(Game game, Shape shape)
{
this.shape = shape;
this.game = game;
}
///
/// Creates a SceneItem with no shape but a position
///
/// The initial position of the item
public SceneItem(Game game, Vector3 initialPosition)
{
this.position = initialPosition;
this.game = game;
}
///
/// Adds an item to the Scene Node
///
/// The item to add
public new void Add(SceneItem childItem)
{
//A new custom 'add' that sets the parent and the root properties
//on the child item
childItem.Parent = this;
if (Root == null)
{
childItem.Root = this;
}
else
{
childItem.Root = Root;
}
//Call the 'real' add method on the dictionary
((List)this).Add(childItem);
}
///
/// Updates any values associated with this scene item and its children
///
/// Game time
/// Elapsed game time since last call
public virtual void Update(TimeSpan time, TimeSpan elapsedTime)
{
if (!paused)
{
//Do the basic acceleration/velocity/position updates
velocity += Vector3.Multiply(acceleration, (float)elapsedTime.TotalSeconds);
position += Vector3.Multiply(velocity, (float)elapsedTime.TotalSeconds);
}
//If this item has something to draw then update it
if (shape != null)
{
shape.World = Matrix.CreateTranslation(-center) *
Matrix.CreateScale(scale) *
Matrix.CreateRotationX(rotation.X) *
Matrix.CreateRotationY(rotation.Y) *
Matrix.CreateRotationZ(rotation.Z) *
Matrix.CreateTranslation(position + center);
if (!paused)
{
shape.Update(time, elapsedTime);
}
}
//Update each child item
foreach (SceneItem item in this)
{
item.Update(time, elapsedTime);
}
//Remove any items that need deletion
int i = 0;
while (i < Count)
{
if (this[i].delete)
{
RemoveAt(i);
}
else
{
i++;
}
}
//RemoveAll(IsDeleted);
}
private static bool IsDeleted(SceneItem item)
{
return item.delete;
}
///
/// Render any items associated with this scene item and its children
///
public virtual void Render()
{
//If this item has something to draw then draw it
if (shape != null)
{
shape.Render();
}
//Then render all of the child nodes
foreach (SceneItem item in this)
{
item.Render();
}
}
///
/// Checks if there is a collision between the this and the passed in item
///
/// A scene item to check
/// True if there is a collision
public virtual bool Collide(SceneItem item)
{
//Until we get collision meshes sorted just do a simple sphere (well circle!) check
if ((position - item.position).Length() < radius + item.radius)
return true;
//If we are a ship and we are a long, thin pencil,
//we have additional extents, check those, too!
Ship shipItem = item as Ship;
if (shipItem != null && shipItem.ExtendedExtent != null)
{
Matrix localRotation = Matrix.CreateRotationZ(shipItem.Rotation.Z);
Vector4 extendedPosition = Vector4.Transform(shipItem.ExtendedExtent[0], localRotation);
Vector3 localPosition = shipItem.Position + new Vector3(extendedPosition.X, extendedPosition.Y, extendedPosition.Z);
if ((Position - localPosition).Length() < radius + item.Radius)
return true;
extendedPosition = Vector4.Transform(shipItem.ExtendedExtent[1], localRotation);
localPosition = shipItem.Position + new Vector3(extendedPosition.X, extendedPosition.Y, extendedPosition.Z);
if ((Position - localPosition).Length() < radius + item.Radius)
return true;
}
Ship ship = this as Ship;
if (ship != null && ship.ExtendedExtent != null)
{
Matrix localRotation = Matrix.CreateRotationZ(ship.Rotation.Z);
Vector4 extendedPosition = Vector4.Transform(ship.ExtendedExtent[0], localRotation);
Vector3 localPosition = ship.Position + new Vector3(extendedPosition.X, extendedPosition.Y, extendedPosition.Z);
if ((localPosition - item.Position).Length() < radius + item.Radius)
return true;
extendedPosition = Vector4.Transform(ship.ExtendedExtent[1], localRotation);
localPosition = ship.Position + new Vector3(extendedPosition.X, extendedPosition.Y, extendedPosition.Z);
if ((localPosition - item.Position).Length() < radius + item.Radius)
return true;
}
return false;
}
public virtual void OnCreateDevice()
{
}
}
}