using System; using System.IO; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Elite; namespace UPWG.Main { internal enum MovementType { Run, Jump, Flip, } internal enum RingPosition { // these use cardinal directions (picture a compass rose laid over the ring) // they will be flipped when animations are reversed SouthWest, West, NorthWest, North, NorthEast, East, SouthEast, South, Center, } abstract class BattleAnimation { protected double ElapsedSeconds; protected readonly double RunSeconds; protected BattleAnimation(double runSeconds) { ElapsedSeconds = 0; RunSeconds = runSeconds; } public bool Done() { return ElapsedSeconds > RunSeconds; } public abstract void Update(double elapsed, ref Vector2 pos, ref float rotation); } class Run : BattleAnimation { private Vector2 _start; private Vector2 _end; public Run(double runSeconds, RingPosition from, RingPosition to) : base(runSeconds) { _start = RingPositionToVector2(from); _end = RingPositionToVector2(to); } public override void Update(double elapsed, ref Vector2 pos, ref float rotation) { ElapsedSeconds += elapsed; pos = Vector2.Lerp(_start, _end, (float) (ElapsedSeconds / RunSeconds)); } private const float EastRopesX = 200; private const float WestRopesX = 500; private const float CenterX = (EastRopesX + WestRopesX) / 2; private const float NorthRopesY = 100; private const float SouthRopesY = 300; private const float CenterY = (NorthRopesY + SouthRopesY) / 2; public static Vector2 RingPositionToVector2(RingPosition position) { return position switch { RingPosition.North => new Vector2(CenterX, NorthRopesY), RingPosition.NorthEast => new Vector2(EastRopesX, NorthRopesY), RingPosition.East => new Vector2(EastRopesX, CenterY), RingPosition.SouthEast => new Vector2(EastRopesX, SouthRopesY), RingPosition.South => new Vector2(CenterX, SouthRopesY), RingPosition.SouthWest => new Vector2(WestRopesX, SouthRopesY), RingPosition.West => new Vector2(WestRopesX, CenterY), RingPosition.NorthWest => new Vector2(WestRopesX, NorthRopesY), RingPosition.Center => new Vector2(CenterX, CenterY), _ => throw new ArgumentOutOfRangeException(nameof(position)) }; } } class Spin : BattleAnimation { private float _angleFrom; private float _angleTo; public Spin(double runSeconds, float angleFrom, float angleTo) : base(runSeconds) { _angleFrom = angleFrom; _angleTo = angleTo; } public override void Update(double elapsed, ref Vector2 pos, ref float rotation) { ElapsedSeconds += elapsed; rotation = MathHelper.Lerp(_angleFrom, _angleTo, (float) (ElapsedSeconds / RunSeconds)); } } public class BattleSprite : IBatchDrawable { private const int Width = 128; private const int Height = 128; private Texture2D _texture; private Vector2 _origin; private Vector2 _pos; private float _rotation; private BattleAnimation[] _animations; private int _animationNum; public BattleSprite(GraphicsDevice graphicsDevice, string filename) { var fileStream = new FileStream("Content/jason.jpg", FileMode.Open); _texture = Texture2D.FromStream(graphicsDevice, fileStream); fileStream.Dispose(); _pos = new Vector2(100, 200); _origin = new Vector2(_texture.Width / 2, _texture.Height / 2); _animations = new BattleAnimation[] { new Run(1, RingPosition.West, RingPosition.East), new Run(1, RingPosition.East, RingPosition.West), //new Run(1, RingPosition.West, RingPosition.East), //new Run(1, RingPosition.East, RingPosition.Center), //new Run(0.2, RingPosition.Center, RingPosition.Center), new Spin(4, 0, 3.14f), }; _animationNum = 0; } public void Update(double elapsedSeconds) { if (_animationNum < _animations.Length) { _animations[_animationNum].Update(elapsedSeconds, ref _pos, ref _rotation); if (_animations[_animationNum].Done()) _animationNum += 1; } } public void Draw(SpriteBatch batch) { batch.Draw(_texture, new Rectangle((int) _pos.X, (int) _pos.Y, Width, Height), null, Color.White, _rotation, _origin, SpriteEffects.None, 0); } } }