diff --git a/multiplayer-game/src/backend/Backend.cs b/multiplayer-game/src/backend/Backend.cs index 2156339..611159e 100644 --- a/multiplayer-game/src/backend/Backend.cs +++ b/multiplayer-game/src/backend/Backend.cs @@ -16,14 +16,14 @@ class Backend : IBackend while (pendingPackets.Count > 0) { var packet = pendingPackets.Dequeue(); - this.ProcessPacket(packet); + this.publisher.Publish(packet); } + this.sendGameState(); } public void ProcessPacket(ValueType packet) { - this.publisher.Publish(packet); - this.sendGameState(); + pendingPackets.Enqueue(packet); } public void Init() diff --git a/multiplayer-game/src/backend/Publisher.cs b/multiplayer-game/src/backend/Publisher.cs index 211439a..d878adb 100644 --- a/multiplayer-game/src/backend/Publisher.cs +++ b/multiplayer-game/src/backend/Publisher.cs @@ -30,7 +30,7 @@ class Publisher continue; } var attr = (Interaction)attrs2[0]; - if (attr.Kind != this.kind && attr.Kind != InteractorKind.Hybrid) + if (attr.Kind == InteractorKind.Server && this.kind == InteractorKind.Client) { continue; } @@ -67,8 +67,12 @@ class Publisher public void Publish(ValueType packet) { var type = PacketUtils.GetType(packet); + if (type != "tick") + Console.WriteLine("Publishing packet: " + type); if (subscribers.ContainsKey(type)) { + if (type != "tick") + Console.WriteLine("Found " + subscribers[type].Count + " subscribers"); foreach (var del in subscribers[type]) { del.DynamicInvoke(packet); diff --git a/multiplayer-game/src/backend/data/Packet.cs b/multiplayer-game/src/backend/data/Packet.cs index beeeb3a..3d30fc7 100644 --- a/multiplayer-game/src/backend/data/Packet.cs +++ b/multiplayer-game/src/backend/data/Packet.cs @@ -36,3 +36,14 @@ readonly struct TickPacket this.tick = tick; } } + +readonly struct SelfMovedPacket +{ + public readonly string type = "selfMoved"; + public readonly Vector2 target; + + public SelfMovedPacket(Vector2 target) + { + this.target = target; + } +} diff --git a/multiplayer-game/src/backend/interactor/Connect.cs b/multiplayer-game/src/backend/interactor/Connect.cs index 22b4208..4565e33 100644 --- a/multiplayer-game/src/backend/interactor/Connect.cs +++ b/multiplayer-game/src/backend/interactor/Connect.cs @@ -7,10 +7,10 @@ class Connect public static void ConnectServer(ConnectPacket packet) { var ctx = Context.Get(); - var player = ctx.GameState.PlayerPositions.Find(p => p.name == packet.playerName); + var player = ctx.GameState.Players.Find(p => p.name == packet.playerName); if (player == null) { - ctx.GameState.PlayerPositions.Add( + ctx.GameState.Players.Add( new Player { name = packet.playerName, diff --git a/multiplayer-game/src/backend/interactor/Move.cs b/multiplayer-game/src/backend/interactor/Move.cs index c6ce3ae..05b78d7 100644 --- a/multiplayer-game/src/backend/interactor/Move.cs +++ b/multiplayer-game/src/backend/interactor/Move.cs @@ -1,24 +1,41 @@ +using System.Numerics; + [Interactor] class Move { - [Interaction(InteractorKind.Hybrid, "move")] - public static void MoveHybrid(MovePacket packet) + [Interaction(InteractorKind.Client, "move")] + public static void MoveClient(MovePacket packet) { var ctx = Context.Get(); - var player = ctx.GameState.PlayerPositions.Find(p => p.name == packet.playerName); + var player = ctx.GameState.Players.Find(p => p.name == packet.playerName); if (player != null) { player.movement = packet.movement * 4; } } - [Interaction(InteractorKind.Hybrid, "tick")] - public static void TickHybrid(TickPacket packet) + [Interaction(InteractorKind.Client, "tick")] + public static void TickClient(TickPacket packet) { var ctx = Context.Get(); - ctx.GameState.PlayerPositions.ForEach(player => + foreach (var player in ctx.GameState.Players) { + if (player.movement == Vector2.Zero) + { + continue; + } player.position += player.movement; - }); + if (player.guid == ctx.FrontendGameState.PlayerGuid) + { + ctx.Backend.ProcessPacket(new SelfMovedPacket(player.position)); + } + } + } + + [Interaction(InteractorKind.Client, "selfMoved")] + public static void SelfMovedClient(SelfMovedPacket packet) + { + var ctx = Context.Get(); + ctx.FrontendGameState.Camera.CenterOn(packet.target); } } diff --git a/multiplayer-game/src/core/Camera.cs b/multiplayer-game/src/core/Camera.cs new file mode 100644 index 0000000..8351ae3 --- /dev/null +++ b/multiplayer-game/src/core/Camera.cs @@ -0,0 +1,21 @@ +using System.Numerics; + +class Camera +{ + public Vector2 position; + + public Camera() + { + position = Vector2.Zero; + } + + public void CenterOn(Vector2 target) + { + Console.WriteLine("Centering camera on " + target); + var ctx = Context.Get(); + var scale = ctx.GameState.Settings.GameScale; + var windowWidth = ctx.FrontendGameState.WindowWidth; + var windowHeight = ctx.FrontendGameState.WindowHeight; + position = target - (new Vector2(windowWidth / 2, windowHeight / 2)) / scale; + } +} diff --git a/multiplayer-game/src/core/tiles/Tile.cs b/multiplayer-game/src/core/tiles/Tile.cs index c17b0fc..1b1fec1 100644 --- a/multiplayer-game/src/core/tiles/Tile.cs +++ b/multiplayer-game/src/core/tiles/Tile.cs @@ -28,6 +28,13 @@ class Tile { var renderer = Context.Get().Renderer; var scale = Context.Get().GameState.Settings.GameScale; - renderer.DrawTexture(this.Texture, x * scale, y * scale, 16 * scale, 16 * scale); + var camera = Context.Get().FrontendGameState.Camera; + renderer.DrawTexture( + this.Texture, + (x - (int)camera.position.X) * scale, + (y - (int)camera.position.Y) * scale, + 16 * scale, + 16 * scale + ); } } diff --git a/multiplayer-game/src/engine/system/annotations/Interactor.cs b/multiplayer-game/src/engine/system/annotations/Interactor.cs index 0aec9f7..74a64f4 100644 --- a/multiplayer-game/src/engine/system/annotations/Interactor.cs +++ b/multiplayer-game/src/engine/system/annotations/Interactor.cs @@ -2,7 +2,6 @@ enum InteractorKind { Client, Server, - Hybrid } [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] diff --git a/multiplayer-game/src/frontend/Frontend.cs b/multiplayer-game/src/frontend/Frontend.cs index d61b1be..1d99fc9 100644 --- a/multiplayer-game/src/frontend/Frontend.cs +++ b/multiplayer-game/src/frontend/Frontend.cs @@ -8,12 +8,16 @@ class Frontend : IFrontend public void Init() { + var ctx = Context.Get(); this.playerName = Context.Get().IsHost ? "Host" : "Client"; var guid = Guid.NewGuid(); - Context.Get().FrontendGameState.PlayerGuid = guid; + ctx.FrontendGameState.PlayerGuid = guid; var connectPacket = new ConnectPacket(playerName, guid); - Context.Get().Backend.ProcessPacket(connectPacket); - Context.Get().TileRegistry.RegisterTile(); + ctx.Backend.ProcessPacket(connectPacket); + ctx.TileRegistry.RegisterTile(); + var windowSize = ctx.Window.GetSize(); + ctx.FrontendGameState.WindowWidth = windowSize.width; + ctx.FrontendGameState.WindowHeight = windowSize.height; } public void Process() @@ -32,6 +36,10 @@ class Frontend : IFrontend ctx.FrontendGameState.WindowWidth = e.window.data1; ctx.FrontendGameState.WindowHeight = e.window.data2; Console.WriteLine($"Window resized to {e.window.data1}x{e.window.data2}"); + var player = ctx.GameState.Players.Find( + p => p.guid == ctx.FrontendGameState.PlayerGuid + ); + ctx.FrontendGameState.Camera.CenterOn(player.position); } } if (e.type == SDL_EventType.SDL_KEYDOWN && e.key.repeat == 0) @@ -115,14 +123,21 @@ class Frontend : IFrontend } ctx.Renderer.Clear(); + var scale = ctx.GameState.Settings.GameScale; + var camera = Context.Get().FrontendGameState.Camera; new WorldRenderer().Render(); - ctx.GameState.PlayerPositions.ForEach(player => + ctx.GameState.Players.ForEach(player => { if (player.name == playerName) ctx.Renderer.SetColor(0, 0, 255, 255); else ctx.Renderer.SetColor(255, 0, 0, 255); - ctx.Renderer.DrawRect(player.position.X, player.position.Y, 10, 10); + ctx.Renderer.DrawRect( + (player.position.X - (int)camera.position.X) * scale, + (player.position.Y - (int)camera.position.Y) * scale, + 10, + 10 + ); }); ctx.Renderer.Present(); } diff --git a/multiplayer-game/src/state/GameState.cs b/multiplayer-game/src/state/GameState.cs index d2abb3b..f7eadfe 100644 --- a/multiplayer-game/src/state/GameState.cs +++ b/multiplayer-game/src/state/GameState.cs @@ -15,6 +15,7 @@ class FrontendGameState public int WindowWidth; public int WindowHeight; public Guid PlayerGuid; + public Camera Camera = new Camera(); } class Settings @@ -25,7 +26,7 @@ class Settings class GameState { - public List PlayerPositions { get; set; } = new List(); + public List Players { get; set; } = new List(); public World World { get; set; } public Settings Settings { get; set; } = new Settings(); }