-- Lesson 12: Score, Lives, And Game Over. The finished script, exactly as the lesson ends. dofile("Singe/Framework.singe") local SHIP_WIDTH = 32 local SHIP_HEIGHT = 24 local SHIP_PAD_X = 6 local SHIP_PAD_Y = 5 local SHIP_SPEED = 3 local ROCK_WIDTH = 24 local ROCK_HEIGHT = 24 local ROCK_PAD = 4 local ROCK_SPEED = 1 local ROCK_CHANCE = 40 local ROCK_POINTS = 10 local SHOT_WIDTH = 4 local SHOT_HEIGHT = 10 local SHOT_SPEED = 6 local START_LIVES = 3 local TITLE = "title" local PLAYING = "playing" local OVER = "over" local shipSprite = spriteLoad(DIR .. "art/ship.png") local rockSprite = spriteLoad(DIR .. "art/rock.png") local shotSprite = spriteLoad(DIR .. "art/shot.png") local shootSound = soundLoad(DIR .. "art/shoot.wav") local boomSound = soundLoad(DIR .. "art/boom.wav") local state = TITLE local score = 0 local lives = START_LIVES local best = saveGet("highScore", 0) local shipX = (overlayGetWidth() - SHIP_WIDTH) / 2 local shipY = overlayGetHeight() - SHIP_HEIGHT - 8 local movingLeft = false local movingRight = false local rocks = {} local shots = {} local function addRock() local rock = {} rock.x = math.random(0, overlayGetWidth() - ROCK_WIDTH) rock.y = -ROCK_HEIGHT rocks[#rocks + 1] = rock end local function fireShot() local shot = {} shot.x = shipX + SHIP_WIDTH / 2 - SHOT_WIDTH / 2 shot.y = shipY - SHOT_HEIGHT shots[#shots + 1] = shot soundPlay(shootSound) end local function rockBox(rock) return rock.x + ROCK_PAD, rock.y + ROCK_PAD, ROCK_WIDTH - ROCK_PAD * 2, ROCK_HEIGHT - ROCK_PAD * 2 end local function shipBox() return shipX + SHIP_PAD_X, shipY + SHIP_PAD_Y, SHIP_WIDTH - SHIP_PAD_X * 2, SHIP_HEIGHT - SHIP_PAD_Y * 2 end local function shipHitsRock(rock) local sx, sy, sw, sh = shipBox() local rx, ry, rw, rh = rockBox(rock) return collideRects(sx, sy, sw, sh, rx, ry, rw, rh) end local function shotHitsRock(shot, rock) local rx, ry, rw, rh = rockBox(rock) return collidePointRect(shot.x + SHOT_WIDTH / 2, shot.y, rx, ry, rw, rh) end local function startGame() score = 0 lives = START_LIVES rocks = {} shots = {} shipX = (overlayGetWidth() - SHIP_WIDTH) / 2 movingLeft = false movingRight = false state = PLAYING end local function endGame() if score > best then best = score saveSet("highScore", best) saveFlush() end state = OVER end local function moveShip() if movingLeft then shipX = shipX - SHIP_SPEED end if movingRight then shipX = shipX + SHIP_SPEED end if shipX < 0 then shipX = 0 end if shipX > overlayGetWidth() - SHIP_WIDTH then shipX = overlayGetWidth() - SHIP_WIDTH end end local function moveRocks() if math.random(ROCK_CHANCE) == 1 then addRock() end for i = #rocks, 1, -1 do local rock = rocks[i] rock.y = rock.y + ROCK_SPEED if rock.y > overlayGetHeight() then table.remove(rocks, i) end end end local function moveShots() for i = #shots, 1, -1 do local shot = shots[i] shot.y = shot.y - SHOT_SPEED if shot.y + SHOT_HEIGHT < 0 then table.remove(shots, i) end end end local function checkHits() for s = #shots, 1, -1 do for r = #rocks, 1, -1 do if shotHitsRock(shots[s], rocks[r]) then table.remove(rocks, r) table.remove(shots, s) soundPlay(boomSound) score = score + ROCK_POINTS break end end end for r = #rocks, 1, -1 do if shipHitsRock(rocks[r]) then table.remove(rocks, r) soundPlay(boomSound) lives = lives - 1 if lives <= 0 then endGame() end end end end local function drawWorld() spriteDraw(shipSprite, shipX, shipY) for _, rock in ipairs(rocks) do spriteDraw(rockSprite, rock.x, rock.y) end for _, shot in ipairs(shots) do spriteDraw(shotSprite, shot.x, shot.y) end end local function drawScore() overlayPrint(1, 1, "SCORE " .. score) overlayPrint(25, 1, "BEST " .. best) overlayPrint(48, 1, "LIVES " .. lives) end local function updateTitle() overlayPrint(25, 5, "R O C K S") overlayPrint(24, 8, "BEST " .. best) overlayPrint(21, 11, "PRESS FIRE TO PLAY") end local function updatePlaying() moveShip() moveRocks() moveShots() checkHits() drawWorld() drawScore() end local function updateOver() drawWorld() drawScore() overlayPrint(25, 8, "GAME OVER") overlayPrint(21, 11, "PRESS FIRE TO PLAY") end function onInputPressed(what) if state == PLAYING then if what == SWITCH_LEFT then movingLeft = true elseif what == SWITCH_RIGHT then movingRight = true elseif what == SWITCH_BUTTON1 then fireShot() end elseif what == SWITCH_BUTTON1 or what == SWITCH_START1 then startGame() end end function onInputReleased(what) if what == SWITCH_LEFT then movingLeft = false elseif what == SWITCH_RIGHT then movingRight = false end end function onOverlayUpdate() overlayClear() if state == TITLE then updateTitle() elseif state == PLAYING then updatePlaying() else updateOver() end return OVERLAY_UPDATED end