From ced3d03bdb3ce866d832e03fb212865140905a9a Mon Sep 17 00:00:00 2001 From: Thomas Leyh Date: Sun, 24 Jul 2016 08:14:18 +0200 Subject: Add project files. --- V3/Objects/Sprite/AbstractSpriteCreature.cs | 201 ++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 V3/Objects/Sprite/AbstractSpriteCreature.cs (limited to 'V3/Objects/Sprite/AbstractSpriteCreature.cs') diff --git a/V3/Objects/Sprite/AbstractSpriteCreature.cs b/V3/Objects/Sprite/AbstractSpriteCreature.cs new file mode 100644 index 0000000..bde139e --- /dev/null +++ b/V3/Objects/Sprite/AbstractSpriteCreature.cs @@ -0,0 +1,201 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; + +namespace V3.Objects.Sprite +{ + public abstract class AbstractSpriteCreature : ISpriteCreature + { + // How many frames are there for each animation type? + protected virtual int IdleFrames { get; } = 4; + protected virtual int MovingFrames { get; } = 8; + protected virtual int AttackingFrames { get; } = 4; + protected virtual int DyingFrames { get; } = 6; + protected virtual int SpecialFrames { get; } = 4; + + /// The row of the specific textures in the texture file. + protected virtual int IdleTextureIndex { get; } = 0; + protected virtual int MovingTextureIndex { get; } = 4; + protected virtual int AttackingTextureIndex { get; } = 12; + protected virtual int DyingTextureIndex { get; } = 18; + protected virtual int SpecialTextureIndex { get; } = 24; + + + // Specify the size of a single animation frame in pixel. + private const int SpriteWidth = 128; + private const int SpriteHeight = 128; + private readonly Point mSpriteShift = new Point(-SpriteWidth / 2, -SpriteHeight * 3 / 4); + private readonly Point mSpriteSize = new Point(SpriteWidth, SpriteHeight); + + private double mTimeSinceUpdate; + private Texture2D mTexture; + // How much time until animation frame is changed (in milliseconds). + private const int UpdatesPerMSec = 125; // 8 FPS + private MovementState mLastMovementState = MovementState.Idle; + private MovementState mCurrentMovementState = MovementState.Idle; + private int mMaxAnimationSteps; + private int mMovementStateRow; + private bool mIdleBackwardsLoop; + private int mAnimationState; + + // Fields for PlayOnce method. + private bool mPriorityAnimation; + private UpdatesPerSecond mUpS; + + protected abstract string TextureFile { get; } + + /// + /// Loads the texture file and prepares animations. + /// + /// + public void Load(ContentManager contentManager) + { + mTexture = contentManager.Load("Sprites/" + TextureFile); + mMaxAnimationSteps = IdleFrames; + } + + /// + /// Draws the sprite on the screen. + /// + /// Sprite batch used for drawing. + /// Position on the screen where sprite is drawn to. + /// What moveset will be used? (Moving, Attacking...) + /// Where does the sprite face? + public void Draw(SpriteBatch spriteBatch, Vector2 position, MovementState movementState, MovementDirection movementDirection) + { + mCurrentMovementState = movementState; + Point sourceLocation = new Point((mMovementStateRow + mAnimationState) * SpriteWidth, + (int) movementDirection * SpriteHeight); + Rectangle sourceRectangle = new Rectangle(sourceLocation, mSpriteSize); + spriteBatch.Draw(mTexture, position + new Vector2(mSpriteShift.X, mSpriteShift.Y), sourceRectangle, Color.White); + } + + public void DrawStatic(SpriteBatch spriteBatch, Point position, MovementState movementState, MovementDirection movementDirection) + { + Point sourceLocation = new Point((int)movementState * SpriteWidth, (int)movementDirection * SpriteHeight); + Rectangle destinationRectangle = new Rectangle(position + mSpriteShift, mSpriteSize); + Rectangle sourceRectangle = new Rectangle(sourceLocation, mSpriteSize); + spriteBatch.Draw(mTexture, destinationRectangle, sourceRectangle, Color.White); + } + + /// + /// Change the sprite to show an animation. + /// + /// Elapsed game time is used for calculating FPS. + public void PlayAnimation(GameTime gameTime) + { + // Playing a single animation cycle just once with higher priority. + if (mPriorityAnimation) + { + if (mAnimationState < mMaxAnimationSteps - 1) + { + if (mUpS.IsItTime(gameTime)) + { + mAnimationState++; + } + return; + } + mAnimationState = 0; + mCurrentMovementState = mLastMovementState; + SelectFrames(mCurrentMovementState); + mPriorityAnimation = false; + return; + } + + // Change texture for showing animations according to elapsed game time. + mTimeSinceUpdate += gameTime.ElapsedGameTime.TotalMilliseconds; + if (mTimeSinceUpdate < UpdatesPerMSec) + { + return; + } + mTimeSinceUpdate = 0; + + // Check which specific animation sprites need to be used. + // Only check if movement state is changed. + if (mCurrentMovementState != mLastMovementState) + { + SelectFrames(mCurrentMovementState); + mAnimationState = 0; + mLastMovementState = mCurrentMovementState; + } + + // Idle animation is looped back and forth. + if (mIdleBackwardsLoop) + { + mAnimationState--; + if (mAnimationState <= 0) + { + mIdleBackwardsLoop = false; + } + return; + } + + if (mAnimationState < mMaxAnimationSteps - 1) + { + mAnimationState++; + } + else + { + if (mLastMovementState == MovementState.Idle) + { + mIdleBackwardsLoop = true; + mAnimationState--; + } + else if (mLastMovementState == MovementState.Dying) + { + } + else + { + mAnimationState = 0; + } + } + } + + private void SelectFrames(MovementState currentMovementState) + { + switch (currentMovementState) + { + case MovementState.Idle: + mMaxAnimationSteps = IdleFrames; + mMovementStateRow = IdleTextureIndex; + mIdleBackwardsLoop = false; + break; + case MovementState.Moving: + mMaxAnimationSteps = MovingFrames; + mMovementStateRow = MovingTextureIndex; + break; + case MovementState.Attacking: + mMaxAnimationSteps = AttackingFrames; + mMovementStateRow = AttackingTextureIndex; + break; + case MovementState.Dying: + mMaxAnimationSteps = DyingFrames; + mMovementStateRow = DyingTextureIndex; + break; + case MovementState.Special: + mMaxAnimationSteps = SpecialFrames; + mMovementStateRow = SpecialTextureIndex; + break; + default: + mMaxAnimationSteps = 1; // No Animation if default case is reached. + break; + } + } + + /// + /// Plays the specified animation fully, but only once. + /// + /// For which movement state the animation should be played. + /// How long (or how slow) should the animation be? + public void PlayOnce(MovementState animation, TimeSpan duration) + { + mLastMovementState = mCurrentMovementState; + mCurrentMovementState = animation; + mPriorityAnimation = true; + SelectFrames(animation); + mAnimationState = 0; + mUpS = new UpdatesPerSecond(1d / (duration.TotalSeconds / mMaxAnimationSteps)); + } + } +} \ No newline at end of file -- cgit v1.2.1