using System.Numerics; using OnekoOnline.Net; using Raylib_cs; namespace OnekoOnline; abstract class Oneko : Drawable { public readonly Bitmap SpriteSheet; public Rectangle Sprite {get; protected set;} = Idle1; protected Color ColorTint = Color.WHITE; protected byte FrameId { get => (byte)Array.IndexOf(FrameArray, Sprite); set => Sprite = FrameArray[value]; } public string Name = "Oneko"; public Oneko() : base() { Size = new(32,32); Position = new(320/2, 240/2); string SpriteSheetPath = OnekoOnline.Config.GetValue("SpriteSheetPath", "nekos/oneko.png"); if (File.Exists(SpriteSheetPath) && new FileInfo(SpriteSheetPath).Length < 128*256*3) { SpriteSheet = Bitmap.FromPNGMemory(File.ReadAllBytes(SpriteSheetPath)); } else { Console.WriteLine("Path to spritesheet was invalid, using the default."); SpriteSheet = Bitmap.FromPNGMemory(EmbeddedResources.GetResource("nekos.oneko.png")); } } public Oneko(Bitmap spriteSheet) : base() { Size = new(32,32); Position = new(0, 0); SpriteSheet = spriteSheet; } public override void Draw() { //Nametag Vector2 NametagPosition = new(Position.X-(Name.Length*3)+4, Position.Y-28); Raylib.DrawTextEx(OnekoOnline.DefaultFont, Name, NametagPosition+Directions.Down, 11, 0, Color.BLACK); //Shadow Raylib.DrawTextEx(OnekoOnline.DefaultFont, Name, NametagPosition, 11, 0, Color.WHITE); //The neko Raylib.DrawTexturePro(SpriteSheet.Texture, Sprite, new Rectangle(Position.X, Position.Y, Size.X, Size.Y), Size/2, Rotation, ColorTint); } public override void Dispose() { SpriteSheet.Dispose(); base.Dispose(); } protected struct OnekoAnimation(Rectangle frame1, Rectangle frame2, byte animSpeed) { public byte AnimSpeed = animSpeed; Rectangle Frame1 = frame1; Rectangle Frame2 = frame2; public readonly Rectangle GetFrame(int frame) { return (frame % 2 == 0) ? Frame1 : Frame2; } } static protected OnekoAnimation GetDirectionalRun(Vector2 direction) { direction = Vector2.Normalize(direction); Vector2 nearestDir = Directions.Up; float nearestDistance = 10f; foreach (Vector2 dir in RunDirections.Keys) { float distanceCheck = Vector2.Distance(direction, dir); if (distanceCheck < nearestDistance) { nearestDir = dir; nearestDistance = distanceCheck; } } return RunDirections[nearestDir]; } static protected readonly Rectangle Idle1 = new(32*3, 32*3, 32, 32); static protected readonly Rectangle Alert1 = new(32*7, 32*3, 32, 32); static protected readonly Rectangle Yawn1 = new(32*3, 32*2, 32, 32); static protected readonly Rectangle Clean1 = new(32*7, 0, 32, 32); static protected readonly Rectangle Scratch1 = new(32*5, 0, 32, 32); static protected readonly Rectangle Scratch2 = new(32*6, 0, 32, 32); static protected readonly Rectangle Sleep1 = new(32*2, 0, 32, 32); static protected readonly Rectangle Sleep2 = new(32*2, 32, 32, 32); static protected readonly Rectangle RunUp1 = new(32, 32*3, 32, 32); static protected readonly Rectangle RunUp2 = new(32, 32*2, 32, 32); static protected readonly Rectangle RunUpLeft1 = new(32, 32, 32, 32); static protected readonly Rectangle RunUpLeft2 = new(32, 0, 32, 32); static protected readonly Rectangle RunLeft1 = new(32*4, 32*3, 32, 32); static protected readonly Rectangle RunLeft2 = new(32*4, 32*2, 32, 32); static protected readonly Rectangle RunDownLeft1 = new(32*6, 32, 32, 32); static protected readonly Rectangle RunDownLeft2 = new(32*5, 32*3, 32, 32); static protected readonly Rectangle RunDown1 = new(32*7, 32*2, 32, 32); static protected readonly Rectangle RunDown2 = new(32*6, 32*3, 32, 32); static protected readonly Rectangle RunDownRight1 = new(32*5, 32*2, 32, 32); static protected readonly Rectangle RunDownRight2 = new(32*5, 32, 32, 32); static protected readonly Rectangle RunRight1 = new(32*3, 32, 32, 32); static protected readonly Rectangle RunRight2 = new(32*3, 0, 32, 32); static protected readonly Rectangle RunUpRight1 = new(0, 32*3, 32, 32); static protected readonly Rectangle RunUpRight2 = new(0, 32*2, 32, 32); static protected readonly Rectangle ScratchUp1 = new(0, 0, 32, 32); static protected readonly Rectangle ScratchUp2 = new(0, 32, 32, 32); static protected readonly Rectangle ScratchLeft1 = new(32*4, 0, 32, 32); static protected readonly Rectangle ScratchLeft2 = new(32*4, 32, 32, 32); static protected readonly Rectangle ScratchDown1 = new(32*7, 32, 32, 32); static protected readonly Rectangle ScratchDown2 = new(32*6, 32*2, 32, 32); static protected readonly Rectangle ScratchRight1 = new(32*2, 32*2, 32, 32); static protected readonly Rectangle ScratchRight2 = new(32*2, 32*3, 32, 32); static protected readonly OnekoAnimation Idle = new(Idle1, Idle1, 1); static protected readonly OnekoAnimation Alert = new(Alert1, Alert1, 1); static protected readonly OnekoAnimation Yawn = new(Yawn1, Yawn1, 1); static protected readonly OnekoAnimation Clean = new(Clean1, Clean1, 1); static protected readonly OnekoAnimation ScratchSelf = new(Scratch1, Scratch2, 1); static protected readonly OnekoAnimation Sleep = new(Sleep1, Sleep2, 10); static protected readonly OnekoAnimation RunUp = new(RunUp1, RunUp2, 1); static protected readonly OnekoAnimation RunUpLeft = new(RunUpLeft1, RunUpLeft2, 1); static protected readonly OnekoAnimation RunLeft = new(RunLeft1, RunLeft2, 1); static protected readonly OnekoAnimation RunDownLeft = new(RunDownLeft1, RunDownLeft2, 1); static protected readonly OnekoAnimation RunDown = new(RunDown1, RunDown2, 1); static protected readonly OnekoAnimation RunDownRight = new(RunDownRight1, RunDownRight2, 1); static protected readonly OnekoAnimation RunRight = new(RunRight1, RunRight2, 1); static protected readonly OnekoAnimation RunUpRight = new(RunUpRight1, RunUpRight2, 1); static protected readonly OnekoAnimation ScratchUp = new(ScratchUp1, ScratchUp2, 1); static protected readonly OnekoAnimation ScratchLeft = new(ScratchLeft1, ScratchLeft2, 1); static protected readonly OnekoAnimation ScratchDown = new(ScratchDown1, ScratchDown2, 1); static protected readonly OnekoAnimation ScratchRight = new(ScratchRight1, ScratchRight2, 1); static readonly Dictionary RunDirections = new() { {Directions.Up, RunUp}, {Directions.Down, RunDown}, {Directions.Left, RunLeft}, {Directions.Right, RunRight}, {Directions.UpLeft, RunUpLeft}, {Directions.UpRight, RunUpRight}, {Directions.DownRight, RunDownRight}, {Directions.DownLeft, RunDownLeft}, }; static readonly Rectangle[] FrameArray = [ Idle1, Alert1, Yawn1, Clean1, Scratch1, Scratch2, Sleep1, Sleep2, RunUp1,RunUpLeft1, RunLeft1, RunDownLeft1, RunDown1, RunDownRight1, RunRight1, RunUpRight1, RunUp2,RunUpLeft2, RunLeft2, RunDownLeft2, RunDown2, RunDownRight2, RunRight2, RunUpRight2, ScratchUp1, ScratchLeft1, ScratchDown1, ScratchRight1, ScratchUp2, ScratchLeft2, ScratchDown2, ScratchRight2 ]; static readonly OnekoAnimation[] AnimationArray = [ Idle, Alert, Yawn, Clean, ScratchSelf, Sleep, RunUp,RunUpLeft, RunLeft, RunDownLeft, RunDown, RunDownRight, RunRight, RunUpRight, ScratchUp, ScratchLeft, ScratchDown, ScratchRight ]; }