destructible walls
This commit is contained in:
parent
a0a0762f84
commit
dec571d8c1
|
@ -4,10 +4,17 @@ internal sealed class CollideBulletsWithMap(BulletManager bullets, MapService ma
|
||||||
{
|
{
|
||||||
public Task TickAsync()
|
public Task TickAsync()
|
||||||
{
|
{
|
||||||
bullets.RemoveWhere(BulletHitsWall);
|
bullets.RemoveWhere(TryHitAndDestroyWall);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool BulletHitsWall(Bullet bullet) =>
|
private bool TryHitAndDestroyWall(Bullet bullet)
|
||||||
map.Current.IsWall(bullet.Position.ToPixelPosition());
|
{
|
||||||
|
var pixel = bullet.Position.ToPixelPosition();
|
||||||
|
if (!map.Current.IsWall(pixel))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
map.Current.DestroyWallAt(pixel);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,20 +12,25 @@ internal sealed class MapService
|
||||||
public const ushort PixelsPerRow = TilesPerRow * TileSize;
|
public const ushort PixelsPerRow = TilesPerRow * TileSize;
|
||||||
public const ushort PixelsPerColumn = TilesPerColumn * TileSize;
|
public const ushort PixelsPerColumn = TilesPerColumn * TileSize;
|
||||||
|
|
||||||
public Map[] All { get; }
|
private readonly Dictionary<string, bool[,]> _maps = new();
|
||||||
|
|
||||||
public Map Current { get; set; }
|
public IEnumerable<string> MapNames => _maps.Keys;
|
||||||
|
|
||||||
|
public Map Current { get; private set; }
|
||||||
|
|
||||||
public MapService()
|
public MapService()
|
||||||
{
|
{
|
||||||
var textMaps = Directory.EnumerateFiles("./assets/maps/", "*.txt").Select(LoadMapString);
|
foreach (var file in Directory.EnumerateFiles("./assets/maps/", "*.txt"))
|
||||||
var pngMaps = Directory.EnumerateFiles("./assets/maps/", "*.png").Select(LoadMapPng);
|
LoadMapString(file);
|
||||||
|
foreach (var file in Directory.EnumerateFiles("./assets/maps/", "*.png"))
|
||||||
|
LoadMapPng(file);
|
||||||
|
|
||||||
All = textMaps.Concat(pngMaps).ToArray();
|
var chosenMapIndex = Random.Shared.Next(_maps.Count);
|
||||||
Current = All[Random.Shared.Next(All.Length)];
|
var chosenMapName = _maps.Keys.Skip(chosenMapIndex).First();
|
||||||
|
Current = new Map(chosenMapName, _maps[chosenMapName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map LoadMapPng(string file)
|
private void LoadMapPng(string file)
|
||||||
{
|
{
|
||||||
using var image = Image.Load<Rgba32>(file);
|
using var image = Image.Load<Rgba32>(file);
|
||||||
|
|
||||||
|
@ -39,10 +44,10 @@ internal sealed class MapService
|
||||||
for (var x = 0; x < image.Width; x++)
|
for (var x = 0; x < image.Width; x++)
|
||||||
walls[x, y] = image[x, y] == whitePixel;
|
walls[x, y] = image[x, y] == whitePixel;
|
||||||
|
|
||||||
return new Map(Path.GetFileName(file),walls);
|
_maps.Add(Path.GetFileName(file), walls);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map LoadMapString(string file)
|
private void LoadMapString(string file)
|
||||||
{
|
{
|
||||||
var map = File.ReadAllText(file).ReplaceLineEndings(string.Empty).Trim();
|
var map = File.ReadAllText(file).ReplaceLineEndings(string.Empty).Trim();
|
||||||
if (map.Length != TilesPerColumn * TilesPerRow)
|
if (map.Length != TilesPerColumn * TilesPerRow)
|
||||||
|
@ -65,7 +70,15 @@ internal sealed class MapService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Map(Path.GetFileName(file), walls);
|
_maps.Add(Path.GetFileName(file), walls);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TrySwitchTo(string name)
|
||||||
|
{
|
||||||
|
if (!_maps.TryGetValue(name, out var mapData))
|
||||||
|
return false;
|
||||||
|
Current = new Map(name, mapData);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,4 +103,6 @@ internal sealed class Map(string name, bool[,] walls)
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DestroyWallAt(PixelPosition pixel) => walls[pixel.X, pixel.Y] = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,5 +6,5 @@ namespace TanksServer.Interactivity;
|
||||||
[JsonSerializable(typeof(IEnumerable<Player>))]
|
[JsonSerializable(typeof(IEnumerable<Player>))]
|
||||||
[JsonSerializable(typeof(Guid))]
|
[JsonSerializable(typeof(Guid))]
|
||||||
[JsonSerializable(typeof(NameId))]
|
[JsonSerializable(typeof(NameId))]
|
||||||
[JsonSerializable(typeof(Dictionary<int, string>))]
|
[JsonSerializable(typeof(IEnumerable<string>))]
|
||||||
internal sealed partial class AppSerializerContext : JsonSerializerContext;
|
internal sealed partial class AppSerializerContext : JsonSerializerContext;
|
||||||
|
|
|
@ -73,19 +73,14 @@ public static class Program
|
||||||
return Results.Empty;
|
return Results.Empty;
|
||||||
});
|
});
|
||||||
|
|
||||||
app.MapGet("/map", () =>
|
app.MapGet("/map", () =>mapService.MapNames);
|
||||||
{
|
|
||||||
var dict = mapService.All
|
|
||||||
.Select((m, i) => (m.Name, i))
|
|
||||||
.ToDictionary(pair => pair.i, pair => pair.Name);
|
|
||||||
return dict;
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapPost("/map", ([FromQuery] int index) =>
|
app.MapPost("/map", ([FromQuery] string name) =>
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= mapService.All.Length)
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
return Results.NotFound("index does not exist");
|
return Results.BadRequest("invalid map name");
|
||||||
mapService.Current = mapService.All[index];
|
if (!mapService.TrySwitchTo(name))
|
||||||
|
return Results.NotFound("map with name not found");
|
||||||
return Results.Ok();
|
return Results.Ok();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
{
|
{
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning",
|
"Microsoft.AspNetCore": "Warning",
|
||||||
"TanksServer": "Debug",
|
"TanksServer": "Debug",
|
||||||
"Microsoft.AspNetCore.HttpLogging": "Information"
|
"Microsoft.AspNetCore.HttpLogging": "Information"
|
||||||
}
|
|
||||||
},
|
|
||||||
"AllowedHosts": "*",
|
|
||||||
"Kestrel": {
|
|
||||||
"Endpoints": {
|
|
||||||
"Http": {
|
|
||||||
"Url": "http://localhost:3000"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ServicePointDisplay": {
|
|
||||||
"Enable": true,
|
|
||||||
"Hostname": "172.23.42.29",
|
|
||||||
"Port": 2342
|
|
||||||
},
|
|
||||||
"Tanks": {
|
|
||||||
"MoveSpeed": 1.5,
|
|
||||||
"TurnSpeed": 0.02,
|
|
||||||
"ShootDelayMs": 450,
|
|
||||||
"BulletSpeed":4
|
|
||||||
},
|
|
||||||
"Players": {
|
|
||||||
"SpawnDelayMs": 3000,
|
|
||||||
"IdleTimeoutMs": 30000
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"Kestrel": {
|
||||||
|
"Endpoints": {
|
||||||
|
"Http": {
|
||||||
|
"Url": "http://localhost:3000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ServicePointDisplay": {
|
||||||
|
"Enable": true,
|
||||||
|
"Hostname": "172.23.42.29",
|
||||||
|
"Port": 2342
|
||||||
|
},
|
||||||
|
"Tanks": {
|
||||||
|
"MoveSpeed": 1.5,
|
||||||
|
"TurnSpeed": 0.02,
|
||||||
|
"ShootDelayMs": 450,
|
||||||
|
"BulletSpeed": 3
|
||||||
|
},
|
||||||
|
"Players": {
|
||||||
|
"SpawnDelayMs": 3000,
|
||||||
|
"IdleTimeoutMs": 30000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue