oma-lander/game/camera.lua
28allday 790ca87bfb Lunar Lander: complete Love2D game with Omarchy integration
Faithful recreation of Atari Lunar Lander (1979) with vector wireframe aesthetic.
Auto-detects Omarchy system theme and font on launch.

Features:
- Dynamic zoom camera (zooms in as you approach the surface)
- Procedural jagged terrain with flat landing pads (2X, 3X, 5X multipliers)
- Apollo-style wireframe lander with thrust flame
- Gravity, thrust, rotation physics
- Landing evaluation: good (speed/angle/pad check), hard, crash
- Fuel management (750 starting, +50 for good landings)
- Crash debris particles, thrust exhaust particles
- Star field background
- HUD: altitude, horizontal/vertical speed, fuel bar, score, time
- Persistent high scores with 3-letter initial entry
- Procedural sound effects (thrust, landing chimes, crash, fuel warning)
- Full-screen scaling, system font detection

Controls: Arrows/WASD rotate+thrust, Space abort, Enter start

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 14:42:13 +01:00

68 lines
1.6 KiB
Lua

local World = require("game.world")
local Camera = {
x = 2000,
y = 400,
zoom = 0.5,
}
local BASE_ALT = 1200
local MAX_ZOOM = 4.0
local MIN_ZOOM = 0.35
function Camera.update(lander, terrain, dt)
-- Track lander position
Camera.x = lander.x
Camera.y = lander.y
-- Compute altitude
local groundY = terrain.getHeightAt(lander.x)
local altitude = groundY - lander.y
altitude = math.max(altitude, 10)
-- Zoom based on altitude
local targetZoom = BASE_ALT / altitude
targetZoom = math.max(MIN_ZOOM, math.min(MAX_ZOOM, targetZoom))
-- Smooth lerp
Camera.zoom = Camera.zoom + (targetZoom - Camera.zoom) * math.min(1, dt * 2.5)
end
function Camera.getAltitude(landerY, terrain, landerX)
local groundY = terrain.getHeightAt(landerX)
return math.max(0, groundY - landerY)
end
function Camera.applyTransform()
local sw, sh = World.screenW, World.screenH
local scale = World.baseScale * Camera.zoom
love.graphics.push()
love.graphics.translate(sw / 2, sh / 2)
love.graphics.scale(scale)
love.graphics.translate(-Camera.x, -Camera.y)
end
function Camera.popTransform()
love.graphics.pop()
end
function Camera.getVisibleRect()
local sw, sh = World.screenW, World.screenH
local scale = World.baseScale * Camera.zoom
local hw = (sw / 2) / scale
local hh = (sh / 2) / scale
return Camera.x - hw, Camera.y - hh, Camera.x + hw, Camera.y + hh
end
function Camera.getZoom()
return Camera.zoom
end
function Camera.reset()
Camera.x = 2000
Camera.y = 400
Camera.zoom = MIN_ZOOM
end
return Camera