singe/testScripts/scene20.singe

69 lines
2.4 KiB
Text

-- Character controller in 2D: a platformer drawn on the overlay with sprites and boxes, no GPU
-- needed. The player runs right, hops a gap, climbs a step, is stopped by a wall and jumps onto a
-- ledge, on a scripted route; gravity points down the screen (+Y) like every 2D game here.
local font = fontLoad("Singe/FreeSansBold.ttf", 24)
local crate = spriteLoad("testScripts/crate.png")
local frames = 0
overlaySetResolution(720, 480)
local width, height = overlayGetWidth(), overlayGetHeight()
fontSelect(font)
physicsSet2D(true)
physicsSetGravity(0, 900, 0)
local blocks = {}
local function block(x, y, w, h)
local node = nodeNew()
nodeSetPosition(node, x, y, 0)
bodyNew(node, BODY_STATIC, SHAPE_BOX, w, h, 50)
blocks[#blocks + 1] = { x = x, y = y, w = w, h = h }
return node
end
-- Ground with a gap, a low step, a wall, and a ledge to jump onto.
local ground = height - 20
block(width * 0.2, ground, width * 0.4, 20)
block(width * 0.72, ground, width * 0.56, 20)
block(width * 0.55, ground - 22, 60, 24)
block(width * 0.85, ground - 60, 20, 100)
block(width * 0.92, ground - 140, 140, 20)
local size = spriteGetWidth(crate)
local player = nodeNew()
nodeSetPosition(player, 40, ground - 10, 0)
playerNew(player, size * 0.45, size * 1.4)
playerSetStep(player, 26)
local hops = 0
function onOverlayUpdate()
local px, py = nodeGetPosition(player)
frames = frames + 1
playerMove(player, (px < width * 0.9) and 220 or 0)
-- Hop the gap, and later the wall, when the ground runs out ahead or the wall is near.
if playerIsOnGround(player) and ((px > width * 0.36 and px < width * 0.42) or (px > width * 0.70 and px < width * 0.75)) then
if playerJump(player, 560) then
hops = hops + 1
end
end
overlayClear()
colorForeground(90, 90, 110)
for _, b in ipairs(blocks) do
overlayBox(b.x - b.w / 2, b.y - b.h / 2, b.x + b.w / 2, b.y + b.h / 2)
end
spriteDraw(crate, px - size / 2, py - size * 1.4, px + size / 2, py)
colorForeground(255, 255, 255)
fontPrint(20, 20, string.format("Platformer, frame %d x %.0f y %.0f ground %s hops %d", frames, px, py, tostring(playerIsOnGround(player)), hops))
if frames % 10 == 0 then
local vx, vy = playerGetVelocity(player)
debugPrint(string.format("frame %d player %.0f %.0f v %.0f %.0f ground %s hops %d", frames, px, py, vx, vy, tostring(playerIsOnGround(player)), hops))
end
if frames == 40 or frames == 90 or frames == 140 then
singeScreenshot()
end
if frames == 180 then
singeQuit()
end
return OVERLAY_UPDATED
end