oma-roids/game/bullets.lua
28allday bc88613e07 Asteroids: complete Love2D game with Omarchy integration
Faithful recreation of Atari Asteroids (1979) with vector wireframe aesthetic.
Auto-detects Omarchy system theme and font on launch.

Features:
- Inertia physics (zero friction), rotate/thrust/fire/hyperspace controls
- 3 asteroid sizes that split on destroy (large→medium→small)
- Large and small UFO saucers with AI (random vs aimed shooting)
- Screen wrapping for ship/asteroids/saucers, bullets expire at edges
- Ship death fragments, explosion particles
- Iconic heartbeat that speeds up as wave clears
- Wave progression (4→11 asteroids, speed ramps)
- 3 lives, extra life every 10k points
- Persistent high scores with 3-letter initial entry
- Procedural sound effects (beat, thrust, fire, explosions, saucer drone)
- Full-screen scaling, system font detection

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

72 lines
1.7 KiB
Lua

local World = require("game.world")
local Palette = require("rendering.palette")
local Bullets = {}
local active = {}
local BULLET_SPEED = 600
local BULLET_LIFETIME = 0.667
local MAX_PLAYER_BULLETS = 4
function Bullets.fire(x, y, angle, shipVx, shipVy, owner)
if owner == "player" then
local count = 0
for _, b in ipairs(active) do
if b.owner == "player" then count = count + 1 end
end
if count >= MAX_PLAYER_BULLETS then return false end
end
table.insert(active, {
x = x, y = y,
vx = shipVx + math.cos(angle) * BULLET_SPEED,
vy = shipVy + math.sin(angle) * BULLET_SPEED,
timer = BULLET_LIFETIME,
owner = owner or "player",
})
return true
end
function Bullets.update(dt)
for i = #active, 1, -1 do
local b = active[i]
b.x = b.x + b.vx * dt
b.y = b.y + b.vy * dt
b.timer = b.timer - dt
-- Bullets don't wrap — remove when out of bounds or expired
if b.timer <= 0 or b.x < -5 or b.x > World.GAME_W + 5 or
b.y < -5 or b.y > World.GAME_H + 5 then
table.remove(active, i)
end
end
end
function Bullets.getAll()
return active
end
function Bullets.remove(idx)
table.remove(active, idx)
end
function Bullets.clear()
active = {}
end
function Bullets.draw()
local p = Palette.get()
local lw = 1 / World.scale
for _, b in ipairs(active) do
if b.owner == "player" then
love.graphics.setColor(p.bullet)
else
love.graphics.setColor(p.saucer)
end
love.graphics.setLineWidth(lw * 2)
love.graphics.circle("fill", b.x, b.y, 1.5)
end
end
return Bullets