OMA-COMMAND — Missile Command arcade clone in Love2D with Omarchy theme integration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
97 lines
2.6 KiB
Lua
97 lines
2.6 KiB
Lua
local World = {
|
|
GAME_W = 256,
|
|
GAME_H = 231,
|
|
visibleH = 231, -- actual visible height in game units (adapts to screen)
|
|
scale = 1,
|
|
offsetX = 0,
|
|
offsetY = 0,
|
|
state = "title",
|
|
wave = 1,
|
|
score = 0,
|
|
highScore = 0,
|
|
gameOverTimer = 0,
|
|
waveEndTimer = 0,
|
|
GROUND_Y = 213,
|
|
screenW = 0,
|
|
screenH = 0,
|
|
bonusCities = 0,
|
|
nextBonusAt = 10000,
|
|
}
|
|
|
|
function World.resize(w, h)
|
|
if not w or not h then
|
|
w, h = love.graphics.getDimensions()
|
|
end
|
|
World.screenW = w
|
|
World.screenH = h
|
|
|
|
-- Scale to fill width, let height adapt
|
|
World.scale = w / World.GAME_W
|
|
World.visibleH = h / World.scale
|
|
World.offsetX = 0
|
|
-- Anchor the bottom of the game (ground) to the bottom of the screen
|
|
-- Ground is at GROUND_Y, bottom of game area is GAME_H
|
|
World.offsetY = h - (World.GAME_H * World.scale)
|
|
end
|
|
|
|
function World.ensureScale()
|
|
local w, h = love.graphics.getDimensions()
|
|
if w ~= World.screenW or h ~= World.screenH then
|
|
World.resize(w, h)
|
|
local Fonts = require("rendering.fonts")
|
|
Fonts.init(World.scale)
|
|
end
|
|
end
|
|
|
|
function World.toGame(sx, sy)
|
|
local gx = (sx - World.offsetX) / World.scale
|
|
local gy = (sy - World.offsetY) / World.scale
|
|
gx = math.max(0, math.min(World.GAME_W, gx))
|
|
gy = math.max(0, math.min(World.GAME_H, gy))
|
|
return gx, gy
|
|
end
|
|
|
|
function World.toScreen(gx, gy)
|
|
return gx * World.scale + World.offsetX, gy * World.scale + World.offsetY
|
|
end
|
|
|
|
-- Top of the visible area in game coordinates (can be negative on widescreen)
|
|
function World.visibleTop()
|
|
return World.GAME_H - World.visibleH
|
|
end
|
|
|
|
function World.addScore(points)
|
|
local Waves = require("data.waves")
|
|
local config = Waves.get(World.wave)
|
|
local earned = points * config.multiplier
|
|
local oldScore = World.score
|
|
World.score = World.score + earned
|
|
|
|
-- Check for bonus city threshold crossing
|
|
while World.score >= World.nextBonusAt do
|
|
World.bonusCities = World.bonusCities + 1
|
|
World.nextBonusAt = World.nextBonusAt + 10000
|
|
end
|
|
|
|
-- Track high score
|
|
if World.score > World.highScore then
|
|
World.highScore = World.score
|
|
end
|
|
end
|
|
|
|
function World.addScoreRaw(points)
|
|
-- Add points without multiplier (used by tally screen)
|
|
local oldScore = World.score
|
|
World.score = World.score + points
|
|
|
|
while World.score >= World.nextBonusAt do
|
|
World.bonusCities = World.bonusCities + 1
|
|
World.nextBonusAt = World.nextBonusAt + 10000
|
|
end
|
|
|
|
if World.score > World.highScore then
|
|
World.highScore = World.score
|
|
end
|
|
end
|
|
|
|
return World
|