2024-04-10 19:25:45 +02:00
|
|
|
namespace TanksServer.GameLogic;
|
2024-04-07 19:52:16 +02:00
|
|
|
|
|
|
|
internal sealed class MoveTanks(
|
2024-04-17 19:34:19 +02:00
|
|
|
MapEntityManager entityManager,
|
2024-04-19 13:37:28 +02:00
|
|
|
IOptions<GameRules> options,
|
2024-04-10 19:25:45 +02:00
|
|
|
MapService map
|
2024-04-07 19:52:16 +02:00
|
|
|
) : ITickStep
|
|
|
|
{
|
2024-04-19 13:37:28 +02:00
|
|
|
private readonly GameRules _config = options.Value;
|
2024-04-07 19:52:16 +02:00
|
|
|
|
2024-04-16 19:40:08 +02:00
|
|
|
public Task TickAsync(TimeSpan delta)
|
2024-04-07 19:52:16 +02:00
|
|
|
{
|
2024-04-17 19:34:19 +02:00
|
|
|
foreach (var tank in entityManager.Tanks)
|
2024-04-22 19:44:28 +02:00
|
|
|
tank.Moving = TryMoveTank(tank, delta);
|
2024-04-07 19:52:16 +02:00
|
|
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
}
|
|
|
|
|
2024-04-16 19:40:08 +02:00
|
|
|
private bool TryMoveTank(Tank tank, TimeSpan delta)
|
2024-04-07 19:52:16 +02:00
|
|
|
{
|
|
|
|
var player = tank.Owner;
|
|
|
|
|
|
|
|
double speed;
|
|
|
|
switch (player.Controls)
|
|
|
|
{
|
|
|
|
case { Forward: false, Backward: false }:
|
|
|
|
case { Forward: true, Backward: true }:
|
|
|
|
return false;
|
|
|
|
case { Forward: true }:
|
|
|
|
speed = +_config.MoveSpeed;
|
|
|
|
break;
|
|
|
|
case { Backward: true }:
|
|
|
|
speed = -_config.MoveSpeed;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-04-16 19:40:08 +02:00
|
|
|
speed *= delta.TotalSeconds;
|
|
|
|
|
2024-04-13 18:35:36 +02:00
|
|
|
var angle = tank.Orientation / 16d * 2d * Math.PI;
|
2024-04-07 19:52:16 +02:00
|
|
|
var newX = tank.Position.X + Math.Sin(angle) * speed;
|
|
|
|
var newY = tank.Position.Y - Math.Cos(angle) * speed;
|
|
|
|
|
|
|
|
return TryMoveTankTo(tank, new FloatPosition(newX, newY))
|
2024-04-12 18:32:10 +02:00
|
|
|
|| TryMoveTankTo(tank, new FloatPosition(newX, tank.Position.Y))
|
|
|
|
|| TryMoveTankTo(tank, new FloatPosition(tank.Position.X, newY));
|
2024-04-07 19:52:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private bool TryMoveTankTo(Tank tank, FloatPosition newPosition)
|
|
|
|
{
|
2024-04-13 14:07:14 +02:00
|
|
|
if (HitsWall(newPosition))
|
2024-04-12 19:49:24 +02:00
|
|
|
return false;
|
|
|
|
if (HitsTank(tank, newPosition))
|
2024-04-07 19:52:16 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
tank.Position = newPosition;
|
|
|
|
return true;
|
|
|
|
}
|
2024-04-12 19:49:24 +02:00
|
|
|
|
|
|
|
private bool HitsTank(Tank tank, FloatPosition newPosition) =>
|
2024-04-17 19:34:19 +02:00
|
|
|
entityManager.Tanks
|
2024-04-12 19:49:24 +02:00
|
|
|
.Where(otherTank => otherTank != tank)
|
|
|
|
.Any(otherTank => newPosition.Distance(otherTank.Position) < MapService.TileSize);
|
|
|
|
|
2024-04-13 14:07:14 +02:00
|
|
|
private bool HitsWall(FloatPosition newPosition)
|
2024-04-12 19:49:24 +02:00
|
|
|
{
|
2024-04-17 19:34:19 +02:00
|
|
|
var (topLeft, _) = newPosition.GetBoundsForCenter(MapService.TileSize);
|
2024-04-14 21:10:21 +02:00
|
|
|
|
|
|
|
for (short y = 0; y < MapService.TileSize; y++)
|
|
|
|
for (short x = 0; x < MapService.TileSize; x++)
|
|
|
|
{
|
|
|
|
var pixelToCheck = topLeft.GetPixelRelative(x, y);
|
2024-04-14 22:45:51 +02:00
|
|
|
if (map.Current.IsWall(pixelToCheck))
|
2024-04-14 21:10:21 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2024-04-12 19:49:24 +02:00
|
|
|
}
|
2024-04-13 14:07:14 +02:00
|
|
|
}
|