move backend to subfolder
This commit is contained in:
parent
d4d1f2f981
commit
8d09663eff
80 changed files with 98 additions and 88 deletions
16
tanks-backend/TanksServer/Graphics/DrawBulletsStep.cs
Normal file
16
tanks-backend/TanksServer/Graphics/DrawBulletsStep.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using TanksServer.GameLogic;
|
||||
|
||||
namespace TanksServer.Graphics;
|
||||
|
||||
internal sealed class DrawBulletsStep(MapEntityManager entityManager) : IDrawStep
|
||||
{
|
||||
public void Draw(GamePixelGrid pixels)
|
||||
{
|
||||
foreach (var bullet in entityManager.Bullets)
|
||||
{
|
||||
var position = bullet.Position.ToPixelPosition();
|
||||
pixels[position.X, position.Y].EntityType = GamePixelEntityType.Bullet;
|
||||
pixels[position.X, position.Y].BelongsTo = bullet.Owner;
|
||||
}
|
||||
}
|
||||
}
|
19
tanks-backend/TanksServer/Graphics/DrawMapStep.cs
Normal file
19
tanks-backend/TanksServer/Graphics/DrawMapStep.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using TanksServer.GameLogic;
|
||||
|
||||
namespace TanksServer.Graphics;
|
||||
|
||||
internal sealed class DrawMapStep(MapService map) : IDrawStep
|
||||
{
|
||||
public void Draw(GamePixelGrid pixels)
|
||||
{
|
||||
for (ushort y = 0; y < MapService.PixelsPerColumn; y++)
|
||||
for (ushort x = 0; x < MapService.PixelsPerRow; x++)
|
||||
{
|
||||
var pixel = new PixelPosition(x, y);
|
||||
if (!map.Current.IsWall(pixel))
|
||||
continue;
|
||||
|
||||
pixels[x, y].EntityType = GamePixelEntityType.Wall;
|
||||
}
|
||||
}
|
||||
}
|
52
tanks-backend/TanksServer/Graphics/DrawPowerUpsStep.cs
Normal file
52
tanks-backend/TanksServer/Graphics/DrawPowerUpsStep.cs
Normal file
|
@ -0,0 +1,52 @@
|
|||
using System.Diagnostics;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using TanksServer.GameLogic;
|
||||
|
||||
namespace TanksServer.Graphics;
|
||||
|
||||
internal sealed class DrawPowerUpsStep : IDrawStep
|
||||
{
|
||||
private readonly MapEntityManager _entityManager;
|
||||
private readonly bool?[,] _explosiveSprite;
|
||||
|
||||
public DrawPowerUpsStep(MapEntityManager entityManager)
|
||||
{
|
||||
_entityManager = entityManager;
|
||||
|
||||
using var tankImage = Image.Load<Rgba32>("assets/powerup_explosive.png");
|
||||
Debug.Assert(tankImage.Width == tankImage.Height && tankImage.Width == MapService.TileSize);
|
||||
_explosiveSprite = new bool?[tankImage.Width, tankImage.Height];
|
||||
|
||||
var whitePixel = new Rgba32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
|
||||
for (var y = 0; y < tankImage.Height; y++)
|
||||
for (var x = 0; x < tankImage.Width; x++)
|
||||
{
|
||||
var pixelValue = tankImage[x, y];
|
||||
_explosiveSprite[x, y] = pixelValue.A == 0
|
||||
? null
|
||||
: pixelValue == whitePixel;
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(GamePixelGrid pixels)
|
||||
{
|
||||
foreach (var powerUp in _entityManager.PowerUps)
|
||||
{
|
||||
var position = powerUp.Bounds.TopLeft;
|
||||
|
||||
for (byte dy = 0; dy < MapService.TileSize; dy++)
|
||||
for (byte dx = 0; dx < MapService.TileSize; dx++)
|
||||
{
|
||||
var pixelState = _explosiveSprite[dx, dy];
|
||||
if (!pixelState.HasValue)
|
||||
continue;
|
||||
|
||||
var (x, y) = position.GetPixelRelative(dx, dy);
|
||||
pixels[x, y].EntityType = pixelState.Value
|
||||
? GamePixelEntityType.PowerUp
|
||||
: null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
56
tanks-backend/TanksServer/Graphics/DrawTanksStep.cs
Normal file
56
tanks-backend/TanksServer/Graphics/DrawTanksStep.cs
Normal file
|
@ -0,0 +1,56 @@
|
|||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using TanksServer.GameLogic;
|
||||
|
||||
namespace TanksServer.Graphics;
|
||||
|
||||
internal sealed class DrawTanksStep : IDrawStep
|
||||
{
|
||||
private readonly MapEntityManager _entityManager;
|
||||
private readonly bool[] _tankSprite;
|
||||
private readonly int _tankSpriteWidth;
|
||||
|
||||
public DrawTanksStep(MapEntityManager entityManager)
|
||||
{
|
||||
_entityManager = entityManager;
|
||||
|
||||
using var tankImage = Image.Load<Rgba32>("assets/tank.png");
|
||||
_tankSprite = new bool[tankImage.Height * tankImage.Width];
|
||||
|
||||
var whitePixel = new Rgba32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
|
||||
var i = 0;
|
||||
for (var y = 0; y < tankImage.Height; y++)
|
||||
for (var x = 0; x < tankImage.Width; x++, i++)
|
||||
_tankSprite[i] = tankImage[x, y] == whitePixel;
|
||||
|
||||
_tankSpriteWidth = tankImage.Width;
|
||||
}
|
||||
|
||||
public void Draw(GamePixelGrid pixels)
|
||||
{
|
||||
foreach (var tank in _entityManager.Tanks)
|
||||
{
|
||||
var tankPosition = tank.Bounds.TopLeft;
|
||||
|
||||
for (byte dy = 0; dy < MapService.TileSize; dy++)
|
||||
for (byte dx = 0; dx < MapService.TileSize; dx++)
|
||||
{
|
||||
if (!TankSpriteAt(dx, dy, tank.Orientation))
|
||||
continue;
|
||||
|
||||
var (x, y) = tankPosition.GetPixelRelative(dx, dy);
|
||||
pixels[x, y].EntityType = GamePixelEntityType.Tank;
|
||||
pixels[x, y].BelongsTo = tank.Owner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TankSpriteAt(int dx, int dy, int tankRotation)
|
||||
{
|
||||
var x = tankRotation % 4 * (MapService.TileSize + 1);
|
||||
var y = (int)Math.Floor(tankRotation / 4d) * (MapService.TileSize + 1);
|
||||
var index = (y + dy) * _tankSpriteWidth + x + dx;
|
||||
|
||||
return _tankSprite[index];
|
||||
}
|
||||
}
|
14
tanks-backend/TanksServer/Graphics/GamePixel.cs
Normal file
14
tanks-backend/TanksServer/Graphics/GamePixel.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
namespace TanksServer.Graphics;
|
||||
|
||||
internal sealed class GamePixel
|
||||
{
|
||||
public Player? BelongsTo { get; set; }
|
||||
|
||||
public GamePixelEntityType? EntityType { get; set; }
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
BelongsTo = null;
|
||||
EntityType = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace TanksServer.Graphics;
|
||||
|
||||
internal enum GamePixelEntityType : byte
|
||||
{
|
||||
Wall = 0x0,
|
||||
Tank = 0x1,
|
||||
Bullet = 0x2,
|
||||
PowerUp = 0x3
|
||||
}
|
48
tanks-backend/TanksServer/Graphics/GamePixelGrid.cs
Normal file
48
tanks-backend/TanksServer/Graphics/GamePixelGrid.cs
Normal file
|
@ -0,0 +1,48 @@
|
|||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TanksServer.Graphics;
|
||||
|
||||
internal sealed class GamePixelGrid : IEnumerable<GamePixel>
|
||||
{
|
||||
public int Width { get; }
|
||||
public int Height { get; }
|
||||
|
||||
private readonly GamePixel[,] _pixels;
|
||||
|
||||
public GamePixelGrid(int width, int height)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
|
||||
_pixels = new GamePixel[width, height];
|
||||
for (var y = 0; y < height; y++)
|
||||
for (var x = 0; x < width; x++)
|
||||
this[x, y] = new GamePixel();
|
||||
}
|
||||
|
||||
public GamePixel this[int x, int y]
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(y * Width + x < _pixels.Length);
|
||||
return _pixels[x, y];
|
||||
}
|
||||
set => _pixels[x, y] = value;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var pixel in _pixels)
|
||||
pixel.Clear();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
public IEnumerator<GamePixel> GetEnumerator()
|
||||
{
|
||||
for (var y = 0; y < Height; y++)
|
||||
for (var x = 0; x < Width; x++)
|
||||
yield return this[x, y];
|
||||
}
|
||||
}
|
34
tanks-backend/TanksServer/Graphics/GeneratePixelsTickStep.cs
Normal file
34
tanks-backend/TanksServer/Graphics/GeneratePixelsTickStep.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
using DisplayCommands;
|
||||
using TanksServer.GameLogic;
|
||||
|
||||
namespace TanksServer.Graphics;
|
||||
|
||||
internal sealed class GeneratePixelsTickStep(
|
||||
IEnumerable<IDrawStep> drawSteps,
|
||||
IEnumerable<IFrameConsumer> consumers
|
||||
) : ITickStep
|
||||
{
|
||||
private readonly List<IDrawStep> _drawSteps = drawSteps.ToList();
|
||||
private readonly List<IFrameConsumer> _consumers = consumers.ToList();
|
||||
|
||||
private readonly PixelGrid _observerPixelGrid = new(MapService.PixelsPerRow, MapService.PixelsPerColumn);
|
||||
private readonly GamePixelGrid _gamePixelGrid = new(MapService.PixelsPerRow, MapService.PixelsPerColumn);
|
||||
|
||||
public async Task TickAsync(TimeSpan _)
|
||||
{
|
||||
_gamePixelGrid.Clear();
|
||||
foreach (var step in _drawSteps)
|
||||
step.Draw(_gamePixelGrid);
|
||||
|
||||
_observerPixelGrid.Clear();
|
||||
for (var y = 0; y < MapService.PixelsPerColumn; y++)
|
||||
for (var x = 0; x < MapService.PixelsPerRow; x++)
|
||||
{
|
||||
if (_gamePixelGrid[x, y].EntityType.HasValue)
|
||||
_observerPixelGrid[(ushort)x, (ushort)y] = true;
|
||||
}
|
||||
|
||||
foreach (var consumer in _consumers)
|
||||
await consumer.OnFrameDoneAsync(_gamePixelGrid, _observerPixelGrid);
|
||||
}
|
||||
}
|
6
tanks-backend/TanksServer/Graphics/IDrawStep.cs
Normal file
6
tanks-backend/TanksServer/Graphics/IDrawStep.cs
Normal file
|
@ -0,0 +1,6 @@
|
|||
namespace TanksServer.Graphics;
|
||||
|
||||
internal interface IDrawStep
|
||||
{
|
||||
void Draw(GamePixelGrid pixels);
|
||||
}
|
8
tanks-backend/TanksServer/Graphics/IFrameConsumer.cs
Normal file
8
tanks-backend/TanksServer/Graphics/IFrameConsumer.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
using DisplayCommands;
|
||||
|
||||
namespace TanksServer.Graphics;
|
||||
|
||||
internal interface IFrameConsumer
|
||||
{
|
||||
Task OnFrameDoneAsync(GamePixelGrid gamePixelGrid, PixelGrid observerPixels);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue