From 74c15e555a27e367b3dccdb9326d069be1e58817 Mon Sep 17 00:00:00 2001 From: 28allday Date: Sat, 18 Apr 2026 22:10:58 +0100 Subject: [PATCH] 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) --- game/camera.lua | 5 +---- game/particles.lua | 7 ++++--- game/terrain.lua | 10 ++++++++-- game/world.lua | 2 +- main.lua | 19 ++++++++----------- rendering/fonts.lua | 2 +- 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/game/camera.lua b/game/camera.lua index 4ae18b4..58856d5 100644 --- a/game/camera.lua +++ b/game/camera.lua @@ -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) diff --git a/game/particles.lua b/game/particles.lua index f096599..9415c0c 100644 --- a/game/particles.lua +++ b/game/particles.lua @@ -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", diff --git a/game/terrain.lua b/game/terrain.lua index ff195d6..27a56f6 100644 --- a/game/terrain.lua +++ b/game/terrain.lua @@ -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) diff --git a/game/world.lua b/game/world.lua index 8db2750..f5c9769 100644 --- a/game/world.lua +++ b/game/world.lua @@ -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 diff --git a/main.lua b/main.lua index 12de54c..6a92add 100644 --- a/main.lua +++ b/main.lua @@ -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 diff --git a/rendering/fonts.lua b/rendering/fonts.lua index 4f8558d..75334d0 100644 --- a/rendering/fonts.lua +++ b/rendering/fonts.lua @@ -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