-- Lesson 11: Hitting Things. 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 SHOT_WIDTH = 4 local SHOT_HEIGHT = 10 local SHOT_SPEED = 6 local SHOW_BOXES = false 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 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 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) break end end end for r = #rocks, 1, -1 do if shipHitsRock(rocks[r]) then table.remove(rocks, r) soundPlay(boomSound) end end end local function drawBox(x, y, width, height) overlayBox(x, y, x + width - 1, y + height - 1) end local function drawBoxes() colorForeground(0, 255, 0, 255) drawBox(shipBox()) for _, rock in ipairs(rocks) do drawBox(rockBox(rock)) end end function onInputPressed(what) if what == SWITCH_LEFT then movingLeft = true elseif what == SWITCH_RIGHT then movingRight = true elseif what == SWITCH_BUTTON1 then fireShot() end end function onInputReleased(what) if what == SWITCH_LEFT then movingLeft = false elseif what == SWITCH_RIGHT then movingRight = false end end function onOverlayUpdate() overlayClear() moveShip() moveRocks() moveShots() checkHits() 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 if SHOW_BOXES then drawBoxes() end return OVERLAY_UPDATED end