Assemble = {} class("Assemble").extends(BaseScene) local scene = Assemble local font = Graphics.font.new('assets/fonts/Mini Sans 2X') local fontMed = Graphics.font.new('assets/fonts/onyx_9') local allButtons = { "A", "B", "DOWN", "LEFT", "RIGHT", "UP" } function scene:popCode(button) if #scene.code == 0 then return end scene.menuConfirmSound:stop() if scene.tickTimer.paused then scene.droneParts = scene:loadDrone(1, #scene.code) scene.tickTimer:start() scene.progressBar:setVisible(true) end if button == scene.code[1] then table.remove(scene.code, 1) scene.tickTimer:reset() scene.dronePartIndex = scene.dronePartIndex + 1 local particle = ParticlePoly(200, 185) particle:setThickness(2) particle:setSize(1, 2) particle:setSpeed(1, 3) particle:setColour(Graphics.kColorXOR) particle:add(5) scene.dY = 5 scene.menuConfirmSound:play(1) else self.buttonTimeout = self.buttonTimeout - 5 scene.code[1] = scene:randomButton() screenShake(100, 5) end end scene.inputHandler = { AButtonDown = function() if #scene.code == 0 then scene.menuConfirmSound:play(1) Noble.transition(Game, nil, Noble.Transition.SpotlightMask) else scene:popCode("A") end end, BButtonDown = function() scene:popCode("B") end, downButtonDown = function() scene:popCode("DOWN") end, leftButtonDown = function() scene:popCode("LEFT") end, rightButtonDown = function() scene:popCode("RIGHT") end, upButtonDown = function() scene:popCode("UP") end, } function scene:randomButton() local button = allButtons[math.random(1, #allButtons)] return button end function scene:drawBackground() end local screwDriver = Graphics.image.new('assets/sprites/assemble/sd.png') local solder = Graphics.image.new('assets/images/solder.png') function scene:loadButtons() local buttons = {} for i = 1, #allButtons do local image = Graphics.image.new('assets/sprites/buttons/' .. allButtons[i] .. '.png') buttons[allButtons[i]] = image end return buttons end function scene:loadDrone(id, parts) local drone = {} for i = 1, parts do local image = Graphics.image.new('assets/sprites/assemble/' .. id .. '/' .. i .. '.png') if image ~= nil then table.insert(drone, image) end end return drone end function scene:setValues() scene.code = {} for i = 1, 1 do table.insert(scene.code, scene:randomButton()) end scene.difficulty = Noble.Settings.get("difficulty") scene.buttons = scene:loadButtons() scene.droneParts = {} scene.dronePartIndex = 0 scene.dY = 5 scene.buttonTimeout = 100 scene.timeToClick = DifficultySettings[scene.difficulty].assebleTime scene.menuConfirmSound = playdate.sound.fileplayer.new("assets/audio/confirm") scene.musicEnabled = Noble.Settings.get("music") scene.levelAudio = playdate.sound.fileplayer.new("assets/audio/assemble") scene.levelAudio:setVolume(0.7) end function scene:init() scene.super.init(self) scene:setValues() scene.progressBar = ProgressBar(200, 175, 50, 5) scene.progressBar:set(self.buttonTimeout) scene.progressBar:setVisible(false) scene.tickTimer = playdate.timer.new(scene.timeToClick, self.buttonTimeout, 0, playdate.easingFunctions.linear) scene.tickTimer.updateCallback = function(timer) scene.buttonTimeout = timer.value scene.progressBar:set(scene.buttonTimeout) end scene.tickTimer.timerEndedCallback = function() scene.buttonTimeout = 0 end scene.tickTimer:pause() end function scene:start() scene.super.start(self) self.optionsMenu:addMenuItem("Main Menu", function() Noble.transition(Menu) end) Noble.showFPS = false end function scene:enter() scene.super.enter(self) scene.buttonTimeout = 100 Noble.Input.setHandler(scene.inputHandler) 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) local formatted = string.format("%.2f", number) return formatted end local elapsedTime = 0 function scene:update() scene.super.update(self) 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.buttonTimeout <= 0 then Noble.Text.draw("Fuck!", 200, 110, Noble.Text.ALIGN_CENTER, false, font) self.progressBar:remove() self.tickTimer:remove() screenShake(100, 5) Noble.Input.setEnabled(false) return end 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 Graphics.drawLine(180, 185, 192, 185) Graphics.drawLine(208, 185, 220, 185) if scene.dY > 0 then scene.dY = self.dY - 0.5 end for i = 1, #scene.code do local button = scene.buttons[scene.code[i]] local first = 1 if #scene.code == 1 then first = 0 end local t = (i - 1) / (#scene.code - first) local opaque = playdate.math.lerp(1, 0.3, t) --TODO: not the best solution local y = 185 + ((i - 1) * 16) - 8 + scene.dY button:drawFaded(192, y, opaque, playdate.graphics.image.kDitherTypeBayer2x2) end end function scene:exit() scene.super.exit(self) scene.levelAudio:stop() Noble.showFPS = false end function scene:finish() scene.super.finish(self) playdate.display.setScale(1) end