diff --git a/source/assets/launcher/card-highlighted/1.png b/source/assets/launcher/card-highlighted/1.png index 6e1903d..4c076c9 100644 Binary files a/source/assets/launcher/card-highlighted/1.png and b/source/assets/launcher/card-highlighted/1.png differ diff --git a/source/assets/launcher/card-highlighted/2.png b/source/assets/launcher/card-highlighted/2.png index bab13ad..a7755b7 100644 Binary files a/source/assets/launcher/card-highlighted/2.png and b/source/assets/launcher/card-highlighted/2.png differ diff --git a/source/assets/launcher/card-highlighted/3.png b/source/assets/launcher/card-highlighted/3.png index 959a6e7..1014773 100644 Binary files a/source/assets/launcher/card-highlighted/3.png and b/source/assets/launcher/card-highlighted/3.png differ diff --git a/source/assets/launcher/card-pressed.png b/source/assets/launcher/card-pressed.png index 16ac6b5..7b21919 100644 Binary files a/source/assets/launcher/card-pressed.png and b/source/assets/launcher/card-pressed.png differ diff --git a/source/assets/launcher/card.png b/source/assets/launcher/card.png index bab13ad..8e52def 100644 Binary files a/source/assets/launcher/card.png and b/source/assets/launcher/card.png differ diff --git a/source/assets/launcher/launchImages/1.png b/source/assets/launcher/launchImages/1.png index e547933..86c2d01 100644 Binary files a/source/assets/launcher/launchImages/1.png and b/source/assets/launcher/launchImages/1.png differ diff --git a/source/assets/launcher/launchImages/2.png b/source/assets/launcher/launchImages/2.png index 3d08a1a..c277860 100644 Binary files a/source/assets/launcher/launchImages/2.png and b/source/assets/launcher/launchImages/2.png differ diff --git a/source/assets/launcher/launchImages/3.png b/source/assets/launcher/launchImages/3.png index 5e6b9cf..72007dd 100644 Binary files a/source/assets/launcher/launchImages/3.png and b/source/assets/launcher/launchImages/3.png differ diff --git a/source/assets/launcher/launchImages/4.png b/source/assets/launcher/launchImages/4.png index 192b4d2..f728ce9 100644 Binary files a/source/assets/launcher/launchImages/4.png and b/source/assets/launcher/launchImages/4.png differ diff --git a/source/assets/launcher/launchImages/5.png b/source/assets/launcher/launchImages/5.png index a577d76..60bf29e 100644 Binary files a/source/assets/launcher/launchImages/5.png and b/source/assets/launcher/launchImages/5.png differ diff --git a/source/assets/launcher/launchImages/6.png b/source/assets/launcher/launchImages/6.png index f8dcca6..8d79a3d 100644 Binary files a/source/assets/launcher/launchImages/6.png and b/source/assets/launcher/launchImages/6.png differ diff --git a/source/assets/launcher/launchImages/7.png b/source/assets/launcher/launchImages/7.png index 0287ac6..51ecacf 100644 Binary files a/source/assets/launcher/launchImages/7.png and b/source/assets/launcher/launchImages/7.png differ diff --git a/source/assets/launcher/launchImages/8.png b/source/assets/launcher/launchImages/8.png index 254938c..16490de 100644 Binary files a/source/assets/launcher/launchImages/8.png and b/source/assets/launcher/launchImages/8.png differ diff --git a/source/assets/launcher/sound.wav b/source/assets/launcher/sound.wav index 923e906..8c53ed2 100644 Binary files a/source/assets/launcher/sound.wav and b/source/assets/launcher/sound.wav differ diff --git a/source/libraries/pdDialogue.lua b/source/libraries/pdDialogue.lua new file mode 100644 index 0000000..e70f4a1 --- /dev/null +++ b/source/libraries/pdDialogue.lua @@ -0,0 +1,755 @@ +------------------------------------------------ +--- Dialogue classes intended to ease the --- +--- implementation of dialogue into playdate --- +--- games. Developed by: --- +--- GammaGames, PizzaFuelDev and NickSr --- +------------------------------------------------ + +-- You can find examples and docs at https://github.com/PizzaFuel/pdDialogue + +local pd = playdate +local gfx = pd.graphics + +---------------------------------------------------------------------------- +-- #Section: pdDialogue +---------------------------------------------------------------------------- +pdDialogue = {} + +function pdDialogue.wrap(lines, width, font) + --[[ + lines: an array of strings + width: the maximum width of each line (in pixels) + font: the font to use (optional, uses default font if not provided) + ]] -- + font = font or gfx.getFont() + + local result = {} + + for _, line in ipairs(lines) do + local currentWidth, currentLine = 0, "" + + if line == "" or font:getTextWidth(line) <= width then + table.insert(result, line) + goto continue + end + + for word in line:gmatch("%S+") do + local wordWidth = font:getTextWidth(word) + local newLine = currentLine .. (currentLine ~= "" and " " or "") .. word + local newWidth = font:getTextWidth(newLine) + + if newWidth >= width then + table.insert(result, currentLine) + currentWidth, currentLine = wordWidth, word + else + currentWidth, currentLine = newWidth, newLine + end + end + + if currentWidth ~= 0 then + table.insert(result, currentLine) + end + + ::continue:: + end + + return result +end + +function pdDialogue.window(text, startIndex, height, font) + --[[ + text: an array of strings (pre-wrapped) + startIndex: the row index to start the window + height: the height (in pixels) of the window + font: the font to use (optional, uses default font if not provided) + ]] -- + font = font or gfx.getFont() + + local result = { text[start_index] } + local rows = pdDialogue.getRows(height, font) - 1 + + for index = 1, rows do + -- Check if index is out of range of the text + if start_index + index > #text then + break + end + + table.insert(result, text[i]) + end + + return table.concat(result, "\n") +end + +function pdDialogue.paginate(lines, height, font) + --[[ + lines: array of strings (pre-wrapped) + height: height to limit text (in pixels) + font: optional, will get current font if not provided + ]] -- + + local result = {} + local currentLine = {} + + font = font or gfx.getFont() + + local rows = pdDialogue.getRows(height, font) + + for _, line in ipairs(lines) do + if line == "" then + -- If line is empty and currentLine has text... + if #currentLine > 0 then + -- Merge currentLine and add to result + table.insert(result, table.concat(currentLine, "\n")) + currentLine = {} + end + else + -- If over row count... + if #currentLine >= rows then + -- Concat currentLine, add to result, and start new line + table.insert(result, table.concat(currentLine, "\n")) + currentLine = { line } + else + table.insert(currentLine, line) + end + end + end + + -- If all lines are complete and currentLine is not empty, add to result + if #currentLine > 0 then + table.insert(result, table.concat(currentLine, "\n")) + currentLine = {} + end + + return result +end + +function pdDialogue.process(text, width, height, font) + --[[ + text: string containing the text to be processed + width: width to limit text (in pixels) + height: height to limit text (in pixels) + font: optional, will get current font if not provided + ]] -- + local lines = {} + font = font or gfx.getFont() + + -- Split newlines in text + for line in text:gmatch("([^\n]*)\n?") do + table.insert(lines, line) + end + + -- Wrap the text + local wrapped = pdDialogue.wrap(lines, width, font) + + -- Paginate the wrapped text + local paginated = pdDialogue.paginate(wrapped, height, font) + + return paginated +end + +function pdDialogue.getRows(height, font) + font = font or gfx.getFont() + local lineHeight = font:getHeight() + font:getLeading() + return math.floor(height / lineHeight) +end + +function pdDialogue.getRowsf(height, font) + font = font or gfx.getFont() + local lineHeight = font:getHeight() + font:getLeading() + return height / lineHeight +end + +---------------------------------------------------------------------------- +-- #Section: pdDialogueSprite +---------------------------------------------------------------------------- +pdDialogueSprite = {} +class("pdDialogueSprite").extends(gfx.sprite) + +function pdDialogueSprite:init(dialogue) + --[[ + dialogue: an instance of pdDialogueBox + ]] -- + pdDialogueSprite.super.init(self) + self.image = gfx.image.new(dialogue.width, dialogue.height) + self:setImage(self.image) + self.dialogue = dialogue + -- Remove sprite when dialogue is closed + local onClose = self.dialogue.onClose + function self.dialogue.onClose() + onClose() + self:remove() + end +end + +function pdDialogueSprite:add() + pdDialogueSprite.super.add(self) + if not self.dialogue.enabled then + self.dialogue:enable() + end +end + +function pdDialogueSprite:update() + pdDialogueSprite.super.update(self) + -- Redraw dialogue if it has changed (update returns true) + if self.dialogue:update() then + self.image:clear(gfx.kColorClear) + gfx.pushContext(self.image) + self.dialogue:draw(0, 0) + gfx.popContext() + self:markDirty() + end +end + +---------------------------------------------------------------------------- +-- #Section: pdDialogueBox +---------------------------------------------------------------------------- +pdDialogueBox = {} +class("pdDialogueBox").extends() + +local ABTN = Graphics.image.new("assets/sprites/buttons/A") + +function pdDialogueBox.buttonPrompt(x, y) + gfx.setImageDrawMode(gfx.kDrawModeCopy) + ABTN:draw(x, y) +end + +function pdDialogueBox.arrowPrompt(x, y, color) + gfx.setColor(color or gfx.kColorBlack) + gfx.fillTriangle( + x, y, + x + 5, y + 5, + x + 10, y + ) +end + +function pdDialogueBox:init(text, width, height, font) + --[[ + text: optional string of text to process + width: width of dialogue box (in pixels) + height: height of dialogue box (in pixels) + font: font to use for drawing text + ]] -- + + pdDialogueBox.super.init(self) + self.speed = 0.5 -- char per frame + self.padding = 2 + self.width = width + self.height = height + self.font = font + self.enabled = false + self.line_complete = false + self.dialogue_complete = false + + if text ~= nil then + self:setText(text) + end +end + +function pdDialogueBox:asSprite() + return pdDialogueSprite(self) +end + +function pdDialogueBox:getInputHandlers() + return { + AButtonDown = function() + self:setSpeed(2) + if self.dialogue_complete then + self:disable() + elseif self.line_complete then + self:nextPage() + end + end, + AButtonUp = function() + self:setSpeed(0.5) + end, + BButtonDown = function() + if self.line_complete then + if self.dialogue_complete then + self:disable() + else + self:nextPage() + self:finishLine() + end + else + self:finishLine() + end + end + } +end + +function pdDialogueBox:enable() + self.enabled = true + self:onOpen() +end + +function pdDialogueBox:disable() + self.enabled = false + self:onClose() +end + +function pdDialogueBox:setText(text) + local font = self.font or gfx.getFont() + + if type(font) == "table" then + font = font[gfx.font.kVariantNormal] + end + self.text = text + if text ~= nil then + self.pages = pdDialogue.process(text, self.width - self.padding * 2, self.height - self.padding * 2, font) + end + self:restartDialogue() +end + +function pdDialogueBox:getText() + return self.text +end + +function pdDialogueBox:setPages(pages) + self.pages = pages + self:restartDialogue() +end + +function pdDialogueBox:getPages() + return self.pages +end + +function pdDialogueBox:setWidth(width) + self.width = width + if self.text ~= nil then + self:setText(self.text) + end +end + +function pdDialogueBox:getWidth() + return self.width +end + +function pdDialogueBox:setHeight(height) + self.height = height + if self.text ~= nil then + self:setText(self.text) + end +end + +function pdDialogueBox:getHeight() + return self.height +end + +function pdDialogueBox:setPadding(padding) + self.padding = padding + -- Set text again because padding affects text wrapping + self:setText(self.text) +end + +function pdDialogueBox:getPadding() + return self.padding +end + +function pdDialogueBox:setFont(font) + self.font = font +end + +function pdDialogueBox:getFont() + return self.font +end + +function pdDialogueBox:setNineSlice(nineSlice) + self.nineSlice = nineSlice +end + +function pdDialogueBox:getNineSlice() + return self.nineSlice +end + +function pdDialogueBox:setSpeed(speed) + self.speed = speed +end + +function pdDialogueBox:getSpeed() + return self.speed +end + +function pdDialogueBox:restartDialogue() + self.currentPage = 1 + self.currentChar = 1 + self.line_complete = false + self.dialogue_complete = false +end + +function pdDialogueBox:finishDialogue() + self.currentPage = #self.pages + self:finishLine() +end + +function pdDialogueBox:restartLine() + self.currentChar = 1 + self.line_complete = false + self.dialogue_complete = false + self.dirty = true +end + +function pdDialogueBox:finishLine() + self.currentChar = #self.pages[self.currentPage] + self.line_complete = true + self.dialogue_complete = self.currentPage == #self.pages + self.dirty = true +end + +function pdDialogueBox:previousPage() + if self.currentPage - 1 >= 1 then + self.currentPage -= 1 + self:restartLine() + end +end + +function pdDialogueBox:nextPage() + if self.currentPage + 1 <= #self.pages then + self.currentPage += 1 + self:restartLine() + end +end + +function pdDialogueBox:drawBackground(x, y) + if self.nineSlice ~= nil then + gfx.setImageDrawMode(gfx.kDrawModeCopy) + self.nineSlice:drawInRect(x, y, self.width, self.height) + else + gfx.setColor(gfx.kColorWhite) + gfx.fillRect(x, y, self.width, self.height) + gfx.setColor(gfx.kColorBlack) + gfx.drawRect(x, y, self.width, self.height) + end +end + +function pdDialogueBox:drawText(x, y, text) + gfx.setImageDrawMode(gfx.kDrawModeCopy) + if self.font ~= nil then + -- variable will be table if a font family + if type(self.font) == "table" then + -- Draw with font family + gfx.drawText(text, x, y, self.font) + else + -- Draw using font + self.font:drawText(text, x, y) + end + else + gfx.drawText(text, x, y) + end +end + +function pdDialogueBox:drawPrompt(x, y) + pdDialogueBox.buttonPrompt(x + self.width - 20, y + self.height - 20) +end + +function pdDialogueBox:draw(x, y) + local currentText = self.pages[self.currentPage] + if not self.line_complete then + currentText = currentText:sub(1, math.floor(self.currentChar)) + end + self:drawBackground(x, y) + self:drawText(x + self.padding, y + self.padding, currentText) + if self.line_complete then + self:drawPrompt(x, y) + end +end + +function pdDialogueBox:onOpen() + -- Overrideable by user +end + +function pdDialogueBox:onPageComplete() + -- Overrideable by user +end + +function pdDialogueBox:onDialogueComplete() + -- Overrideable by user +end + +function pdDialogueBox:onClose() + -- Overrideable by user +end + +function pdDialogueBox:update() + local dirty = self.dirty + self.dirty = false + if not self.enabled then + return dirty + end + local pageLength = #self.pages[self.currentPage] + if self.currentChar < pageLength then + dirty = true + self.currentChar += self.speed + if self.currentChar > pageLength then + self.currentChar = pageLength + end + end + + local previous_line_complete = self.line_complete + local previous_dialogue_complete = self.dialogue_complete + self.line_complete = self.currentChar == pageLength + self.dialogue_complete = self.line_complete and self.currentPage == #self.pages + + if previous_line_complete ~= self.line_complete then + self:onPageComplete() + dirty = true + end + if previous_dialogue_complete ~= self.dialogue_complete then + self:onDialogueComplete() + dirty = true + end + + return dirty +end + +---------------------------------------------------------------------------- +-- #Section: pdPortraitDialogueBox +---------------------------------------------------------------------------- +pdPortraitDialogueBox = {} +class("pdPortraitDialogueBox").extends(pdDialogueBox) + +function pdPortraitDialogueBox:init(name, drawable, text, width, height, font) + self.name = name + self.portrait = drawable + if self.portrait.getSize ~= nil then + self.portrait_width, self.portrait_height = self.portrait:getSize() + elseif self.portrait.getImage ~= nil then + self.portrait_width, self.portrait_height = self.portrait:getImage(1):getSize() + elseif self.portrait.image ~= nil then + if type(self.portrait.image) ~= "function" then + self.portrait_width, self.portrait_height = self.portrait.image:getSize() + else + self.portrait_width, self.portrait_height = self.portrait:image():getSize() + end + end + pdDialogueBox.init(self, text, width - self.portrait_width, height, font) + self:setAlignment(kTextAlignment.left) +end + +function pdPortraitDialogueBox:setAlignment(alignment) + self.alignment = alignment + if self.alignment == kTextAlignment.left then + self.portrait_x_position = 0 + else + self.portrait_x_position = self.width + end +end + +function pdPortraitDialogueBox:getAlignment() + return self.alignment +end + +function pdPortraitDialogueBox:draw(x, y) + local offset = self.alignment == kTextAlignment.left and self.portrait_width or 0 + pdPortraitDialogueBox.super.draw(self, x + offset, y) +end + +function pdPortraitDialogueBox:drawBackground(x, y) + pdPortraitDialogueBox.super.drawBackground(self, x, y) + self:drawPortrait(x + self.portrait_x_position - self.portrait_width, y) +end + +function pdPortraitDialogueBox:drawPortrait(x, y) + if self.nineSlice ~= nil then + self.nineSlice:drawInRect(x, y, self.portrait_width, self.portrait_height) + else + gfx.setColor(gfx.kColorWhite) + gfx.fillRect(x, y, self.portrait_width, self.portrait_height) + gfx.setColor(gfx.kColorBlack) + gfx.drawRect(x, y, self.portrait_width, self.height) + end + + local font = self.font or gfx.getFont() + self.portrait:draw(x, y) + font:drawTextAligned( + self.name, + x + self.portrait_width / 2, + y + self.height - font:getHeight() - self.padding, + kTextAlignment.center + ) +end + +---------------------------------------------------------------------------- +-- #Section: dialogue box used in pdDialogue +---------------------------------------------------------------------------- +pdDialogue.DialogueBox_x, pdDialogue.DialogueBox_y = 5, 186 +pdDialogue.DialogueBox = pdDialogueBox(nil, 390, 48) +pdDialogue.DialogueBox_Callbacks = {} +pdDialogue.DialogueBox_Say_Default = nil +pdDialogue.DialogueBox_Say_Nils = nil +pdDialogue.DialogueBox_KeyValueMap = { + width = { + set = function(value) pdDialogue.DialogueBox:setWidth(value) end, + get = function() return pdDialogue.DialogueBox:getWidth() end + }, + height = { + set = function(value) pdDialogue.DialogueBox:setHeight(value) end, + get = function() return pdDialogue.DialogueBox:getHeight() end + }, + x = { + set = function(value) pdDialogue.DialogueBox_x = value end, + get = function() return pdDialogue.DialogueBox_x end + }, + y = { + set = function(value) pdDialogue.DialogueBox_y = value end, + get = function() return pdDialogue.DialogueBox_y end + }, + padding = { + set = function(value) pdDialogue.DialogueBox:setPadding(value) end, + get = function() return pdDialogue.DialogueBox:getPadding() end + }, + font = { + set = function(value) pdDialogue.DialogueBox:setFont(value) end, + get = function() return pdDialogue.DialogueBox:getFont() end + }, + fontFamily = { + set = function(value) pdDialogue.DialogueBox.fontFamily = value end, + get = function() return pdDialogue.DialogueBox.fontFamily end + }, + nineSlice = { + set = function(value) pdDialogue.DialogueBox:setNineSlice(value) end, + get = function() return pdDialogue.DialogueBox:getNineSlice() end + }, + speed = { + set = function(value) pdDialogue.DialogueBox:setSpeed(value) end, + get = function() return pdDialogue.DialogueBox:getSpeed() end + }, + drawBackground = { + set = function(func) pdDialogue.DialogueBox_Callbacks["drawBackground"] = func end, + get = function() return pdDialogue.DialogueBox_Callbacks["drawBackground"] end + }, + drawText = { + set = function(func) pdDialogue.DialogueBox_Callbacks["drawText"] = func end, + get = function() return pdDialogue.DialogueBox_Callbacks["drawText"] end + }, + drawPrompt = { + set = function(func) pdDialogue.DialogueBox_Callbacks["drawPrompt"] = func end, + get = function() return pdDialogue.DialogueBox_Callbacks["drawPrompt"] end + }, + onOpen = { + set = function(func) pdDialogue.DialogueBox_Callbacks["onOpen"] = func end, + get = function() return pdDialogue.DialogueBox_Callbacks["onOpen"] end + }, + onPageComplete = { + set = function(func) pdDialogue.DialogueBox_Callbacks["onPageComplete"] = func end, + get = function() return pdDialogue.DialogueBox_Callbacks["onPageComplete"] end + }, + onDialogueComplete = { + set = function(func) pdDialogue.DialogueBox_Callbacks["onDialogueComplete"] = func end, + get = function() return pdDialogue.DialogueBox_Callbacks["onDialogueComplete"] end + }, + onClose = { + set = function(func) pdDialogue.DialogueBox_Callbacks["onClose"] = func end, + get = function() return pdDialogue.DialogueBox_Callbacks["onClose"] end + } +} +function pdDialogue.DialogueBox:drawBackground(x, y) + if pdDialogue.DialogueBox_Callbacks["drawBackground"] ~= nil then + pdDialogue.DialogueBox_Callbacks["drawBackground"](dialogue, x, y) + else + pdDialogue.DialogueBox.super.drawBackground(self, x, y) + end +end + +function pdDialogue.DialogueBox:drawText(x, y, text) + if pdDialogue.DialogueBox_Callbacks["drawText"] ~= nil then + pdDialogue.DialogueBox_Callbacks["drawText"](dialogue, x, y, text) + else + pdDialogue.DialogueBox.super.drawText(self, x, y, text) + end +end + +function pdDialogue.DialogueBox:drawPrompt(x, y) + if pdDialogue.DialogueBox_Callbacks["drawPrompt"] ~= nil then + pdDialogue.DialogueBox_Callbacks["drawPrompt"](dialogue, x, y) + else + pdDialogue.DialogueBox.super.drawPrompt(self, x, y) + end +end + +function pdDialogue.DialogueBox:onOpen() + pd.inputHandlers.push(self:getInputHandlers(), true) + if pdDialogue.DialogueBox_Callbacks["onOpen"] ~= nil then + pdDialogue.DialogueBox_Callbacks["onOpen"]() + end +end + +function pdDialogue.DialogueBox:onPageComplete() + if pdDialogue.DialogueBox_Callbacks["onPageComplete"] ~= nil then + pdDialogue.DialogueBox_Callbacks["onPageComplete"]() + end +end + +function pdDialogue.DialogueBox:onDialogueComplete() + if pdDialogue.DialogueBox_Callbacks["onDialogueComplete"] ~= nil then + pdDialogue.DialogueBox_Callbacks["onDialogueComplete"]() + end +end + +function pdDialogue.DialogueBox:onClose() + -- Make a backup of the current onClose callback + local current = pdDialogue.DialogueBox_Callbacks["onClose"] + -- This will reset all (including the callbacks) + if pdDialogue.DialogueBox_Say_Default ~= nil then + pdDialogue.setup(pdDialogue.DialogueBox_Say_Default) + pdDialogue.DialogueBox_Say_Default = nil + end + if pdDialogue.DialogueBox_Say_Nils ~= nil then + for _, key in ipairs(pdDialogue.DialogueBox_Say_Nils) do + pdDialogue.set(key, nil) + end + pdDialogue.DialogueBox_Say_Nils = nil + end + + pd.inputHandlers.pop() + -- If the current wasn't nil, call it + if current ~= nil then + current() + end +end + +---------------------------------------------------------------------------- +-- #Section: pdDialogue main user functions +---------------------------------------------------------------------------- +function pdDialogue.set(key, value) + if pdDialogue.DialogueBox_KeyValueMap[key] ~= nil then + local backup = pdDialogue.DialogueBox_KeyValueMap[key].get() + pdDialogue.DialogueBox_KeyValueMap[key].set(value) + return backup + end + return nil +end + +function pdDialogue.setup(config) + -- config: table of key value pairs. Supported keys are in pdDialogue.DialogueBox_KeyValueMap + local backup = {} + local nils = {} + for key, value in pairs(config) do + local backup_value = pdDialogue.set(key, value) + if backup_value ~= nil then + backup[key] = backup_value + else + table.insert(nils, key) + end + end + return backup, nils +end + +function pdDialogue.say(text, config) + --[[ + text: string (can be multiline) to say + config: optional table, will provide temporary overrides for this one dialogue box + ]] -- + if config ~= nil then + pdDialogue.DialogueBox_Say_Default, pdDialogue.DialogueBox_Say_Nils = pdDialogue.setup(config) + end + pdDialogue.DialogueBox:setText(text) + pdDialogue.DialogueBox:enable() + return pdDialogue.DialogueBox +end + +function pdDialogue.update() + if pdDialogue.DialogueBox.enabled then + pdDialogue.DialogueBox:update() + pdDialogue.DialogueBox:draw(pdDialogue.DialogueBox_x, pdDialogue.DialogueBox_y) + end +end diff --git a/source/main.lua b/source/main.lua index ea3a9a8..5c9d895 100644 --- a/source/main.lua +++ b/source/main.lua @@ -10,6 +10,7 @@ import 'libraries/noble/Noble' import "libraries/AnimatedSprite" import "libraries/pdParticles" import "libraries/playout" +import "libraries/pdDialogue" import 'utilities/enum' import 'utilities/ui' @@ -129,4 +130,4 @@ playdate.display.setRefreshRate(50) Noble.showFPS = false -Noble.new(Menu) +Noble.new(Assemble) diff --git a/source/pdxinfo b/source/pdxinfo index 9e2d82c..c5863b9 100644 --- a/source/pdxinfo +++ b/source/pdxinfo @@ -2,7 +2,7 @@ name=FPV Game author=ut3usw description=This is a FPV Game bundleID=guru.dead.fpv -version=0.1.1 -buildNumber=2 +version=0.1.2 +buildNumber=3 imagePath=assets/launcher/ launchSoundPath=assets/launcher/sound.wav \ No newline at end of file diff --git a/source/scenes/Assemble.lua b/source/scenes/Assemble.lua index 1b54925..00a3920 100644 --- a/source/scenes/Assemble.lua +++ b/source/scenes/Assemble.lua @@ -88,7 +88,7 @@ end function scene:setValues() scene.code = {} - for i = 1, 9 do + for i = 1, 1 do table.insert(scene.code, scene:randomButton()) end @@ -104,7 +104,6 @@ function scene:setValues() scene.timeToClick = DifficultySettings[scene.difficulty].assebleTime scene.menuConfirmSound = playdate.sound.fileplayer.new("assets/audio/confirm") - self.aKey = Graphics.image.new("assets/sprites/buttons/A") scene.musicEnabled = Noble.Settings.get("music") @@ -148,6 +147,17 @@ function scene:enter() if scene.musicEnabled then scene.levelAudio:play(0) end + local text = + [[The drone is assembled and operational. We are ready for the mission. + +An enemy tank is confirmed in the field. It threatens our advance. + +Your task: eliminate the target. Clear the path for our assault units. + +This operation is crucial. Execute with precision. Command out.]] + + self.dialogue = pdDialogueBox(text, 390, 46) + -- self.dialogue:setPadding(4) end function round(number) @@ -158,35 +168,60 @@ end local elapsedTime = 0 function scene:update() scene.super.update(self) - elapsedTime = elapsedTime + 1 / playdate.display.getRefreshRate() - local sddy = 4 * math.sin(10 * elapsedTime) - local sdy = 4 * math.sin(7 * elapsedTime) - local sddx = 2 * math.cos(5 * elapsedTime) + elapsedTime = elapsedTime + 1 / playdate.display.getRefreshRate() + local sddy = 0 + local sdy = 0 + local sddx = 0 + + if #scene.code == 0 then + if self.dialogue.enabled ~= true then + Noble.Input.setHandler(self.dialogue:getInputHandlers()) + function self.dialogue:onClose() + Noble.Transition.setDefaultProperties(Noble.Transition.SpotlightMask, { + x = 325, + y = 95, + xEnd = 96, + yEnd = 100, + invert = false + }) + scene.menuConfirmSound:play(1) + Noble.transition(Game, nil, Noble.Transition.SpotlightMask) + end + + self.dialogue:enable() + return + else + scene.droneParts[#scene.droneParts]:draw(100, 20) + local dy = 1 * math.sin(10 * elapsedTime) + + self.dialogue:update() + self.dialogue:draw(5, 186 + dy) + end + + self.progressBar:remove() + self.tickTimer:remove() + end + + if #scene.code ~= 0 then -- TODO: this is a hack. no, it's not. it's a SHIT. Why i am do this? What i do with my life? + sddy = 4 * math.sin(10 * elapsedTime) + sdy = 4 * math.sin(7 * elapsedTime) + sddx = 2 * math.cos(5 * elapsedTime) + end + + screwDriver:draw(300 + sddx, 100 + sddy) + solder:draw(0, 100 + sdy) + + if #scene.code == 0 then + return + end if scene.tickTimer.paused then Noble.Text.draw("Assemble the drone!", 200, 110, Noble.Text.ALIGN_CENTER, false, font) end - if #scene.code == 0 then - local dy = 1 * math.sin(10 * elapsedTime) - - Noble.Transition.setDefaultProperties(Noble.Transition.SpotlightMask, { - x = 325, - y = 95, - xEnd = 96, - yEnd = 100, - invert = false - }) - self.aKey:draw(200, 170 + dy) - Noble.Text.draw("Start Mission", 218, 175, Noble.Text.ALIGN_LEFT, false, fontMed) - self.progressBar:remove() - self.tickTimer:remove() - return - end - if scene.buttonTimeout <= 0 then - Noble.Text.draw("LOSE!", 200, 110, Noble.Text.ALIGN_CENTER, false, font) + Noble.Text.draw("Fuck!", 200, 110, Noble.Text.ALIGN_CENTER, false, font) self.progressBar:remove() self.tickTimer:remove() screenShake(100, 5) @@ -194,9 +229,6 @@ function scene:update() return end - screwDriver:draw(300 + sddx, 100 + sddy) - solder:draw(0, 100 + sdy) - if scene.droneParts ~= nil and scene.dronePartIndex ~= nil and scene.dronePartIndex > 0 and #scene.droneParts > 0 then scene.droneParts[scene.dronePartIndex]:draw(100, 20) end diff --git a/source/scenes/BaseScene.lua b/source/scenes/BaseScene.lua index 134846c..75dee4e 100644 --- a/source/scenes/BaseScene.lua +++ b/source/scenes/BaseScene.lua @@ -7,26 +7,25 @@ class("BaseScene").extends(NobleScene) function BaseScene:init() BaseScene.super.init(self) - pd.resetElapsedTime() -- Reset time so each scene starts at 0 - self.optionsMenu = pd.getSystemMenu() -- Store this so we have access to it in all scenes + pd.resetElapsedTime() -- Reset time so each scene starts at 0 + self.optionsMenu = pd.getSystemMenu() -- Store this so we have access to it in all scenes end function BaseScene:update() BaseScene.super.update(self) - - Particles:update() -- Update our particle library + Particles:update() end function BaseScene:exit() BaseScene.super.exit(self) - self.optionsMenu:removeAllMenuItems() -- Remove all custom menu items and reset menu image + self.optionsMenu:removeAllMenuItems() -- Remove all custom menu items and reset menu image pd.setMenuImage(nil) end function BaseScene:drawBackground() - BaseScene.super.drawBackground(self) + BaseScene.super.drawBackground(self) - if self.background ~= nil then -- Helper so you can set a scene's background to an image + if self.background ~= nil then -- Helper so you can set a scene's background to an image self.background:draw(0, 0) end -end \ No newline at end of file +end diff --git a/source/scenes/Game.lua b/source/scenes/Game.lua index e79f8b0..f8f03c3 100644 --- a/source/scenes/Game.lua +++ b/source/scenes/Game.lua @@ -129,6 +129,7 @@ function scene:update() end if scene.player.isDead() then + scene.ground:setMoveSpeed(0) if scene.resultShowed ~= true then Noble.Text.draw("Telemetry Lost", 200, 110, Noble.Text.ALIGN_CENTER, false, font) end diff --git a/source/scripts/player.lua b/source/scripts/player.lua index 5ed7e62..81bcefa 100644 --- a/source/scripts/player.lua +++ b/source/scripts/player.lua @@ -63,6 +63,7 @@ end function Player:handleInput() if Player.bat <= 0 or Player.dead then + self.yInertia = self.yInertia * self.friction return end @@ -104,13 +105,17 @@ function Player:handleInput() -- Y velocity if crankChange ~= 0 then if Player.moveRight == false and Player.moveLeft == false then - if crankChange > 0 then - self.animation:setState("up") + if crankChange < 0 then -- TODO: animation depending on inertia + if self.animation.current == "down" then -- TODO: ABSOLUTE BULLSHIT + self.animation:setState("up") + end else - self.animation:setState("down") + if self.animation.current == "up" then + self.animation:setState("down") + end end end - self.yInertia = self.yInertia - (acceleratedChange * 0.007) + self.yInertia = self.yInertia - (acceleratedChange * 0.02) else self.yInertia = self.yInertia * self.friction end @@ -156,6 +161,10 @@ function Player:handleMovementAndCollisions() xVel = 0 end + if self.y < -20 and yVel < 0 and Player.bat > 0 then + yVel = 0 + end + local _, _, collisions, length = self:checkCollisions(self.x + xVel, self.y + yVel) self.touchingGround = false