diff --git a/.gitignore b/.gitignore index e00b594..fce2768 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.pdx +build/ diff --git a/.luarc.json b/.luarc.json new file mode 100644 index 0000000..41d7519 --- /dev/null +++ b/.luarc.json @@ -0,0 +1,14 @@ +{ + + "$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json", + "runtime.nonstandardSymbol": [ + "+=", "-=", "*=", "/=", "//=", "%=", "<<=", ">>=", "&=", "|=", "^=" + ], + "runtime.version": "Lua 5.4", + "diagnostics.globals": [ + "import" + ], + "workspace.library": [ + "./" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e69de29 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9ece86f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "playdate.source": "src", + "playdate.output": "build/out.pdx", + "playdate.sdkPath": "/Users/peter/Developer/PlaydateSDK", + "Lua.diagnostics.globals": [ + "playdate", "import" + ], + "Lua.diagnostics.disable": [ + "undefined-global", "lowercase-global" + ], + "Lua.runtime.noluanstandardSymbol": [ + "+=", "-=", "*=", "/=" + ], + "Lua.workspace.library": ["$PLAYDATE_SDK_PATH/CoreLibs"], + "Lua.workspace.preloadFileSize": 1000 +} diff --git a/src/balls.lua b/src/balls.lua index 94b7c04..ba43290 100644 --- a/src/balls.lua +++ b/src/balls.lua @@ -17,10 +17,10 @@ local function draw3(radius) gfx.fillCircleInRect(0, 0, radius * 2, radius * 2) gfx.setLineWidth(line_width) gfx.setColor(black) - gfx.drawLine(right, top, right, bottom) -- right edge - gfx.drawLine(right, top, left, top) -- top - gfx.drawLine(right, middle, left_mid, middle) -- middle - gfx.drawLine(right, bottom, left, bottom) -- bottom + gfx.drawLine(right, top, right, bottom) -- right edge + gfx.drawLine(right, top, left, top) -- top + gfx.drawLine(right, middle, left_mid, middle) -- middle + gfx.drawLine(right, bottom, left, bottom) -- bottom end local function draw2(radius) @@ -34,11 +34,11 @@ local function draw2(radius) gfx.fillCircleInRect(0, 0, radius * 2, radius * 2) gfx.setLineWidth(line_width) gfx.setColor(black) - gfx.drawLine(right, top, left, top) -- top - gfx.drawLine(right, top, right, middle) -- up right - gfx.drawLine(right, middle, left, middle) -- middle - gfx.drawLine(left, bottom, left, middle) -- bottom left - gfx.drawLine(right, bottom, left, bottom) -- bottom + gfx.drawLine(right, top, left, top) -- top + gfx.drawLine(right, top, right, middle) -- up right + gfx.drawLine(right, middle, left, middle) -- middle + gfx.drawLine(left, bottom, left, middle) -- bottom left + gfx.drawLine(right, bottom, left, bottom) -- bottom end local function draw1(radius) @@ -70,19 +70,19 @@ end local function loadImage(diameter, cnt) -- Note returns nil file not found. Which won't get stored in the Lua tbl. local filename = string.format("images/ball_%s-%s", diameter, cnt) - local i = img.new( filename ) + local i = img.new(filename) return i end local function makeImage(radius, draw_func) local image = img.new(radius * 2, radius * 2) gfx.lockFocus(image) - draw_func(radius) + draw_func(radius) gfx.unlockFocus() return image end -local draw_funcs = {[0]=draw0, [1]=draw1, [2]=draw2, [3]=draw3} +local draw_funcs = { [0] = draw0, [1] = draw1, [2] = draw2, [3] = draw3 } function get_ball(r, n) local rint = math.floor(r) if rint < 4 then @@ -95,20 +95,3 @@ function get_ball(r, n) end return ball end - -function balls_setup() - if gimme_balls then - return gimme_balls - end - gimme_balls = {[0]={}, [1]={}, [2]={}, [3]={}} - gfx.setLineCapStyle(playdate.graphics.kLineCapStyleSquare) - n = 3 -- only load 3s. 0/1/2 generated on-demand during update() - for radius = 1,90 do - if radius >= 9 then - gimme_balls[n][radius] = makeImage(radius, draw3) - else - gimme_balls[n][radius] = loadImage(2 * radius, n) - end - end - return gimme_balls -end diff --git a/src/draw.lua b/src/draw.lua new file mode 100644 index 0000000..1db2719 --- /dev/null +++ b/src/draw.lua @@ -0,0 +1,235 @@ +local geo = playdate.geometry +local gfx = playdate.graphics +local img = playdate.graphics.image +local white = playdate.graphics.kColorWhite +local black = playdate.graphics.kColorBlack + +-- Constants +local screenX = 400 +local screenY = 240 +local digit_font = playdate.graphics.font.new("fonts/gimme-digits") +local small_font = playdate.graphics.font.new("fonts/gimme-small") + +gimme_balls = nil + +draw = {} + +function draw.ball3(radius) + local right = 1.25 * radius + local left = .75 * radius + local left_mid = .85 * radius + local middle = radius + local top = .5 * radius + local bottom = 1.5 * radius + local line_width = radius // 5 + 1 + gfx.setColor(white) + gfx.fillCircleInRect(0, 0, radius * 2, radius * 2) + gfx.setLineWidth(line_width) + gfx.setColor(black) + gfx.drawLine(right, top, right, bottom) -- right edge + gfx.drawLine(right, top, left, top) -- top + gfx.drawLine(right, middle, left_mid, middle) -- middle + gfx.drawLine(right, bottom, left, bottom) -- bottom +end + +function draw.ball2(radius) + local right = 1.25 * radius + local left = .75 * radius + local middle = radius + local top = .5 * radius + local bottom = 1.5 * radius + local line_width = radius // 5 + 1 + gfx.setColor(white) + gfx.fillCircleInRect(0, 0, radius * 2, radius * 2) + gfx.setLineWidth(line_width) + gfx.setColor(black) + gfx.drawLine(right, top, left, top) -- top + gfx.drawLine(right, top, right, middle) -- up right + gfx.drawLine(right, middle, left, middle) -- middle + gfx.drawLine(left, bottom, left, middle) -- bottom left + gfx.drawLine(right, bottom, left, bottom) -- bottom +end + +function draw.ball1(radius) + local middle = radius + local top = .5 * radius + local bottom = 1.5 * radius + local line_width = radius // 5 + 1 + gfx.setColor(white) + gfx.fillCircleInRect(0, 0, radius * 2, radius * 2) + gfx.setLineWidth(line_width) + gfx.setColor(black) + gfx.drawLine(middle, top, middle, bottom) +end + +function draw.ball0(radius) + local right = 1.25 * radius + local left = .75 * radius + local top = .5 * radius + local bottom = 1.5 * radius + local line_width = radius // 5 + 1 + gfx.setLineWidth(line_width) + gfx.setColor(white) + gfx.drawLine(right, top, left, top) + gfx.drawLine(left, top, left, bottom) + gfx.drawLine(left, bottom, right, bottom) + gfx.drawLine(right, bottom, right, top) +end + +local function loadImage(diameter, cnt) + -- Note returns nil file not found. Which won't get stored in the Lua tbl. + local filename = string.format("images/ball_%s-%s", diameter, cnt) + local i = img.new(filename) + return i +end + +local function makeImage(radius, draw_func) + local image = img.new(radius * 2, radius * 2) + gfx.lockFocus(image) + draw_func(radius) + gfx.unlockFocus() + return image +end + +function balls_setup() + print("ball setup") + if gimme_balls then + return gimme_balls + else + gimme_balls = {} + end + local min_size, max_size = 1, 175 + gfx.setLineCapStyle(playdate.graphics.kLineCapStyleSquare) + for n, draw_func in pairs( + { [0] = draw.ball0, [1] = draw.ball1, [2] = draw.ball2, [3] = draw.ball3 } + ) do + gimme_balls[n] = {} + for radius = min_size, max_size do + if radius >= 9 then -- custom drawn balls are up to 16x16 (radius=8) + gimme_balls[n][radius] = makeImage(radius, draw_func) + else + gimme_balls[n][radius] = loadImage(2 * radius, n) + end + end + end + return gimme_balls +end + +function draw.background(image_background, left_x, right_x, passing_y) + gfx.lockFocus(image_background) + gfx.setColor(white) + gfx.fillRect(0, 0, screenX, screenY) + gfx.setColor(black) + gfx.fillRect(left_x, 0, right_x - left_x, screenY) + gfx.setColor(white) + gfx.drawLine(left_x, passing_y, right_x, passing_y) + gfx.setColor(black) + small_font:drawTextAligned("SCORE", right_x + (screenX - right_x) / 2, 15, kTextAlignment.center) + small_font:drawTextAligned("HI\n\nSCORE", right_x + (screenX - right_x) / 2, 110, kTextAlignment.center) + gfx.unlockFocus() +end + +-- The fixed base of the shooter +function draw.tripod(tripod_size) + local x, y = 42, 42 + local image_tripod = img.new(x, y) + gfx.lockFocus(image_tripod) + gfx.setColor(white) + gfx.fillCircleAtPoint(x // 2, 30, tripod_size) + local rx = x // 2 - tripod_size + gfx.fillRect(rx, 25, y - 2 * rx, y - 25) + -- TODO: Make tall/narrow digit variation instead of this ugly hack. + local tracking = math.floor(tripod_size // 20) + 1 + digit_font:setTracking(tracking) + digit_font:drawTextAligned("3210", x // 2, 25, kTextAlignment.center) + gfx.unlockFocus() + return image_tripod +end + +-- The moving aimer part of the shooter. +function draw.shooter(diameter) + local image = img.new(diameter, diameter) + local d = diameter - 1 + gfx.lockFocus(image) + playdate.graphics.setColor(white) + -- playdate.graphics.drawLine(0, 0, 0, d) + -- playdate.graphics.drawLine(0, 0, d, 0) + -- playdate.graphics.drawLine(d, d, d, 0) + playdate.graphics.fillCircleInRect(0, 0, diameter, diameter) + playdate.graphics.setColor(black) + playdate.graphics.drawCircleInRect(0, 0, diameter, diameter) + gfx.unlockFocus() + return image +end + +function draw.gameover(width, height) + local image = img.new(width, height, black) + local gameover_image = img.new("images/gameover150") + gfx.lockFocus(image) + gameover_image:draw((width - 150) / 2, (height - 150) / 2) + gfx.unlockFocus() + return image +end + +function draw.score(image, num) + image:clear(white) + gfx.lockFocus(image) + gfx.setColor(black) + digit_font:drawTextAligned(num, 20, 0, kTextAlignment.center) + gfx.unlockFocus() +end + +function draw.sidebar(image, font) + local s = [[GIMME +FRICTION +BABY + + +CONCEPT +CODE +DESIGN +WOUTER +VISSER + +MUSICSAMPLE +WE VS DEATH + +PLAYDATE +PORT +PETER +TRIPP +]] + gfx.lockFocus(image) + gfx.clear(white) + gfx.setColor(black) + small_font:drawTextAligned(s, 37, 5, kTextAlignment.center, 2) + gfx.unlockFocus() + return image +end + +-- +-- function shooter_draw(diameter) +-- local d = diameter - 1 +-- local center = geo.point.new(diameter // 2, diameter // 2) +-- local l1 = geo.lineSegment.new(0, 0, 0, d) +-- local l2 = geo.lineSegment.new(d, 0, 0, 0) +-- local l3 = geo.lineSegment.new(d, d, d, 0) +-- local t = table.create(181, 0) +-- local at = geo.affineTransform.new() +-- local center = geo.point.new(diameter // 2, diameter // 2) +-- for a = 0,90 do +-- local s = img.new(diameter, diameter) +-- at:reset() +-- at:rotate(a, center) +-- print(a, l2, at:transformedLineSegment(l2)) +-- gfx.lockFocus(s) +-- gfx.setColor(white) +-- gfx.drawLine(0, center.y, d, center.y) +-- gfx.drawLine(at:transformedLineSegment(l1)) +-- gfx.drawLine(at:transformedLineSegment(l2)) +-- gfx.drawLine(at:transformedLineSegment(l3)) +-- gfx.unlockFocus() +-- t[a] = s:rotatedImage(a) +-- end +-- return t +-- end diff --git a/src/gimme.lua b/src/gimme.lua index 143dd1e..98e90c7 100644 --- a/src/gimme.lua +++ b/src/gimme.lua @@ -18,30 +18,72 @@ end -- Constants local screenX = 400 local screenY = 240 -local ballSize = 9 -- was 10 -local startX = screenX // 2 -- was 320 -local startY = screenY - 20 -- was 450 -local wallLeft = 75 + ballSize -local wallRight = screenX - wallLeft -local wallBottom = screenY - 62 -local wallTop = 0 +-- Variable board shapes +local game_mode +local sidebar +local tripod_size +local shooter_radius +local ballSize +local velocity +local startX +local startY +local wallLeft +local wallRight +local wallBottom +local wallTop + +local function mode_playdate() + sidebar = 75 + ballSize = 9 + tripod_size = 21 + shooter_radius = 28 + velocity = 3.5 + startX = screenX // 2 -- was 320 + startY = screenY - 10 -- was 450 + wallLeft = sidebar + ballSize + wallRight = screenX - sidebar - ballSize + wallBottom = screenY - 62 + wallTop = 0 +end +local function mode_classic() + sidebar = 100 + -- local x, y = 200, 240 -- original was 400x480 + ballSize = 5 -- original was 10 + tripod_size = 16 + shooter_radius = 20 + velocity = 3.225 + startX = screenX // 2 -- was 320 + startY = screenY - 10 -- was 450 + wallLeft = sidebar + ballSize + wallRight = screenX - sidebar - ballSize + wallBottom = screenY - 42 + wallTop = 0 +end +local function set_mode(mode) + assert(mode ~= nil, "Attempting to set game_mode to nil, should be 1 or 2.") + if mode % 2 == 0 then + mode_classic() + else + mode_playdate() + end +end -- GLOBAL VARIABLES -local i = 10 -- ? number of balls -local friction = 0.975 -- coefficient of friction -local n = -1 -- Next closest ball (num) -local nd = 10000 -- Next closest ball distance -local b = nil -- Currently active Ball {lx,ly,r,vx,vy,f,m,_rotation} -local l = {deg=180, mov=2} -- Shooter state and step -local arrow = {} -- Rotating shooter {_x, _y, _rotation} +local i = 10 -- ? number of balls +local friction = 0.975 -- coefficient of friction +local n = -1 -- Next closest ball (num) +local nd = 10000 -- Next closest ball distance +local b = nil -- Currently active Ball {lx,ly,r,vx,vy,f,m,_rotation} +local l = { deg = 180, mov = 2 } -- Shooter state and step +local arrow = {} -- Rotating shooter {_x, _y, _rotation} barray = {} ubarray = {} local zeroes = {} -local firstshot = false -- has the first shot occured +local firstshot = false -- has the first shot occured local wall = false -local news = 0 -- New Scale (growing to) -local score = 0 -- Score +local news = 0 -- New Scale (growing to) +local score = 0 -- Score local hiscore = (playdate.datastore.read("score") or {})["score"] or 0 local fsm = nil @@ -51,99 +93,99 @@ local sound_shoot = playdate.sound.sampleplayer.new("sound/shoot") local sound_wall = playdate.sound.sampleplayer.new("sound/wall") local ball_images = {} -local shooter_image = img.new( 2 * ballSize, 2 * ballSize) -local shooter_sprite = spr.new( shooter_image ) -local image_background = img.new("images/background") -local image_sidebar = {} -local sidebar_sprite = nil -local image_tripod = img.new("images/tripod") -local image_gameover = img.new("images/gameover250") -local goscreen = spr.new( image_gameover ) -goscreen:setZIndex(500) +-- This are done globally for dumb reasons. local image_logo = img.new("images/logo") -local title_sprite = spr.new( image_logo ) -local background = nil +local title_sprite = spr.new(image_logo) + +-- Images & sprites +local image_tripod +local tripod = spr.new(image_tripod) +local image_gameover +local image_background = img.new(screenX, screenY) +local score_image +local score_sprite +local hiscore_image +local hiscore_sprite +local background -- sprite +local sidebar_sprite +local goscreen -- sprite +local shooter_sprite = nil +local image_sidebar = {} + + +-- Images which are identical in both modes. +local function image_setup_static() + hiscore_image = img.new(45, 15, white) + hiscore_sprite = spr.new(hiscore_image) + + score_image = img.new(45, 15, white) + score_sprite = spr.new(score_image) -local small_font = playdate.graphics.font.new("fonts/gimme-small") -local digit_font = playdate.graphics.font.new("fonts/gimme-digits") -local score_image = img.new( 40, 15, white) -local score_sprite = spr.new ( score_image ) -score_sprite:moveTo(362, 50) -score_sprite:add() -local hiscore_image = img.new( 45, 15, white) -local hiscore_sprite = spr.new ( hiscore_image ) -hiscore_sprite:moveTo(362, 155) -hiscore_sprite:add() - -local tripod = spr.new( image_tripod ) - -local function draw_shooter(image) - gfx.lockFocus(image) - playdate.graphics.setColor(white) - playdate.graphics.fillCircleInRect(0, 0, 2 * ballSize, 2 * ballSize) - playdate.graphics.setColor(black) - playdate.graphics.drawCircleInRect(0, 0, 2 * ballSize, 2 * ballSize) - gfx.unlockFocus() - return image -end -local function draw_score(image, num) - image:clear(white) - gfx.lockFocus(image) - gfx.setColor(black) - digit_font:drawTextAligned(num, 20, 0, kTextAlignment.center) - gfx.unlockFocus() + goscreen = spr.new(image_gameover) + goscreen:setCenter(0.5, 0) + goscreen:setZIndex(500) + + background = spr.setBackgroundDrawingCallback( + function(x, y, width, height) + gfx.setClipRect(x, y, width, height) + image_background:draw(0, 0) + gfx.clearClipRect() + end + ) end -local function draw_sidebar(image) - local b = [[GIMME -FRICTION -BABY - - -CONCEPT -CODE -DESIGN -WOUTER -VISSER - -MUSICSAMPLE -WE VS DEATH - -PLAYDATE -PORT -PETER -TRIPP -]] - gfx.lockFocus(image) - gfx.clear(white) - gfx.setColor(black) - small_font:drawTextAligned(b, 37, 5, kTextAlignment.center, 2) - gfx.unlockFocus() - return image + +-- This does mode-dependent image/sprite setup +local function image_setup_variable() + draw.background(image_background, + wallLeft - ballSize, -- left_x + wallRight + ballSize, -- right_x + wallBottom - 1 -- passing_line + ) + image_tripod = draw.tripod(tripod_size) + image_gameover = draw.gameover(screenX - 2 * sidebar, wallBottom) + tripod:setCenter(0.5, 1) + tripod:moveTo(199, screenY) + tripod:add() + tripod:setZIndex(200) + + + score_sprite:moveTo(screenX - sidebar // 2, 50) + score_sprite:add() + hiscore_sprite:moveTo(screenX - sidebar // 2, 155) + hiscore_sprite:add() + + image_sidebar = { + tribute = img.new("images/sidebar1"), + credits = draw.sidebar(img.new(75, screenY)), + } + sidebar_sprite = spr.new(image_sidebar) end +local small_font = playdate.graphics.font.new("fonts/gimme-small") +local digit_font = playdate.graphics.font.new("fonts/gimme-digits") + local function update_score(s) score = s if score > hiscore then hiscore = score - playdate.datastore.write({score=hiscore}, "score") + playdate.datastore.write({ score = hiscore }, "score") end - draw_score(score_image, score) - draw_score(hiscore_image, hiscore) + draw.score(score_image, score) + draw.score(hiscore_image, hiscore) end - -- local title_screen = playdate.graphics.sprite.new(320, 200) local function ball_str(b) return string.format("BallSprite(x=%s, y=%s, r=%s, vx=%s, vy=%s)", b._x, b._y, b.r, b.vx, b.vy) end -function newball() +local function newball() i = i + 1 - b = spr.new( get_ball(ballSize, 3) ) - b:moveTo( startX, startY ) + b = spr.new(get_ball(ballSize, 3)) + b:moveTo(startX, startY) b:setVisible(true) b:setZIndex(100) b:add() @@ -151,25 +193,32 @@ function newball() b._yscale = ballSize b._x = startX b._y = startY - b.r = ballSize -- radius - b.vx = 0 -- velocity + b.r = ballSize -- radius + b.vx = 0 -- velocity b.vy = 0 - b.m = 1 -- mass? - b.n = 3 -- frame number 1-4 (3,2,1,0) - barray[#barray+1] = b + b.m = 1 -- mass? + b.n = 3 -- frame number 1-4 (3,2,1,0) + barray[#barray + 1] = b end function update_shooter() local angle_rad = rad(l.deg) - b.lx = math.cos(angle_rad) * (3.1 * ballSize) + startX - b.ly = math.sin(angle_rad) * (3.1 * ballSize) + startY + b.lx = math.cos(angle_rad) * shooter_radius + startX + b.ly = math.sin(angle_rad) * shooter_radius + startY arrow._x = b.lx arrow._y = b.ly - -- l -- line = {startX, startY, b.lx, b.ly} + -- l line = {startX, startY, b.lx, b.ly} local dx = b._x - b.lx local dy = b._y - b.ly - arrow._rotation = deg(math.atan2(dy, dx)) -90 + arrow._rotation = deg(math.atan2(dy, dx)) - 90 + if math.floor(arrow._rotation) == -270 then + arrow._rotation += 360 + end + + gfx.setColor(black) + -- gfx.drawLine(startX, startY, b.lx, b.ly) shooter_sprite:moveTo(arrow._x, arrow._y) + -- shooter_sprite:setImage(shooter_images[math.floor(arrow._rotation)]) end function shooter() @@ -178,6 +227,7 @@ function shooter() if num < min then return min end return num end + playdate.AButtonDown = shootnow playdate.upButtonDown = shootnow if playdate.isCrankDocked() then @@ -187,7 +237,7 @@ function shooter() end -- original game only supported 0,180; step=2. -- this rand term at the end keeps things interesting. - l.deg = (l.deg + l.mov) + math.random(-10,10) * .01; + l.deg = (l.deg + l.mov) + math.random(-10, 10) * .01; end update_shooter() end @@ -198,8 +248,8 @@ function shootnow() title_sprite:setVisible(false) end sound_shoot:play() - b.vx = (- (b.lx - startX)) / 3.5 - b.vy = (- (b.ly - startY)) / 3.5 + b.vx = (-(b.lx - startX)) / velocity + b.vy = (-(b.ly - startY)) / velocity fsm = moveball playdate.AButtonDown = nil playdate.upButtonDown = nil @@ -209,29 +259,29 @@ function moveball() findn() b.vx *= friction b.vy *= friction - if(b._x - b.vx < wallLeft or b._x - b.vx > wallRight) then + if (b._x - b.vx < wallLeft or b._x - b.vx > wallRight) then b.vx *= -1 sound_wall:play() end - if(b._y - b.vy - b.r < wallTop) then + if (b._y - b.vy - b.r < wallTop) then b.vy *= -1 sound_wall:play() end b._x -= b.vx b._y -= b.vy b:moveTo(b._x, b._y) - if(b.vy < 0 and b._y + b.r > wallBottom) then -- death + if (b.vy < 0 and b._y + b.r > wallBottom) then -- death sound_music:stop() -- createexp(b) -- create explosion b:remove() - goscreen:moveTo(startX, -80) + goscreen:moveTo(startX, -1 * goscreen.height) goscreen:setVisible(true) goscreen:add() playdate.datastore.delete("state") fsm = gomove playdate.AButtonDown = restore playdate.upButtonDown = restore - playdate.cranked = nil -- disable moving shooter when dead. + playdate.cranked = nil -- disable moving shooter when dead. end -- Use of 0.2 here is arbitrary. Playdate only supports integer x,y -- positions. Original (flash) could render non integer coords. Anything @@ -254,7 +304,7 @@ function findn() local xdist_next = b._x - b.vx - barray[p]._x local ydist_next = b._y - b.vy - barray[p]._y local ball_dist = math.sqrt(xdist_next * xdist_next + ydist_next * ydist_next) - barray[p].r - if(ball_dist < nd) then + if (ball_dist < nd) then nd = ball_dist n = p end @@ -267,7 +317,7 @@ function findn() end function calc() - for p = 1,#barray-1 do -- last element of barray is b, so skip + for p = 1, #barray - 1 do -- last element of barray is b, so skip local xdist = b._x - barray[p]._x local ydist = b._y - barray[p]._y local next_dist = math.sqrt(xdist * xdist + ydist * ydist) - barray[p].r @@ -289,10 +339,10 @@ function calc() nd = b._y - wallTop wall = true end - if(wallBottom - b._y < nd) then + if (wallBottom - b._y < nd) then nd = wallBottom - b._y if nd < 0 then - ubarray[#ubarray+1] = b + ubarray[#ubarray + 1] = b table.remove(barray, #barray) nd = math.abs(nd) end @@ -306,6 +356,7 @@ function grow2() b._yscale = b._yscale + _loc1_ / 5 local img = get_ball(b._xscale, b.n) b:setImage(img) + -- do the above, until we're within 1pixel of the new size. if _loc1_ < 1 then b._xscale = news b._yscale = news @@ -332,15 +383,15 @@ function checkColl(b1, b2) local xdist = b2._x - b1._x local ydist = b2._y - b1._y local dist = math.sqrt(xdist * xdist + ydist * ydist) -- center to center - if dist < b1.r + b2.r then -- Collide - local between = dist - (b1.r + b2.r) -- between balls + if dist < b1.r + b2.r then -- Collide + local between = dist - (b1.r + b2.r) -- between balls local xratio = xdist / dist local yratio = ydist / dist b1._x = b1._x + between * xratio b1._y = b1._y + between * yratio b2.n = b2.n - 1 sound_crack:play() - b2:setImage( get_ball(b2.r, b2.n) ) + b2:setImage(get_ball(b2.r, b2.n)) local atan2 = math.atan2(ydist, xdist) local cosa = math.cos(atan2) @@ -358,10 +409,10 @@ function checkColl(b1, b2) local diff = (b1.r + b2.r - dist) / 2 cosd = cosa * diff sind = sina * diff - if(b2.n == 0) then + if (b2.n == 0) then update_score(score + 1) - b2:setImage( get_ball(b2.r, b2.n)) - zeroes[#zeroes+1] = b2 + b2:setImage(get_ball(b2.r, b2.n)) + zeroes[#zeroes + 1] = b2 b2.vx = 0 b2.vy = 5 table.remove(barray, n) @@ -370,14 +421,14 @@ function checkColl(b1, b2) end end - -- game over screen move down +-- game over screen move down function gomove() if playdate.buttonIsPressed(playdate.kButtonB) then goscreen:setVisible(false) else goscreen:setVisible(true) end - local stop_y = 88 + local stop_y = -1 if goscreen.y < stop_y then goscreen:moveBy(0, 5) if goscreen.y > stop_y then @@ -389,10 +440,10 @@ end function restore() update_score(0) goscreen:remove() - for j = 1,#barray do + for j = 1, #barray do barray[j]:remove() end - for k = 1,#ubarray do + for k = 1, #ubarray do ubarray[k]:remove() end ubarray = {} @@ -412,7 +463,6 @@ function restore() end end - -- Create parts of ball that fall function createpart(b1, b2) sound_crack:play() @@ -442,11 +492,18 @@ function playdate.crankUndocked() end function gimme_update() - playdate.graphics.sprite.update() playdate.timer.updateTimers() + playdate.graphics.sprite.update() + -- playdate.drawFPS() + -- eek. + if playdate.buttonIsPressed("right") then + crank(10, 10) + elseif playdate.buttonIsPressed("left") then + crank(-10, -10) + end fsm() - for z = #zeroes,1,-1 do + for z = #zeroes, 1, -1 do local zero = zeroes[z] zero:moveBy(zero.vx, zero.vy) if zero.y > 250 + zero.r then @@ -454,39 +511,42 @@ function gimme_update() table.remove(zeroes, z) end end + -- shooter_image:draw(200,0) end function save_state() local balls = {} for _, ball in ipairs(barray) do local bb = {} - for _a, attr in ipairs({"_xscale", "_yscale", "_x", "_y", "vx", "vy", "m", "n", "r"}) do + for _a, attr in ipairs({ "_xscale", "_yscale", "_x", "_y", "vx", "vy", "m", "n", "r" }) do bb[attr] = ball[attr] end - balls[#balls+1] = bb + balls[#balls + 1] = bb end table.remove(balls) -- the last ball in barray is the unshot shot (b) local state = { l = l, barray = balls, score = score, + game_mode = game_mode, } playdate.datastore.write(state, "state") end function load_state(state) for _, _ball in ipairs(state["barray"]) do - local _b = spr.new( get_ball(_ball.r, _ball.n) ) + local _b = spr.new(get_ball(_ball.r, _ball.n)) _b:moveTo(_ball._x, _ball._y) _b:setZIndex(100) _b:add() for attr, value in pairs(_ball) do _b[attr] = value end - barray[#barray+1] = _b + barray[#barray + 1] = _b end b = barray[#barray] l = state["l"] + game_mode = state["game_mode"] or 1 score = state["score"] end @@ -497,53 +557,53 @@ function gimme_setup() else local state = playdate.datastore.read("state") if state then + game_mode = 1 load_state(state) -- maybe use pcall? else + game_mode = 2 title_sprite:moveTo(200, 100) title_sprite:add() end end - background = spr.setBackgroundDrawingCallback( - function( x, y, width, height ) - gfx.setClipRect( x, y, width, height ) - image_background:draw( 0, 0 ) - gfx.clearClipRect() - end - ) + + set_mode(2) + image_setup_static() + image_setup_variable() + gfx.setColor(black) update_score(score) newball() - tripod:moveTo(startX, screenY - 20) - tripod:add() - tripod:setZIndex(200) - - draw_shooter(shooter_image) + shooter_image = draw.shooter(ballSize * 2) + shooter_sprite = spr.new(shooter_image) update_shooter() shooter_sprite:setZIndex(201) shooter_sprite:add() + local function mode_toggle() + game_mode = (game_mode + 1) % 2 + set_mode(game_mode) + image_setup_variable() + playdate.datastore.delete("state") + restore() + end - local sidebar_x = 75 - image_sidebar = { - tribute= img.new("images/sidebar1"), - credits= draw_sidebar( img.new( sidebar_x, screenY ) ), - } - sidebar_sprite = spr.new( image_sidebar ) local sidebar_callbacks = {} sidebar_callbacks.credits = function() - sidebar_sprite:setImage( image_sidebar.credits ) + sidebar_sprite:setImage(image_sidebar.credits) playdate.getSystemMenu():removeAllMenuItems() playdate.getSystemMenu():addMenuItem("tribute", sidebar_callbacks.tribute) + playdate.getSystemMenu():addMenuItem("mode", mode_toggle) end sidebar_callbacks.tribute = function() - sidebar_sprite:setImage( image_sidebar.tribute ) + sidebar_sprite:setImage(image_sidebar.tribute) playdate.getSystemMenu():removeAllMenuItems() playdate.getSystemMenu():addMenuItem("credits", sidebar_callbacks.credits) + playdate.getSystemMenu():addMenuItem("mode", mode_toggle) end sidebar_callbacks.tribute() - sidebar_sprite:setCenter(0,0) - sidebar_sprite:moveTo(0,0) + sidebar_sprite:setCenter(0, 0) + sidebar_sprite:moveTo((wallLeft - image_sidebar.tribute.width) // 2 - 3, 0) sidebar_sprite:add() sound_music:setVolume(0.1) diff --git a/src/images/background.png b/src/images/background.png deleted file mode 100644 index 6a134e3..0000000 Binary files a/src/images/background.png and /dev/null differ diff --git a/src/images/ball_11-0.png b/src/images/ball_11-0.png new file mode 100644 index 0000000..76ef021 Binary files /dev/null and b/src/images/ball_11-0.png differ diff --git a/src/images/ball_11-1.png b/src/images/ball_11-1.png new file mode 100644 index 0000000..fe712b4 Binary files /dev/null and b/src/images/ball_11-1.png differ diff --git a/src/images/ball_11-2.png b/src/images/ball_11-2.png new file mode 100644 index 0000000..981d2c7 Binary files /dev/null and b/src/images/ball_11-2.png differ diff --git a/src/images/ball_11-3.png b/src/images/ball_11-3.png new file mode 100644 index 0000000..097600a Binary files /dev/null and b/src/images/ball_11-3.png differ diff --git a/src/images/ball_12-0.png b/src/images/ball_12-0.png deleted file mode 100644 index df5cd92..0000000 Binary files a/src/images/ball_12-0.png and /dev/null differ diff --git a/src/images/ball_12-1.png b/src/images/ball_12-1.png deleted file mode 100644 index e723c41..0000000 Binary files a/src/images/ball_12-1.png and /dev/null differ diff --git a/src/images/ball_12-2.png b/src/images/ball_12-2.png deleted file mode 100644 index 6b48e8b..0000000 Binary files a/src/images/ball_12-2.png and /dev/null differ diff --git a/src/images/ball_12-3.png b/src/images/ball_12-3.png deleted file mode 100644 index bbf86ca..0000000 Binary files a/src/images/ball_12-3.png and /dev/null differ diff --git a/src/images/ball_13-0.png b/src/images/ball_13-0.png new file mode 100644 index 0000000..f883936 Binary files /dev/null and b/src/images/ball_13-0.png differ diff --git a/src/images/ball_13-1.png b/src/images/ball_13-1.png new file mode 100644 index 0000000..0b365a7 Binary files /dev/null and b/src/images/ball_13-1.png differ diff --git a/src/images/ball_13-2.png b/src/images/ball_13-2.png new file mode 100644 index 0000000..c0dd25c Binary files /dev/null and b/src/images/ball_13-2.png differ diff --git a/src/images/ball_13-3.png b/src/images/ball_13-3.png new file mode 100644 index 0000000..6088a3f Binary files /dev/null and b/src/images/ball_13-3.png differ diff --git a/src/images/ball_9-0.png b/src/images/ball_9-0.png new file mode 100644 index 0000000..9e89ed6 Binary files /dev/null and b/src/images/ball_9-0.png differ diff --git a/src/images/ball_9-1.png b/src/images/ball_9-1.png new file mode 100644 index 0000000..f7a7658 Binary files /dev/null and b/src/images/ball_9-1.png differ diff --git a/src/images/ball_9-2.png b/src/images/ball_9-2.png new file mode 100644 index 0000000..8b76883 Binary files /dev/null and b/src/images/ball_9-2.png differ diff --git a/src/images/ball_9-3.png b/src/images/ball_9-3.png new file mode 100644 index 0000000..a04baf4 Binary files /dev/null and b/src/images/ball_9-3.png differ diff --git a/src/images/gameover150.png b/src/images/gameover150.png new file mode 100644 index 0000000..1df4856 Binary files /dev/null and b/src/images/gameover150.png differ diff --git a/src/images/gameover250.png b/src/images/gameover250.png deleted file mode 100644 index e4cfa53..0000000 Binary files a/src/images/gameover250.png and /dev/null differ diff --git a/src/images/tripod.png b/src/images/tripod.png deleted file mode 100644 index 4695f24..0000000 Binary files a/src/images/tripod.png and /dev/null differ diff --git a/src/main.lua b/src/main.lua index 631b314..a70170b 100644 --- a/src/main.lua +++ b/src/main.lua @@ -6,6 +6,7 @@ import "CoreLibs/timer" import "CoreLibs/animator" import "CoreLibs/crank" import "balls" +import "draw" import "gimme" local function setup()