using Mine2d.engine; using Mine2d.game.core; using Mine2d.game.core.world; namespace Mine2d.game.frontend.renderer; public class WorldRenderer : IRenderer { private readonly IntPtr light; private IntPtr overlay; private int overlayWidth, overlayHeight; public WorldRenderer() { var rl = Context.Get().ResourceLoader; var (ptr, size) = rl.LoadToIntPtr("assets.light2.png"); var sdlBuffer = SDL_RWFromMem(ptr, size); var surface = IMG_Load_RW(sdlBuffer, 1); this.light = Context.Get().Renderer.CreateTextureFromSurface(surface); SDL_FreeSurface(surface); var (w, h) = Context.Get().Window.GetSize(); this.overlay = SDL_CreateTexture(Context.Get().Renderer.GetRaw(), SDL_PIXELFORMAT_RGBA8888, (int)SDL_TextureAccess.SDL_TEXTUREACCESS_TARGET, w, h); } public void Render() { var ctx = Context.Get(); var world = ctx.GameState.World; var tileRegistry = ctx.TileRegistry; Renderer.ProcessStatus(SDL_SetRenderTarget(ctx.Renderer.GetRaw(), this.overlay)); var (ww, wh) = ctx.Window.GetSize(); if (wh != this.overlayHeight || ww != this.overlayWidth) { SDL_DestroyTexture(this.overlay); this.overlay = SDL_CreateTexture(ctx.Renderer.GetRaw(), SDL_PIXELFORMAT_RGBA8888, (int)SDL_TextureAccess.SDL_TEXTUREACCESS_TARGET, ww, wh); this.overlayWidth = ww; this.overlayHeight = wh; } ClearTexture(this.overlay); var renderer = Context.Get().Renderer; var scale = ctx.FrontendGameState.Settings.GameScale; var camera = Context.Get().FrontendGameState.Camera; Renderer.ProcessStatus(SDL_SetTextureBlendMode(this.light, SDL_BlendMode.SDL_BLENDMODE_BLEND)); var player = PlayerEntity.GetSelf(); foreach (var (_, chunk) in world.Chunks) { if (player == null) { continue; } if ((player.Position - new Vector2(chunk.X * Constants.ChunkSize * Constants.TileSize, chunk.Y * Constants.ChunkSize * Constants.TileSize)).Length() > 1300) { continue; } for (var y = 0; y < Constants.ChunkSize; y++) { for (var x = 0; x < Constants.ChunkSize; x++) { var stile = chunk.GetTile(x, y); var chunkOffsetX = chunk.X * Constants.TileSize * Constants.ChunkSize; var chunkOffsetY = chunk.Y * Constants.TileSize * Constants.ChunkSize; var drawX = x * 16 + chunkOffsetX; var drawY = y * 16 + chunkOffsetY; if (stile.Id == 0 || !tileRegistry.GetTile(stile.Id).IsSolid()) { Renderer.ProcessStatus(SDL_SetRenderTarget(ctx.Renderer.GetRaw(), this.overlay)); renderer.DrawTexture( this.light, (drawX - (int)camera.Position.X - 40) * scale, (drawY - (int)camera.Position.Y - 40) * scale, 96 * scale, 96 * scale ); } Renderer.ProcessStatus(SDL_SetRenderTarget(ctx.Renderer.GetRaw(), IntPtr.Zero)); if (stile.Id != 0) { var tile = tileRegistry.GetTile(stile.Id); tile.Render(drawX, drawY, stile); } // Console.WriteLine( // (chunk.Y * Constants.ChunkSize) + y + " "+ // (chunk.X * Constants.ChunkSize) + x // ); if (ctx.FrontendGameState.DebugState.Overlay == "noise") { ctx.Renderer.DrawText("" + Math.Round(ChunkGenerator.Noise.coherentNoise( (chunk.X * Constants.ChunkSize) + x, (int)(((chunk.Y * Constants.ChunkSize) + y)*0.7), 0 ), 4), (drawX - (int)camera.Position.X) * scale, (drawY - (int)camera.Position.Y) * scale); } } } } Renderer.ProcessStatus(SDL_SetRenderTarget(ctx.Renderer.GetRaw(), IntPtr.Zero)); if (ctx.FrontendGameState.DebugState.NoFog) { return; } Renderer.ProcessStatus(SDL_SetTextureBlendMode(this.overlay, SDL_BlendMode.SDL_BLENDMODE_MUL)); Renderer.ProcessStatus(SDL_RenderCopy(ctx.Renderer.GetRaw(), this.overlay, IntPtr.Zero, IntPtr.Zero)); Renderer.ProcessStatus(SDL_SetRenderTarget(ctx.Renderer.GetRaw(), IntPtr.Zero)); } public static void ClearTexture(IntPtr texture) { var ctx = Context.Get(); var renderer = ctx.Renderer; var (w, h) = renderer.GetTextureSize(texture); var clearRect = new SDL_Rect { x = 0, y = 0, w = w, h = h }; Renderer.ProcessStatus(SDL_SetRenderTarget(ctx.Renderer.GetRaw(), texture)); _ = SDL_SetRenderDrawColor(ctx.Renderer.GetRaw(), 0, 0, 0, 255); Renderer.ProcessStatus(SDL_RenderFillRect(ctx.Renderer.GetRaw(), ref clearRect)); } }