diff --git a/src/images/game/grass.png b/src/images/game/grass.png new file mode 100644 index 0000000..4da3e6e Binary files /dev/null and b/src/images/game/grass.png differ diff --git a/src/images/launcher/card.png b/src/images/launcher/card.png new file mode 100644 index 0000000..36f134b Binary files /dev/null and b/src/images/launcher/card.png differ diff --git a/src/main.lua b/src/main.lua index 0c24ed8..d77a0fa 100644 --- a/src/main.lua +++ b/src/main.lua @@ -1,42 +1,53 @@ -import 'CoreLibs/graphics.lua' import 'CoreLibs/animator.lua' import 'CoreLibs/easing.lua' +import 'CoreLibs/graphics.lua' +import 'CoreLibs/object.lua' +import 'CoreLibs/ui.lua' local gfx = playdate.graphics playdate.display.setRefreshRate(50) - gfx.setBackgroundColor(gfx.kColorWhite) -lastPosition = playdate.getCrankPosition() +local grassBackground = gfx.image.new("images/game/grass.png") --- text = "Oop" - -timeSinceLastSwing = 999999 - -local ball = gfx.image.new(10, 10, gfx.kColorBlack) -local animationDuration = 2000 -local ballStartY, endY = -20, 250 +local pitchFlyTimeMs = 2500 +local ballStartY, endY = 90, 250 local easingFunction = playdate.easingFunctions.outQuint -local ballAnimator = gfx.animator.new(animationDuration, ballStartY, endY, easingFunction) +local pitchAnimator = gfx.animator.new(pitchFlyTimeMs, ballStartY, endY, easingFunction) + +local ballSizeMs = 2000 +local ballSizeAnimator = gfx.animator.new(ballSizeMs, 9, 6, playdate.easingFunctions.outBounce) local screenW, screenH = 400, 240 local centerX, centerY = screenW / 2, screenH / 2 -local batBaseX, batBaseY = centerX - 34, 200 +local batBaseX, batBaseY = centerX - 34, 220 -local circleR = 45 +local batLength = 45 local ballY = ballStartY local lastBallY = ballY local ballX = 200 local ballVelX, ballVelY = 0, 0 +local ballSize = 6 local batTipX = 0 local batTipY = 0 local hit = false +local hitAnimatorY +local hitAnimatorX + +local hitMult = 10 + +function hitBall(destX, destY, hitFlyTime) + ballSizeAnimator:reset() + hitAnimatorY = gfx.animator.new(hitFlyTime, ballY, destY, playdate.easingFunctions.outQuint) + hitAnimatorX = gfx.animator.new(hitFlyTime, ballX, destX, playdate.easingFunctions.outQuint) +end + function pitch() - ballAnimator:reset() + pitchAnimator:reset() ballVelX = 0 ballVelY = 0 ballX = 200 @@ -47,10 +58,111 @@ function playdate.AButtonDown() pitch() end +function playdate.upButtonDown() + -- hitMult += 1 + batBaseY -= 1 +end + +function playdate.downButtonDown() + -- hitMult -= 1 + batBaseY += 1 +end + +function playdate.rightButtonDown() + batBaseX += 1 +end + +function playdate.leftButtonDown() + batBaseX -= 1 +end + local pitchClockSec = 5 local elapsedTime = 0 -function playdate.update() +-- No-abs failure +-- Hit early! +-- { +-- [b] = 220, +-- [ballX] = 200, +-- [ballY] = 138.2103, +-- [batBaseX] = 166.0, +-- [batBaseY] = 220, +-- [batTipX] = 207.4227, +-- [batTipY] = 202.4171, +-- [m] = -0.4244749, +-- [mx] = -84.89497, +-- [mxPlusB] = 135.105, +-- [x] = 200, +-- [y] = 135.105, +-- } + + +-- With-abs failure +-- Did not hit! +-- { +-- [b] = 220, +-- [ballY] = 234.121, +-- [m] = 0.4244749, +-- [mx] = 84.89497, +-- [mxPlusB] = 304.895, +-- [x] = 200, +-- [y] = 304.895, +-- } + + +function ballPassedThruBat(ballX, ballY, batBaseX, batBaseY, batTipX, batTipY) + + -- This check currently assumes right-handedness. + -- I.e. it assumes the ball is to the right of batBaseX + if ballX < batBaseX or ballX > batTipX or ballY > screenH then + return false + end + + local m = (batTipY - batBaseY) / (batTipX - batBaseX) + + -- y = mx + b + -- b = y1 - (m * x1) + local b = batBaseY - (m * batBaseX) + local yOnLine = (m * ballX) + b + local yP = ballY + local yDelta = yOnLine - yP + + -- printTable({ + -- m = m, + -- mx = m * ballX, + -- mxPlusB = y, + -- y = y, + -- x = ballX, + -- b = batBaseY, + -- ballY = ballY, + -- ballX = ballX, + -- batTipY = batTipY, + -- batBaseY = batBaseY, + -- batTipX = batTipX, + -- batBaseX = batBaseX + -- }) + printTable({ + b = batBaseY, + m = m, + yOnLine = yOnLine, + yP = yP, + yDelta = yDelta, + batTipY = batTipY, + batBaseY = batBaseY, + batTipX = batTipX, + batBaseX = batBaseX + }) + + return yDelta <= 0 + + -- return ballY > y + + -- -- return (lastBallY - 2) < batTipY and ballY >= batTipY and batTipX > ballX + -- -- return math.abs(batTipX - ballX) < 10 + -- return (math.abs(ballY - batTipY) < 10) and (batTipX > ballX) +end + +function updateGameState() local deltaTime = playdate.getElapsedTime() playdate.resetElapsedTime() elapsedTime = elapsedTime + deltaTime @@ -60,41 +172,57 @@ function playdate.update() pitch() end - gfx.clear() - crankChange, acceleratedChange = playdate.getCrankChange() - if hit then - ballX = ballX + ballVelX - ballY = ballY + ballVelY + -- ballX = ballX + ballVelX + -- ballY = ballY + ballVelY + ballX = hitAnimatorX:currentValue() + ballY = hitAnimatorY:currentValue() + ballSize = ballSizeAnimator:currentValue() else - ballY = ballAnimator:currentValue() + ballY = pitchAnimator:currentValue() + ballSize = 6 end - batAngle = math.rad(playdate.getCrankPosition() + 180) - batTipX = batBaseX + (circleR * math.sin(batAngle)) - batTipY = batBaseY + (circleR * math.cos(batAngle)) + batAngle = math.rad(playdate.getCrankPosition() + 90) + batTipX = batBaseX + (batLength * math.sin(batAngle)) + batTipY = batBaseY + (batLength * math.cos(batAngle)) - if hit == false and - --(lastBallY - 2) < batTipY and ballY >= batTipY and batTipX > ballX then - math.abs(ballY - batTipY) < 10 and batTipX > ballX then -- math.abs(batTipX - ballX) < 10 then + if hit == false and ballPassedThruBat(ballX, ballY, batBaseX, batBaseY, batTipX, batTipY) then ballAngle = batAngle + math.rad(90) + + crankChange, acceleratedChange = playdate.getCrankChange() mult = math.abs(acceleratedChange / 15) - ballVelX = mult * -15 * math.sin(ballAngle) + ballVelX = mult * 10 * math.sin(ballAngle) ballVelY = mult * 5 * math.cos(ballAngle) if ballVelY > 0 then ballVelX = ballVelX * -1 ballVelY = ballVelY * -1 end + ballDestX = ballX + (ballVelX * hitMult) + ballDestY = ballY + (ballVelY * hitMult) + hitBall(ballDestX, ballDestY, 2000) hit = true end lastBallY = ballY +end + +function playdate.update() + updateGameState() + + -- gfx.clear() + grassBackground:draw(0, 0) gfx.setColor(gfx.kColorBlack) - -- ball:draw(ballX, ballY) gfx.setLineWidth(2) - gfx.drawCircleAtPoint(ballX, ballY, 8) + gfx.drawCircleAtPoint(ballX, ballY, ballSize) gfx.setLineWidth(5) gfx.drawLine(batBaseX, batBaseY, batTipX, batTipY) -end + -- gfx.drawText("Hit Mult:", 3, screenH - 15) + -- gfx.drawText(hitMult, 65, screenH - 15) + + if playdate.isCrankDocked() then + playdate.ui.crankIndicator:draw() + end +end diff --git a/src/pdxinfo b/src/pdxinfo new file mode 100644 index 0000000..450b7c8 --- /dev/null +++ b/src/pdxinfo @@ -0,0 +1,7 @@ +name=Batter Up! +author=Sage Vaillancourt +description=Crush dingers and hustle around the bases! +bundleID=space.sagev.batterup +imagePath=images/launcher +version=0.1 +buildNumber=1