#region File Description
//-----------------------------------------------------------------------------
// SmokePuff.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 HoneycombRush
{
///
/// Represents a puff of smoke fired from the beekeeper's smoke gun.
///
/// Smoke puffs add and remove themselves from the list of game components as appropriate.
public class SmokePuff : TexturedDrawableGameComponent
{
#region Fields/Properties
readonly TimeSpan growthTimeInterval = TimeSpan.FromMilliseconds(50);
const float growthStep = 0.05f;
TimeSpan lifeTime;
TimeSpan growthTimeTrack;
///
/// Used to scale the smoke puff
///
float spreadFactor;
Vector2 initialVelocity;
Vector2 velocity;
Vector2 acceleration;
Vector2 drawOrigin;
Random random = new Random();
public bool IsGone
{
get
{
return lifeTime <= TimeSpan.Zero;
}
}
bool isInGameComponents;
///
/// Represents an area used for collision calculations.
///
public override Rectangle CentralCollisionArea
{
get
{
int boundsWidth = (int)(texture.Width * spreadFactor * 1.5f * scaledSpriteBatch.ScaleVector.X);
int boundsHeight = (int)(texture.Height * spreadFactor * 1.5f * scaledSpriteBatch.ScaleVector.Y);
return new Rectangle((int)position.X - boundsWidth / 4, (int)position.Y - boundsHeight / 4,
boundsWidth, boundsHeight);
}
}
#endregion
#region Initialization
///
/// Creates a new puff of smoke.
///
/// Associated game object.
/// The gameplay screen where the smoke puff will be displayed.
/// The texture which represents the smoke puff.
public SmokePuff(Game game, GameplayScreen gameplayScreen, Texture2D texture)
: base(game, gameplayScreen)
{
this.texture = texture;
drawOrigin = new Vector2(texture.Width / 2, texture.Height / 2);
DrawOrder = Int32.MaxValue - 15;
}
///
/// Fires the smoke puff from a specified position and at a specified velocity. This also adds the smoke puff
/// to the game component collection.
///
/// The position where the smoke puff should first appear.
/// A vector indicating the initial velocity for this new smoke puff.
/// The smoke puff's acceleration is internaly derived from
/// .
/// This method is not thread safe and calling it from another thread while the smoke puff expires (via
/// its method) might have undesired effects.
public void Fire(Vector2 origin, Vector2 initialVelocity)
{
spreadFactor = 0.05f;
lifeTime = TimeSpan.FromSeconds(5);
growthTimeTrack = TimeSpan.Zero;
position = origin;
velocity = initialVelocity;
this.initialVelocity = initialVelocity;
initialVelocity.Normalize();
acceleration = -(initialVelocity) * 6;
if (!isInGameComponents)
{
Game.Components.Add(this);
isInGameComponents = true;
}
}
#endregion
#region Update
///
/// Performs update logic for the smoke puff. The smoke puff slows down while growing and eventually
/// evaporates.
///
/// Game time information.
public override void Update(GameTime gameTime)
{
if (!gamePlayScreen.IsActive)
{
base.Update(gameTime);
return;
}
lifeTime -= gameTime.ElapsedGameTime;
// The smoke puff needs to vanish
if (lifeTime <= TimeSpan.Zero)
{
Game.Components.Remove(this);
isInGameComponents = false;
base.Update(gameTime);
return;
}
growthTimeTrack += gameTime.ElapsedGameTime;
// See if it is time for the smoke puff to grow
if ((spreadFactor < 1) && (growthTimeTrack >= growthTimeInterval))
{
growthTimeTrack = TimeSpan.Zero;
spreadFactor += growthStep;
}
// Stop the smoke once it starts moving in the other direction
if (Vector2.Dot(initialVelocity, velocity) > 0)
{
position += velocity;
velocity += acceleration * (float)gameTime.ElapsedGameTime.TotalSeconds;
}
base.Update(gameTime);
}
#endregion
#region Render
///
/// Draws the smoke puff.
///
/// Game time information.
public override void Draw(GameTime gameTime)
{
if (!gamePlayScreen.IsActive)
{
base.Draw(gameTime);
return;
}
scaledSpriteBatch.Begin();
Vector2 offset = GetRandomOffset();
scaledSpriteBatch.Draw(texture, position + offset, null, Color.White, 0, drawOrigin, spreadFactor,
SpriteEffects.None, 0);
scaledSpriteBatch.End();
base.Draw(gameTime);
}
///
/// Used to make the smoke puff shift randomly.
///
/// An offset which should be added to the smoke puff's position.
private Vector2 GetRandomOffset()
{
return new Vector2(random.Next(2) - 4, random.Next(2) - 4);
}
#endregion
}
}