experiments-monogame/UPWG/UPWG.Main/Animation.cs

160 lines
5.1 KiB
C#
Raw Permalink Normal View History

2024-09-06 23:47:51 +00:00
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);
}
}
}