oma-lander/game/camera.lua
28allday 74c15e555a OMA-LANDER: fix flash, terrain overshoot, thrust particles, cleanups
- main.lua: flash logic was always true; now flashes only on crash,
  always on when landed. Remove empty fuel-depleted branch. Rotate
  thrust-particle spawn point by lander angle.
- particles.lua: jet velocity had wrong vy sign, shooting particles
  upward; now emits along local (0,1) rotated by the lander angle.
- terrain.lua: jagged step could overshoot the pad approach zone and
  produce an out-of-order point (zig-zag line, bad getHeightAt). Clamp
  the step to the approach boundary. Move Camera/World requires to
  module top instead of re-requiring inside the draw loop.
- camera.lua: drop unused midY local.
- fonts.lua/world.lua/main.lua: drop unused scale parameter on
  Fonts.init.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 22:10:58 +01:00

75 lines
2.1 KiB
Lua

local World = require("game.world")
local Camera = {
x = 2000,
y = 900,
zoom = 0.35,
}
local MAX_ZOOM = 3.5
local MIN_ZOOM = 0.3
local ZOOM_SPEED = 2.0
function Camera.update(lander, terrain, dt)
-- Track lander X
Camera.x = lander.x
-- Get ground height below lander
local groundY = terrain.getHeightAt(lander.x)
local altitude = groundY - lander.y
-- Camera Y: keep terrain in the lower portion of the viewport even at high altitude
local targetY = lander.y + altitude * 0.45
Camera.y = Camera.y + (targetY - Camera.y) * math.min(1, dt * 3)
-- Zoom: fit the distance from lander to ground within the viewport
-- We want the full altitude span to fit in about 70% of screen height
local sw, sh = World.screenW, World.screenH
local effectiveScale = World.baseScale
local neededHeight = math.max(altitude + 100, 200) -- minimum view range
local viewportFraction = 0.7
local targetZoom = (sh * viewportFraction) / (neededHeight * effectiveScale)
targetZoom = math.max(MIN_ZOOM, math.min(MAX_ZOOM, targetZoom))
Camera.zoom = Camera.zoom + (targetZoom - Camera.zoom) * math.min(1, dt * ZOOM_SPEED)
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 = 900
Camera.zoom = MIN_ZOOM
end
return Camera