servicepoint-tanks/TanksServer/GameLogic/MoveTanks.cs

81 lines
2.3 KiB
C#
Raw Normal View History

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-12 19:49:24 +02:00
TankManager tanks,
2024-04-10 19:25:45 +02:00
IOptions<TanksConfiguration> options,
MapService map
2024-04-07 19:52:16 +02:00
) : ITickStep
{
private readonly TanksConfiguration _config = options.Value;
2024-04-16 19:40:08 +02:00
public Task TickAsync(TimeSpan delta)
2024-04-07 19:52:16 +02:00
{
foreach (var tank in tanks)
2024-04-16 19:40:08 +02:00
tank.Moved = 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)
{
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) =>
tanks
.Where(otherTank => otherTank != tank)
.Any(otherTank => newPosition.Distance(otherTank.Position) < MapService.TileSize);
private bool HitsWall(FloatPosition newPosition)
2024-04-12 19:49:24 +02:00
{
2024-04-14 21:10:21 +02:00
var (topLeft, _) = Tank.GetBoundsForCenter(newPosition);
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
}
}