diff --git a/tanks-backend/TanksServer/GameLogic/GameRules.cs b/tanks-backend/TanksServer/GameLogic/GameRules.cs index 50d79e1..eb28672 100644 --- a/tanks-backend/TanksServer/GameLogic/GameRules.cs +++ b/tanks-backend/TanksServer/GameLogic/GameRules.cs @@ -21,4 +21,6 @@ internal sealed class GameRules public int SpawnDelayMs { get; set; } public int IdleTimeoutMs { get; set; } + + public byte MagazineSize { get; set; } = 5; } diff --git a/tanks-backend/TanksServer/GameLogic/MapEntityManager.cs b/tanks-backend/TanksServer/GameLogic/MapEntityManager.cs index ce63a05..cd0ed6b 100644 --- a/tanks-backend/TanksServer/GameLogic/MapEntityManager.cs +++ b/tanks-backend/TanksServer/GameLogic/MapEntityManager.cs @@ -6,6 +6,7 @@ internal sealed class MapEntityManager( IOptions options ) { + private readonly GameRules _rules = options.Value; private readonly HashSet _bullets = []; private readonly HashSet _powerUps = []; private readonly Dictionary _playerTanks = []; @@ -15,24 +16,31 @@ internal sealed class MapEntityManager( public IEnumerable Tanks => _playerTanks.Values; public IEnumerable PowerUps => _powerUps; - public void SpawnBullet(Player tankOwner, FloatPosition position, double rotation, bool isExplosive) - => _bullets.Add(new Bullet + public void SpawnBullet(Player tankOwner, FloatPosition position, double rotation, MagazineType type) + { + var speed = _rules.BulletSpeed * (type.HasFlag(MagazineType.Fast) ? 2 : 1); + _bullets.Add(new Bullet { Owner = tankOwner, Position = position, Rotation = rotation, - IsExplosive = isExplosive, + IsExplosive = type.HasFlag(MagazineType.Explosive), Timeout = DateTime.Now + _bulletTimeout, OwnerCollisionAfter = DateTime.Now + TimeSpan.FromSeconds(1), + Speed = speed }); + } public void RemoveWhere(Predicate predicate) => _bullets.RemoveWhere(predicate); public void SpawnTank(Player player) { - var tank = new Tank(player, ChooseSpawnPosition()) + var tank = new Tank { - Rotation = Random.Shared.NextDouble() + Owner = player, + Position = ChooseSpawnPosition(), + Rotation = Random.Shared.NextDouble(), + Magazine = new Magazine(MagazineType.Basic, 0, _rules.MagazineSize) }; _playerTanks[player] = tank; logger.LogInformation("Tank added for player {}", player.Name); diff --git a/tanks-backend/TanksServer/GameLogic/MoveBullets.cs b/tanks-backend/TanksServer/GameLogic/MoveBullets.cs index 63e3661..755e454 100644 --- a/tanks-backend/TanksServer/GameLogic/MoveBullets.cs +++ b/tanks-backend/TanksServer/GameLogic/MoveBullets.cs @@ -1,9 +1,6 @@ namespace TanksServer.GameLogic; -internal sealed class MoveBullets( - MapEntityManager entityManager, - IOptions config -) : ITickStep +internal sealed class MoveBullets(MapEntityManager entityManager) : ITickStep { public ValueTask TickAsync(TimeSpan delta) { @@ -13,9 +10,9 @@ internal sealed class MoveBullets( return ValueTask.CompletedTask; } - private void MoveBullet(Bullet bullet, TimeSpan delta) + private static void MoveBullet(Bullet bullet, TimeSpan delta) { - var speed = config.Value.BulletSpeed * delta.TotalSeconds; + var speed = bullet.Speed * delta.TotalSeconds; var angle = bullet.Rotation * 2 * Math.PI; bullet.Position = new FloatPosition( bullet.Position.X + Math.Sin(angle) * speed, diff --git a/tanks-backend/TanksServer/GameLogic/ShootFromTanks.cs b/tanks-backend/TanksServer/GameLogic/ShootFromTanks.cs index 71637d6..86a46d3 100644 --- a/tanks-backend/TanksServer/GameLogic/ShootFromTanks.cs +++ b/tanks-backend/TanksServer/GameLogic/ShootFromTanks.cs @@ -1,5 +1,3 @@ -using System.Diagnostics; - namespace TanksServer.GameLogic; internal sealed class ShootFromTanks( @@ -32,8 +30,7 @@ internal sealed class ShootFromTanks( UsedBullets = (byte)(tank.Magazine.UsedBullets + 1) }; - var explosive = tank.Magazine.Type.HasFlag(MagazineType.Explosive); tank.Owner.Scores.ShotsFired++; - entityManager.SpawnBullet(tank.Owner, tank.Position, tank.Orientation / 16d, explosive); + entityManager.SpawnBullet(tank.Owner, tank.Position, tank.Orientation / 16d, tank.Magazine.Type); } } diff --git a/tanks-backend/TanksServer/Models/Bullet.cs b/tanks-backend/TanksServer/Models/Bullet.cs index c6e87d9..f685741 100644 --- a/tanks-backend/TanksServer/Models/Bullet.cs +++ b/tanks-backend/TanksServer/Models/Bullet.cs @@ -15,4 +15,6 @@ internal sealed class Bullet : IMapEntity public PixelBounds Bounds => new(Position.ToPixelPosition(), Position.ToPixelPosition()); internal required DateTime OwnerCollisionAfter { get; init; } + + public required double Speed { get; init; } } diff --git a/tanks-backend/TanksServer/Models/Magazine.cs b/tanks-backend/TanksServer/Models/Magazine.cs index 8980b80..8994e61 100644 --- a/tanks-backend/TanksServer/Models/Magazine.cs +++ b/tanks-backend/TanksServer/Models/Magazine.cs @@ -5,11 +5,11 @@ namespace TanksServer.Models; [Flags] internal enum MagazineType { - Basic = 1 << 0, - Fast = 1 << 1, - Explosive = 1 << 2, - Smart = 1 << 3, - Mine = 1 << 4, + Basic = 0, + Fast = 1 << 0, + Explosive = 1 << 1, + Smart = 1 << 2, + Mine = 1 << 3, } internal readonly record struct Magazine(MagazineType Type, byte UsedBullets, byte MaxBullets) diff --git a/tanks-backend/TanksServer/Models/Tank.cs b/tanks-backend/TanksServer/Models/Tank.cs index 3a1be87..4d449a2 100644 --- a/tanks-backend/TanksServer/Models/Tank.cs +++ b/tanks-backend/TanksServer/Models/Tank.cs @@ -3,11 +3,11 @@ using TanksServer.GameLogic; namespace TanksServer.Models; -internal sealed class Tank(Player player, FloatPosition spawnPosition) : IMapEntity +internal sealed class Tank : IMapEntity { private double _rotation; - public Player Owner { get; } = player; + public required Player Owner { get; init; } public double Rotation { @@ -24,11 +24,11 @@ internal sealed class Tank(Player player, FloatPosition spawnPosition) : IMapEnt public bool Moving { get; set; } - public FloatPosition Position { get; set; } = spawnPosition; + public required FloatPosition Position { get; set; } public PixelBounds Bounds => Position.GetBoundsForCenter(MapService.TileSize); public int Orientation => (int)Math.Round(Rotation * 16) % 16; - public Magazine Magazine { get; set; } = new(MagazineType.Basic, 0, 5); + public required Magazine Magazine { get; set; } }