implement fast bullets

This commit is contained in:
Vinzenz Schroeter 2024-04-29 16:59:37 +02:00
parent 9ccb7c8df8
commit 9164d90443
7 changed files with 30 additions and 24 deletions

View file

@ -21,4 +21,6 @@ internal sealed class GameRules
public int SpawnDelayMs { get; set; } public int SpawnDelayMs { get; set; }
public int IdleTimeoutMs { get; set; } public int IdleTimeoutMs { get; set; }
public byte MagazineSize { get; set; } = 5;
} }

View file

@ -6,6 +6,7 @@ internal sealed class MapEntityManager(
IOptions<GameRules> options IOptions<GameRules> options
) )
{ {
private readonly GameRules _rules = options.Value;
private readonly HashSet<Bullet> _bullets = []; private readonly HashSet<Bullet> _bullets = [];
private readonly HashSet<PowerUp> _powerUps = []; private readonly HashSet<PowerUp> _powerUps = [];
private readonly Dictionary<Player, Tank> _playerTanks = []; private readonly Dictionary<Player, Tank> _playerTanks = [];
@ -15,24 +16,31 @@ internal sealed class MapEntityManager(
public IEnumerable<Tank> Tanks => _playerTanks.Values; public IEnumerable<Tank> Tanks => _playerTanks.Values;
public IEnumerable<PowerUp> PowerUps => _powerUps; public IEnumerable<PowerUp> PowerUps => _powerUps;
public void SpawnBullet(Player tankOwner, FloatPosition position, double rotation, bool isExplosive) public void SpawnBullet(Player tankOwner, FloatPosition position, double rotation, MagazineType type)
=> _bullets.Add(new Bullet {
var speed = _rules.BulletSpeed * (type.HasFlag(MagazineType.Fast) ? 2 : 1);
_bullets.Add(new Bullet
{ {
Owner = tankOwner, Owner = tankOwner,
Position = position, Position = position,
Rotation = rotation, Rotation = rotation,
IsExplosive = isExplosive, IsExplosive = type.HasFlag(MagazineType.Explosive),
Timeout = DateTime.Now + _bulletTimeout, Timeout = DateTime.Now + _bulletTimeout,
OwnerCollisionAfter = DateTime.Now + TimeSpan.FromSeconds(1), OwnerCollisionAfter = DateTime.Now + TimeSpan.FromSeconds(1),
Speed = speed
}); });
}
public void RemoveWhere(Predicate<Bullet> predicate) => _bullets.RemoveWhere(predicate); public void RemoveWhere(Predicate<Bullet> predicate) => _bullets.RemoveWhere(predicate);
public void SpawnTank(Player player) 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; _playerTanks[player] = tank;
logger.LogInformation("Tank added for player {}", player.Name); logger.LogInformation("Tank added for player {}", player.Name);

View file

@ -1,9 +1,6 @@
namespace TanksServer.GameLogic; namespace TanksServer.GameLogic;
internal sealed class MoveBullets( internal sealed class MoveBullets(MapEntityManager entityManager) : ITickStep
MapEntityManager entityManager,
IOptions<GameRules> config
) : ITickStep
{ {
public ValueTask TickAsync(TimeSpan delta) public ValueTask TickAsync(TimeSpan delta)
{ {
@ -13,9 +10,9 @@ internal sealed class MoveBullets(
return ValueTask.CompletedTask; 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; var angle = bullet.Rotation * 2 * Math.PI;
bullet.Position = new FloatPosition( bullet.Position = new FloatPosition(
bullet.Position.X + Math.Sin(angle) * speed, bullet.Position.X + Math.Sin(angle) * speed,

View file

@ -1,5 +1,3 @@
using System.Diagnostics;
namespace TanksServer.GameLogic; namespace TanksServer.GameLogic;
internal sealed class ShootFromTanks( internal sealed class ShootFromTanks(
@ -32,8 +30,7 @@ internal sealed class ShootFromTanks(
UsedBullets = (byte)(tank.Magazine.UsedBullets + 1) UsedBullets = (byte)(tank.Magazine.UsedBullets + 1)
}; };
var explosive = tank.Magazine.Type.HasFlag(MagazineType.Explosive);
tank.Owner.Scores.ShotsFired++; 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);
} }
} }

View file

@ -15,4 +15,6 @@ internal sealed class Bullet : IMapEntity
public PixelBounds Bounds => new(Position.ToPixelPosition(), Position.ToPixelPosition()); public PixelBounds Bounds => new(Position.ToPixelPosition(), Position.ToPixelPosition());
internal required DateTime OwnerCollisionAfter { get; init; } internal required DateTime OwnerCollisionAfter { get; init; }
public required double Speed { get; init; }
} }

View file

@ -5,11 +5,11 @@ namespace TanksServer.Models;
[Flags] [Flags]
internal enum MagazineType internal enum MagazineType
{ {
Basic = 1 << 0, Basic = 0,
Fast = 1 << 1, Fast = 1 << 0,
Explosive = 1 << 2, Explosive = 1 << 1,
Smart = 1 << 3, Smart = 1 << 2,
Mine = 1 << 4, Mine = 1 << 3,
} }
internal readonly record struct Magazine(MagazineType Type, byte UsedBullets, byte MaxBullets) internal readonly record struct Magazine(MagazineType Type, byte UsedBullets, byte MaxBullets)

View file

@ -3,11 +3,11 @@ using TanksServer.GameLogic;
namespace TanksServer.Models; namespace TanksServer.Models;
internal sealed class Tank(Player player, FloatPosition spawnPosition) : IMapEntity internal sealed class Tank : IMapEntity
{ {
private double _rotation; private double _rotation;
public Player Owner { get; } = player; public required Player Owner { get; init; }
public double Rotation public double Rotation
{ {
@ -24,11 +24,11 @@ internal sealed class Tank(Player player, FloatPosition spawnPosition) : IMapEnt
public bool Moving { get; set; } 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 PixelBounds Bounds => Position.GetBoundsForCenter(MapService.TileSize);
public int Orientation => (int)Math.Round(Rotation * 16) % 16; 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; }
} }