-- 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 -- 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 GameUI.drawBacking() local cellSize = width / gridWidth local sidebarWidth = cellSize * 2 if gameUiBox.w < sidebarWidth or not uiVennCanvas then return end local previousCanvas = love.graphics.getCanvas() 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 if has[color] then local layout = vennLayout[color] local rgb = channelColor[color] if active[color] then love.graphics.setColor(rgb[1], rgb[2], rgb[3], 1) love.graphics.circle("fill", layout.x, layout.y, radius) else drawDottedCircle(layout.x, layout.y, radius, rgb, dotRadius) end end end love.graphics.setCanvas(previousCanvas) GameUI.drawVennOverlay() end 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 return GameUI