summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah B <git@sarahduck.ca>2023-12-24 21:04:19 -0800
committerSarah B <git@sarahduck.ca>2023-12-24 21:04:19 -0800
commit0206e04e0a3542b8f0fc97996f1d885f7604a6fa (patch)
tree575f1388978b110064993445b73dcf268218a750
parentc4dd5d6fe58a21f9cab5ce271cd3554c2fe791e3 (diff)
network mouse click, restructure oneko, add framework for NPCState stuff
-rw-r--r--MathExtensions.cs2
-rw-r--r--Mouse.cs2
-rw-r--r--MouseLocal.cs6
-rw-r--r--MouseNet.cs4
-rw-r--r--Net.cs16
-rw-r--r--NetServer.cs2
-rw-r--r--Oneko.cs171
-rw-r--r--OnekoLocal.cs55
-rw-r--r--OnekoNet.cs15
9 files changed, 158 insertions, 115 deletions
diff --git a/MathExtensions.cs b/MathExtensions.cs
index 81db592..2e74442 100644
--- a/MathExtensions.cs
+++ b/MathExtensions.cs
@@ -28,6 +28,4 @@ public static class Directions
public static readonly Vector2 UpRight = Vector2.Normalize(Up+Right);
public static readonly Vector2 DownLeft = Vector2.Normalize(Down+Left);
public static readonly Vector2 DownRight = Vector2.Normalize(Down+Right);
-
- public static readonly Vector2[] AllDirections = [Up,Down,Left,Right,UpLeft,UpRight,DownLeft,DownRight];
} \ No newline at end of file
diff --git a/Mouse.cs b/Mouse.cs
index d316ea2..71b79ca 100644
--- a/Mouse.cs
+++ b/Mouse.cs
@@ -13,6 +13,8 @@ abstract class Mouse : Drawable
protected static List<Mouse> allMice = [];
public static ReadOnlyCollection<Mouse> AllMice => allMice.AsReadOnly();
+ public static Action<Mouse>? Clicked;
+
public Mouse() : base()
{
DrawOrder = 100;
diff --git a/MouseLocal.cs b/MouseLocal.cs
index 6a84731..0b38cd5 100644
--- a/MouseLocal.cs
+++ b/MouseLocal.cs
@@ -19,10 +19,14 @@ class MouseLocal : Mouse
Visible = Raylib.IsCursorOnScreen() && Raylib.IsWindowFocused();
Position = Raylib.GetMousePosition()/OnekoOnline.WindowScale;
+ bool clicked = Raylib.IsMouseButtonPressed(MouseButton.MOUSE_BUTTON_LEFT);
+ if (clicked && Visible) Clicked?.Invoke(this);
+
if (Visible && OnekoOnline.Client!.Connected) {
NetDataWriter writer = new();
- writer.Put(new PacketInfo(PacketType.MousePosition, OnekoOnline.Client.Id));
+ writer.Put(new PacketInfo(PacketType.MouseState, OnekoOnline.Client.Id));
writer.Put(Position);
+ writer.Put(clicked);
OnekoOnline.Client?.ConnectedServer.Send(writer, LiteNetLib.DeliveryMethod.Unreliable);
}
}
diff --git a/MouseNet.cs b/MouseNet.cs
index 9521a25..1588dd0 100644
--- a/MouseNet.cs
+++ b/MouseNet.cs
@@ -18,9 +18,11 @@ class MouseNet : Mouse
};
Client.PacketRecived += (reader, user, packetType) => {
- if (user != MyUser || packetType != PacketType.MousePosition) return;
+ if (user != MyUser || packetType != PacketType.MouseState) return;
Position = reader.GetVector2();
+ bool clicked = reader.GetBool();
+ if (clicked) Clicked?.Invoke(this);
InvisibleTimer = 0f;
};
diff --git a/Net.cs b/Net.cs
index 3fa5f8a..4bf984e 100644
--- a/Net.cs
+++ b/Net.cs
@@ -50,29 +50,23 @@ public static class NetExtensions
public enum PacketType : byte
{
- MousePosition,
- OnekoTargetPosition,
+ MouseState,
+ OnekoState,
UserInfo,
UserId,
Disconnect,
Invalid
}
-public struct PacketInfo
+public struct PacketInfo(PacketType type, int id)
{
- public readonly PacketType Type;
- public readonly int FromId;
+ public readonly PacketType Type = type;
+ public readonly int FromId = id;
public const int SizeOf = sizeof(int) + 1;
public readonly bool IsValid => Type != PacketType.Invalid;
public static readonly PacketInfo InvalidPacket = new(PacketType.Invalid, -1);
- public PacketInfo(PacketType type, int id)
- {
- Type = type;
- FromId = id;
- }
-
public readonly void Serialize(Span<byte> span)
{
span[0] = (byte)Type;
diff --git a/NetServer.cs b/NetServer.cs
index 5ff35f1..a8e3130 100644
--- a/NetServer.cs
+++ b/NetServer.cs
@@ -83,7 +83,7 @@ class Server
}
}
- if (info.Type == PacketType.OnekoTargetPosition || info.Type == PacketType.MousePosition) {
+ if (info.Type == PacketType.OnekoState || info.Type == PacketType.MouseState) {
writer.ResetWithInfo(new PacketInfo(info.Type, fromPeer.Id));
writer.Put(dataReader.GetRemainingBytes());
foreach (ServerUser toSend in users.Values) {
diff --git a/Oneko.cs b/Oneko.cs
index 5b28ca4..dfb00fb 100644
--- a/Oneko.cs
+++ b/Oneko.cs
@@ -4,19 +4,16 @@ using Raylib_cs;
namespace OnekoOnline;
-class Oneko : Drawable
+abstract class Oneko : Drawable
{
public readonly Bitmap SpriteSheet;
- OnekoAnimation Animation = ScratchSelf;
+ public Rectangle Sprite {get; protected set;} = Idle1;
+ protected Color ColorTint = Color.WHITE;
- public Vector2 TargetPosition;
-
- float updateTimer = 0f;
- const float updateRate = 1f/5f;
- int Frame = 0;
- int FrameCounter = 0;
-
- float InactivityTimer = 0f;
+ protected byte FrameId {
+ get => (byte)Array.IndexOf(FrameArray, Sprite);
+ set => Sprite = FrameArray[value];
+ }
public string Name = "Oneko";
@@ -50,36 +47,7 @@ class Oneko : Drawable
Raylib.DrawTextEx(OnekoOnline.DefaultFont, Name, NametagPosition, 11, 0, Color.WHITE);
//The neko
- 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)
- {
- InactivityTimer += delta;
- updateTimer += delta;
- if (updateTimer < updateRate) return;
-
- OnekoUpdate();
-
- updateTimer = 0f;
- }
-
- public virtual void OnekoUpdate()
- {
- Vector2 TargetDirection = (TargetPosition-Position).LimitLength(10f);
- if (TargetDirection.Length() > 1) {
- Animation = GetDirectionalRun(TargetDirection);
- InactivityTimer = 0f;
- }
- else Animation = Idle;
- Position += TargetDirection;
-
- if (InactivityTimer > 3f) Animation = ScratchSelf;
- if (InactivityTimer > 5f) Animation = Yawn;
- if (InactivityTimer > 6f) Animation = Sleep;
-
- FrameCounter = (FrameCounter+1)%(Animation.AnimSpeed+1);
- Frame = (int)MathF.Round((float)FrameCounter/(float)Animation.AnimSpeed);
+ Raylib.DrawTexturePro(SpriteSheet.Texture, Sprite, new Rectangle(Position.X, Position.Y, Size.X, Size.Y), Size/2, Rotation, ColorTint);
}
public override void Dispose()
@@ -88,7 +56,7 @@ class Oneko : Drawable
base.Dispose();
}
- struct OnekoAnimation(Rectangle frame1, Rectangle frame2, byte animSpeed)
+ protected struct OnekoAnimation(Rectangle frame1, Rectangle frame2, byte animSpeed)
{
public byte AnimSpeed = animSpeed;
Rectangle Frame1 = frame1;
@@ -99,13 +67,13 @@ class Oneko : Drawable
}
}
- static OnekoAnimation GetDirectionalRun(Vector2 direction)
+ static protected OnekoAnimation GetDirectionalRun(Vector2 direction)
{
direction = Vector2.Normalize(direction);
Vector2 nearestDir = Directions.Up;
float nearestDistance = 10f;
- foreach (Vector2 dir in Directions.AllDirections) {
+ foreach (Vector2 dir in RunDirections.Keys) {
float distanceCheck = Vector2.Distance(direction, dir);
if (distanceCheck < nearestDistance) {
nearestDir = dir;
@@ -116,57 +84,57 @@ class Oneko : Drawable
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, 1);
- static readonly OnekoAnimation Alert = new(Alert1, Alert1, 1);
- static readonly OnekoAnimation Yawn = new(Yawn1, Yawn1, 1);
- static readonly OnekoAnimation Clean = new(Clean1, Clean1, 1);
- static readonly OnekoAnimation ScratchSelf = new(Scratch1, Scratch2, 1);
- static readonly OnekoAnimation Sleep = new(Sleep1, Sleep2, 10);
- static readonly OnekoAnimation RunUp = new(RunUp1, RunUp2, 1);
- static readonly OnekoAnimation RunUpLeft = new(RunUpLeft1, RunUpLeft2, 1);
- static readonly OnekoAnimation RunLeft = new(RunLeft1, RunLeft2, 1);
- static readonly OnekoAnimation RunDownLeft = new(RunDownLeft1, RunDownLeft2, 1);
- static readonly OnekoAnimation RunDown = new(RunDown1, RunDown2, 1);
- static readonly OnekoAnimation RunDownRight = new(RunDownRight1, RunDownRight2, 1);
- static readonly OnekoAnimation RunRight = new(RunRight1, RunRight2, 1);
- static readonly OnekoAnimation RunUpRight = new(RunUpRight1, RunUpRight2, 1);
- static readonly OnekoAnimation ScratchUp = new(ScratchUp1, ScratchUp2, 1);
- static readonly OnekoAnimation ScratchLeft = new(ScratchLeft1, ScratchLeft2, 1);
- static readonly OnekoAnimation ScratchDown = new(ScratchDown1, ScratchDown2, 1);
- static readonly OnekoAnimation ScratchRight = new(ScratchRight1, ScratchRight2, 1);
+ 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<Vector2, OnekoAnimation> RunDirections = new() {
{Directions.Up, RunUp},
@@ -178,4 +146,19 @@ class Oneko : Drawable
{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
+ ];
} \ No newline at end of file
diff --git a/OnekoLocal.cs b/OnekoLocal.cs
index 00eaf82..c33dd66 100644
--- a/OnekoLocal.cs
+++ b/OnekoLocal.cs
@@ -11,6 +11,17 @@ class OnekoLocal : Oneko
static int Id => OnekoOnline.Client?.Id ?? -1;
+ OnekoAIState? CurrentAIState;
+
+ Vector2 TargetPosition = Vector2.Zero;
+ float InactivityTimer = 0f;
+
+ OnekoAnimation Animation;
+ float updateTimer = 0f;
+ const float updateRate = 1f/5f;
+ int Frame = 0;
+ int FrameCounter = 0;
+
public OnekoLocal() : base()
{
Instance ??= this;
@@ -20,19 +31,55 @@ class OnekoLocal : Oneko
Name = Client.UserName;
}
- public override void OnekoUpdate()
+ public override void Update(float delta)
+ {
+ updateTimer += delta;
+ if (updateTimer < updateRate) return;
+
+ OnekoUpdate(updateTimer);
+ updateTimer = 0f;
+ }
+
+ public void OnekoUpdate(float delta)
{
+ InactivityTimer += delta;
+
Mouse? NearestMouse = Mouse.AllMice.Where(m => m.Visible).MinBy(m => Vector2.Distance(m.Position, Position));
if (NearestMouse != null) TargetPosition = NearestMouse.Position;
else TargetPosition = new Vector2(Math.Clamp((Id+1)*40, 20, 300), 240/2);
+ Vector2 TargetDirection = (TargetPosition-Position).LimitLength(10f);
+ if (TargetDirection.Length() > 1) {
+ Animation = GetDirectionalRun(TargetDirection);
+ InactivityTimer = 0f;
+ }
+ else Animation = Idle;
+ Position += TargetDirection;
+
+ if (InactivityTimer > 3f) Animation = ScratchSelf;
+ if (InactivityTimer > 5f) Animation = Yawn;
+ if (InactivityTimer > 6f) Animation = Sleep;
+
+ FrameCounter = (FrameCounter+1)%(Animation.AnimSpeed+1);
+ Frame = (int)MathF.Round(FrameCounter/(float)Animation.AnimSpeed);
+
+ Sprite = Animation.GetFrame(Frame);
+
if (OnekoOnline.Client!.Connected) {
NetDataWriter writer = new();
- writer.Put(new PacketInfo(PacketType.OnekoTargetPosition, Id));
- writer.Put(TargetPosition);
+ writer.Put(new PacketInfo(PacketType.OnekoState, Id));
+ writer.Put(Position);
+ writer.Put(FrameId);
OnekoOnline.Client?.ConnectedServer.Send(writer, LiteNetLib.DeliveryMethod.Unreliable);
}
+ }
+
+ protected abstract class OnekoAIState(OnekoLocal neko)
+ {
+ protected OnekoLocal Neko = neko;
- base.OnekoUpdate();
+ public abstract int GetPriority();
+ public abstract void Update(float delta);
+ protected bool IsCurrentState => Neko.CurrentAIState == this;
}
} \ No newline at end of file
diff --git a/OnekoNet.cs b/OnekoNet.cs
index 27d6187..a5b2008 100644
--- a/OnekoNet.cs
+++ b/OnekoNet.cs
@@ -10,6 +10,8 @@ class OnekoNet : Oneko
public static Dictionary<int, OnekoNet> NetNekos = [];
+ float NetworkIssueTimer = 0f;
+
public OnekoNet(Bitmap bitmap, User user) : base(bitmap)
{
MyUser = user;
@@ -22,12 +24,23 @@ class OnekoNet : Oneko
Client.PacketRecived += (reader, user, packetType) => {
if (user != MyUser) return;
- if (packetType == PacketType.OnekoTargetPosition) TargetPosition = reader.GetVector2();
+ if (packetType == PacketType.OnekoState) {
+ Position = reader.GetVector2();
+ FrameId = reader.GetByte();
+ NetworkIssueTimer = 0f;
+ }
};
Client.ServerDisconnected += Dispose;
}
+ public override void Update(float delta)
+ {
+ NetworkIssueTimer += delta;
+ if (NetworkIssueTimer < 0.6f) ColorTint = Color.WHITE;
+ else ColorTint = Color.WHITE with {A = 120};
+ }
+
public static void SpawnNetNeko(User user)
{
if (!NetNekos.ContainsKey(user.Id)) {