/*
* PrimitiveLine.cs
* Authors: Mike Dapiran
* Copyright (c) 2007-2008 Cornell University
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
using System;
using System.Collections;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Util;
namespace ColonySim
{
///
/// A class to make primitive 2D objects out of lines.
///
public class PrimitiveLine : DrawableGameScreenComponent
{
#region Fields
// Pixel texture used to render line
private readonly Texture2D pixel;
// List of vector
private readonly ArrayList vectors;
// The sprite batch used for rendering
private readonly SpriteBatch spriteBatch;
///
/// Gets/sets the colour of the primitive line object.
///
public Color Colour;
///
/// Gets/sets the position of the primitive line object.
///
public Vector2 Position;
///
/// Gets/sets the render depth of the primitive line object (0 = front, 1 = back)
///
public float Depth;
///
/// Whether or not this could auto clear
///
public bool AutoClear = true;
#endregion
#region Properties
///
/// Gets the number of vectors which make up the primtive line object.
///
public int CountVectors { get { return vectors.Count; } }
#endregion
#region Creation
///
/// Creates a new primitive line object.
///
/// The Graphics Device object to use.
/// The sprite batch to render with
public PrimitiveLine(GraphicsDevice graphicsDevice, SpriteBatch pSpriteBatch)
{
// create pixels
pixel = new Texture2D(graphicsDevice, 1, 1, 1, TextureUsage.None, SurfaceFormat.Color);
Color[] pixels = new Color[1];
pixels[0] = Color.White;
pixel.SetData(pixels);
Colour = Color.White;
Position = new Vector2(0, 0);
Depth = 0;
vectors = new ArrayList();
spriteBatch = pSpriteBatch;
}
#endregion
#region Render
///
/// Renders the primtive line object.
///
/// Time that has passed in game so far
public override void Draw(GameTime gameTime)
{
if (vectors.Count < 2)
return;
for (int i = 1; i < vectors.Count; i++)
{
Vector2 vector1 = (Vector2)vectors[i - 1];
Vector2 vector2 = (Vector2)vectors[i];
// calculate the distance between the two vectors
float distance = Vector2.Distance(vector1, vector2);
// calculate the angle between the two vectors
float angle = (float)Math.Atan2(vector2.Y - vector1.Y, vector2.X - vector1.X);
// stretch the pixel between the two vectors
spriteBatch.Begin();
spriteBatch.Draw(pixel,
Position + vector1,
null,
Colour,
angle,
Vector2.Zero,
new Vector2(distance, 1),
SpriteEffects.None,
Depth);
spriteBatch.End();
}
if (AutoClear)
{
ClearVectors();
}
}
#endregion
#region Vector Modifiers
///
/// Adds a vector to the primive live object.
///
/// The vector to add.
public void AddVector(Vector2 vector)
{
vectors.Add(vector);
}
///
/// Insers a vector into the primitive line object.
///
/// The index to insert it at.
/// The vector to insert.
public void InsertVector(int index, Vector2 vector)
{
vectors.Insert(index, vectors);
}
///
/// Removes a vector from the primitive line object.
///
/// The vector to remove.
public void RemoveVector(Vector2 vector)
{
vectors.Remove(vector);
}
///
/// Removes a vector from the primitive line object.
///
/// The index of the vector to remove.
public void RemoveVector(int index)
{
vectors.RemoveAt(index);
}
///
/// Clears all vectors from the primitive line object.
///
public void ClearVectors()
{
vectors.Clear();
}
#endregion
#region Util
///
/// Creates a circle at the given position with the given radius.
///
/// The position origin of the circle
/// The radius (half the width) of the circle.
/// The number of sides on the circle (the more the detailed).
public void CreateCircle(Vector2 position, float radius, int sides)
{
vectors.Clear();
const float max = MathHelper.TwoPi;
float step = max / sides;
for (float theta = 0; theta < max; theta += step)
{
vectors.Add(position + new Vector2(radius * (float)Math.Cos(theta),
radius * (float)Math.Sin(theta)));
}
// then add the first vector again so it's a complete loop
vectors.Add(position + new Vector2(radius * (float)Math.Cos(0),
radius * (float)Math.Sin(0)));
}
#endregion
}
}