From ecb6379d3c7894da8f3db4de81c56c45153a5a91 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 18 Jul 2025 20:04:44 +0200 Subject: [PATCH] Adding initial render system --- render/constants.go | 16 +++++++++ render/render.go | 83 +++++++++++++++++++++++++++++++++++++++++++++ render/tile.go | 28 +++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 render/constants.go create mode 100644 render/render.go create mode 100644 render/tile.go diff --git a/render/constants.go b/render/constants.go new file mode 100644 index 0000000..dfa0f0a --- /dev/null +++ b/render/constants.go @@ -0,0 +1,16 @@ +package render + +const ( + // WIDTH defines the width of the rendering surface in pixels. + // This is the logical resolution of the renderer, not the actual window size. + // The final image will be scaled to fit the window. + WIDTH = 224 + + // HEIGHT defines the height of the rendering surface in pixels. + // Like WIDTH, this is the fixed resolution used for tile-based rendering. + HEIGHT = 288 + + // TileSize defines the size of a single tile in pixels. + // All tile-based rendering operates on this 8×8 pixel grid. + TileSize = 8 +) diff --git a/render/render.go b/render/render.go new file mode 100644 index 0000000..2e974f9 --- /dev/null +++ b/render/render.go @@ -0,0 +1,83 @@ +// Package render provides a tile-based rendering system inspired by the NES 8-bit graphics API. +// +// This is not an emulator, but rather a rendering layer designed to mimic the style +// and constraints of 8-bit consoles. It exposes a simplified API for tile-based drawing, +// allowing rendering of graphics in a grid-based fashion similar to early consoles. +// +// The render target is an off-screen texture with a fixed resolution of 224×288 pixels, +// divided into 8x8 pixel tiles: +// +// - Screen dimensions: 28 tiles wide, 36 tiles high +// - Tile size: 8x8 pixels +// +// This off-screen texture is then scaled to fit the actual window size when presented to the screen. +// Rendering is double-buffered and must follow a Begin/Draw/End pattern each frame. +package render + +import rl "github.com/gen2brain/raylib-go/raylib" + +// target is the off-screen render target where all drawing operations are performed. +// It has a fixed resolution of WIDTHxHEIGHT and is later scaled to the window size. +var target rl.RenderTexture2D + +// Init initializes the rendering system. +// +// It creates an off-screen render texture with the fixed resolution defined by WIDTH and HEIGHT. +// This texture is where all tiles and game graphics are drawn before being scaled and presented. +func Init() { + target = rl.LoadRenderTexture(WIDTH, HEIGHT) +} + +// Exit shuts down the rendering system. +// +// It unloads the render texture and frees any associated GPU resources. +// This should be called before the application exits. +func Exit() { + rl.UnloadRenderTexture(target) +} + +// Begin prepares the rendering system for a new frame. +// +// It binds the off-screen texture target and clears it to a black background. +// All tile drawing operations (e.g., DrawTile) should occur after Begin() and +// before End(). +func Begin() { + // Bind texture so that all draw calls after are applied to target texture + rl.BeginTextureMode(target) + // Clear background + rl.ClearBackground(rl.Black) +} + +// End finalizes the current frame and displays it on the screen. +// +// It ends the off-screen drawing session and stretches the texture target +// to fill the window. This function must be called after all drawing is done. +func End() { + // End drawing to the texture target. + rl.EndTextureMode() + + // Begin drawing to screen buffer. + rl.BeginDrawing() + + // Define source rectangle (flip vertically to match coordinate systems). + src := rl.Rectangle{ + X: 0, + Y: 0, + Width: float32(target.Texture.Width), + Height: -float32(target.Texture.Height), + } + + // Define destination rectangle (window). + dest := rl.Rectangle{ + X: 0, + Y: 0, + Width: float32(rl.GetScreenWidth()), + Height: float32(rl.GetScreenHeight()), + } + + // Blit the off-screen texture to the screen. + rl.DrawTexturePro(target.Texture, src, dest, rl.Vector2Zero(), 0.0, rl.White) + + // End drawing to screen. + rl.EndDrawing() +} diff --git a/render/tile.go b/render/tile.go new file mode 100644 index 0000000..2aab1aa --- /dev/null +++ b/render/tile.go @@ -0,0 +1,28 @@ +package render + +import ( + "pacman/assets" + + rl "github.com/gen2brain/raylib-go/raylib" +) + +// DrawTile draws a single tile at the specified tile coordinates (x, y). +// +// The coordinates are in tile space, not pixels. The top-left tile is (0, 0), +// and the bottom-right is (27, 35) given the fixed resolution and tile size. +// +// The appearance of the tile is determined by the provided assets.Tile value. +func DrawTile(x, y uint8, tile assets.Tile) { + px := int32(x) * TileSize + py := int32(y) * TileSize + + // For now, just draw simple circles and rectangles. + switch tile { + case assets.TILE_PELLET: + rl.DrawCircle(px+(TileSize/2), py+(TileSize/2), 1, rl.Beige) + case assets.TILE_POWER_PELLET: + rl.DrawCircle(px+(TileSize/2), py+(TileSize/2), 2, rl.Beige) + case assets.TILE_WALL: + rl.DrawRectangle(px, py, TileSize, TileSize, rl.DarkBlue) + } +}