wall collision
This commit is contained in:
		
							parent
							
								
									54b840da3e
								
							
						
					
					
						commit
						dd6b0fffc1
					
				
					 6 changed files with 68 additions and 39 deletions
				
			
		|  | @ -1,6 +1,7 @@ | |||
| using System.Collections.Concurrent; | ||||
| using System.Diagnostics; | ||||
| using System.Net.WebSockets; | ||||
| using System.Threading.Channels; | ||||
| using Microsoft.Extensions.Hosting; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using TanksServer.Helpers; | ||||
|  | @ -76,7 +77,14 @@ internal sealed class ClientScreenServer( | |||
|             if (await _wantedFrames.WaitAsync(TimeSpan.Zero)) | ||||
|             { | ||||
|                 _logger.LogTrace("sending"); | ||||
|                 await _channel.Writer.WriteAsync(buf.Data); | ||||
|                 try | ||||
|                 { | ||||
|                     await _channel.Writer.WriteAsync(buf.Data); | ||||
|                 } | ||||
|                 catch (ChannelClosedException) | ||||
|                 { | ||||
|                     _logger.LogWarning("send failed, channel is closed"); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  | @ -87,9 +95,7 @@ internal sealed class ClientScreenServer( | |||
|         private async Task ReceiveAsync() | ||||
|         { | ||||
|             await foreach (var _ in _channel.Reader.ReadAllAsync())  | ||||
|             { | ||||
|                 _wantedFrames.Release(); | ||||
|             } | ||||
|              | ||||
|             _logger.LogTrace("done receiving"); | ||||
|             _server.Remove(this); | ||||
|  |  | |||
|  | @ -1,3 +1,8 @@ | |||
| using TanksServer.Services; | ||||
| 
 | ||||
| namespace TanksServer.Models; | ||||
| 
 | ||||
| internal record struct FloatPosition(double X, double Y); | ||||
| internal readonly record struct FloatPosition(double X, double Y) | ||||
| { | ||||
|     public PixelPosition ToPixelPosition() => new((int)X % MapService.PixelsPerRow, (int)Y % MapService.PixelsPerRow); | ||||
| } | ||||
|  |  | |||
|  | @ -6,10 +6,13 @@ internal sealed class Tank(Player player, FloatPosition spawnPosition) | |||
| 
 | ||||
|     public Player Owner { get; } = player; | ||||
| 
 | ||||
|     /// <summary> | ||||
|     /// Bounds: 0 (inclusive) .. 16 (exclusive) | ||||
|     /// </summary> | ||||
|     public double Rotation | ||||
|     { | ||||
|         get => _rotation; | ||||
|         set => _rotation = value % 16d; | ||||
|         set => _rotation = (value + 16d) % 16d; | ||||
|     } | ||||
| 
 | ||||
|     public FloatPosition Position { get; set; } = spawnPosition; | ||||
|  |  | |||
|  | @ -75,7 +75,7 @@ internal sealed class PixelDrawer : ITickStep | |||
|     { | ||||
|         foreach (var tank in _tanks) | ||||
|         { | ||||
|             var pos = new PixelPosition((int)tank.Position.X, (int)tank.Position.Y); | ||||
|             var pos = tank.Position.ToPixelPosition(); | ||||
|             var rotationVariant = (int)Math.Floor(tank.Rotation); | ||||
|             for (var dy = 0; dy < MapService.TileSize; dy++) | ||||
|             { | ||||
|  | @ -83,9 +83,11 @@ internal sealed class PixelDrawer : ITickStep | |||
| 
 | ||||
|                 for (var dx = 0; dx < MapService.TileSize; dx++) | ||||
|                 { | ||||
|                     if (!TankSpriteAt(dx, dy, rotationVariant)) | ||||
|                         continue; | ||||
|                      | ||||
|                     var i = rowStartIndex + pos.X + dx; | ||||
|                     if (TankSpriteAt(dx, dy, rotationVariant)) | ||||
|                         buf.Pixels[i] = true; | ||||
|                     buf.Pixels[i] = true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ using TanksServer.Models; | |||
| 
 | ||||
| namespace TanksServer.Services; | ||||
| 
 | ||||
| internal sealed class TankManager(ILogger<TankManager> logger, IOptions<TanksConfiguration> options) | ||||
| internal sealed class TankManager(ILogger<TankManager> logger, IOptions<TanksConfiguration> options, MapService map) | ||||
|     : ITickStep, IEnumerable<Tank> | ||||
| { | ||||
|     private readonly ConcurrentBag<Tank> _tanks = new(); | ||||
|  | @ -33,38 +33,51 @@ internal sealed class TankManager(ILogger<TankManager> logger, IOptions<TanksCon | |||
|         logger.LogTrace("moving tank for player {}", tank.Owner.Id); | ||||
|         var player = tank.Owner; | ||||
| 
 | ||||
|         // move turret | ||||
|         if (player.Controls.TurnLeft) Rotate(tank, -_config.TurnSpeed); | ||||
|         if (player.Controls.TurnRight) Rotate(tank, +_config.TurnSpeed); | ||||
|         if (player.Controls.TurnLeft) | ||||
|             tank.Rotation -= _config.TurnSpeed; | ||||
|         if (player.Controls.TurnRight) | ||||
|             tank.Rotation += _config.TurnSpeed; | ||||
| 
 | ||||
|         if (player.Controls is { Forward: false, Backward: false }) | ||||
|         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; | ||||
|         } | ||||
| 
 | ||||
|         var angle = tank.Rotation / 16d * 2d * Math.PI; | ||||
|         var newX = tank.Position.X + Math.Sin(angle) * speed; | ||||
|         var newY = tank.Position.Y - Math.Cos(angle) * speed; | ||||
| 
 | ||||
|         return TryMove(tank, new FloatPosition(newX, newY)) | ||||
|                || TryMove(tank, tank.Position with { X = newX }) | ||||
|                || TryMove(tank, tank.Position with { Y = newY }); | ||||
|     } | ||||
| 
 | ||||
|     private bool TryMove(Tank tank, FloatPosition newPosition) | ||||
|     { | ||||
|         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; | ||||
| 
 | ||||
|         var direction = player.Controls.Forward ? 1 : -1; | ||||
|         var angle = tank.Rotation / 16d * 2d * Math.PI; | ||||
|         var newX = tank.Position.X + Math.Sin(angle) * direction * _config.MoveSpeed; | ||||
|         var newY = tank.Position.Y - Math.Cos(angle) * direction * _config.MoveSpeed; | ||||
| 
 | ||||
|         return TryMove(tank, newX, newY) | ||||
|                || TryMove(tank, newX, tank.Position.Y) | ||||
|                || TryMove(tank, tank.Position.X, newY); | ||||
|     } | ||||
| 
 | ||||
|     private static bool TryMove(Tank tank, double newX, double newY) | ||||
|     { | ||||
|         // TODO implement | ||||
| 
 | ||||
|         tank.Position = new FloatPosition(newX, newY); | ||||
|         tank.Position = newPosition; | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     private void Rotate(Tank t, double speed) | ||||
|     { | ||||
|         var newRotation = (t.Rotation + speed + 16) % 16; | ||||
|         logger.LogTrace("rotating tank for {} from {} to {}", t.Owner.Id, t.Rotation, newRotation); | ||||
|         t.Rotation = newRotation; | ||||
|     } | ||||
| 
 | ||||
|     IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | ||||
|     public IEnumerator<Tank> GetEnumerator() => _tanks.GetEnumerator(); | ||||
| } | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
|         "LogLevel": { | ||||
|             "Default": "Information", | ||||
|             "Microsoft.AspNetCore": "Warning", | ||||
|             "TanksServer": "Trace" | ||||
|             "TanksServer": "Debug" | ||||
|         } | ||||
|     }, | ||||
|     "AllowedHosts": "*", | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vinzenz Schroeter
						Vinzenz Schroeter