(Disclaimer: I wouldn't normally have this many comments cluttering my code.)
using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace Blog.Drawing.Actors { /// <summary> /// An image of a hero. /// He can run, jump and fall. /// </summary> public class Hero : DrawableGameComponent { private const int NumberOfFrames = 5; private Texture2D Image; private Vector2 Position = new Vector2(0f, 200f); private Rectangle CurrentFrame; private SpriteBatch SpriteBatch; private List<Rectangle> Frames = new List<Rectangle>(); private float VelocityX = 10; private float VelocityY = 0; private Game CurrentGame; private Random Random = new Random(); public Hero(Game game): base(game) { CurrentGame = game; } /// <summary> /// Initializes the component. /// Override this method to load any non-graphics resources /// and query for any required services. /// </summary> public override void Initialize() { // Add frames. // Assumes the image file shows five heros stood side by side. // It uses rectangles to show where to crop the image. const int width = 75; const int height = 111; for (int ii = 0; ii < NumberOfFrames; ii++) { Rectangle frame = new Rectangle() { X = width * ii, Y = 0, Width = width, Height = height }; Frames.Add(frame); } CurrentFrame = Frames[0]; base.Initialize(); } /// <summary> /// Called when graphics resources need to be loaded. /// Override this method to load any component-specific /// graphics resources. /// </summary> protected override void LoadContent() { // Load the image of the hero Image = CurrentGame.Content.Load<Texture2D>("hero"); // Get the current spritebatch. // This will be used later to draw the images. SpriteBatch = (SpriteBatch)CurrentGame.Services.GetService( typeof(SpriteBatch)); base.LoadContent(); } /// <summary> /// Keeps track of if it is time to update the Hero yet. /// </summary> private ElapsedTime UpdateElapsedTime = new ElapsedTime(100); /// <summary> /// Called when the GameComponent needs to be updated. /// Override this method with component-specific update code. /// </summary> public override void Update(GameTime gameTime) { // If enough time has passed then we are ready to update the hero. if (UpdateElapsedTime.Ready(gameTime)) { // Apply the force of gravity VelocityY += 100f; // Stop him from falling off the bottom of the screen if (Position.Y > 400f && VelocityY > 0f) { VelocityY = 0f; } // Made him jump every now and then: if (this.Random.Next(30) == 0) { VelocityY -= 100f; } // Update his position based on his speed Position = new Vector2( Position.X + VelocityX, Position.Y + VelocityY ); // Display one of the hero images at random // This will make it look as if he is running CurrentFrame = Frames[this.Random.Next(NumberOfFrames)]; } base.Update(gameTime); } /// <summary> /// Called when the DrawableGameComponent needs to be drawn. /// Override this method with component-specific drawing code. /// Reference page contains links to related conceptual articles. /// </summary> public override void Draw(GameTime gameTime) { //Draw the hero SpriteBatch.Draw(Image, Position, CurrentFrame, Color.White); base.Draw(gameTime); } } /// <summary> /// Keeps track of the passing of time. /// </summary> public class ElapsedTime { private TimeSpan Total; private readonly TimeSpan RefreshInterval; /// <summary> /// Keeps track of the passing of time. /// </summary> /// <param name="milliseconds"> /// The ammount of it should wait for before declaring itself ready. /// </param> public ElapsedTime(int milliseconds) { RefreshInterval = TimeSpan.FromMilliseconds(milliseconds); } /// <summary> /// Updates the internal timer and shows if sufficient time has passed. /// </summary> public bool Ready(GameTime gameTime) { Total += gameTime.ElapsedGameTime; if (Total > RefreshInterval) { Total -= RefreshInterval; return true; } else { return false; } } } }
0 comments:
Post a Comment