diff --git a/src/assets.lua b/src/assets.lua index 972b732..11da147 100644 --- a/src/assets.lua +++ b/src/assets.lua @@ -28,6 +28,8 @@ TomatoSprite = playdate.graphics.image.new("assets/images/TomatoSprite.png") -- !!(dirLookup('assets/sounds', 'wav', 'playdate.sound.sampleplayer.new', 'pd_sampleplayer')) -- !!(dirLookup('assets/music', 'wav', 'playdate.sound.sampleplayer.new', 'pd_sampleplayer')) --- !!(dirLookup('assets/fonts', 'fnt', 'playdate.graphics.font.new', 'pd_font', nil, nil, function(varName, value) --- return varName:gsub("[- ]", "") .. " = " .. value:gsub("fnt", "pft") --- end)) +-- luacheck: ignore +---@type pd_font +AshevilleSans14Bold = playdate.graphics.font.new("assets/fonts/Asheville-Sans-14-Bold.pft") + + diff --git a/src/assets.lua2p b/src/assets.lua2p index 99a0f6c..d200829 100644 --- a/src/assets.lua2p +++ b/src/assets.lua2p @@ -28,6 +28,6 @@ end)!!(generatedFileWarning()) !!(dirLookup('assets/images', 'png', 'playdate.graphics.image.new', 'pd_image')) -- !!(dirLookup('assets/sounds', 'wav', 'playdate.sound.sampleplayer.new', 'pd_sampleplayer')) -- !!(dirLookup('assets/music', 'wav', 'playdate.sound.sampleplayer.new', 'pd_sampleplayer')) --- !!(dirLookup('assets/fonts', 'fnt', 'playdate.graphics.font.new', 'pd_font', nil, nil, function(varName, value) --- return varName:gsub("[- ]", "") .. " = " .. value:gsub("fnt", "pft") --- end)) +!!(dirLookup('assets/fonts', 'fnt', 'playdate.graphics.font.new', 'pd_font', nil, nil, function(varName, value) + return varName:gsub("[- ]", "") .. " = " .. value:gsub("fnt", "pft") +end)) diff --git a/src/assets/fonts/Asheville-Sans-14-Bold-table-20-20.png b/src/assets/fonts/Asheville-Sans-14-Bold-table-20-20.png new file mode 100755 index 0000000..2b3c6a8 Binary files /dev/null and b/src/assets/fonts/Asheville-Sans-14-Bold-table-20-20.png differ diff --git a/src/assets/fonts/Asheville-Sans-14-Bold.fnt b/src/assets/fonts/Asheville-Sans-14-Bold.fnt new file mode 100755 index 0000000..3ee7fa3 --- /dev/null +++ b/src/assets/fonts/Asheville-Sans-14-Bold.fnt @@ -0,0 +1,295 @@ +tracking=1 +space 3 +! 2 +" 5 +# 9 +$ 8 +% 12 +& 11 +' 3 +( 5 +) 5 +* 8 ++ 8 +, 3 +- 6 +. 2 +/ 6 +0 9 +1 4 +2 9 +3 9 +4 9 +5 9 +6 9 +7 9 +8 10 +9 9 +: 2 +; 2 +< 7 += 7 +> 7 +? 9 +@ 11 +A 10 +B 9 +C 9 +D 9 +E 8 +F 8 +G 9 +H 9 +I 2 +J 8 +K 10 +L 9 +M 12 +N 9 +O 9 +P 9 +Q 9 +R 9 +S 9 +T 10 +U 9 +V 10 +W 14 +X 8 +Y 8 +Z 8 +[ 3 +\ 6 +] 3 +^ 6 +_ 8 +` 3 +a 8 +b 8 +c 8 +d 8 +e 8 +f 6 +g 8 +h 8 +i 2 +j 4 +k 8 +l 2 +m 12 +n 8 +o 8 +p 8 +q 8 +r 6 +s 8 +t 6 +u 8 +v 8 +w 12 +x 9 +y 8 +z 8 +{ 6 +| 2 +} 6 +~ 10 +… 8 +¥ 8 +‼ 5 +™ 8 +© 11 +® 11 +。 16 +、 16 +ぁ 16 +あ 16 +ぃ 16 +い 16 +ぅ 16 +う 16 +ぇ 16 +え 16 +ぉ 16 +お 16 +か 16 +が 16 +き 16 +ぎ 16 +く 16 +ぐ 16 +け 16 +げ 16 +こ 16 +ご 16 +さ 16 +ざ 16 +し 16 +じ 16 +す 16 +ず 16 +せ 16 +ぜ 16 +そ 16 +ぞ 16 +た 16 +だ 16 +ち 16 +ぢ 16 +っ 16 +つ 16 +づ 16 +て 16 +で 16 +と 16 +ど 16 +な 16 +に 16 +ぬ 16 +ね 16 +の 16 +は 16 +ば 16 +ぱ 16 +ひ 16 +び 16 +ぴ 16 +ふ 16 +ぶ 16 +ぷ 16 +へ 16 +べ 16 +ぺ 16 +ほ 16 +ぼ 16 +ぽ 16 +ま 16 +み 16 +む 16 +め 16 +も 16 +ゃ 16 +や 16 +ゅ 16 +ゆ 16 +ょ 16 +よ 16 +ら 16 +り 16 +る 16 +れ 16 +ろ 16 +ゎ 16 +わ 16 +ゐ 16 +ゑ 16 +を 16 +ん 16 +ゔ 16 +ゕ 16 +ゖ 16 +゛ 1 +゜ 0 +ゝ 16 +ゞ 16 +ゟ 16 +゠ 16 +ァ 16 +ア 16 +ィ 16 +イ 16 +ゥ 16 +ウ 16 +ェ 16 +エ 16 +ォ 16 +オ 16 +カ 16 +ガ 16 +キ 16 +ギ 16 +ク 16 +グ 16 +ケ 16 +ゲ 16 +コ 16 +ゴ 16 +サ 16 +ザ 16 +シ 16 +ジ 16 +ス 16 +ズ 16 +セ 16 +ゼ 16 +ソ 16 +ゾ 16 +タ 16 +ダ 16 +チ 16 +ヂ 16 +ッ 16 +ツ 16 +ヅ 16 +テ 16 +デ 16 +ト 16 +ド 16 +ナ 16 +ニ 16 +ヌ 16 +ネ 16 +ノ 16 +ハ 16 +バ 16 +パ 16 +ヒ 16 +ビ 16 +ピ 16 +フ 16 +ブ 16 +プ 16 +ヘ 16 +ベ 16 +ペ 16 +ホ 16 +ボ 16 +ポ 16 +マ 16 +ミ 16 +ム 16 +メ 16 +モ 16 +ャ 16 +ヤ 16 +ュ 16 +ユ 16 +ョ 16 +ヨ 16 +ラ 16 +リ 16 +ル 16 +レ 16 +ロ 16 +ヮ 16 +ワ 16 +ヰ 16 +ヱ 16 +ヲ 16 +ン 16 +ヴ 16 +ヵ 16 +ヶ 16 +ヷ 16 +ヸ 16 +ヹ 16 +ヺ 16 +・ 16 +ー 16 +ヽ 16 +ヾ 16 +ヿ 16 +「 16 +」 16 +円 16 +� 13 \ No newline at end of file diff --git a/src/main.lua b/src/main.lua index 529c20b..3b31cf4 100644 --- a/src/main.lua +++ b/src/main.lua @@ -15,15 +15,19 @@ world = tiny.world() import("tiny-tools.lua") import("assets.lua") import("systems/filter-types.lua") -import("systems/camera-pan.lua") -import("systems/collision-detection.lua") -import("systems/collision-resolution.lua") -import("systems/draw.lua") import("systems/gravity.lua") import("systems/move-toward.lua") +import("systems/velocity.lua") import("systems/rounds.lua") import("systems/spawner.lua") -import("systems/velocity.lua") +import("systems/camera-pan.lua") +import("systems/collision-resolution.lua") +import("systems/collision-detection.lua") + +import("systems/draw.lua") +import("systems/input.lua") +import("systems/menu.lua") + import("ingredients/ingredients.lua") import("cart.lua") import("utils.lua") @@ -79,7 +83,7 @@ function playdate.update() floor.position.x = Camera.pan.x - 600 - world:update(deltaSeconds) + world:update(math.min(1 / 40, deltaSeconds)) gfx.setDrawOffset(0, 0) Score:draw() diff --git a/src/systems/draw.lua b/src/systems/draw.lua index e683fdf..89c6020 100644 --- a/src/systems/draw.lua +++ b/src/systems/draw.lua @@ -4,10 +4,46 @@ drawRectanglesSystem = filteredSystem({ position = T.XyPair, drawAsRectangle = { gfx.fillRect(e.position.x, e.position.y, e.drawAsRectangle.size.x, e.drawAsRectangle.size.y) end) -drawTextSystem = filteredSystem({ position = T.XyPair, drawAsText = { text = T.str } }, function(e, dt) - gfx.drawTextAligned(e.drawAsText.text, e.position.x, e.position.y, gfx.kAlignCenter) -end) - drawSpriteSystem = filteredSystem({ position = T.XyPair, drawAsSprite = T.PdImage }, function(e, dt, system) e.drawAsSprite:draw(e.position.x, e.position.y) end) + +local textHeight = AshevilleSans14Bold:getHeight() +local xMargin = 4 + +drawTextSystem = filteredSystem( + { position = T.XyPair, drawAsText = { text = T.str, style = Maybe(T.str) } }, + function(e, dt) + local textWidth = AshevilleSans14Bold:getTextWidth(e.drawAsText.text) + if e.drawAsText.style == TextStyle.Inverted then + gfx.fillRect( + e.position.x - xMargin - textWidth / 2, + e.position.y - 2, + textWidth + (xMargin * 2), + textHeight + 2 + ) + gfx.setImageDrawMode(gfx.kDrawModeInverted) + end + if e.drawAsText.style == TextStyle.Bordered then + gfx.setColor(gfx.kColorWhite) + gfx.fillRect( + e.position.x - xMargin - textWidth / 2, + e.position.y - 2, + textWidth + (xMargin * 2), + textHeight + 2 + ) + gfx.setColor(gfx.kColorBlack) + gfx.setImageDrawMode(gfx.kDrawModeCopy) + gfx.drawRect( + e.position.x - xMargin - textWidth / 2, + e.position.y - 2, + textWidth + (xMargin * 2), + textHeight + 2 + ) + end + AshevilleSans14Bold:drawTextAligned(e.drawAsText.text, e.position.x, e.position.y, kTextAlignment.center) + if e.drawAsText.style == TextStyle.Inverted then + gfx.setImageDrawMode(gfx.kDrawModeCopy) + end + end +) diff --git a/src/systems/filter-types.lua b/src/systems/filter-types.lua index cadb85d..2667283 100644 --- a/src/systems/filter-types.lua +++ b/src/systems/filter-types.lua @@ -18,6 +18,8 @@ local XyPair = { x = 1, y = 1 } ---@alias CanSpawn { entity: Entity } +---@alias InRelations Entity[] + T = { XyPair = XyPair, bool = true, @@ -49,6 +51,10 @@ T = { RoundStateAction = "start", ---@type CanSpawn CanSpawn = {}, + ---@type InRelations + InRelations = {}, + ---@type InputState + InputState = {}, } ---@generic T @@ -57,3 +63,9 @@ T = { function Maybe(t) return { maybe = t } end + +TextStyle = { + Inverted = "INVERTED", + Bordered = "BORDERED", + None = "None", +} diff --git a/src/systems/input.lua b/src/systems/input.lua new file mode 100644 index 0000000..a226204 --- /dev/null +++ b/src/systems/input.lua @@ -0,0 +1,18 @@ +---@alias InputState { upJustPressed: boolean, downJustPressed: boolean, rightJustPressed: boolean, leftJustPressed: boolean, aJustPressed: boolean, bJustPressed: boolean } + +local buttonJustPressed = playdate.buttonJustPressed +local inputState = {} + +inputSystem = filteredSystem({ canReceiveInput = T.marker }, function(e, _, system) + e.inputState = inputState + system.world:addEntity(e) +end) + +function inputSystem:preProcess() + inputState.upJustPressed = buttonJustPressed(playdate.kButtonUp) + inputState.downJustPressed = buttonJustPressed(playdate.kButtonDown) + inputState.rightJustPressed = buttonJustPressed(playdate.kButtonRight) + inputState.leftJustPressed = buttonJustPressed(playdate.kButtonLeft) + inputState.aJustPressed = buttonJustPressed(playdate.kButtonA) + inputState.bJustPressed = buttonJustPressed(playdate.kButtonB) +end diff --git a/src/systems/menu.lua b/src/systems/menu.lua new file mode 100644 index 0000000..d226fc1 --- /dev/null +++ b/src/systems/menu.lua @@ -0,0 +1,26 @@ +menuController = filteredSystem({ menuItems = T.InRelations, inputState = T.InputState }, function(e, _, _) + for _, menuItem in pairs(e.menuItems) do + if menuItem.highlighted then + if e.inputState.aJustPressed then + menuItem.onSelect() + end + if e.inputState.downJustPressed and menuItem.navigateDown then + menuItem.highlighted = false + menuItem.navigateDown.highlighted = true + return + end + if e.inputState.upJustPressed and menuItem.navigateUp then + menuItem.highlighted = false + menuItem.navigateUp.highlighted = true + return + end + end + end + for _, menuItem in pairs(e.menuItems) do + if menuItem.highlighted then + menuItem.drawAsText.style = TextStyle.Inverted + else + menuItem.drawAsText.style = TextStyle.Bordered + end + end +end) diff --git a/src/systems/move-toward.lua b/src/systems/move-toward.lua index bb0ece1..3777c09 100644 --- a/src/systems/move-toward.lua +++ b/src/systems/move-toward.lua @@ -15,27 +15,24 @@ local function normalizeVector(xy1, xy2) return x / distance, y / distance, distance end -moveTowardSystem = filteredSystem( - { moveToward = MoveToward, position = T.XyPair }, - function(e, dt, system) - local xNorm, yNorm, distance = normalizeVector(e.position, e.moveToward.target) - if distance > e.moveToward.range then - return - end - - -- TODO May be incorrect when signs are mismatched between vel and diff - local xVel = xNorm * e.moveToward.speed * dt - if abs(e.position.x - e.moveToward.target.x) < abs(xVel) then - e.position.x = e.moveToward.target.x - else - e.position.x = e.position.x + xVel - end - - local yVel = yNorm * e.moveToward.speed * dt - if abs(e.position.y - e.moveToward.target.y) < abs(yVel) then - e.position.y = e.moveToward.target.y - else - e.position.y = e.position.y + yVel - end +moveTowardSystem = filteredSystem({ moveToward = MoveToward, position = T.XyPair }, function(e, dt, system) + local xNorm, yNorm, distance = normalizeVector(e.position, e.moveToward.target) + if distance > e.moveToward.range then + return end -) + + -- TODO May be incorrect when signs are mismatched between vel and diff + local xVel = xNorm * e.moveToward.speed * dt + if abs(e.position.x - e.moveToward.target.x) < abs(xVel) then + e.position.x = e.moveToward.target.x + else + e.position.x = e.position.x + xVel + end + + local yVel = yNorm * e.moveToward.speed * dt + if abs(e.position.y - e.moveToward.target.y) < abs(yVel) then + e.position.y = e.moveToward.target.y + else + e.position.y = e.position.y + yVel + end +end) diff --git a/src/systems/rounds.lua b/src/systems/rounds.lua index 344f1f3..3a5ec37 100644 --- a/src/systems/rounds.lua +++ b/src/systems/rounds.lua @@ -22,6 +22,8 @@ roundSystem = filteredSystem({ roundAction = T.RoundStateAction, position = Mayb stopMovingOnCollision = true, }) + -- TODO: Big ol' numbers displaying how many ingredients were collected? + -- TODO: Could layer ingredients in rows of three? Maybe just when it's higher? local delayPerDrop = 150 local delay = 0 for i, collectable in ipairs(collectedEntities.entities) do @@ -48,30 +50,51 @@ roundSystem = filteredSystem({ roundAction = T.RoundStateAction, position = Mayb end local availableUpgrades = Utils.getNDifferentValues(getAvailableSpawnerUpgrades(), 3) + -- Sorting from shortest to longest sort of makes them look like a bun? + table.sort(availableUpgrades, function(a, b) + return #a.name > #b.name + end) y = y - 50 + local menuEntity = { + menuItems = {}, + canReceiveInput = T.marker, + } + local upgradeBelow for _, upgrade in ipairs(availableUpgrades) do - printTable(upgrade) - local collX, collY = 75, 30 + local collX, collY = 75, 21 y = y - collY - 15 - playdate.timer.new(delay, function(ee, ccollX, ccollY, yy, ii, ssystem, ccollectable) - ssystem.world:addEntity({ - drawAsText = { - text = upgrade.name, - }, - size = { x = ccollX, y = ccollY / 2 }, - mass = 0.5, - velocity = { x = 0, y = 0 }, - position = { x = ee.position.x - (ccollX / 2), y = yy }, - canCollideWith = 2, - canBeCollidedBy = 2, - isSolid = true, - stopMovingOnCollision = true, - onCollidingRemove = onCollidingRemove, - focusOnCollide = ii, - }) - end, e, collX, collY, y, i, system, collectable) + local upgradeEntity = { + onSelect = upgrade.apply, + drawAsText = { + text = upgrade.name, + style = TextStyle.Inverted, + }, + size = { x = collX, y = collY }, + mass = 0.5, + velocity = { x = 0, y = 0 }, + position = { x = e.position.x, y = y }, + canCollideWith = 2, + canBeCollidedBy = 2, + isSolid = true, + stopMovingOnCollision = true, + onCollidingRemove = onCollidingRemove, + focusOnCollide = i, + navigateDown = upgradeBelow, + highlighted = true, + } + if upgradeBelow then + upgradeBelow.navigateUp = upgradeEntity + upgradeBelow.highlighted = false + upgradeBelow.drawAsText.style = TextStyle.Bordered + end + upgradeBelow = upgradeEntity + menuEntity.menuItems[#menuEntity.menuItems + 1] = upgradeEntity + playdate.timer.new(delay, function(_system, _upgradeEntity) + _system.world:addEntity(_upgradeEntity) + end, system, upgradeEntity) delay = delay + delayPerDrop + system.world:addEntity(menuEntity) end system.world:removeEntity(e) end diff --git a/src/systems/spawner.lua b/src/systems/spawner.lua index 3ff3efb..ed01416 100644 --- a/src/systems/spawner.lua +++ b/src/systems/spawner.lua @@ -109,7 +109,7 @@ function getAvailableSpawnerUpgrades() local upgrades = {} for _, spawner in pairs(spawnerSystem.entities) do if spawner.hasUpgradeSpeed then - upgrades[#upgrades + 1] = { hasUpgradeSpeed = spawner.hasUpgradeSpeed } + -- upgrades[#upgrades + 1] = { hasUpgradeSpeed = spawner.hasUpgradeSpeed } end if spawner.canSpawn.entity.score then @@ -117,7 +117,7 @@ function getAvailableSpawnerUpgrades() name = "Double " .. spawner.name .. " value", apply = function() spawner.canSpawn.entity.score = spawner.canSpawn.entity.score * 2 - end + end, } end @@ -126,7 +126,8 @@ function getAvailableSpawnerUpgrades() name = "Double " .. spawner.name .. " frequency", apply = function() spawner.odds = spawner.odds * 2 - end + -- addEntity({ roundAction = "NEXT_ROUND" }) + end, } -- if not spawner.canSpawn.entity.velocity then diff --git a/src/systems/velocity.lua b/src/systems/velocity.lua index 8e2ed74..7de745d 100644 --- a/src/systems/velocity.lua +++ b/src/systems/velocity.lua @@ -1,10 +1,7 @@ local sqrt = math.sqrt velocitySystem = filteredSystem({ position = T.XyPair, velocity = T.XyPair }, function(e, dt, system) - if not e.velocity then - return - end - if sqrt((e.velocity.x * e.velocity.x) + (e.velocity.y * e.velocity.y)) < 1.5 then + if sqrt((e.velocity.x * e.velocity.x) + (e.velocity.y * e.velocity.y)) < 2 then e.velocity = nil if e.spawnEntitiesWhenStopped then e:spawnEntitiesWhenStopped(system.world) diff --git a/src/utils.lua b/src/utils.lua index 189eaef..6281b04 100644 --- a/src/utils.lua +++ b/src/utils.lua @@ -25,4 +25,4 @@ function Utils.getNDifferentValues(fromArr, n) randoms[#randoms + 1] = fromArr[i] end return randoms -end \ No newline at end of file +end