diff --git a/ball.lua b/ball.lua new file mode 100644 index 0000000..4f12983 --- /dev/null +++ b/ball.lua @@ -0,0 +1,44 @@ +import "pixie" + +class("Ball").extends(Pixie) + +function Ball:init(width, height, color, x, y) + Ball.super.init(self, width, height, color, x, y) + self.dirX = -1 + self.dirY = 1 + self.vector = {} + self.vector.x = -1 + self.vector.y = 1 + self.speed = 3 + return self +end + +function Ball:levelUp() + self.speed += 1 +end + +function Ball:move() + -- self:moveBy(self.vector.x * self.speed, + -- self.vector.y * self.speed) + self:moveBy(self.dirX * self.speed, + self.dirY * self.speed) +end + +function Ball:setDirection(x, y) + x = x or self.dirX + y = y or self.dirY + self.dirX = x + self.dirY = y +end + +function Ball:_normalizePosition() + local changeVector = Ball.super._normalizePosition(self) + if changeVector[1] ~= 0 then + -- self.vector.x = changeVector[1] + self.dirX = changeVector[1] + end + if changeVector[2] ~= 0 then + -- self.vector.y = changeVector[2] + self.dirY = changeVector[2] + end +end diff --git a/main.lua b/main.lua index 71d7f83..dbb875e 100644 --- a/main.lua +++ b/main.lua @@ -4,43 +4,31 @@ import "CoreLibs/sprites" import "CoreLibs/timer" import "CoreLibs/crank" +import "pixie" +import "ball" + local gfx = playdate.graphics -local paddleSprite = nil -local boundarySprite = nil -local ballSprite = nil +local paddle = nil +local boundary = nil +local ball = 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 - + paddle = Pixie(6, 80, gfx.kColorWhite, 5, 120) + paddle:add() + boundary = Pixie(2, 240, gfx.kColorClear) + boundary:add() + ball = Ball(6, 6, gfx.kColorWhite, 200, 120) + ball:add() + local backgroundImage = gfx.image.new(400, 240, gfx.kColorBlack) gfx.sprite.setBackgroundDrawingCallback( function(x, y, width, height) @@ -48,7 +36,7 @@ function setup() if gameOver then gfx.setColor(gfx.kColorWhite) gfx.fillRect(0, 80, 400, 80) - local level = ballSpeed - 2 + local level = ball.speed - 2 playdate.graphics.drawTextAligned("Game Over!\nYou reached level " .. level .. "\nPress 'A' to play again.", 200, 90, kTextAlignment.center) @@ -60,106 +48,49 @@ end function levelTimer() playdate.timer.new(10000, function() - ballSpeed += 1 + ball:levelUp() levelTimer() end ) - - end +end function playdate.update() - gfx.clear(gfx.kColorBlack) - + gfx.clear() if gameOver then if playdate.buttonJustPressed(playdate.kButtonA) then - paddleSprite:remove() - boundarySprite:remove() - ballSprite:remove() + paddle:remove() + boundary:remove() + ball:remove() playdate.file.run("main.pdz") end else -- Check collisions - local collisions = ballSprite:overlappingSprites() + local collisions = ball:overlappingSprites() for i = 1, #collisions do local collision = collisions[i] - if collision == paddleSprite then + if collision == paddle then redirectBall() end - if collision == boundarySprite then + if collision == boundary then gameOver = true end end -- Handle movement movePaddle(playdate.getCrankTicks(80)) - moveBall() - + ball:move() 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 + ball:setDirection(1) 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} + paddle:moveBy(0, ticks*-5) end setup() diff --git a/pixie.lua b/pixie.lua new file mode 100644 index 0000000..8455346 --- /dev/null +++ b/pixie.lua @@ -0,0 +1,71 @@ +-- A pixie is like a sprite, but better + +import "CoreLibs/object" +import "CoreLibs/graphics" +import "CoreLibs/sprites" + +local gfx = playdate.graphics + +class("Pixie").extends(gfx.sprite) + +-- Crong pixies are simple rectangles, so they take an initial position, width, height, and color +-- They are also collidable +function Pixie:init(width, height, color, x, y) + x = x or 0 + y = y or 0 + + Pixie.super.init(self, gfx.image.new(width, height, color)) + self:setCollideRect(0, 0, self:getSize()) + self:moveTo(x, y) + return self +end + +function Pixie:moveTo(x, y) + Pixie.super.moveTo(self, x, y) + self:_normalizePosition() +end + +function Pixie:moveBy(x, y) + Pixie.super.moveBy(self, x, y) + self:_normalizePosition() +end + +function Pixie:_normalizePosition() + local limitTop = self.height / 2 + local limitBottom = 240 - limitTop + local limitLeft = self.width / 2 + local limitRight = 400 - limitLeft + + local changedX = 0 + local changedY = 0 + local newX = self.x + local newY = self.y + + if self.y < limitTop then + newY = limitTop + changedY = 1 + end + + if self.y > limitBottom then + newY = limitBottom + changedY = -1 + end + + if self.x < limitLeft then + newX = limitLeft + changedX = 1 + end + + if self.x > limitRight then + newX = limitRight + changedX = -1 + end + + if changedX ~= 0 or changedY ~= 0 then + -- call super to avoid the odd possibility that we recurse back into + -- this function + Pixie.super.moveTo(self, newX, newY) + end + + return {changedX, changedY} +end