From 9ccb7c8df845ed8c86006c25942809201b1d86df Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Mon, 29 Apr 2024 16:39:37 +0200 Subject: [PATCH] add magazine system (cannot reload currently) --- tank-frontend/src/PlayerInfo.tsx | 4 +- .../TanksServer/GameLogic/CollectPowerUp.cs | 6 ++- .../TanksServer/GameLogic/ShootFromTanks.cs | 11 +++-- .../Interactivity/PlayerInfoConnection.cs | 23 ++-------- tanks-backend/TanksServer/Models/Magazine.cs | 44 +++++++++++++++++++ .../TanksServer/Models/PlayerControls.cs | 22 +++++++++- .../TanksServer/Models/PlayerInfo.cs | 6 +-- tanks-backend/TanksServer/Models/Tank.cs | 2 +- 8 files changed, 86 insertions(+), 32 deletions(-) create mode 100644 tanks-backend/TanksServer/Models/Magazine.cs diff --git a/tank-frontend/src/PlayerInfo.tsx b/tank-frontend/src/PlayerInfo.tsx index e6f9b16..8a3cfad 100644 --- a/tank-frontend/src/PlayerInfo.tsx +++ b/tank-frontend/src/PlayerInfo.tsx @@ -22,7 +22,7 @@ function ScoreRow({name, value}: { } type TankInfo = { - readonly explosiveBullets: number; + readonly magazine: string; readonly position: { x: number; y: number }; readonly orientation: number; readonly moving: boolean; @@ -63,8 +63,8 @@ export default function PlayerInfo({player}: { player: string }) { + - diff --git a/tanks-backend/TanksServer/GameLogic/CollectPowerUp.cs b/tanks-backend/TanksServer/GameLogic/CollectPowerUp.cs index cc74e23..e0c5ec4 100644 --- a/tanks-backend/TanksServer/GameLogic/CollectPowerUp.cs +++ b/tanks-backend/TanksServer/GameLogic/CollectPowerUp.cs @@ -21,7 +21,11 @@ internal sealed class CollectPowerUp( continue; // now the tank overlaps the power up by at least 0.5 tiles - tank.ExplosiveBullets += 10; + tank.Magazine = tank.Magazine with + { + UsedBullets = 0, + Type = MagazineType.Explosive + }; tank.Owner.Scores.PowerUpsCollected++; return true; } diff --git a/tanks-backend/TanksServer/GameLogic/ShootFromTanks.cs b/tanks-backend/TanksServer/GameLogic/ShootFromTanks.cs index e6bb65e..71637d6 100644 --- a/tanks-backend/TanksServer/GameLogic/ShootFromTanks.cs +++ b/tanks-backend/TanksServer/GameLogic/ShootFromTanks.cs @@ -21,15 +21,18 @@ internal sealed class ShootFromTanks( { if (!tank.Owner.Controls.Shoot) return; + if (tank.Magazine.Empty) + return; if (tank.NextShotAfter >= DateTime.Now) return; tank.NextShotAfter = DateTime.Now.AddMilliseconds(_config.ShootDelayMs); + tank.Magazine = tank.Magazine with + { + UsedBullets = (byte)(tank.Magazine.UsedBullets + 1) + }; - var explosive = tank.ExplosiveBullets > 0; - if (explosive) - tank.ExplosiveBullets--; - + var explosive = tank.Magazine.Type.HasFlag(MagazineType.Explosive); tank.Owner.Scores.ShotsFired++; entityManager.SpawnBullet(tank.Owner, tank.Position, tank.Orientation / 16d, explosive); } diff --git a/tanks-backend/TanksServer/Interactivity/PlayerInfoConnection.cs b/tanks-backend/TanksServer/Interactivity/PlayerInfoConnection.cs index c8fbbe7..b231ec5 100644 --- a/tanks-backend/TanksServer/Interactivity/PlayerInfoConnection.cs +++ b/tanks-backend/TanksServer/Interactivity/PlayerInfoConnection.cs @@ -46,10 +46,10 @@ internal sealed class PlayerInfoConnection( private byte[]? GetMessageToSend() { var tank = entityManager.GetCurrentTankOfPlayer(player); - var tankInfo = tank != null - ? new TankInfo(tank.Orientation, tank.ExplosiveBullets, tank.Position.ToPixelPosition(), tank.Moving) + TankInfo? tankInfo = tank != null + ? new TankInfo(tank.Orientation, tank.Magazine.ToDisplayString(), tank.Position.ToPixelPosition(), tank.Moving) : null; - var info = new PlayerInfo(player.Name, player.Scores, ControlsToString(player.Controls), tankInfo); + var info = new PlayerInfo(player.Name, player.Scores, player.Controls.ToDisplayString(), tankInfo); var response = JsonSerializer.SerializeToUtf8Bytes(info, _context.PlayerInfo); if (response.SequenceEqual(_lastMessage)) @@ -57,21 +57,4 @@ internal sealed class PlayerInfoConnection( return _lastMessage = response; } - - private static string ControlsToString(PlayerControls controls) - { - var str = new StringBuilder("[ "); - if (controls.Forward) - str.Append("▲ "); - if (controls.Backward) - str.Append("▼ "); - if (controls.TurnLeft) - str.Append("◄ "); - if (controls.TurnRight) - str.Append("► "); - if (controls.Shoot) - str.Append("• "); - str.Append(']'); - return str.ToString(); - } } diff --git a/tanks-backend/TanksServer/Models/Magazine.cs b/tanks-backend/TanksServer/Models/Magazine.cs new file mode 100644 index 0000000..8980b80 --- /dev/null +++ b/tanks-backend/TanksServer/Models/Magazine.cs @@ -0,0 +1,44 @@ +using System.Text; + +namespace TanksServer.Models; + +[Flags] +internal enum MagazineType +{ + Basic = 1 << 0, + Fast = 1 << 1, + Explosive = 1 << 2, + Smart = 1 << 3, + Mine = 1 << 4, +} + +internal readonly record struct Magazine(MagazineType Type, byte UsedBullets, byte MaxBullets) +{ + public bool Empty => UsedBullets >= MaxBullets; + + public string ToDisplayString() + { + var sb = new StringBuilder(); + + if (Type.HasFlag(MagazineType.Fast)) + sb.Append('»'); + if (Type.HasFlag(MagazineType.Explosive)) + sb.Append('*'); + if (Type.HasFlag(MagazineType.Smart)) + sb.Append('@'); + if (Type.HasFlag(MagazineType.Mine)) + sb.Append('\u263c'); + + if (sb.Length > 0) + sb.Append(' '); + + sb.Append("[ "); + for (var i = 0; i < UsedBullets; i++) + sb.Append("\u25cb "); + for (var i = UsedBullets; i < MaxBullets; i++) + sb.Append("• "); + sb.Append(']'); + + return sb.ToString(); + } +} diff --git a/tanks-backend/TanksServer/Models/PlayerControls.cs b/tanks-backend/TanksServer/Models/PlayerControls.cs index 82e0bef..b5b82dd 100644 --- a/tanks-backend/TanksServer/Models/PlayerControls.cs +++ b/tanks-backend/TanksServer/Models/PlayerControls.cs @@ -1,3 +1,5 @@ +using System.Text; + namespace TanksServer.Models; internal sealed class PlayerControls @@ -7,4 +9,22 @@ internal sealed class PlayerControls public bool TurnLeft { get; set; } public bool TurnRight { get; set; } public bool Shoot { get; set; } -} \ No newline at end of file + + + public string ToDisplayString() + { + var str = new StringBuilder("[ "); + if (Forward) + str.Append("▲ "); + if (Backward) + str.Append("▼ "); + if (TurnLeft) + str.Append("◄ "); + if (TurnRight) + str.Append("► "); + if (Shoot) + str.Append("• "); + str.Append(']'); + return str.ToString(); + } +} diff --git a/tanks-backend/TanksServer/Models/PlayerInfo.cs b/tanks-backend/TanksServer/Models/PlayerInfo.cs index be46707..118eb42 100644 --- a/tanks-backend/TanksServer/Models/PlayerInfo.cs +++ b/tanks-backend/TanksServer/Models/PlayerInfo.cs @@ -1,13 +1,13 @@ namespace TanksServer.Models; -internal sealed record class TankInfo( +internal record struct TankInfo( int Orientation, - byte ExplosiveBullets, + string Magazine, PixelPosition Position, bool Moving ); -internal sealed record class PlayerInfo( +internal record struct PlayerInfo( string Name, Scores Scores, string Controls, diff --git a/tanks-backend/TanksServer/Models/Tank.cs b/tanks-backend/TanksServer/Models/Tank.cs index 5f64a81..3a1be87 100644 --- a/tanks-backend/TanksServer/Models/Tank.cs +++ b/tanks-backend/TanksServer/Models/Tank.cs @@ -30,5 +30,5 @@ internal sealed class Tank(Player player, FloatPosition spawnPosition) : IMapEnt public int Orientation => (int)Math.Round(Rotation * 16) % 16; - public byte ExplosiveBullets { get; set; } + public Magazine Magazine { get; set; } = new(MagazineType.Basic, 0, 5); }