#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() { } } }