summaryrefslogtreecommitdiff
path: root/main.lua
diff options
context:
space:
mode:
authorcursed22bc <admin@pixeldawn.org>2026-03-10 23:16:58 +0200
committercursed22bc <admin@pixeldawn.org>2026-03-10 23:16:58 +0200
commit0dce23b4b24ae74889550dc0b81ea393c047f929 (patch)
tree849eec42d84928ea235a51c1d6df984282e3af91 /main.lua
parentd2dab6c8efcf126503c004e935fda9190533729c (diff)
evil window hacks
Diffstat (limited to 'main.lua')
-rw-r--r--main.lua216
1 files changed, 203 insertions, 13 deletions
diff --git a/main.lua b/main.lua
index 0d66c98..608d82a 100644
--- a/main.lua
+++ b/main.lua
@@ -1,7 +1,7 @@
local VIRTUAL_WIDTH, VIRTUAL_HEIGHT = 16*10*5, 9*10*5
local CANVAS_PADDING = 6
-DEBUG = false
+DEBUG = true
local CANVAS_WIDTH = VIRTUAL_WIDTH + CANVAS_PADDING
local CANVAS_HEIGHT = VIRTUAL_HEIGHT + CANVAS_PADDING
@@ -13,6 +13,10 @@ local offsetX, offsetY = 0, 0
local dpiScale = 1
local canvas = nil
local smoothCameraShader = nil
+local menuBgShader = nil
+local liquidShader = nil
+local menuCanvas = nil
+local menuTime = 0
local shaderEnabled = true
local cameraModule = require("camera")
@@ -22,7 +26,7 @@ local HUD = require("hud")
local hud = nil
local previousState = nil
-local currentState = "game"
+local currentState = "menu"
local currentMapPath = "assets/maps/tilemap.lua"
local currentTilesets = {
tileset = { path = "assets/maps/tileset.png", tilewidth = 16, tileheight = 16 },
@@ -30,6 +34,15 @@ local currentTilesets = {
}
local world = nil
+local menuItems = {}
+local menuHover = nil
+
+local gameFinishPhase = nil
+local gameFinishTimer = 0
+local irisRadius = 0
+local IRIS_CLOSE_DURATION = 1.5
+local TEXT_DISPLAY_DURATION = 5.0
+
local states = {
game = {},
menu = {},
@@ -39,41 +52,185 @@ local states = {
local function recalcScale(w, h)
dpiScale = (love.window.getDPIScale and love.window.getDPIScale()) or 1
- scale = math.max(1, math.floor(math.min(w / VIRTUAL_WIDTH, h / VIRTUAL_HEIGHT) / dpiScale))
+ scale = math.max(1, math.min(w / VIRTUAL_WIDTH, h / VIRTUAL_HEIGHT) / dpiScale)
finalScale = scale * dpiScale
offsetX = math.floor((w - VIRTUAL_WIDTH * finalScale) / 2)
offsetY = math.floor((h - VIRTUAL_HEIGHT * finalScale) / 2)
end
+local function screenToCanvas(sx, sy)
+ local drawX = offsetX - (CANVAS_PADDING * finalScale) / 2
+ local drawY = offsetY - (CANVAS_PADDING * finalScale) / 2
+ return (sx - drawX) / finalScale, (sy - drawY) / finalScale
+end
+
+local function buildMenuItems()
+ local btnW, btnH = 120, 32
+ local centerX = CANVAS_WIDTH / 2
+ local centerY = CANVAS_HEIGHT / 2
+ local spacing = 12
+ local totalH = 2 * btnH + spacing
+ local startY = centerY - totalH / 2 + 20
+ menuItems = {
+ { label = "Play", x = centerX - btnW / 2, y = startY, w = btnW, h = btnH, action = "play" },
+ { label = "Exit", x = centerX - btnW / 2, y = startY + btnH + spacing, w = btnW, h = btnH, action = "exit" },
+ }
+end
+
function states.game.load()
local World = require("world")
world = World:new()
world:load(currentMapPath, currentTilesets)
local target = world:getPlayer() or { x = 0, y = 0, width = 16, height = 16 }
- camera = cameraModule:new(target, VIRTUAL_WIDTH/2, VIRTUAL_HEIGHT/2, true, WORLD_TO_CANVAS)
+ camera = cameraModule:new(target, VIRTUAL_WIDTH / 2, VIRTUAL_HEIGHT / 2, true, WORLD_TO_CANVAS)
world:setCamera(camera)
hud = HUD:new()
+ gameFinishPhase = nil
+ gameFinishTimer = 0
+ irisRadius = 0
end
function states.game.update(dt)
- if world then world:update(dt) end
+ if not world then return end
+
+ if not gameFinishPhase then
+ world:update(dt)
+ if world.doorOpened then
+ gameFinishPhase = "iris"
+ gameFinishTimer = 0
+ irisRadius = math.sqrt((CANVAS_WIDTH / 2) ^ 2 + (CANVAS_HEIGHT / 2) ^ 2)
+ end
+ elseif gameFinishPhase == "iris" then
+ world:update(dt)
+ gameFinishTimer = gameFinishTimer + dt
+ local maxR = math.sqrt((CANVAS_WIDTH / 2) ^ 2 + (CANVAS_HEIGHT / 2) ^ 2)
+ local progress = math.min(gameFinishTimer / IRIS_CLOSE_DURATION, 1)
+ local eased = 1 - (1 - progress) ^ 2
+ irisRadius = maxR * (1 - eased)
+ if progress >= 1 then
+ gameFinishPhase = "text"
+ gameFinishTimer = 0
+ irisRadius = 0
+ end
+ elseif gameFinishPhase == "text" then
+ gameFinishTimer = gameFinishTimer + dt
+ if gameFinishTimer >= TEXT_DISPLAY_DURATION then
+ gameFinishPhase = nil
+ gameFinishTimer = 0
+ currentState = "menu"
+ states.menu.load()
+ end
+ end
end
function states.game.draw()
- if camera then camera:set() end
- if world then world:draw() end
- if camera then camera:unset() end
+ if gameFinishPhase ~= "text" then
+ if camera then camera:set() end
+ if world then world:draw() end
+ if camera then camera:unset() end
+ end
+
+ if gameFinishPhase == "iris" then
+ local cx = CANVAS_WIDTH / 2
+ local cy = CANVAS_HEIGHT / 2
+ local outerR = math.sqrt(cx * cx + cy * cy) + 10
+ local innerR = math.max(irisRadius, 0)
+ local segments = 64
+ local verts = {}
+ for i = 0, segments do
+ local angle = (i / segments) * math.pi * 2
+ local cs, sn = math.cos(angle), math.sin(angle)
+ verts[#verts + 1] = { cx + cs * innerR, cy + sn * innerR, 0, 0, 0, 0, 0, 1 }
+ verts[#verts + 1] = { cx + cs * outerR, cy + sn * outerR, 0, 0, 0, 0, 0, 1 }
+ end
+ local mesh = love.graphics.newMesh(verts, "strip", "stream")
+ love.graphics.setColor(1, 1, 1, 1)
+ love.graphics.draw(mesh)
+ elseif gameFinishPhase == "text" then
+ love.graphics.setColor(0, 0, 0, 1)
+ love.graphics.rectangle("fill", 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)
+ local font = fonts.get(14)
+ love.graphics.setFont(font)
+ love.graphics.setColor(1, 1, 1, 1)
+ love.graphics.printf("The Frog Escaped the Evil Aquarium", 0, CANVAS_HEIGHT / 2 - font:getHeight() / 2, CANVAS_WIDTH, "center")
+ love.graphics.setFont(fonts.default)
+ end
end
function states.menu.load()
camera = nil
world = nil
+ hud = nil
+ gameFinishPhase = nil
+ gameFinishTimer = 0
+ irisRadius = 0
+ menuTime = 0
+ love.mouse.setVisible(true)
+ menuHover = nil
end
-function states.menu.update(dt) end
+function states.menu.update(dt)
+ menuTime = menuTime + dt
+ local mx, my = love.mouse.getPosition()
+ local cx, cy = screenToCanvas(mx, my)
+ menuHover = nil
+ for _, btn in ipairs(menuItems) do
+ if cx >= btn.x and cx <= btn.x + btn.w and cy >= btn.y and cy <= btn.y + btn.h then
+ menuHover = btn.action
+ break
+ end
+ end
+end
function states.menu.draw()
- love.graphics.print("Menu (state machine ready)", 10, 10)
+ local prevCanvas = love.graphics.getCanvas()
+
+ love.graphics.setCanvas(menuCanvas)
+ love.graphics.clear()
+ if menuBgShader then
+ love.graphics.setShader(menuBgShader)
+ end
+ love.graphics.setColor(1, 1, 1, 1)
+ love.graphics.rectangle("fill", 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)
+ love.graphics.setShader()
+ love.graphics.setCanvas(prevCanvas)
+
+ if liquidShader then
+ liquidShader:send("scene", menuCanvas)
+ liquidShader:send("time", menuTime)
+ liquidShader:send("resolution", { CANVAS_WIDTH, CANVAS_HEIGHT })
+ liquidShader:send("splashCenter", { -10.0, -10.0 })
+ liquidShader:send("splashTime", 0.0)
+ love.graphics.setShader(liquidShader)
+ end
+ love.graphics.setColor(1, 1, 1, 1)
+ love.graphics.draw(menuCanvas, 0, 0)
+ love.graphics.setShader()
+
+ local titleFont = fonts.get(20)
+ love.graphics.setFont(titleFont)
+ love.graphics.setColor(1, 1, 1, 1)
+ love.graphics.printf("The Frog Escapes Evil Aquarium", 0, CANVAS_HEIGHT / 2 - 80, CANVAS_WIDTH, "center")
+
+ local btnFont = fonts.get(20)
+ love.graphics.setFont(btnFont)
+ for _, btn in ipairs(menuItems) do
+ local hover = menuHover == btn.action
+
+ if hover then
+ love.graphics.setColor(1, 1, 1, 1)
+ love.graphics.setLineWidth(1)
+ love.graphics.rectangle("line", btn.x, btn.y, btn.w, btn.h)
+ end
+
+ love.graphics.setColor(1, 1, 1, 1)
+ local tw = btnFont:getWidth(btn.label)
+ local th = btnFont:getHeight()
+ love.graphics.print(btn.label, btn.x + btn.w / 2 - tw / 2, btn.y + btn.h / 2 - th / 2)
+ end
+
+ love.graphics.setFont(fonts.default)
+ love.graphics.setColor(1, 1, 1, 1)
end
function states.settings.load()
@@ -103,7 +260,7 @@ end
function love.load()
love.graphics.setDefaultFilter("nearest", "nearest")
- love.window.setTitle("Openformer")
+ love.window.setTitle("The Frog Escapes Evil Aquarium")
fonts.load()
love.graphics.setFont(fonts.default)
@@ -116,10 +273,20 @@ function love.load()
print("Warning: smooth_camera.glsl not loaded, using fallback (no sub-pixel offset)")
end
+ local ok2, shader2 = pcall(love.graphics.newShader, "shaders/missing_texture.glsl")
+ menuBgShader = ok2 and shader2 or nil
+
+ local ok3, shader3 = pcall(love.graphics.newShader, "shaders/liquid.glsl")
+ liquidShader = ok3 and shader3 or nil
+
+ menuCanvas = love.graphics.newCanvas(CANVAS_WIDTH, CANVAS_HEIGHT)
+ menuCanvas:setFilter("nearest", "nearest")
+
local w, h = love.graphics.getWidth(), love.graphics.getHeight()
recalcScale(w, h)
+ buildMenuItems()
- love.mouse.setVisible(false)
+ love.mouse.setVisible(true)
local state = states[currentState]
if state and state.load then state.load() end
@@ -130,6 +297,9 @@ function love.resize(w, h)
if canvas then canvas:release() end
canvas = love.graphics.newCanvas(CANVAS_WIDTH, CANVAS_HEIGHT)
canvas:setFilter("nearest", "nearest")
+ if menuCanvas then menuCanvas:release() end
+ menuCanvas = love.graphics.newCanvas(CANVAS_WIDTH, CANVAS_HEIGHT)
+ menuCanvas:setFilter("nearest", "nearest")
end
function love.update(dt)
@@ -144,6 +314,12 @@ function love.keypressed(key, scancode, isrepeat)
if key == "f1" and DEBUG then
shaderEnabled = not shaderEnabled
end
+ if key == "escape" and not isrepeat then
+ if currentState == "game" or currentState == "hud" then
+ currentState = "menu"
+ states.menu.load()
+ end
+ end
if key == "tab" and not isrepeat then
if currentState == "game" then
previousState = currentState
@@ -164,7 +340,21 @@ function love.keypressed(key, scancode, isrepeat)
end
function love.mousepressed(x, y, button)
- if currentState == "hud" and hud then
+ if currentState == "menu" and button == 1 then
+ local cx, cy = screenToCanvas(x, y)
+ for _, btn in ipairs(menuItems) do
+ if cx >= btn.x and cx <= btn.x + btn.w and cy >= btn.y and cy <= btn.y + btn.h then
+ if btn.action == "play" then
+ currentState = "game"
+ states.game.load()
+ love.mouse.setVisible(false)
+ elseif btn.action == "exit" then
+ love.event.quit()
+ end
+ break
+ end
+ end
+ elseif currentState == "hud" and hud then
hud:mousepressed(x, y, button)
end
end