/* * Meteor.cs * Authors: August Zinsser, Adam Nabinger * 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 Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Random = Util.Random; namespace MaritimeDefender { /// /// Represents the flying meteors in Meteor Madness. /// The player can shoot them, and they explode. /// Meteors can also crash into the player, causing it damage /// class Meteor : Entity { public const float SPAWN_RATE = .75f; public const float MIN_SIZE = .1f; public const float MAX_SIZE = .5f; #region Fields // The various sprites used to render the meteor private static Animation[] mMeteorSprites; // How far away (along the z-axis) from the player that the meteors spawn at private readonly float mSpawnDepth; // The z-depth where the meteors should kill themselves (which should be behind the player and off camera) private float mKillDepth; // If the meteor is alive or not private new bool mAlive = true; // Size of this entity in space3D coordinates private Vector3 mSpace3DSize; #endregion #region Properties /// /// Gets the depth at which the meteor spawns at /// public float SpawnDepth { get { return mSpawnDepth; } } /// /// Gets the size of the meteor /// public override Vector3 Size { get { return mSpace3DSize; } } /// /// Gets/Sets the depth at which the meteor dies at /// public float KillDepth { get { return mKillDepth; } set { mKillDepth = value; } } /// /// Gets/Sets whether or not the meteor is alive /// public bool Alive { get { return mAlive; } set { mAlive = value; } } /// /// Gets/Sets the width of the meteor /// public override float Width { get { return mSpace3DSize.X; } set { mSpace3DSize.X = value; } } /// /// Gets/Sets the height of the meteor /// public override float Height { get { return mSpace3DSize.Y; } set { mSpace3DSize.Y = value; } } #endregion #region Predicates /// /// Defines when the meteor is considered dead and can be cleaned up /// public new static readonly Predicate NotAlive = new Predicate(delegate(Meteor o) { return !o.mAlive; }); #endregion #region Creation /// /// Constructor /// /// Width of the meteor /// Height of the meteor /// Depth of the meteor /// Speed at which the meteor moves /// The depth at which the meteor spawns at /// The depth at which the meteor dies at /// Reference to the current content manager used loading content public Meteor(float width, float height, float depth, float speed, float spawnDepth, float killDepth, ContentManager content) { mSpace3DSize = new Vector3(width, height, depth); mVel.Z = -1 * speed; mSpawnDepth = spawnDepth; mKillDepth = killDepth; mAngVel = (spawnDepth + 3) * Random.Sign(); float ArcPosition = MathHelper.TwoPi * Random.NextFloat(); Vector2 PositionFromOrigin = new Vector2((float)Math.Cos(ArcPosition), (float)Math.Sin(ArcPosition)); mPos.X = .8F * PositionFromOrigin.X; mPos.Y = .8F * PositionFromOrigin.Y; mPos.Z = spawnDepth; mSize.Z = width; // TODO: Make sure load content gets called where it should and not in constructor LoadContent(content); } #endregion #region Management /// /// Loads in any necessary information for all content dependent objects /// /// Reference to the current content manager for loading in content public override void LoadContent(ContentManager content) { if (mMeteorSprites == null || mMeteorSprites[0].CurrentSpriteSheet == null || mMeteorSprites[0].CurrentSpriteSheet.IsDisposed || mMeteorSprites[0].CurrentSpriteSheet.GraphicsDevice == null || mMeteorSprites[0].CurrentSpriteSheet.GraphicsDevice.IsDisposed) { mMeteorSprites = new Animation[4]; Texture2D spriteSheet = content.Load(@"MiniGames\Meteors"); for (int i = 0; i < mMeteorSprites.Length; i++) { mMeteorSprites[i] = new Animation(new Vector2(spriteSheet.Width >> 1, spriteSheet.Height >> 1)); mMeteorSprites[i].AddClip("Default", spriteSheet, 1, i, 1f); mMeteorSprites[i].Play("Default"); } } int p = Random.Next(3); switch (p) { case 0: mSprite = mMeteorSprites[0]; break; case 1: mSprite = mMeteorSprites[1]; break; case 2: mSprite = mMeteorSprites[2]; break; } base.LoadContent(content); } #endregion #region Update /// /// Updates the meteor /// /// Time passed in game public override void Update(GameTime gameTime) { base.Update(gameTime); // Kill the meteor if it has scrolled past the player if (mPos.Z < mKillDepth) { mAlive = false; } } #endregion } }