From 079b096c167680ef22187e896aaa794d6a2eff68 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sun, 5 May 2024 13:01:37 +0200 Subject: [PATCH] allocate predicate once instead of per tick --- .../TanksServer/GameLogic/CollectPowerUp.cs | 66 ++++++++++--------- .../TanksServer/GameLogic/CollideBullets.cs | 39 +++++++---- 2 files changed, 61 insertions(+), 44 deletions(-) diff --git a/tanks-backend/TanksServer/GameLogic/CollectPowerUp.cs b/tanks-backend/TanksServer/GameLogic/CollectPowerUp.cs index cf1fc04..3b3571f 100644 --- a/tanks-backend/TanksServer/GameLogic/CollectPowerUp.cs +++ b/tanks-backend/TanksServer/GameLogic/CollectPowerUp.cs @@ -6,16 +6,18 @@ internal sealed class CollectPowerUp( MapEntityManager entityManager ) : ITickStep { + private readonly Predicate _collectPredicate = b => TryCollect(b, entityManager.Tanks); + public ValueTask TickAsync(TimeSpan delta) { - entityManager.RemoveWhere(TryCollect); + entityManager.RemoveWhere(_collectPredicate); return ValueTask.CompletedTask; } - private bool TryCollect(PowerUp obj) + private static bool TryCollect(PowerUp powerUp, IEnumerable tanks) { - var position = obj.Position; - foreach (var tank in entityManager.Tanks) + var position = powerUp.Position; + foreach (var tank in tanks) { var (topLeft, bottomRight) = tank.Bounds; if (position.X < topLeft.X || position.X > bottomRight.X || @@ -24,36 +26,40 @@ internal sealed class CollectPowerUp( // now the tank overlaps the power up by at least 0.5 tiles - switch (obj.Type) - { - case PowerUpType.MagazineType: - if (obj.MagazineType == null) - throw new UnreachableException(); - - tank.Magazine = tank.Magazine with - { - Type = tank.Magazine.Type | obj.MagazineType.Value, - UsedBullets = 0 - }; - - if (tank.ReloadingUntil >= DateTime.Now) - tank.ReloadingUntil = DateTime.Now; - - break; - case PowerUpType.MagazineSize: - tank.Magazine = tank.Magazine with - { - MaxBullets = (byte)int.Clamp(tank.Magazine.MaxBullets + 1, 1, 32) - }; - break; - default: - throw new UnreachableException(); - } - + ApplyPowerUpEffect(powerUp, tank); tank.Owner.Scores.PowerUpsCollected++; return true; } return false; } + + private static void ApplyPowerUpEffect(PowerUp powerUp, Tank tank) + { + switch (powerUp.Type) + { + case PowerUpType.MagazineType: + if (powerUp.MagazineType == null) + throw new UnreachableException(); + + tank.Magazine = tank.Magazine with + { + Type = tank.Magazine.Type | powerUp.MagazineType.Value, + UsedBullets = 0 + }; + + if (tank.ReloadingUntil >= DateTime.Now) + tank.ReloadingUntil = DateTime.Now; + + break; + case PowerUpType.MagazineSize: + tank.Magazine = tank.Magazine with + { + MaxBullets = (byte)int.Clamp(tank.Magazine.MaxBullets + 1, 1, 32) + }; + break; + default: + throw new UnreachableException(); + } + } } diff --git a/tanks-backend/TanksServer/GameLogic/CollideBullets.cs b/tanks-backend/TanksServer/GameLogic/CollideBullets.cs index aefd13e..4be0dca 100644 --- a/tanks-backend/TanksServer/GameLogic/CollideBullets.cs +++ b/tanks-backend/TanksServer/GameLogic/CollideBullets.cs @@ -2,20 +2,31 @@ using TanksServer.Graphics; namespace TanksServer.GameLogic; -internal sealed class CollideBullets( - MapEntityManager entityManager, - MapService map, - IOptions options, - TankSpawnQueue tankSpawnQueue -) : ITickStep +internal sealed class CollideBullets : ITickStep { private readonly Sprite _explosiveSprite = Sprite.FromImageFile("assets/explosion.png"); + private readonly Predicate _removeBulletsPredicate; + private readonly MapEntityManager _entityManager; + private readonly MapService _map; + private readonly bool _destructibleWalls; + private readonly TankSpawnQueue _tankSpawnQueue; + + public CollideBullets(MapEntityManager entityManager, + MapService map, + IOptions options, + TankSpawnQueue tankSpawnQueue) + { + _entityManager = entityManager; + _map = map; + _tankSpawnQueue = tankSpawnQueue; + + _destructibleWalls = options.Value.DestructibleWalls; + _removeBulletsPredicate = b => BulletHitsTank(b) || BulletHitsWall(b) || BulletTimesOut(b); + } public ValueTask TickAsync(TimeSpan _) { - entityManager.RemoveWhere(BulletHitsTank); - entityManager.RemoveWhere(BulletHitsWall); - entityManager.RemoveWhere(BulletTimesOut); + _entityManager.RemoveWhere(_removeBulletsPredicate); return ValueTask.CompletedTask; } @@ -31,7 +42,7 @@ internal sealed class CollideBullets( private bool BulletHitsWall(Bullet bullet) { var pixel = bullet.Position.ToPixelPosition(); - if (!map.Current.IsWall(pixel)) + if (!_map.Current.IsWall(pixel)) return false; ExplodeAt(pixel, bullet.IsExplosive, bullet.Owner); @@ -50,7 +61,7 @@ internal sealed class CollideBullets( private Tank? GetTankAt(FloatPosition position, Player owner, bool canHitOwnTank) { - foreach (var tank in entityManager.Tanks) + foreach (var tank in _entityManager.Tanks) { var hitsOwnTank = owner == tank.Owner; if (hitsOwnTank && !canHitOwnTank) @@ -89,7 +100,7 @@ internal sealed class CollideBullets( void Core(PixelPosition position) { - if (options.Value.DestructibleWalls && map.Current.TryDestroyWallAt(position)) + if (_destructibleWalls && _map.Current.TryDestroyWallAt(position)) owner.Scores.WallsDestroyed++; var tank = GetTankAt(position.ToFloatPosition(), owner, true); @@ -100,8 +111,8 @@ internal sealed class CollideBullets( owner.Scores.Kills++; tank.Owner.Scores.Deaths++; - entityManager.Remove(tank); - tankSpawnQueue.EnqueueForDelayedSpawn(tank.Owner); + _entityManager.Remove(tank); + _tankSpawnQueue.EnqueueForDelayedSpawn(tank.Owner); } } }