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>
This commit is contained in:
28allday 2026-04-18 22:10:58 +01:00
parent 515f78a3e7
commit 74c15e555a
6 changed files with 23 additions and 22 deletions

View file

@ -18,10 +18,7 @@ function Camera.update(lander, terrain, dt)
local groundY = terrain.getHeightAt(lander.x)
local altitude = groundY - lander.y
-- Camera Y: always frame BOTH the lander and the terrain
-- Centre the view between the lander and the ground, biased toward showing terrain
local midY = (lander.y + groundY) / 2
-- Bias: keep terrain in the lower third even at high altitude
-- 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)

View file

@ -5,13 +5,14 @@ local Particles = {}
local particles = {}
function Particles.spawnThrust(x, y, angle)
-- Jet direction is local (0, 1) rotated by jetAngle (same convention as lander transformPoint)
local spread = 0.5
local speed = 30 + math.random() * 40
local dir = angle + math.pi + (math.random() - 0.5) * spread
local jetAngle = angle + (math.random() - 0.5) * spread
table.insert(particles, {
x = x, y = y,
vx = math.sin(dir) * speed,
vy = math.cos(dir) * speed,
vx = -math.sin(jetAngle) * speed,
vy = math.cos(jetAngle) * speed,
life = 0.2 + math.random() * 0.2,
maxLife = 0.4,
ptype = "dot",

View file

@ -1,5 +1,6 @@
local World = require("game.world")
local Palette = require("rendering.palette")
local Camera = require("game.camera")
local Terrain = {}
@ -61,6 +62,13 @@ function Terrain.generate()
else
-- Normal jagged terrain
local step = 25 + math.random() * 35
-- Don't overshoot the next pad's approach zone — would cause out-of-order points
if padIdx <= #pads then
local approach = pads[padIdx].x1 - 40
if x < approach and x + step > approach then
step = approach - x
end
end
x = x + step
y = y + (math.random() - 0.5) * 100
y = math.max(baseline - 250, math.min(baseline + 250, y))
@ -133,8 +141,6 @@ function Terrain.draw(visMinX, visMaxX)
-- Multiplier label — constant screen size regardless of zoom
love.graphics.setColor(p.pad[1], p.pad[2], p.pad[3], 0.8)
local cx = (pad.x1 + pad.x2) / 2
local Camera = require("game.camera")
local World = require("game.world")
local invZoom = 1 / (World.baseScale * Camera.getZoom())
love.graphics.push()
love.graphics.translate(cx, pad.y + 15 * invZoom)

View file

@ -26,7 +26,7 @@ function World.ensureScale()
if w ~= World.screenW or h ~= World.screenH then
World.resize(w, h)
local Fonts = require("rendering.fonts")
Fonts.init(1)
Fonts.init()
end
end

View file

@ -126,7 +126,7 @@ function love.load()
love.graphics.setLineStyle("smooth")
Palette.loadFromSystem()
World.resize(love.graphics.getDimensions())
Fonts.init(1)
Fonts.init()
HighScores.init()
Sounds.init()
Stars.init()
@ -136,7 +136,7 @@ end
function love.resize(w, h)
World.resize(w, h)
Fonts.init(1)
Fonts.init()
end
function love.update(dt)
@ -160,8 +160,10 @@ function love.update(dt)
thrustSoundTimer = 0
Sounds.play("thrust")
end
-- Thrust particles
local fx, fy = l.x, l.y + 8
-- Thrust particles — spawn at nozzle transformed by lander angle
local sa, ca = math.sin(l.angle), math.cos(l.angle)
local fx = l.x - sa * 8
local fy = l.y + ca * 8
Particles.spawnThrust(fx, fy, l.angle)
else
thrustSoundTimer = 0.15
@ -179,11 +181,6 @@ function love.update(dt)
-- Check terrain collision
checkLanding()
-- Game over if fuel depleted and landed/still
if World.fuel <= 0 and not l.thrusting then
-- Let them coast until they crash or land
end
elseif World.state == "landed" or World.state == "crashed" then
World.stateTimer = World.stateTimer + dt
Particles.update(dt)
@ -249,8 +246,8 @@ function love.draw()
-- Landing/crash result text
if World.state == "landed" or World.state == "crashed" then
love.graphics.setFont(Fonts.medium)
local flash = World.state == "crashed" and
(math.floor(World.stateTimer * 4) % 2 == 0) or true
local flash = World.state == "landed" or
(math.floor(World.stateTimer * 4) % 2 == 0)
if flash then
if World.state == "crashed" then

View file

@ -27,7 +27,7 @@ function Fonts.detectSystemFont()
return nil
end
function Fonts.init(scale)
function Fonts.init()
local h = love.graphics.getHeight()
if h == Fonts.currentH then return end
Fonts.currentH = h