summaryrefslogtreecommitdiff
path: root/Oneko.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Oneko.cs')
-rw-r--r--Oneko.cs178
1 files changed, 178 insertions, 0 deletions
diff --git a/Oneko.cs b/Oneko.cs
new file mode 100644
index 0000000..274782c
--- /dev/null
+++ b/Oneko.cs
@@ -0,0 +1,178 @@
+using System.Numerics;
+using OnekoOnline.Net;
+using Raylib_cs;
+
+namespace OnekoOnline;
+
+class Oneko : Drawable
+{
+ public readonly Bitmap SpriteSheet;
+ Vector2 TargetPosition;
+ OnekoAnimation Animation = ScratchSelf;
+
+ float updateTimer = 0f;
+ const float updateRate = 1f/5f;
+ int Frame = 0;
+
+ public static Oneko? LocalOneko;
+
+ public static Dictionary<int, Oneko> NetNekos = [];
+
+ public Oneko()
+ {
+ Size = new(32,32);
+ Position = new(320/2, 240/2);
+
+ string SpriteSheetPath = OnekoOnline.Config.GetValue("SpriteSheetPath", "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("oneko.png"));
+ }
+
+ LocalOneko ??= this;
+
+ Drawables.Add(this);
+ }
+
+ public Oneko(Bitmap spriteSheet)
+ {
+ Size = new(32,32);
+ Position = new(0, 0);
+ SpriteSheet = spriteSheet;
+
+ Drawables.Add(this);
+ }
+
+ public override void Draw()
+ {
+ Raylib.DrawTexturePro(SpriteSheet.Texture, Animation.GetFrame(Frame), new Rectangle(Position.X, Position.Y, Size.X, Size.Y), Size/2, Rotation, Color.WHITE);
+ }
+
+ public override void Update(float delta)
+ {
+ if (this == LocalOneko) {
+ foreach (User user in Client.Users.Values) {
+ if (!NetNekos.ContainsKey(user.Id)) {
+ Bitmap spriteSheet = Bitmap.Deserialize(user.SpriteSheet);
+ NetNekos.Add(user.Id, new Oneko(spriteSheet));
+ }
+ }
+ }
+
+ updateTimer += delta;
+ if (updateTimer < updateRate) return;
+
+ if (Raylib.IsWindowFocused()) {
+ TargetPosition = Raylib.GetMousePosition()/2;
+ } else {
+ TargetPosition = new Vector2(320/2, 240/2);
+ }
+ Vector2 TargetDirection = (TargetPosition-Position).LimitLength(10f);
+ if (TargetDirection.Length() > 1) Animation = GetDirectionalRun(TargetDirection);
+ else Animation = Idle;
+ Position += TargetDirection;
+
+ Frame = (Frame + 1) % 2;
+
+ updateTimer = 0f;
+ }
+
+ public override void Dispose()
+ {
+ SpriteSheet.Dispose();
+ Drawables.Remove(this);
+ }
+
+ struct OnekoAnimation(Rectangle frame1, Rectangle frame2)
+ {
+ public Rectangle Frame1 = frame1;
+ Rectangle Frame2 = frame2;
+
+ public readonly Rectangle GetFrame(int frame) {
+ return (frame % 2 == 0) ? Frame1 : Frame2;
+ }
+ }
+
+ static OnekoAnimation GetDirectionalRun(Vector2 direction)
+ {
+ direction = Vector2.Normalize(direction);
+
+ Vector2 nearestDir = Directions.Up;
+ float nearestDistance = 10f;
+ foreach (Vector2 dir in Directions.AllDirections) {
+ float distanceCheck = Vector2.Distance(direction, dir);
+ if (distanceCheck < nearestDistance) {
+ nearestDir = dir;
+ nearestDistance = distanceCheck;
+ }
+ }
+
+ return RunDirections[nearestDir];
+ }
+
+ static readonly Rectangle Idle1 = new(32*3, 32*3, 32, 32);
+ static readonly Rectangle Alert1 = new(32*7, 32*3, 32, 32);
+ static readonly Rectangle Yawn1 = new(32*3, 32*2, 32, 32);
+ static readonly Rectangle Clean1 = new(32*7, 0, 32, 32);
+ static readonly Rectangle Scratch1 = new(32*5, 0, 32, 32);
+ static readonly Rectangle Scratch2 = new(32*6, 0, 32, 32);
+ static readonly Rectangle Sleep1 = new(32*2, 0, 32, 32);
+ static readonly Rectangle Sleep2 = new(32*2, 32, 32, 32);
+ static readonly Rectangle RunUp1 = new(32, 32*3, 32, 32);
+ static readonly Rectangle RunUp2 = new(32, 32*2, 32, 32);
+ static readonly Rectangle RunUpLeft1 = new(32, 32, 32, 32);
+ static readonly Rectangle RunUpLeft2 = new(32, 0, 32, 32);
+ static readonly Rectangle RunLeft1 = new(32*4, 32*3, 32, 32);
+ static readonly Rectangle RunLeft2 = new(32*4, 32*2, 32, 32);
+ static readonly Rectangle RunDownLeft1 = new(32*6, 32, 32, 32);
+ static readonly Rectangle RunDownLeft2 = new(32*5, 32*3, 32, 32);
+ static readonly Rectangle RunDown1 = new(32*7, 32*2, 32, 32);
+ static readonly Rectangle RunDown2 = new(32*6, 32*3, 32, 32);
+ static readonly Rectangle RunDownRight1 = new(32*5, 32*2, 32, 32);
+ static readonly Rectangle RunDownRight2 = new(32*5, 32, 32, 32);
+ static readonly Rectangle RunRight1 = new(32*3, 32, 32, 32);
+ static readonly Rectangle RunRight2 = new(32*3, 0, 32, 32);
+ static readonly Rectangle RunUpRight1 = new(0, 32*3, 32, 32);
+ static readonly Rectangle RunUpRight2 = new(0, 32*2, 32, 32);
+ static readonly Rectangle ScratchUp1 = new(0, 0, 32, 32);
+ static readonly Rectangle ScratchUp2 = new(0, 32, 32, 32);
+ static readonly Rectangle ScratchLeft1 = new(32*4, 0, 32, 32);
+ static readonly Rectangle ScratchLeft2 = new(32*4, 32, 32, 32);
+ static readonly Rectangle ScratchDown1 = new(32*7, 32, 32, 32);
+ static readonly Rectangle ScratchDown2 = new(32*6, 32*2, 32, 32);
+ static readonly Rectangle ScratchRight1 = new(32*2, 32*2, 32, 32);
+ static readonly Rectangle ScratchRight2 = new(32*2, 32*3, 32, 32);
+
+ static readonly OnekoAnimation Idle = new(Idle1, Idle1);
+ static readonly OnekoAnimation Alert = new(Alert1, Alert1);
+ static readonly OnekoAnimation Yawn = new(Yawn1, Yawn1);
+ static readonly OnekoAnimation Clean = new(Clean1, Clean1);
+ static readonly OnekoAnimation ScratchSelf = new(Scratch1, Scratch2);
+ static readonly OnekoAnimation Sleep = new(Sleep1, Sleep2);
+ static readonly OnekoAnimation RunUp = new(RunUp1, RunUp2);
+ static readonly OnekoAnimation RunUpLeft = new(RunUpLeft1, RunUpLeft2);
+ static readonly OnekoAnimation RunLeft = new(RunLeft1, RunLeft2);
+ static readonly OnekoAnimation RunDownLeft = new(RunDownLeft1, RunDownLeft2);
+ static readonly OnekoAnimation RunDown = new(RunDown1, RunDown2);
+ static readonly OnekoAnimation RunDownRight = new(RunDownRight1, RunDownRight2);
+ static readonly OnekoAnimation RunRight = new(RunRight1, RunRight2);
+ static readonly OnekoAnimation RunUpRight = new(RunUpRight1, RunUpRight2);
+ static readonly OnekoAnimation ScratchUp = new(ScratchUp1, ScratchUp2);
+ static readonly OnekoAnimation ScratchLeft = new(ScratchLeft1, ScratchLeft2);
+ static readonly OnekoAnimation ScratchDown = new(ScratchDown1, ScratchDown2);
+ static readonly OnekoAnimation ScratchRight = new(ScratchRight1, ScratchRight2);
+
+ static readonly Dictionary<Vector2, OnekoAnimation> 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},
+ };
+} \ No newline at end of file