singe/docs/learn/25-particles.singe
2026-09-22 21:57:42 -05:00

116 lines
3.1 KiB
Text

-- Lesson 25: Particles. The finished script, exactly as the lesson ends.
dofile("Singe/Framework.singe")
local SHIP_WIDTH = 32
local SHIP_HEIGHT = 24
local SHIP_SPEED = 120
local RESPAWN_MS = 1400
local shipSprite = spriteLoad(DIR .. "art/ship.png")
local sparkSprite = spriteLoad(DIR .. "art/star.png")
local boomSound = soundLoad(DIR .. "art/boom.wav")
local ground = overlayGetHeight() - 20
local shipX = (overlayGetWidth() - SHIP_WIDTH) / 2
local shipY = overlayGetHeight() - 56
local flying = true
local movingLeft = false
local movingRight = false
local lastTicks = singeGetTicks()
local exhaust = emitterNew()
emitterSetBlend(exhaust, PARTICLE_ADD)
emitterSetRate(exhaust, 90)
emitterSetLife(exhaust, 0.15, 0.40)
emitterSetDirection(exhaust, 0, 1)
emitterSetSpread(exhaust, 12)
emitterSetSpeed(exhaust, 40, 90)
emitterSetSize(exhaust, 7, 1)
emitterSetColor(exhaust, 255, 240, 180, 255, 255, 60, 0, 0)
emitterSetMax(exhaust, 120)
emitterStart(exhaust)
local boom = emitterNew()
emitterSetTexture(boom, sparkSprite)
emitterSetBlend(boom, PARTICLE_ADD)
emitterSetLife(boom, 0.4, 1.1)
emitterSetSpeed(boom, 40, 220)
emitterSetSpread(boom, 180)
emitterSetGravity(boom, 0, 160)
emitterSetDrag(boom, 0.9)
emitterSetSize(boom, 10, 2, 0.4)
emitterSetSpin(boom, -240, 240)
emitterSetColor(boom, 255, 255, 220, 255, 255, 70, 20, 0)
emitterSetCollide(boom, COLLIDE_FLOOR, 0.35, 0.3, ground)
emitterSetTrail(boom, 4, 2)
emitterSetMax(boom, 400)
function explode()
if not flying then
return
end
flying = false
emitterStop(exhaust)
emitterSetPosition(boom, shipX + SHIP_WIDTH / 2, shipY + SHIP_HEIGHT / 2)
emitterBurst(boom, 140)
soundPlay(boomSound)
timerAfter(RESPAWN_MS, function()
flying = true
emitterStart(exhaust)
end)
end
function onInputPressed(what)
if what == SWITCH_LEFT then
movingLeft = true
elseif what == SWITCH_RIGHT then
movingRight = true
elseif what == SWITCH_BUTTON1 then
explode()
end
end
function onInputReleased(what)
if what == SWITCH_LEFT then
movingLeft = false
elseif what == SWITCH_RIGHT then
movingRight = false
end
end
function onOverlayUpdate()
local now = singeGetTicks()
local seconds = (now - lastTicks) / 1000
lastTicks = now
if flying then
if movingLeft then
shipX = shipX - SHIP_SPEED * seconds
end
if movingRight then
shipX = shipX + SHIP_SPEED * seconds
end
if shipX < 0 then
shipX = 0
end
if shipX > overlayGetWidth() - SHIP_WIDTH then
shipX = overlayGetWidth() - SHIP_WIDTH
end
emitterSetPosition(exhaust, shipX + SHIP_WIDTH / 2, shipY + SHIP_HEIGHT - 2)
end
overlayClear()
if flying then
spriteDraw(shipSprite, shipX, shipY)
end
emitterDraw(exhaust)
emitterDraw(boom)
overlayPrint(2, 2, "Left and right to fly. Button 1 to blow up.")
overlayPrint(2, 4, "Particles alive: " .. (emitterGetCount(exhaust) + emitterGetCount(boom)))
return OVERLAY_UPDATED
end