servicepoint-tanks/TanksServer/Services/TankManager.cs

84 lines
2.6 KiB
C#
Raw Normal View History

2024-04-07 13:02:49 +02:00
using System.Collections;
using System.Collections.Concurrent;
using Microsoft.Extensions.Logging;
2024-04-07 17:17:11 +02:00
using Microsoft.Extensions.Options;
2024-04-07 13:02:49 +02:00
using TanksServer.Models;
namespace TanksServer.Services;
2024-04-07 18:18:26 +02:00
internal sealed class TankManager(ILogger<TankManager> logger, IOptions<TanksConfiguration> options, MapService map)
2024-04-07 17:17:11 +02:00
: ITickStep, IEnumerable<Tank>
2024-04-07 13:02:49 +02:00
{
private readonly ConcurrentBag<Tank> _tanks = new();
2024-04-07 17:17:11 +02:00
private readonly TanksConfiguration _config = options.Value;
2024-04-07 13:02:49 +02:00
public void Add(Tank tank)
{
2024-04-07 17:17:11 +02:00
logger.LogInformation("Tank added for player {}", tank.Owner.Id);
2024-04-07 13:02:49 +02:00
_tanks.Add(tank);
}
2024-04-07 17:17:11 +02:00
public Task TickAsync()
{
foreach (var tank in _tanks)
{
TryMoveTank(tank);
}
return Task.CompletedTask;
}
private bool TryMoveTank(Tank tank)
{
logger.LogTrace("moving tank for player {}", tank.Owner.Id);
var player = tank.Owner;
2024-04-07 18:18:26 +02:00
if (player.Controls.TurnLeft)
tank.Rotation -= _config.TurnSpeed;
if (player.Controls.TurnRight)
tank.Rotation += _config.TurnSpeed;
2024-04-07 17:17:11 +02:00
2024-04-07 18:18:26 +02:00
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-07 17:17:11 +02:00
var angle = tank.Rotation / 16d * 2d * Math.PI;
2024-04-07 18:18:26 +02:00
var newX = tank.Position.X + Math.Sin(angle) * speed;
var newY = tank.Position.Y - Math.Cos(angle) * speed;
2024-04-07 17:17:11 +02:00
2024-04-07 18:18:26 +02:00
return TryMove(tank, new FloatPosition(newX, newY))
|| TryMove(tank, tank.Position with { X = newX })
|| TryMove(tank, tank.Position with { Y = newY });
2024-04-07 17:17:11 +02:00
}
2024-04-07 18:18:26 +02:00
private bool TryMove(Tank tank, FloatPosition newPosition)
2024-04-07 17:17:11 +02:00
{
2024-04-07 18:18:26 +02:00
var x0 = (int)Math.Floor(newPosition.X / MapService.TileSize);
var x1 = (int)Math.Ceiling(newPosition.X / MapService.TileSize);
var y0 = (int)Math.Floor(newPosition.Y / MapService.TileSize);
var y1 = (int)Math.Ceiling(newPosition.Y / MapService.TileSize);
TilePosition[] positions = { new(x0, y0), new(x0, y1), new(x1, y0), new(x1, y1) };
if (positions.Any(map.IsCurrentlyWall))
return false;
2024-04-07 17:17:11 +02:00
2024-04-07 18:18:26 +02:00
tank.Position = newPosition;
2024-04-07 17:17:11 +02:00
return true;
}
2024-04-07 13:02:49 +02:00
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator<Tank> GetEnumerator() => _tanks.GetEnumerator();
}