chroma_solstice/game_ui.lua

101 lines
3.2 KiB
Lua
Raw Permalink Normal View History

2026-08-12 14:52:06 -04:00
-- Player-facing HUD drawn into gameCanvas. Keeping it here (rather than in
-- the editor sidebar) means its RGB circles use the same screen blend as the
-- room, so their overlaps are the real additive colour combinations.
local GameUI = {}
local channelColor = {
red = {1, 0, 0},
green = {0, 1, 0},
blue = {0, 0, 1},
}
local vennSize = 32
local vennLayout = {
red = {x = 12, y = 10},
green = {x = 20, y = 10},
blue = {x = 16, y = 18},
}
local function drawDottedCircle(x, y, radius, color, dotRadius)
local dots = math.max(14, math.floor((2 * math.pi * radius) / (dotRadius * 4)))
love.graphics.setColor(color[1], color[2], color[3], 1)
for index = 0, dots - 1 do
local angle = index / dots * math.pi * 2
love.graphics.circle("fill", x + math.cos(angle) * radius, y + math.sin(angle) * radius, dotRadius)
end
end
function GameUI.init()
uiVennCanvas = love.graphics.newCanvas(vennSize, vennSize)
uiVennCanvas:setFilter("nearest", "nearest")
end
function GameUI.drawBacking()
if not gameUiBox then return end
love.graphics.setBlendMode("alpha")
love.graphics.setColor(0, 0, 0, 1)
love.graphics.rectangle("fill", gameUiBox.x, gameUiBox.y, gameUiBox.w, gameUiBox.h)
end
function GameUI.drawVennOverlay()
if not gameUiBox or not uiVennCanvas then return end
local cellSize = width / gridWidth
local sidebarWidth = cellSize * 2
if gameUiBox.w < sidebarWidth then return end
love.graphics.setBlendMode("screen")
love.graphics.setColor(1, 1, 1, 1)
local scale = cellSize / 22
local vennWidth = vennSize * scale
local left = gameUiBox.x + (gameUiBox.w - vennWidth) / 2
love.graphics.draw(uiVennCanvas, left, cellSize * 1.1, 0, scale, scale)
end
2026-08-21 10:57:32 -04:00
-- Render the venn from explicit colour sets: `has` are the channels the player
-- possesses (drawn as a circle), `active` the subset shown filled (the rest
-- dotted). Restores whatever canvas was bound, so callers drawing straight to
-- the screen (e.g. the map overlay) work as well as the in-game HUD pass.
function GameUI.drawColorVennChannels(has, active)
if not gameUiBox then return end
2026-08-12 14:52:06 -04:00
GameUI.drawBacking()
local cellSize = width / gridWidth
local sidebarWidth = cellSize * 2
if gameUiBox.w < sidebarWidth or not uiVennCanvas then return end
2026-08-21 10:57:32 -04:00
local previousCanvas = love.graphics.getCanvas()
2026-08-12 14:52:06 -04:00
love.graphics.setCanvas(uiVennCanvas)
love.graphics.clear(0, 0, 0, 0)
love.graphics.setBlendMode("screen")
local radius = 9
local dotRadius = 1
for _, color in ipairs({"red", "green", "blue"}) do
2026-08-21 10:57:32 -04:00
if has[color] then
2026-08-12 14:52:06 -04:00
local layout = vennLayout[color]
local rgb = channelColor[color]
if active[color] then
love.graphics.setColor(rgb[1], rgb[2], rgb[3], 1)
2026-08-21 10:57:32 -04:00
love.graphics.circle("fill", layout.x, layout.y, radius)
2026-08-12 14:52:06 -04:00
else
2026-08-21 10:57:32 -04:00
drawDottedCircle(layout.x, layout.y, radius, rgb, dotRadius)
2026-08-12 14:52:06 -04:00
end
end
end
2026-08-21 10:57:32 -04:00
love.graphics.setCanvas(previousCanvas)
2026-08-12 14:52:06 -04:00
GameUI.drawVennOverlay()
end
2026-08-21 10:57:32 -04:00
function GameUI.drawColorVenn(room)
if not room or not gameUiBox then return end
local has, active = {}, {}
for _, color in ipairs({"red", "green", "blue"}) do
if room.player[color] then has[color] = true end
end
for _, color in ipairs(room:getActiveColors()) do active[color] = true end
GameUI.drawColorVennChannels(has, active)
end
2026-08-12 14:52:06 -04:00
return GameUI