import "CoreLibs/object" import "CoreLibs/graphics" import "CoreLibs/sprites" import "CoreLibs/timer" import "CoreLibs/crank" local gfx = playdate.graphics local paddleSprite = nil local boundarySprite = nil local ballSprite = nil local ballVector = {} local ballSize = 6 local ballSpeed = 3 local paddleLength = 80 local paddleWidth = 6 local gameOver = false local gameOverText = "Game Over!\nPress 'A' to play again." function setup() levelTimer() paddleSprite = gfx.sprite.new(gfx.image.new(paddleWidth, paddleLength, gfx.kColorWhite)) paddleSprite:setCollideRect(0, 0, paddleSprite:getSize()) paddleSprite:moveTo(5, 100) paddleSprite:add() boundarySprite = gfx.sprite.new(gfx.image.new(2, 240, gfx.kColorClear)) boundarySprite:setCollideRect(0, 0, boundarySprite:getSize()) boundarySprite:moveTo(0, 120) boundarySprite:add() ballSprite = gfx.sprite.new(gfx.image.new(ballSize, ballSize, gfx.kColorWhite)) ballSprite:setCollideRect(0, 0, ballSprite:getSize()) ballSprite:moveTo(200,120) ballSprite:add() ballVector[1] = -1 ballVector[2] = 1 local backgroundImage = gfx.image.new(400, 240, gfx.kColorBlack) gfx.sprite.setBackgroundDrawingCallback( function(x, y, width, height) backgroundImage:draw(0, 0) if gameOver then gfx.setColor(gfx.kColorWhite) gfx.fillRect(0, 80, 400, 80) local level = ballSpeed - 2 playdate.graphics.drawTextAligned("Game Over!\nYou reached level " .. level .. "\nPress 'A' to play again.", 200, 90, kTextAlignment.center) end end ) end function levelTimer() playdate.timer.new(10000, function() ballSpeed += 1 levelTimer() end ) end function playdate.update() gfx.clear(gfx.kColorBlack) if gameOver then if playdate.buttonJustPressed(playdate.kButtonA) then paddleSprite:remove() boundarySprite:remove() ballSprite:remove() playdate.file.run("main.pdz") end else -- Check collisions local collisions = ballSprite:overlappingSprites() for i = 1, #collisions do local collision = collisions[i] if collision == paddleSprite then redirectBall() end if collision == boundarySprite then gameOver = true end end -- Handle movement movePaddle(playdate.getCrankTicks(80)) moveBall() playdate.timer.updateTimers() end gfx.sprite.update() end function redirectBall() ballVector[1] = 1 end function moveBall() ballSprite:moveTo(ballSprite.x + (ballVector[1] * ballSpeed), ballSprite.y + (ballVector[2] * ballSpeed)) local changeVector = normalizePosition(ballSprite) if changeVector[1] ~= 0 then ballVector[1] = changeVector[1] end if changeVector[2] ~= 0 then ballVector[2] = changeVector[2] end end function movePaddle(ticks) if ticks == 0 then return end paddleSprite:moveBy(0, ticks*-5) normalizePosition(paddleSprite) end -- Keep sprite inside screen bounds function normalizePosition(sprite) local limitTop = sprite.height / 2 local limitBottom = 240 - limitTop local limitLeft = sprite.width / 2 local limitRight = 400 - limitLeft local changedX = 0 local changedY = 0 local newX = sprite.x local newY = sprite.y if sprite.y < limitTop then newY = limitTop changedY = 1 end if sprite.y > limitBottom then newY = limitBottom changedY = -1 end if sprite.x < limitLeft then newX = limitLeft changedX = 1 end if sprite.x > limitRight then newX = limitRight changedX = -1 end if changedX ~= 0 or changedY ~= 0 then sprite:moveTo(newX, newY) end return {changedX, changedY} end setup()