refactoring WIP

This commit is contained in:
Erik Simon 2022-11-09 19:29:50 +01:00
parent 2742e0100c
commit 7eea232196
49 changed files with 474 additions and 251 deletions

13
.idea/.idea.mine2d.dir/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/modules.xml
/.idea.mine2d.iml
/contentModel.xml
/projectSettingsUpdater.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

2
Folder.DotSettings Normal file
View File

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=trimmable/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -1,4 +1,6 @@
class Program namespace mine2d;
class Program
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
@ -10,4 +12,4 @@
// p.Dump(); // p.Dump();
// Console.WriteLine("Hello World!"); // Console.WriteLine("Hello World!");
} }
} }

View File

@ -5,20 +5,20 @@
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<RootNamespace>mine2d</RootNamespace> <RootNamespace>mine2d</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<PublishTrimmed>true</PublishTrimmed> <PublishTrimmed>true</PublishTrimmed>
<TrimmerDefaultAction>link</TrimmerDefaultAction> <TrimmerDefaultAction>link</TrimmerDefaultAction>
<PublishReadyToRun>true</PublishReadyToRun> <PublishReadyToRun>true</PublishReadyToRun>
<PublishSingleFile>true</PublishSingleFile> <PublishSingleFile>true</PublishSingleFile>
<Nullable>disable</Nullable> <Nullable>disable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="ppy.SDL2-CS" Version="1.0.596-alpha" /> <PackageReference Include="ppy.SDL2-CS" Version="1.0.596-alpha" />
<PackageReference Include="WatsonTcp" Version="4.8.14.14" /> <PackageReference Include="WatsonTcp" Version="4.8.14.14" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="assets/*" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="assets/*" />
</ItemGroup>
</Project> </Project>

View File

@ -1,3 +1,11 @@
using mine2d.backend;
using mine2d.core.tiles;
using mine2d.engine;
using mine2d.frontend;
using mine2d.state;
namespace mine2d;
class Context class Context
{ {
public bool IsHost { get; set; } public bool IsHost { get; set; }
@ -9,7 +17,7 @@ class Context
public Renderer Renderer { get; set; } public Renderer Renderer { get; set; }
public TileRegistry TileRegistry { get; set; } public TileRegistry TileRegistry { get; set; }
public ResourceLoader ResourceLoader { get; set; } public ResourceLoader ResourceLoader { get; set; }
public static Context instance { get; set; } public static Context Instance { get; set; }
public Context( public Context(
bool isHost, bool isHost,
@ -30,16 +38,16 @@ class Context
this.Window = window; this.Window = window;
this.TileRegistry = new TileRegistry(); this.TileRegistry = new TileRegistry();
this.ResourceLoader = new ResourceLoader(); this.ResourceLoader = new ResourceLoader();
Context.instance = this; Context.Instance = this;
} }
public static Context Get() public static Context Get()
{ {
if (Context.instance == null) if (Context.Instance == null)
{ {
throw new Exception("Context not initialized"); throw new Exception("Context not initialized");
} }
return Context.instance; return Context.Instance;
} }
} }

View File

@ -1,13 +1,13 @@
using static SDL2.SDL; namespace mine2d;
enum Control enum Control
{ {
UP, Up,
DOWN, Down,
LEFT, Left,
RIGHT, Right,
STAY, Stay,
CONFIRM, Confirm,
} }
static class ControlKeyExtension static class ControlKeyExtension
@ -16,20 +16,20 @@ static class ControlKeyExtension
{ {
switch (c) switch (c)
{ {
case Control.UP: case Control.Up:
return SDL_Keycode.SDLK_w; return SDL_Keycode.SDLK_w;
case Control.DOWN: case Control.Down:
return SDL_Keycode.SDLK_s; return SDL_Keycode.SDLK_s;
case Control.LEFT: case Control.Left:
return SDL_Keycode.SDLK_a; return SDL_Keycode.SDLK_a;
case Control.RIGHT: case Control.Right:
return SDL_Keycode.SDLK_d; return SDL_Keycode.SDLK_d;
case Control.STAY: case Control.Stay:
return SDL_Keycode.SDLK_LCTRL; return SDL_Keycode.SDLK_LCTRL;
case Control.CONFIRM: case Control.Confirm:
return SDL_Keycode.SDLK_SPACE; return SDL_Keycode.SDLK_SPACE;
default: default:
throw new ArgumentException("Invalid control"); throw new ArgumentException("Invalid control");
} }
} }
} }

View File

@ -1,3 +1,11 @@
using mine2d.backend;
using mine2d.core;
using mine2d.engine;
using mine2d.frontend;
using mine2d.state;
namespace mine2d;
class Mine2d : Game class Mine2d : Game
{ {
private readonly Context ctx; private readonly Context ctx;
@ -29,13 +37,13 @@ class Mine2d : Game
this.ctx.Frontend.Init(); this.ctx.Frontend.Init();
} }
protected override void draw() protected override void Draw()
{ {
this.ctx.Frontend.Process(); this.ctx.Frontend.Process();
} }
protected override void update(double dt) protected override void Update(double dt)
{ {
this.ctx.Backend.Process(dt); this.ctx.Backend.Process(dt);
} }
} }

View File

@ -1,13 +1,18 @@
using System.Text; using System.Text;
using mine2d.backend.data;
using mine2d.engine.system.annotations;
using mine2d.network;
using Newtonsoft.Json; using Newtonsoft.Json;
using WatsonTcp; using WatsonTcp;
namespace mine2d.backend;
class Backend : IBackend class Backend : IBackend
{ {
private WatsonTcpServer server; private WatsonTcpServer server;
private Publisher publisher; private Publisher publisher;
private Queue<ValueType> pendingPackets = new(); private Queue<ValueType> pendingPackets = new();
private uint tick = 0; private uint tick;
public void Process(double dt) public void Process(double dt)
{ {
@ -17,7 +22,7 @@ class Backend : IBackend
var packet = this.pendingPackets.Dequeue(); var packet = this.pendingPackets.Dequeue();
this.publisher.Publish(packet); this.publisher.Publish(packet);
} }
this.sendGameState(); this.SendGameState();
} }
public void ProcessPacket(ValueType packet) public void ProcessPacket(ValueType packet)
@ -34,13 +39,13 @@ class Backend : IBackend
public void Run() public void Run()
{ {
this.server = new WatsonTcpServer("127.0.0.1", 42069); this.server = new WatsonTcpServer("127.0.0.1", 42069);
this.server.Events.ClientConnected += this.clientConnected; this.server.Events.ClientConnected += this.ClientConnected;
this.server.Events.ClientDisconnected += this.clientDisconnected; this.server.Events.ClientDisconnected += this.ClientDisconnected;
this.server.Events.MessageReceived += this.messageReceived; this.server.Events.MessageReceived += this.MessageReceived;
this.server.Start(); this.server.Start();
} }
private void clientConnected(object sender, ConnectionEventArgs args) private void ClientConnected(object sender, ConnectionEventArgs args)
{ {
Console.WriteLine("Client connected: " + args.IpPort); Console.WriteLine("Client connected: " + args.IpPort);
var gameState = Context.Get().GameState; var gameState = Context.Get().GameState;
@ -51,12 +56,12 @@ class Backend : IBackend
} }
} }
private void clientDisconnected(object sender, DisconnectionEventArgs args) private void ClientDisconnected(object sender, DisconnectionEventArgs args)
{ {
Console.WriteLine("Client disconnected: " + args.IpPort); Console.WriteLine("Client disconnected: " + args.IpPort);
} }
private void messageReceived(object sender, MessageReceivedEventArgs args) private void MessageReceived(object sender, MessageReceivedEventArgs args)
{ {
var time = DateTime.Now; var time = DateTime.Now;
Console.WriteLine("Message Received: " + args.IpPort); Console.WriteLine("Message Received: " + args.IpPort);
@ -64,24 +69,24 @@ class Backend : IBackend
Console.WriteLine("Received packet: " + packet); Console.WriteLine("Received packet: " + packet);
if (packet != null) if (packet != null)
{ {
pendingPackets.Enqueue(packet); this.pendingPackets.Enqueue(packet);
} }
Console.WriteLine(DateTime.Now - time); Console.WriteLine(DateTime.Now - time);
} }
private void sendGameState() private void SendGameState()
{ {
if (server == null) if (this.server == null)
return; return;
var clients = server.ListClients(); var clients = this.server.ListClients().ToArray();
if (clients.Count() == 0) if (!clients.Any())
return; return;
var gameState = Context.Get().GameState; var gameState = Context.Get().GameState;
var json = JsonConvert.SerializeObject(gameState); var json = JsonConvert.SerializeObject(gameState);
var bytes = Encoding.UTF8.GetBytes(json); var bytes = Encoding.UTF8.GetBytes(json);
foreach (var client in clients) foreach (var client in clients)
{ {
server.Send(client, bytes); this.server.Send(client, bytes);
} }
} }
} }

View File

@ -1,6 +1,8 @@
namespace mine2d.backend;
interface IBackend interface IBackend
{ {
public void Process(double dt); public void Process(double dt);
public void ProcessPacket(ValueType packet); public void ProcessPacket(ValueType packet);
public void Init(); public void Init();
} }

View File

@ -1,3 +1,10 @@
using System.Reflection;
using mine2d.core.extensions;
using mine2d.engine;
using mine2d.engine.system.annotations;
namespace mine2d.backend;
class Publisher class Publisher
{ {
private readonly Dictionary<string, HashSet<Delegate>> subscribers = private readonly Dictionary<string, HashSet<Delegate>> subscribers =
@ -7,13 +14,14 @@ class Publisher
public Publisher(InteractorKind kind) public Publisher(InteractorKind kind)
{ {
this.kind = kind; this.kind = kind;
this.scan(); this.Scan();
} }
private void scan() private void Scan()
{ {
var assembly = this.GetType().Assembly; var types = Assembly
var types = assembly.GetTypes(); .GetAssembly(this.GetType())!
.GetTypesSafe();
foreach (var type in types) foreach (var type in types)
{ {
var attrs = type.GetCustomAttributes(typeof(Interactor), false); var attrs = type.GetCustomAttributes(typeof(Interactor), false);
@ -35,15 +43,15 @@ class Publisher
continue; continue;
} }
var del = Delegate.CreateDelegate( var del = Delegate.CreateDelegate(
typeof(Action<>).MakeGenericType(method.GetParameters()[0].ParameterType), typeof(Action<>).MakeGenericTypeSafely(method.GetParameters()[0].ParameterType),
method method
); );
this.subscribe(attr.Type, del); this.Subscribe(attr.Type, del);
} }
} }
} }
private void subscribe(string type, Delegate callback) private void Subscribe(string type, Delegate callback)
{ {
if (!this.subscribers.ContainsKey(type)) if (!this.subscribers.ContainsKey(type))
{ {
@ -83,4 +91,4 @@ class Publisher
} }
} }
} }
} }

View File

@ -1,21 +1,25 @@
using WatsonTcp;
using Newtonsoft.Json;
using System.Text; using System.Text;
using mine2d.backend.data;
using mine2d.engine.system.annotations;
using mine2d.state;
using Newtonsoft.Json;
using WatsonTcp;
namespace mine2d.backend;
class RemoteBackend : IBackend class RemoteBackend : IBackend
{ {
private WatsonTcpClient client; private WatsonTcpClient client;
private Publisher publisher; private Publisher publisher;
private Queue<ValueType> pendingPackets = new Queue<ValueType>(); private readonly Queue<ValueType> pendingPackets = new();
private uint tick = 0; private uint tick = 0;
public void Process(double dt) public void Process(double dt)
{ {
var ctx = Context.Get(); this.ProcessPacket(new TickPacket(this.tick++));
this.ProcessPacket(new TickPacket(tick++)); while (this.pendingPackets.Count > 0)
while (pendingPackets.Count > 0)
{ {
var packet = pendingPackets.Dequeue(); var packet = this.pendingPackets.Dequeue();
this.ProcessPacket(packet); this.ProcessPacket(packet);
} }
} }
@ -25,7 +29,7 @@ class RemoteBackend : IBackend
this.publisher.Publish(packet); this.publisher.Publish(packet);
var json = JsonConvert.SerializeObject(packet); var json = JsonConvert.SerializeObject(packet);
var bytes = Encoding.UTF8.GetBytes(json); var bytes = Encoding.UTF8.GetBytes(json);
client.Send(bytes); this.client.Send(bytes);
} }
public void Init() public void Init()
@ -36,8 +40,8 @@ class RemoteBackend : IBackend
public void Run() public void Run()
{ {
client = new WatsonTcpClient("127.0.0.1", 42069); this.client = new WatsonTcpClient("127.0.0.1", 42069);
client.Events.MessageReceived += (sender, args) => this.client.Events.MessageReceived += (_, args) =>
{ {
var ctx = Context.Get(); var ctx = Context.Get();
var message = Encoding.UTF8.GetString(args.Data); var message = Encoding.UTF8.GetString(args.Data);
@ -47,6 +51,6 @@ class RemoteBackend : IBackend
ctx.GameState = packet; ctx.GameState = packet;
} }
}; };
client.Connect(); this.client.Connect();
} }
} }

View File

@ -1,49 +1,55 @@
using System.Numerics; namespace mine2d.backend.data;
readonly struct MovePacket public interface IPacket
{ {
readonly public string type = "move"; string Type { get; }
readonly public string playerName; }
readonly public Vector2 movement;
readonly struct MovePacket : IPacket
{
public string Type => "move";
readonly public string PlayerName;
readonly public Vector2 Movement;
public MovePacket(string playerName, Vector2 movement) public MovePacket(string playerName, Vector2 movement)
{ {
this.playerName = playerName; this.PlayerName = playerName;
this.movement = movement; this.Movement = movement;
} }
} }
readonly struct ConnectPacket readonly struct ConnectPacket
{ {
public readonly string type = "connect"; public readonly string Type = "connect";
public readonly string playerName; public readonly string PlayerName;
public readonly Guid playerGuid; public readonly Guid PlayerGuid;
public ConnectPacket(string playerName, Guid playerGuid) public ConnectPacket(string playerName, Guid playerGuid)
{ {
this.playerName = playerName; this.PlayerName = playerName;
this.playerGuid = playerGuid; this.PlayerGuid = playerGuid;
} }
} }
readonly struct TickPacket readonly struct TickPacket
{ {
public readonly string type = "tick"; public readonly string Type = "tick";
public readonly uint tick; public readonly uint Tick;
public TickPacket(uint tick) public TickPacket(uint tick)
{ {
this.tick = tick; this.Tick = tick;
} }
} }
readonly struct SelfMovedPacket readonly struct SelfMovedPacket
{ {
public readonly string type = "selfMoved"; public readonly string Type = "selfMoved";
public readonly Vector2 target; public readonly Vector2 Target;
public SelfMovedPacket(Vector2 target) public SelfMovedPacket(Vector2 target)
{ {
this.target = target; this.Target = target;
} }
} }

View File

@ -1,3 +1,8 @@
using mine2d.backend.data;
using mine2d.engine.system.annotations;
namespace mine2d.backend.interactor;
[Interactor] [Interactor]
class Breaking class Breaking
{ {
@ -7,8 +12,8 @@ class Breaking
var ctx = Context.Get(); var ctx = Context.Get();
ctx.GameState.Players.ForEach(player => ctx.GameState.Players.ForEach(player =>
{ {
Math.Max(0, player.MiningCooldown -= 1); player.MiningCooldown = Math.Max(0, player.MiningCooldown - 1);
if (player.Mining != null && player.MiningCooldown == 0) if (player.Mining != Vector2.Zero && player.MiningCooldown == 0)
{ {
var chunk = ctx.GameState.World.GetChunkAt(player.Mining); var chunk = ctx.GameState.World.GetChunkAt(player.Mining);
// chunk.SetTileAt(player.Mining, tile with { Hits = tile.Hits + 1 }); // chunk.SetTileAt(player.Mining, tile with { Hits = tile.Hits + 1 });
@ -22,4 +27,4 @@ class Breaking
} }
); );
} }
} }

View File

@ -1,3 +1,9 @@
using mine2d.backend.data;
using mine2d.engine.system.annotations;
using mine2d.state;
namespace mine2d.backend.interactor;
[Interactor] [Interactor]
class Connect class Connect
{ {
@ -5,18 +11,18 @@ class Connect
public static void ConnectServer(ConnectPacket packet) public static void ConnectServer(ConnectPacket packet)
{ {
var ctx = Context.Get(); var ctx = Context.Get();
var player = ctx.GameState.Players.Find(p => p.Name == packet.playerName); var player = ctx.GameState.Players.Find(p => p.Name == packet.PlayerName);
if (player == null) if (player == null)
{ {
ctx.GameState.Players.Add( ctx.GameState.Players.Add(
new Player new Player
{ {
Name = packet.playerName, Name = packet.PlayerName,
Guid = packet.playerGuid, Guid = packet.PlayerGuid,
Position = new Vector2(20, 16 * 16), Position = new Vector2(20, 16 * 16),
Movement = new Vector2(0, 0) Movement = new Vector2(0, 0)
} }
); );
} }
} }
} }

View File

@ -1,3 +1,9 @@
using mine2d.backend.data;
using mine2d.core;
using mine2d.engine.system.annotations;
namespace mine2d.backend.interactor;
[Interactor] [Interactor]
class Move class Move
{ {
@ -5,10 +11,10 @@ class Move
public static void MoveHybrid(MovePacket packet) public static void MoveHybrid(MovePacket packet)
{ {
var ctx = Context.Get(); var ctx = Context.Get();
var player = ctx.GameState.Players.Find(p => p.Name == packet.playerName); var player = ctx.GameState.Players.Find(p => p.Name == packet.PlayerName);
if (player != null) if (player != null)
{ {
player.Movement = packet.movement * 4; player.Movement = packet.Movement * 4;
} }
} }
@ -26,4 +32,4 @@ class Move
var camera = Context.Get().FrontendGameState.Camera; var camera = Context.Get().FrontendGameState.Camera;
camera.CenterOn(PlayerEntity.GetSelf().Position); camera.CenterOn(PlayerEntity.GetSelf().Position);
} }
} }

View File

@ -1,11 +1,17 @@
using mine2d.core.data;
using mine2d.core.tiles;
using mine2d.core.world;
namespace mine2d.core;
class Bootstrapper class Bootstrapper
{ {
public static void Bootstrap() public static void Bootstrap()
{ {
var ctx = Context.Get(); var ctx = Context.Get();
ctx.GameState.World = new World(); ctx.GameState.World = new World();
ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(0, 1, STile.From(Tiles.stone))); ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(0, 1, STile.From(Tiles.Stone)));
ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(1, 1, STile.From(Tiles.stone))); ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(1, 1, STile.From(Tiles.Stone)));
ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(1, 0, STile.From(Tiles.stone))); ctx.GameState.World.AddChunk(ChunkGenerator.CreateFilledChunk(1, 0, STile.From(Tiles.Stone)));
} }
} }

View File

@ -1,10 +1,12 @@
namespace mine2d.core;
class Camera class Camera
{ {
public Vector2 position; public Vector2 Position;
public Camera() public Camera()
{ {
position = Vector2.Zero; this.Position = Vector2.Zero;
} }
public void CenterOn(Vector2 target) public void CenterOn(Vector2 target)
@ -13,6 +15,6 @@ class Camera
var scale = ctx.FrontendGameState.Settings.GameScale; var scale = ctx.FrontendGameState.Settings.GameScale;
var windowWidth = ctx.FrontendGameState.WindowWidth; var windowWidth = ctx.FrontendGameState.WindowWidth;
var windowHeight = ctx.FrontendGameState.WindowHeight; var windowHeight = ctx.FrontendGameState.WindowHeight;
position = target - (new Vector2(windowWidth / 2, windowHeight / 2)) / scale; this.Position = target - (new Vector2(windowWidth, windowHeight) / 2) / scale;
} }
} }

View File

@ -1,6 +1,8 @@
namespace mine2d.core;
class Constants class Constants
{ {
public const int ChunkSize = 32; public const int ChunkSize = 32;
public const int TileSize = 16; public const int TileSize = 16;
public static Vector2 gravity = new Vector2(0, 0.1f); public static Vector2 Gravity = new Vector2(0, 0.1f);
} }

View File

@ -1,6 +1,10 @@
using mine2d.state;
namespace mine2d.core;
class PlayerEntity class PlayerEntity
{ {
public static bool isSelf(Player p) public static bool IsSelf(Player p)
{ {
return p.Guid == GetSelf().Guid; return p.Guid == GetSelf().Guid;
} }
@ -16,7 +20,7 @@ class PlayerEntity
public static void Move(Player p) public static void Move(Player p)
{ {
p.Movement += Constants.gravity; p.Movement += Constants.Gravity;
p.Position += p.Movement; p.Position += p.Movement;
} }
@ -28,7 +32,7 @@ class PlayerEntity
{ {
var pL = p.Position + new Vector2(0, -8); var pL = p.Position + new Vector2(0, -8);
hasCollision = hasCollision =
world.HasChunkAt(pL) && world.GetChunkAt(pL).hasTileAt(pL); world.HasChunkAt(pL) && world.GetChunkAt(pL).HasTileAt(pL);
if (hasCollision) if (hasCollision)
{ {
p.Movement = p.Movement with { X = 0 }; p.Movement = p.Movement with { X = 0 };
@ -39,7 +43,7 @@ class PlayerEntity
{ {
var pR = p.Position + new Vector2(16, -8); var pR = p.Position + new Vector2(16, -8);
hasCollision = hasCollision =
world.HasChunkAt(pR) && world.GetChunkAt(pR).hasTileAt(pR); world.HasChunkAt(pR) && world.GetChunkAt(pR).HasTileAt(pR);
if (hasCollision) if (hasCollision)
{ {
p.Movement = p.Movement with { X = 0 }; p.Movement = p.Movement with { X = 0 };
@ -51,8 +55,8 @@ class PlayerEntity
var pL = p.Position; var pL = p.Position;
var pR = p.Position + new Vector2(16, 0); var pR = p.Position + new Vector2(16, 0);
hasCollision = hasCollision =
world.HasChunkAt(pL) && world.GetChunkAt(pL).hasTileAt(pL) world.HasChunkAt(pL) && world.GetChunkAt(pL).HasTileAt(pL)
|| world.HasChunkAt(pR) && world.GetChunkAt(pR).hasTileAt(pR); || world.HasChunkAt(pR) && world.GetChunkAt(pR).HasTileAt(pR);
if (hasCollision) if (hasCollision)
{ {
p.Movement = p.Movement with { Y = 0 }; p.Movement = p.Movement with { Y = 0 };
@ -64,8 +68,8 @@ class PlayerEntity
var pL = p.Position + new Vector2(0, -32); var pL = p.Position + new Vector2(0, -32);
var pR = p.Position + new Vector2(16, -32); var pR = p.Position + new Vector2(16, -32);
hasCollision = hasCollision =
world.HasChunkAt(pL) && world.GetChunkAt(pL).hasTileAt(pL) world.HasChunkAt(pL) && world.GetChunkAt(pL).HasTileAt(pL)
|| world.HasChunkAt(pR) && world.GetChunkAt(pR).hasTileAt(pR); || world.HasChunkAt(pR) && world.GetChunkAt(pR).HasTileAt(pR);
if (hasCollision) if (hasCollision)
{ {
p.Movement = p.Movement with { Y = 0 }; p.Movement = p.Movement with { Y = 0 };
@ -73,4 +77,4 @@ class PlayerEntity
} }
} while (hasCollision); } while (hasCollision);
} }
} }

View File

@ -1,3 +1,5 @@
namespace mine2d.core.data;
class Chunk class Chunk
{ {
public STile[,] Tiles { get; set; } = new STile[Constants.ChunkSize, Constants.ChunkSize]; public STile[,] Tiles { get; set; } = new STile[Constants.ChunkSize, Constants.ChunkSize];
@ -20,17 +22,17 @@ class Chunk
return this.Tiles[x, y]; return this.Tiles[x, y];
} }
public bool hasTileAt(Vector2 pos) public bool HasTileAt(Vector2 pos)
{ {
return this.hasTileAt((int)pos.X, (int)pos.Y); return this.HasTileAt((int)pos.X, (int)pos.Y);
} }
public bool hasTileAt(int x, int y) public bool HasTileAt(int x, int y)
{ {
var posInChunk = this.GetPositionInChunk(new Vector2(x, y)); var posInChunk = this.GetPositionInChunk(new Vector2(x, y));
var tileX = (int)Math.Floor(posInChunk.X / Constants.TileSize); var tileX = (int)Math.Floor(posInChunk.X / Constants.TileSize);
var tileY = (int)Math.Floor(posInChunk.Y / Constants.TileSize); var tileY = (int)Math.Floor(posInChunk.Y / Constants.TileSize);
return this.hasTile(tileX, tileY); return this.HasTile(tileX, tileY);
} }
public STile GetTileAt(Vector2 pos) public STile GetTileAt(Vector2 pos)
@ -59,14 +61,14 @@ class Chunk
this.SetTile(tileX, tileY, tile); this.SetTile(tileX, tileY, tile);
} }
public bool hasTile(int x, int y) public bool HasTile(int x, int y)
{ {
return x >= 0 && x < this.Tiles.Length && y >= 0 && y < this.Tiles.Length && this.Tiles[x, y].Id != 0; return x >= 0 && x < this.Tiles.Length && y >= 0 && y < this.Tiles.Length && this.Tiles[x, y].Id != 0;
} }
public bool hasTile(Vector2 pos) public bool HasTile(Vector2 pos)
{ {
return this.hasTile((int)pos.X, (int)pos.Y); return this.HasTile((int)pos.X, (int)pos.Y);
} }
public Vector2 GetPositionInChunk(Vector2 pos) public Vector2 GetPositionInChunk(Vector2 pos)
@ -74,4 +76,4 @@ class Chunk
return pos - new Vector2(this.X * Constants.ChunkSize * Constants.TileSize, return pos - new Vector2(this.X * Constants.ChunkSize * Constants.TileSize,
this.Y * Constants.ChunkSize * Constants.TileSize); this.Y * Constants.ChunkSize * Constants.TileSize);
} }
} }

View File

@ -1,3 +1,7 @@
using mine2d.core.tiles;
namespace mine2d.core.data;
struct STile struct STile
{ {
public int Id { get; set; } public int Id { get; set; }
@ -15,4 +19,4 @@ struct STile
{ {
return From((int)id); return From((int)id);
} }
} }

View File

@ -1,3 +1,5 @@
namespace mine2d.core.data;
class World class World
{ {
public Dictionary<string, Chunk> Chunks { get; set; } = new Dictionary<string, Chunk>(); public Dictionary<string, Chunk> Chunks { get; set; } = new Dictionary<string, Chunk>();
@ -75,6 +77,6 @@ class World
public bool HasTileAt(int x, int y) public bool HasTileAt(int x, int y)
{ {
return this.HasChunkAt(x, y) && this.GetChunkAt(x, y).hasTileAt(new Vector2(x, y)); return this.HasChunkAt(x, y) && this.GetChunkAt(x, y).HasTileAt(new Vector2(x, y));
} }
} }

View File

@ -0,0 +1,20 @@
using System.Reflection;
namespace mine2d.core.extensions;
public static class AssemblyExtensions
{
public static Type[] GetTypesSafe(this Assembly assembly)
{
try
{
#pragma warning disable IL2026
return assembly.GetTypes();
#pragma warning restore IL2026
}
catch (ReflectionTypeLoadException ex)
{
return ex.Types.Where(t => t != null).ToArray();
}
}
}

View File

@ -0,0 +1,23 @@
using System.Reflection;
namespace mine2d.core.extensions;
public static class TypeExtensions
{
public static Type MakeGenericTypeSafely(this Type type, params Type[] typeArguments)
{
try
{
#pragma warning disable IL2026
return type.MakeGenericType(typeArguments);
#pragma warning restore IL2026
}
catch (ReflectionTypeLoadException e)
{
var missingTypes = e.Types
.Where(t => typeArguments.Contains(t) && t != null);
throw new Exception($"Failed to make generic type {type} with arguments {string.Join(", ", missingTypes)}", e);
}
}
}

View File

@ -1,3 +1,7 @@
using mine2d.core.data;
namespace mine2d.core.tiles;
class Tile class Tile
{ {
public string Name { get; set; } public string Name { get; set; }
@ -14,11 +18,10 @@ class Tile
var (ptr, size) = rl.LoadToIntPtr("assets." + textureName + ".png"); var (ptr, size) = rl.LoadToIntPtr("assets." + textureName + ".png");
var sdlBuffer = SDL_RWFromMem(ptr, size); var sdlBuffer = SDL_RWFromMem(ptr, size);
var surface = IMG_Load_RW(sdlBuffer, 1); var surface = IMG_Load_RW(sdlBuffer, 1);
var texture = Context.Get().Renderer.CreateTextureFromSurface(surface); this.texture = Context.Get().Renderer.CreateTextureFromSurface(surface);
this.texture = texture;
if (breakingTexture == IntPtr.Zero) if (breakingTexture == IntPtr.Zero)
{ {
loadBreakingTexture(); LoadBreakingTexture();
} }
SDL_FreeSurface(surface); SDL_FreeSurface(surface);
} }
@ -35,8 +38,8 @@ class Tile
var camera = Context.Get().FrontendGameState.Camera; var camera = Context.Get().FrontendGameState.Camera;
renderer.DrawTexture( renderer.DrawTexture(
this.texture, this.texture,
(x - (int)camera.position.X) * scale, (x - (int)camera.Position.X) * scale,
(y - (int)camera.position.Y) * scale, (y - (int)camera.Position.Y) * scale,
Constants.TileSize * scale, Constants.TileSize * scale,
Constants.TileSize * scale Constants.TileSize * scale
); );
@ -45,8 +48,8 @@ class Tile
var breakingOffset = (int)((double)tile.Hits / this.Hardness * 4); var breakingOffset = (int)((double)tile.Hits / this.Hardness * 4);
renderer.DrawTexture( renderer.DrawTexture(
breakingTexture, breakingTexture,
(x - (int)camera.position.X) * scale, (x - (int)camera.Position.X) * scale,
(y - (int)camera.position.Y) * scale, (y - (int)camera.Position.Y) * scale,
Constants.TileSize * scale, Constants.TileSize * scale,
Constants.TileSize * scale, Constants.TileSize * scale,
breakingOffset, breakingOffset,
@ -56,7 +59,7 @@ class Tile
} }
} }
private static void loadBreakingTexture() private static void LoadBreakingTexture()
{ {
var rl = Context.Get().ResourceLoader; var rl = Context.Get().ResourceLoader;
var (ptr, size) = rl.LoadToIntPtr("assets.breaking.png"); var (ptr, size) = rl.LoadToIntPtr("assets.breaking.png");
@ -65,4 +68,4 @@ class Tile
breakingTexture = Context.Get().Renderer.CreateTextureFromSurface(surface); breakingTexture = Context.Get().Renderer.CreateTextureFromSurface(surface);
SDL_FreeSurface(surface); SDL_FreeSurface(surface);
} }
} }

View File

@ -1,11 +1,13 @@
enum Tiles : int namespace mine2d.core.tiles;
enum Tiles
{ {
stone = 1, Stone = 1,
} }
class TileRegistry class TileRegistry
{ {
public Dictionary<int, Tile> Tiles { get; set; } = new Dictionary<int, Tile>(); public Dictionary<int, Tile> Tiles { get; set; } = new();
public void RegisterTile() public void RegisterTile()
{ {
@ -16,4 +18,4 @@ class TileRegistry
{ {
return this.Tiles[id]; return this.Tiles[id];
} }
} }

View File

@ -1,3 +1,7 @@
using mine2d.core.data;
namespace mine2d.core.world;
class ChunkGenerator class ChunkGenerator
{ {
public static Chunk CreateFilledChunk(int x, int y, STile fill) public static Chunk CreateFilledChunk(int x, int y, STile fill)
@ -12,4 +16,4 @@ class ChunkGenerator
} }
return chunk; return chunk;
} }
} }

View File

@ -1,3 +1,5 @@
namespace mine2d.engine;
enum Sound { } enum Sound { }
class AudioPlayer class AudioPlayer
@ -12,7 +14,7 @@ class AudioPlayer
public void Register(Sound name, string path) public void Register(Sound name, string path)
{ {
var buffer = resourceLoader.LoadBytes(path); var buffer = this.resourceLoader.LoadBytes(path);
this.audioFiles.Add(name, buffer); this.audioFiles.Add(name, buffer);
} }
@ -22,4 +24,4 @@ class AudioPlayer
var sound = SDL2.SDL_mixer.Mix_QuickLoad_WAV(buffer); var sound = SDL2.SDL_mixer.Mix_QuickLoad_WAV(buffer);
SDL2.SDL_mixer.Mix_PlayChannel((int)name, sound, 0); SDL2.SDL_mixer.Mix_PlayChannel((int)name, sound, 0);
} }
} }

View File

@ -1,5 +1,4 @@
using static SDL2.SDL_ttf; namespace mine2d.engine;
using static SDL2.SDL;
class FontManager class FontManager
{ {
@ -17,20 +16,20 @@ class FontManager
public void RegisterFont(string name, string path, int fontSize) public void RegisterFont(string name, string path, int fontSize)
{ {
if (fonts.ContainsKey(name)) if (this.fonts.ContainsKey(name))
return; return;
var res = resourceLoader.LoadToIntPtr(path); var res = this.resourceLoader.LoadToIntPtr(path);
var sdlBuffer = SDL_RWFromConstMem(res.ptr, res.size); var sdlBuffer = SDL_RWFromConstMem(res.ptr, res.size);
var font = TTF_OpenFontRW(sdlBuffer, 1, fontSize); var font = TTF_OpenFontRW(sdlBuffer, 1, fontSize);
if (font == IntPtr.Zero) if (font == IntPtr.Zero)
{ {
throw new Exception("TTF_OpenFont failed"); throw new Exception("TTF_OpenFont failed");
} }
fonts.Add(name, font); this.fonts.Add(name, font);
} }
public IntPtr GetFont(string name) public IntPtr GetFont(string name)
{ {
return fonts[name]; return this.fonts[name];
} }
} }

View File

@ -1,30 +1,34 @@
namespace mine2d.engine;
abstract class Game abstract class Game
{ {
public const int TPS = 128; public const int Tps = 128;
private Queue<int> fpsQueue = new Queue<int>();
protected abstract void update(double dt); private bool running = true;
protected abstract void draw(); private Queue<int> fpsQueue = new();
protected abstract void Update(double dt);
protected abstract void Draw();
public void Run() public void Run()
{ {
var tLast = DateTime.Now; var tLast = DateTime.Now;
var tAcc = TimeSpan.Zero; var tAcc = TimeSpan.Zero;
while (true) while (this.running)
{ {
var dt = DateTime.Now - tLast; var dt = DateTime.Now - tLast;
tLast = DateTime.Now; tLast = DateTime.Now;
tAcc += dt; tAcc += dt;
var fps = (int)(1 / dt.TotalSeconds); var fps = (int)(1 / dt.TotalSeconds);
fpsQueue.Enqueue(fps); this.fpsQueue.Enqueue(fps);
while (fpsQueue.Count > fps) while (this.fpsQueue.Count > fps)
fpsQueue.Dequeue(); this.fpsQueue.Dequeue();
while (tAcc >= TimeSpan.FromSeconds(1.0 / TPS)) while (tAcc >= TimeSpan.FromSeconds(1.0 / Tps))
{ {
update(dt.TotalSeconds); this.Update(dt.TotalSeconds);
tAcc -= TimeSpan.FromSeconds(1.0 / TPS); tAcc -= TimeSpan.FromSeconds(1.0 / Tps);
} }
draw(); this.Draw();
} }
} }
} }

View File

@ -1,4 +1,8 @@
class PacketUtils using mine2d.backend.data;
namespace mine2d.engine;
public static class PacketUtils
{ {
public static string GetType(ValueType packet) public static string GetType(ValueType packet)
{ {
@ -7,16 +11,16 @@ class PacketUtils
{ {
Console.WriteLine(pp.Name); Console.WriteLine(pp.Name);
} }
var p = t.GetField("type"); var p = t.GetField(nameof(IPacket.Type));
if (p == null) if (p == null)
{ {
throw new Exception("p undef"); throw new ArgumentNullException(nameof(p), "p undef");
} }
var v = p.GetValue(packet); var v = p.GetValue(packet);
if (v == null) if (v == null)
{ {
throw new Exception("v undef"); throw new ArgumentNullException(nameof(v), "v undef");
} }
return (string)v; return (string)v;
} }
} }

View File

@ -1,6 +1,10 @@
using mine2d.engine.utils;
namespace mine2d.engine;
class Renderer class Renderer
{ {
private IntPtr renderer; private readonly IntPtr renderer;
private IntPtr font; private IntPtr font;
private SDL_Color color; private SDL_Color color;
@ -15,13 +19,13 @@ class Renderer
public void Clear() public void Clear()
{ {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_SetRenderDrawColor(this.renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer); SDL_RenderClear(this.renderer);
} }
public void Present() public void Present()
{ {
SDL_RenderPresent(renderer); SDL_RenderPresent(this.renderer);
} }
public void DrawRect(double x, double y, int w, int h) public void DrawRect(double x, double y, int w, int h)
@ -31,13 +35,15 @@ class Renderer
public void DrawRect(int x, int y, int w, int h) public void DrawRect(int x, int y, int w, int h)
{ {
SDL_Rect rect = new SDL_Rect(); var rect = new SDL_Rect
rect.x = x; {
rect.y = y; x = x,
rect.w = w; y = y,
rect.h = h; w = w,
h = h
};
SDL_RenderFillRect(renderer, ref rect); SDL_RenderFillRect(this.renderer, ref rect);
} }
public void DrawOutline(int x, int y, int w, int h) public void DrawOutline(int x, int y, int w, int h)
@ -50,24 +56,24 @@ class Renderer
h = h h = h
}; };
_ = SDL_RenderDrawRect(renderer, ref rect); _ = SDL_RenderDrawRect(this.renderer, ref rect);
} }
public void DrawLines(double[][] points) public void DrawLines(double[][] points)
{ {
SDL_Point[] sdlPoints = new SDL_Point[points.Length]; var sdlPoints = new SDL_Point[points.Length];
for (int i = 0; i < points.Length; i++) for (var i = 0; i < points.Length; i++)
{ {
sdlPoints[i].x = (int)points[i][0]; sdlPoints[i].x = (int)points[i][0];
sdlPoints[i].y = (int)points[i][1]; sdlPoints[i].y = (int)points[i][1];
} }
SDL_RenderDrawLines(renderer, sdlPoints, points.Length); SDL_RenderDrawLines(this.renderer, sdlPoints, points.Length);
} }
public void SetColor(int r, int g, int b, int a = 255) public void SetColor(int r, int g, int b, int a = 255)
{ {
SDL_SetRenderDrawColor(renderer, (byte)r, (byte)g, (byte)b, (byte)a); SDL_SetRenderDrawColor(this.renderer, (byte)r, (byte)g, (byte)b, (byte)a);
} }
public void SetFont(IntPtr font, SDL_Color color) public void SetFont(IntPtr font, SDL_Color color)
@ -79,24 +85,23 @@ class Renderer
public void SetFont(IntPtr font, Color color) public void SetFont(IntPtr font, Color color)
{ {
this.font = font; this.font = font;
this.color = color.toSDLColor(); this.color = color.ToSdlColor();
} }
public void DrawText(string text, int x, int y, bool center = false) public void DrawText(string text, int x, int y, bool center = false)
{ {
var surfaceMessage = TTF_RenderText_Solid(this.font, text, this.color); var surfaceMessage = TTF_RenderText_Solid(this.font, text, this.color);
var texture = SDL_CreateTextureFromSurface(this.renderer, surfaceMessage); var texture = SDL_CreateTextureFromSurface(this.renderer, surfaceMessage);
int width;
int height;
SDL_QueryTexture(texture, out _, out _, out width, out height); SDL_QueryTexture(texture, out _, out _, out var width, out var height);
SDL_Rect rect = new SDL_Rect(); var rect = new SDL_Rect
rect.x = x; {
rect.y = y; x = x,
rect.w = width; y = y,
rect.h = height; w = width,
h = height
};
if (center) if (center)
{ {
@ -111,12 +116,12 @@ class Renderer
public IntPtr GetRaw() public IntPtr GetRaw()
{ {
return renderer; return this.renderer;
} }
public IntPtr CreateTextureFromSurface(IntPtr surface) public IntPtr CreateTextureFromSurface(IntPtr surface)
{ {
return SDL_CreateTextureFromSurface(renderer, surface); return SDL_CreateTextureFromSurface(this.renderer, surface);
} }
public void DrawTexture(IntPtr texture, int x, int y, int w, int h) public void DrawTexture(IntPtr texture, int x, int y, int w, int h)
@ -149,4 +154,4 @@ class Renderer
}; };
_ = SDL_RenderCopy(this.renderer, texture, ref srcRect, ref rect); _ = SDL_RenderCopy(this.renderer, texture, ref srcRect, ref rect);
} }
} }

View File

@ -1,5 +1,7 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace mine2d.engine;
class ResourceLoader class ResourceLoader
{ {
private string assemblyName; private string assemblyName;
@ -14,11 +16,12 @@ class ResourceLoader
#if (DEBUG) #if (DEBUG)
Console.WriteLine("Loading resource: " + resourceName); Console.WriteLine("Loading resource: " + resourceName);
return File.ReadAllText(ToPath(resourceName)); return File.ReadAllText(ToPath(resourceName));
#endif #else
using var stream = this.GetType() using var stream = this.GetType()
.Assembly.GetManifestResourceStream($"{this.assemblyName}.{resourceName}"); .Assembly.GetManifestResourceStream($"{this.assemblyName}.{resourceName}");
using var reader = new StreamReader(stream!); using var reader = new StreamReader(stream!);
return reader.ReadToEnd(); return reader.ReadToEnd();
#endif
} }
public byte[] LoadBytes(string resourceName) public byte[] LoadBytes(string resourceName)
@ -49,4 +52,4 @@ class ResourceLoader
var s = resourceName.Split('.'); var s = resourceName.Split('.');
return String.Join('/', s[..^1]) + "." + s[^1]; return String.Join('/', s[..^1]) + "." + s[^1];
} }
} }

View File

@ -1,11 +1,13 @@
namespace mine2d.engine;
struct Line struct Line
{ {
public Vector2 start; public Vector2 Start;
public Vector2 end; public Vector2 End;
public Line(Vector2 start, Vector2 end) public Line(Vector2 start, Vector2 end)
{ {
this.start = start; this.Start = start;
this.end = end; this.End = end;
} }
} }

View File

@ -1,10 +1,12 @@
namespace mine2d.engine;
class Window class Window
{ {
IntPtr window; IntPtr window;
public Window(string title, int w, int h) public Window(string title, int w, int h)
{ {
window = SDL_CreateWindow( this.window = SDL_CreateWindow(
title, title,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
@ -41,4 +43,4 @@ class Window
{ {
return this.window; return this.window;
} }
} }

View File

@ -1,4 +1,6 @@
enum EventPriority : int namespace mine2d.engine.system;
enum EventPriority
{ {
Lowest = 0, Lowest = 0,
Low = 1, Low = 1,
@ -6,4 +8,4 @@ enum EventPriority : int
High = 3, High = 3,
Highest = 4, Highest = 4,
Important = 5, Important = 5,
} }

View File

@ -1,3 +1,5 @@
namespace mine2d.engine.system.annotations;
enum InteractorKind enum InteractorKind
{ {
Client, Client,
@ -19,4 +21,4 @@ class Interaction : Attribute
this.Type = type; this.Type = type;
this.Kind = kind; this.Kind = kind;
} }
} }

View File

@ -1,33 +1,35 @@
namespace mine2d.engine.utils;
class Color class Color
{ {
public int r, public int R,
g, G,
b, B,
a; A;
public Color(int r, int g, int b, int a) public Color(int r, int g, int b, int a)
{ {
this.r = r; this.R = r;
this.g = g; this.G = g;
this.b = b; this.B = b;
this.a = a; this.A = a;
} }
public Color(int r, int g, int b) public Color(int r, int g, int b)
{ {
this.r = r; this.R = r;
this.g = g; this.G = g;
this.b = b; this.B = b;
this.a = 255; this.A = 255;
} }
public SDL_Color toSDLColor() public SDL_Color ToSdlColor()
{ {
SDL_Color color = new(); SDL_Color color = new();
color.r = (byte)r; color.r = (byte)this.R;
color.g = (byte)g; color.g = (byte)this.G;
color.b = (byte)b; color.b = (byte)this.B;
color.a = (byte)a; color.a = (byte)this.A;
return color; return color;
} }
} }

View File

@ -1,7 +1,9 @@
namespace mine2d.engine.utils;
class Point class Point
{ {
public static double Distance(double x1, double y1, double x2, double y2) public static double Distance(double x1, double y1, double x2, double y2)
{ {
return Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2)); return Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2));
} }
} }

View File

@ -1,3 +1,10 @@
using mine2d.backend.data;
using mine2d.core;
using mine2d.core.data;
using mine2d.frontend.renderer;
namespace mine2d.frontend;
class Frontend : IFrontend class Frontend : IFrontend
{ {
public void Init() public void Init()
@ -44,7 +51,7 @@ class Frontend : IFrontend
} }
if (e.type == SDL_EventType.SDL_MOUSEBUTTONDOWN && e.button.button == SDL_BUTTON_LEFT) if (e.type == SDL_EventType.SDL_MOUSEBUTTONDOWN && e.button.button == SDL_BUTTON_LEFT)
{ {
var amp = ctx.FrontendGameState.MousePosition / ctx.FrontendGameState.Settings.GameScale + ctx.FrontendGameState.Camera.position; var amp = ctx.FrontendGameState.MousePosition / ctx.FrontendGameState.Settings.GameScale + ctx.FrontendGameState.Camera.Position;
if (ctx.GameState.World.HasChunkAt(amp)) if (ctx.GameState.World.HasChunkAt(amp))
{ {
var chunk = ctx.GameState.World.GetChunkAt(amp); var chunk = ctx.GameState.World.GetChunkAt(amp);
@ -122,9 +129,9 @@ class Frontend : IFrontend
if ( if (
e.key.keysym.scancode e.key.keysym.scancode
is SDL_Scancode.SDL_SCANCODE_A is SDL_Scancode.SDL_SCANCODE_A
or SDL_Scancode.SDL_SCANCODE_D or SDL_Scancode.SDL_SCANCODE_D
or SDL_Scancode.SDL_SCANCODE_W or SDL_Scancode.SDL_SCANCODE_W
or SDL_Scancode.SDL_SCANCODE_S or SDL_Scancode.SDL_SCANCODE_S
&& e.key.repeat == 0 && e.key.repeat == 0
&& e.type is SDL_EventType.SDL_KEYDOWN or SDL_EventType.SDL_KEYUP && e.type is SDL_EventType.SDL_KEYDOWN or SDL_EventType.SDL_KEYUP
) )
@ -156,29 +163,29 @@ class Frontend : IFrontend
{ {
if (player.Name == ctx.FrontendGameState.PlayerName) if (player.Name == ctx.FrontendGameState.PlayerName)
{ {
ctx.Renderer.SetColor(0, 0, 255, 255); ctx.Renderer.SetColor(0, 0, 255);
} }
else else
{ {
ctx.Renderer.SetColor(255, 0, 0, 255); ctx.Renderer.SetColor(255, 0, 0);
} }
ctx.Renderer.DrawRect( ctx.Renderer.DrawRect(
(player.Position.X - (int)camera.position.X) * scale, (player.Position.X - (int)camera.Position.X) * scale,
(player.Position.Y - (int)camera.position.Y) * scale - 32 * scale, (player.Position.Y - (int)camera.Position.Y) * scale - 32 * scale,
16 * scale, 16 * scale,
32 * scale 32 * scale
); );
}); });
var absoluteMousePos = ctx.FrontendGameState.MousePosition / ctx.FrontendGameState.Settings.GameScale + camera.position; var absoluteMousePos = ctx.FrontendGameState.MousePosition / ctx.FrontendGameState.Settings.GameScale + camera.Position;
if (ctx.GameState.World.HasTileAt((int)absoluteMousePos.X, (int)absoluteMousePos.Y)) if (ctx.GameState.World.HasTileAt((int)absoluteMousePos.X, (int)absoluteMousePos.Y))
{ {
var a = Constants.TileSize; var a = Constants.TileSize;
var tilePos = new Vector2(absoluteMousePos.X - absoluteMousePos.X % a, absoluteMousePos.Y - absoluteMousePos.Y % a); var tilePos = new Vector2(absoluteMousePos.X - absoluteMousePos.X % a, absoluteMousePos.Y - absoluteMousePos.Y % a);
ctx.Renderer.SetColor(255, 255, 255, 255); ctx.Renderer.SetColor(255, 255, 255);
ctx.Renderer.DrawOutline( ctx.Renderer.DrawOutline(
(int)tilePos.X * scale - (int)camera.position.X * scale, (int)tilePos.X * scale - (int)camera.Position.X * scale,
(int)tilePos.Y * scale - (int)camera.position.Y * scale, (int)tilePos.Y * scale - (int)camera.Position.Y * scale,
16 * scale, 16 * scale,
16 * scale 16 * scale
); );
@ -186,4 +193,4 @@ class Frontend : IFrontend
ctx.Renderer.Present(); ctx.Renderer.Present();
} }
} }

View File

@ -1,5 +1,7 @@
namespace mine2d.frontend;
interface IFrontend interface IFrontend
{ {
public void Process(); public void Process();
public void Init(); public void Init();
} }

View File

@ -1,4 +1,6 @@
namespace mine2d.frontend.renderer;
interface IRenderer interface IRenderer
{ {
public void Render(); public void Render();
} }

View File

@ -1,3 +1,7 @@
using mine2d.core;
namespace mine2d.frontend.renderer;
class WorldRenderer : IRenderer class WorldRenderer : IRenderer
{ {
public void Render() public void Render()
@ -25,4 +29,4 @@ class WorldRenderer : IRenderer
} }
} }
} }
} }

View File

@ -1,6 +1,9 @@
using System.Text; using System.Text;
using Newtonsoft.Json.Linq; using mine2d.backend.data;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace mine2d.network;
class Converter class Converter
{ {
@ -33,4 +36,4 @@ class Converter
var jsonString = JsonConvert.SerializeObject(packet); var jsonString = JsonConvert.SerializeObject(packet);
return Encoding.UTF8.GetBytes(jsonString); return Encoding.UTF8.GetBytes(jsonString);
} }
} }

View File

@ -1,3 +1,8 @@
using mine2d.core;
using mine2d.core.data;
namespace mine2d.state;
class FrontendGameState class FrontendGameState
{ {
public Vector2 MovementInput; public Vector2 MovementInput;
@ -14,7 +19,7 @@ class FrontendGameState
class Settings class Settings
{ {
public int GameScale = 4; public int GameScale = 4;
public int UIScale = 4; public int UiScale = 4;
public bool ShowCollision = true; public bool ShowCollision = true;
public bool Fullscreen = false; public bool Fullscreen = false;
} }
@ -23,4 +28,4 @@ class GameState
{ {
public List<Player> Players { get; set; } = new List<Player>(); public List<Player> Players { get; set; } = new List<Player>();
public World World { get; set; } public World World { get; set; }
} }

View File

@ -1,3 +1,7 @@
using mine2d.engine;
namespace mine2d.state;
class Player class Player
{ {
public string Name; public string Name;
@ -11,4 +15,4 @@ class Player
{ {
return new Line(this.Position, this.Position + new Vector2(16, 0)); return new Line(this.Position, this.Position + new Vector2(16, 0));
} }
} }