diff --git a/source/.DS_Store b/source/.DS_Store new file mode 100644 index 0000000..5c2c7a9 Binary files /dev/null and b/source/.DS_Store differ diff --git a/source/assets/.DS_Store b/source/assets/.DS_Store new file mode 100644 index 0000000..1c14d07 Binary files /dev/null and b/source/assets/.DS_Store differ diff --git a/source/assets/audio/boom1.wav b/source/assets/audio/boom1.wav new file mode 100644 index 0000000..b7a3204 Binary files /dev/null and b/source/assets/audio/boom1.wav differ diff --git a/source/assets/audio/boom2.wav b/source/assets/audio/boom2.wav new file mode 100644 index 0000000..988495b Binary files /dev/null and b/source/assets/audio/boom2.wav differ diff --git a/source/assets/audio/boom3.wav b/source/assets/audio/boom3.wav new file mode 100644 index 0000000..1a585b8 Binary files /dev/null and b/source/assets/audio/boom3.wav differ diff --git a/source/assets/audio/boom4.wav b/source/assets/audio/boom4.wav new file mode 100644 index 0000000..0cf2027 Binary files /dev/null and b/source/assets/audio/boom4.wav differ diff --git a/source/assets/bg_bomber.psd b/source/assets/bg_bomber.psd new file mode 100644 index 0000000..83d3e04 Binary files /dev/null and b/source/assets/bg_bomber.psd differ diff --git a/source/assets/images/.DS_Store b/source/assets/images/.DS_Store new file mode 100644 index 0000000..b5eb54d Binary files /dev/null and b/source/assets/images/.DS_Store differ diff --git a/source/assets/images/bg_bomber33.png b/source/assets/images/bg_bomber33.png new file mode 100644 index 0000000..2650ef3 Binary files /dev/null and b/source/assets/images/bg_bomber33.png differ diff --git a/source/assets/images/card_2.png b/source/assets/images/card_2.png index 701de87..8c10656 100644 Binary files a/source/assets/images/card_2.png and b/source/assets/images/card_2.png differ diff --git a/source/assets/images/maps/map_2.png b/source/assets/images/maps/map_2.png new file mode 100644 index 0000000..b648aff Binary files /dev/null and b/source/assets/images/maps/map_2.png differ diff --git a/source/assets/sprites/bg2.png b/source/assets/sprites/bg2.png new file mode 100644 index 0000000..3686d6e Binary files /dev/null and b/source/assets/sprites/bg2.png differ diff --git a/source/assets/sprites/boomSplash1.png b/source/assets/sprites/boomSplash1.png new file mode 100644 index 0000000..4229393 Binary files /dev/null and b/source/assets/sprites/boomSplash1.png differ diff --git a/source/assets/sprites/boomSplash2.png b/source/assets/sprites/boomSplash2.png new file mode 100644 index 0000000..a8224ff Binary files /dev/null and b/source/assets/sprites/boomSplash2.png differ diff --git a/source/assets/sprites/smallboom-table-400-240.png b/source/assets/sprites/smallboom-table-400-240.png new file mode 100644 index 0000000..78c2d59 Binary files /dev/null and b/source/assets/sprites/smallboom-table-400-240.png differ diff --git a/source/libraries/pdDialogue.lua b/source/libraries/pdDialogue.lua index e70f4a1..6bd50fd 100644 --- a/source/libraries/pdDialogue.lua +++ b/source/libraries/pdDialogue.lua @@ -20,7 +20,7 @@ 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 = {} @@ -62,10 +62,10 @@ function pdDialogue.window(text, startIndex, height, font) 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 result = {text[start_index]} local rows = pdDialogue.getRows(height, font) - 1 for index = 1, rows do @@ -85,7 +85,7 @@ 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 = {} @@ -129,7 +129,7 @@ function pdDialogue.process(text, width, height, font) 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() @@ -168,10 +168,10 @@ 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.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 @@ -182,22 +182,22 @@ function pdDialogueSprite:init(dialogue) end function pdDialogueSprite:add() - pdDialogueSprite.super.add(self) - if not self.dialogue.enabled then - self.dialogue:enable() - end + 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 + 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 ---------------------------------------------------------------------------- @@ -206,11 +206,9 @@ end 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) + gfx.getSystemFont():drawText("Ⓐ", x, y) end function pdDialogueBox.arrowPrompt(x, y, color) @@ -228,7 +226,7 @@ function pdDialogueBox:init(text, width, height, font) 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 @@ -250,17 +248,19 @@ function pdDialogueBox:asSprite() end function pdDialogueBox:getInputHandlers() + local _speed = self:getSpeed() return { AButtonDown = function() - self:setSpeed(2) if self.dialogue_complete then self:disable() elseif self.line_complete then self:nextPage() + else + self:setSpeed(_speed * 2) end end, AButtonUp = function() - self:setSpeed(0.5) + self:setSpeed(_speed) end, BButtonDown = function() if self.line_complete then @@ -406,6 +406,7 @@ function pdDialogueBox:nextPage() if self.currentPage + 1 <= #self.pages then self.currentPage += 1 self:restartLine() + self:onNextPage() end end @@ -461,6 +462,10 @@ function pdDialogueBox:onPageComplete() -- Overrideable by user end +function pdDialogueBox:onNextPage() + -- Overrideable by user +end + function pdDialogueBox:onDialogueComplete() -- Overrideable by user end @@ -522,7 +527,7 @@ function pdPortraitDialogueBox:init(name, drawable, text, width, height, font) end end pdDialogueBox.init(self, text, width - self.portrait_width, height, font) - self:setAlignment(kTextAlignment.left) + self:setAlignment(kTextAlignment.left) end function pdPortraitDialogueBox:setAlignment(alignment) @@ -539,7 +544,7 @@ function pdPortraitDialogueBox:getAlignment() end function pdPortraitDialogueBox:draw(x, y) - local offset = self.alignment == kTextAlignment.left and self.portrait_width or 0 + local offset = self.alignment == kTextAlignment.left and self.portrait_width or 0 pdPortraitDialogueBox.super.draw(self, x + offset, y) end @@ -571,120 +576,123 @@ end ---------------------------------------------------------------------------- -- #Section: dialogue box used in pdDialogue ---------------------------------------------------------------------------- -pdDialogue.DialogueBox_x, pdDialogue.DialogueBox_y = 5, 186 +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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + onNextPage={ + set=function(func) pdDialogue.DialogueBox_Callbacks["onNextPage"] = func end, + get=function() return pdDialogue.DialogueBox_Callbacks["onNextPage"] end }, - onClose = { - set = function(func) pdDialogue.DialogueBox_Callbacks["onClose"] = func end, - get = function() return pdDialogue.DialogueBox_Callbacks["onClose"] 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) + pdDialogue.DialogueBox_Callbacks["drawBackground"](self, x, y) else pdDialogue.DialogueBox.super.drawBackground(self, x, y) end end - -function pdDialogue.DialogueBox:drawText(x, y, text) +function pdDialogue.DialogueBox:drawText(x, y ,text) if pdDialogue.DialogueBox_Callbacks["drawText"] ~= nil then - pdDialogue.DialogueBox_Callbacks["drawText"](dialogue, x, y, text) + pdDialogue.DialogueBox_Callbacks["drawText"](self, 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) + pdDialogue.DialogueBox_Callbacks["drawPrompt"](self, 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:onNextPage() + if pdDialogue.DialogueBox_Callbacks["onNextPage"] ~= nil then + pdDialogue.DialogueBox_Callbacks["onNextPage"]() + 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"] @@ -738,7 +746,7 @@ 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 @@ -752,4 +760,4 @@ function pdDialogue.update() pdDialogue.DialogueBox:update() pdDialogue.DialogueBox:draw(pdDialogue.DialogueBox_x, pdDialogue.DialogueBox_y) end -end +end \ No newline at end of file diff --git a/source/libraries/pdParticles.lua b/source/libraries/pdParticles.lua index 3c8cb8a..a572a6b 100644 --- a/source/libraries/pdParticles.lua +++ b/source/libraries/pdParticles.lua @@ -569,7 +569,7 @@ function ParticlePixel:update() for part = 1, #self.particles, 1 do local pix = self.particles[part] - playdate.graphics.drawPixel(pix.x,pix.y,pix.size) + playdate.graphics.drawPixel(pix.x,pix.y) pix.x += math.sin(math.rad(pix.dir)) * pix.speed pix.y -= math.cos(math.rad(pix.dir)) * pix.speed diff --git a/source/main.lua b/source/main.lua index 1616469..439576b 100644 --- a/source/main.lua +++ b/source/main.lua @@ -40,12 +40,24 @@ Maps = { name = "Vovchansk", description = "This is a map", locked = false, + }, + { + id = 2, + name = "Mariupol", + description = "This is a map", + locked = false, } } +Modes = { + fpv = "FPV", + bomber = "Bomber" +} + Drones = { { id = 1, + mode = Modes.fpv, name = "Quad FPV", description = "This is a quadrocopter with a camera on it. It's a good drone for beginners. It's easy to control and has a good battery life.", @@ -56,10 +68,11 @@ Drones = { }, { id = 2, + mode = Modes.bomber, name = "Drone 2", description = "This is a drone", price = 200, - locked = true, + locked = false, preview = nil, full = nil }, @@ -85,6 +98,7 @@ Drones = { import "scripts/player" import "scripts/bigBoomSprite" +import "scripts/bomber/boom" import "scripts/groundSprite" import "scripts/balebaSprite" import "scripts/dangerSprite" @@ -96,6 +110,7 @@ import "scripts/pageSprite" import "scripts/MapCard" import "scripts/bomber/movableCrosshair" import "scripts/bomber/granade" +import "scripts/bomber/explosionMark" import "scenes/BaseScene" import 'scenes/Assemble' diff --git a/source/pdxinfo b/source/pdxinfo index c5863b9..2525648 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.2 -buildNumber=3 +version=0.2.0 +buildNumber=10 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 e9c593a..d5a3ee6 100644 --- a/source/scenes/Assemble.lua +++ b/source/scenes/Assemble.lua @@ -143,10 +143,6 @@ end function scene:enter() scene.super.enter(self) - local soundTable = playdate.sound.playingSources() - for i=1, #soundTable do - soundTable[i]:stop() - end scene.buttonTimeout = 100 Noble.Input.setHandler(scene.inputHandler) diff --git a/source/scenes/DroneCardSelector.lua b/source/scenes/DroneCardSelector.lua index 658131e..430a0a1 100644 --- a/source/scenes/DroneCardSelector.lua +++ b/source/scenes/DroneCardSelector.lua @@ -10,7 +10,16 @@ scene.inputHandler = { return end scene.menuConfirmSound:play(1) - Noble.transition(Assemble) + mode = Drones[scene.menuIndex].mode + local soundTable = playdate.sound.playingSources() + for i=1, #soundTable do + soundTable[i]:stop() + end + if mode == Modes.bomber then + Noble.transition(BomberScene) + else + Noble.transition(Assemble) + end end, BButtonDown = function() scene.menuBackSound:play(1) diff --git a/source/scenes/MapSelector.lua b/source/scenes/MapSelector.lua index 0fa0cb1..0ac8f6e 100644 --- a/source/scenes/MapSelector.lua +++ b/source/scenes/MapSelector.lua @@ -55,7 +55,7 @@ function scene:update() local x = 0 for i = 1, #scene.cards do - x = 0 + (339 + 16) * (i - 1) + x = 400 * (i - 1) scene.cards[i]:moveTo(x + scene.currentX, 0) end @@ -107,7 +107,7 @@ scene.inputHandler = { return end scene.menuSelSound:play(1) - scene.targetX = scene.targetX + 355 + scene.targetX = scene.targetX + 400 scene.menuIndex = scene.menuIndex - 1 end, rightButtonDown = function() @@ -115,7 +115,7 @@ scene.inputHandler = { return end scene.menuSelSound:play(1) - scene.targetX = scene.targetX - 355 + scene.targetX = scene.targetX - 400 scene.menuIndex = scene.menuIndex + 1 end, upButtonDown = function() diff --git a/source/scenes/Menu.lua b/source/scenes/Menu.lua index c213420..00e26a4 100644 --- a/source/scenes/Menu.lua +++ b/source/scenes/Menu.lua @@ -24,6 +24,10 @@ function scene:setValues() end function scene:init() + local soundTable = playdate.sound.playingSources() + for i=1, #soundTable do + soundTable[i]:stop() + end scene.super.init(self) local menuSelSound = playdate.sound.fileplayer.new("assets/audio/menu_select") diff --git a/source/scenes/bomber/BomberScene.lua b/source/scenes/bomber/BomberScene.lua index c262ca0..484bfb3 100644 --- a/source/scenes/bomber/BomberScene.lua +++ b/source/scenes/bomber/BomberScene.lua @@ -2,9 +2,38 @@ BomberScene = {} class("BomberScene").extends(BaseScene) local scene = BomberScene +local font = Graphics.font.new('assets/fonts/Mini Sans 2X') + function scene:init() scene.super.init(self) - scene.granade = nil + + self.bg = Graphics.image.new("assets/sprites/bg2") + self.bgY = 0 + self.scrollSpeed = 0.6 + + scene.progressBar = ProgressBar(50, 210, 50, 5) + scene.progressBar:set(0) + scene.progressBar:setVisible(false) + + scene.grenadeCooldown = false + scene.grenadeCooldownTimer = nil + scene.grenadeCooldownDuration = 100 + scene.progressBarMax = 100 + + scene.availableGrenades = 8 + + BomberScene.instance = self +end + +function scene:drawBackground() + self.bgY = self.bgY + self.scrollSpeed + + if self.bgY >= 720 then + self.bgY = 0 + end + + self.bg:draw(0, self.bgY - 720) + self.bg:draw(0, self.bgY) end @@ -22,8 +51,29 @@ scene.inputHandler = { scene.crosshair:moveRight() end, AButtonDown = function() + if scene.availableGrenades <= 0 then + return + end + print("AButtonDown") - scene.granade = Granade(scene.crosshair.x, scene.crosshair.y) + if not scene.grenadeCooldown then + Granade(scene.crosshair.x, scene.crosshair.y) + scene.grenadeCooldown = true + + scene.progressBar:set(0) + scene.progressBar:setVisible(true) + scene.availableGrenades = scene.availableGrenades - 1 + + scene.grenadeCooldownTimer = playdate.timer.new(scene.grenadeCooldownDuration, function() + scene.grenadeCooldown = false + scene.progressBar:setVisible(false) + end) + + scene.grenadeCooldownTimer.updateCallback = function(timer) + local percentage = (scene.grenadeCooldownDuration - timer.timeLeft) / scene.grenadeCooldownDuration * scene.progressBarMax + scene.progressBar:set(percentage) + end + end end } @@ -35,13 +85,29 @@ end function scene:start() scene.super.start(self) + self.optionsMenu:addMenuItem("Main Menu", function() Noble.transition(Menu) end) + Noble.showFPS = true end function scene:update() scene.super.update(self) - -- scene.crosshair:update() - - -- if scene.granade then - -- scene.granade:update() - -- end + Noble.Text.draw(scene.availableGrenades .. "x", 10, 210, Noble.Text.ALIGN_LEFT, false, font) + + if scene.availableGrenades <= 0 then + Noble.Text.draw("No grenades left", 200, 110, Noble.Text.ALIGN_CENTER, false, font) + scene.crosshair:setVisible(false) + end + + if playdate.isCrankDocked() then + Noble.Text.draw("Crank it to reload!", 200, 110, Noble.Text.ALIGN_CENTER, false, font) + playdate.ui.crankIndicator:draw() + end end + +-- TODO: to reset grenades spin crank +-- TODO: random spawn of enemies +-- TODO: random spawn some decorations +-- TODO: add some music +-- TODO: add some sound effects +-- TODO: add clouds or smoke +-- TODO: random disactivate granades \ No newline at end of file diff --git a/source/scripts/bomber/boom.lua b/source/scripts/bomber/boom.lua new file mode 100644 index 0000000..c66c4d2 --- /dev/null +++ b/source/scripts/bomber/boom.lua @@ -0,0 +1,28 @@ +SmallBoom = {} +class("SmallBoom").extends(AnimatedSprite) + +local smallBoomImageTable = Graphics.imagetable.new("assets/sprites/smallboom") + +function SmallBoom:init() + SmallBoom.super.init(self, smallBoomImageTable) + + -- Animation properties + self:addState("play", 1, 3, { tickStep = 1, loop = 2 }) + self:setDefaultState("play") + self:playAnimation() + self:setCenter(0, 0) + self:setSize(playdate.display.getSize()) + self:setZIndex(ZIndex.flash) + + self:moveTo(0, 0) + + self:add() +end + +function SmallBoom:update() + self:updateAnimation() +end + +function SmallBoom:stopAnimation() + self:remove() +end diff --git a/source/scripts/bomber/explosionMark.lua b/source/scripts/bomber/explosionMark.lua new file mode 100644 index 0000000..94cb0e6 --- /dev/null +++ b/source/scripts/bomber/explosionMark.lua @@ -0,0 +1,20 @@ +ExplosionMark = {} +class('ExplosionMark').extends(NobleSprite) + +function ExplosionMark:init(x, y) + ExplosionMark.super.init(self) + self.id = math.random(1, 2) + self.markImage = Graphics.image.new("assets/sprites/boomSplash" .. self.id) -- TODO: make it random + self:setImage(self.markImage) + self:moveTo(x, y) + self:setZIndex(5) + self:add(x, y) +end + +function ExplosionMark:update() + self:moveBy(0, BomberScene.instance.scrollSpeed) + + if self.y > 240 + 32 then + self:remove() + end +end \ No newline at end of file diff --git a/source/scripts/bomber/granade.lua b/source/scripts/bomber/granade.lua index 2c3f659..d579b4a 100644 --- a/source/scripts/bomber/granade.lua +++ b/source/scripts/bomber/granade.lua @@ -1,34 +1,91 @@ Granade = {} class('Granade').extends(NobleSprite) +local function screenShake(shakeTime, shakeMagnitude) + local shakeTimer = playdate.timer.new(shakeTime, shakeMagnitude, 0) + shakeTimer.updateCallback = function(timer) + local magnitude = math.floor(timer.value) + local shakeX = math.random(-magnitude, magnitude) + local shakeY = math.random(-magnitude, magnitude) + playdate.display.setOffset(shakeX, shakeY) + end + shakeTimer.timerEndedCallback = function() + playdate.display.setOffset(0, 0) + end +end + function Granade:init(x, y) Granade.super.init(self) self.initialRadius = 10 self.currentRadius = self.initialRadius self.shrinkRate = 0.2 + + random = math.random(1, 4) + self.boomSound = playdate.sound.fileplayer.new("assets/audio/boom" .. random) + self.boomSound:setVolume(0.5) self.isActive = true + -- Variables for random movement + self.randomMovementTimer = 0 + self.randomXVelocity = 0 + self.randomYVelocity = 0 + local size = self.initialRadius * 2 + self.spriteSize = size + self:setSize(size, size) self:moveTo(x, y) - + self:setCenter(0.5, 0.5) + print("Granade init") print(self.x, self.y) + self:add(x, y) + self:markDirty() end function Granade:update() if self.isActive then + if BomberScene.instance then + self:moveBy(0, BomberScene.instance.scrollSpeed - 0.2) + + self.randomMovementTimer = self.randomMovementTimer + 1 + + if self.randomMovementTimer >= 10 then + self.randomMovementTimer = 0 + self.randomXVelocity = math.random(-50, 50) / 100 + self.randomYVelocity = math.random(-5, 10) / 100 + end + + self:moveBy(self.randomXVelocity, self.randomYVelocity) + end + self.currentRadius = self.currentRadius - self.shrinkRate if self.currentRadius <= 0 then print("Granade deactivated") self.isActive = false + local particleB = ParticlePoly(self.x, self.y) + particleB:setThickness(1) + particleB:setAngular(-5, 5122) + particleB:setSize(1, 2) + particleB:setSpeed(1, 20) + particleB:setMode(Particles.modes.STAY) + particleB:setBounds(0, 0, 400, 240) + particleB:setColour(Graphics.kColorXOR) + particleB:add(20) + self.boomSound:play(1) + screenShake(1000, 5) + SmallBoom() + ExplosionMark(self.x, self.y) + self:remove() end end - self:draw() + self:markDirty() end function Granade:draw() - playdate.graphics.fillCircleAtPoint(self.x, self.y, self.currentRadius) + local centerX = self.spriteSize / 2 + local centerY = self.spriteSize / 2 + playdate.graphics.fillCircleAtPoint(centerX, centerY, self.currentRadius) end \ No newline at end of file diff --git a/source/scripts/bomber/movableCrosshair.lua b/source/scripts/bomber/movableCrosshair.lua index eb15178..1937647 100644 --- a/source/scripts/bomber/movableCrosshair.lua +++ b/source/scripts/bomber/movableCrosshair.lua @@ -1,5 +1,5 @@ MovableCrosshair = {} -class('MovableCrosshair').extends(NobleSprite) +class('MovableCrosshair').extends(playdate.graphics.sprite) function MovableCrosshair:init() MovableCrosshair.super.init(self) @@ -14,40 +14,53 @@ function MovableCrosshair:init() self.moveRadius = 2 self.moveSpeed = 2 self.time = 0 + + -- Calculate size based on crosshair dimensions + local totalSize = (self.lineLength + self.gapSize) * 2 + 10 + self:setSize(totalSize, totalSize) + + -- Set the drawing offset to middle of sprite + self.drawOffsetX = totalSize / 2 + self.drawOffsetY = totalSize / 2 + + self:add(self.baseX, self.baseY) + self:setCenter(0.5, 0.5) + self:markDirty() end function MovableCrosshair:update() - -- Update time + MovableCrosshair.super.update(self) self.time = self.time + playdate.display.getRefreshRate() / 1000 - - -- Calculate new position with slight movement + local offsetX = math.sin(self.time) * self.moveRadius local offsetY = math.cos(self.time * 1.3) * self.moveRadius self:moveTo(self.baseX + offsetX, self.baseY + offsetY) - - self:draw() + self:markDirty() end function MovableCrosshair:draw() - -- Draw horizontal lines + local centerX = self.drawOffsetX + local centerY = self.drawOffsetY + playdate.graphics.drawLine( - self.x - self.lineLength - self.gapSize, self.y, - self.x - self.gapSize, self.y - ) - playdate.graphics.drawLine( - self.x + self.gapSize, self.y, - self.x + self.lineLength + self.gapSize, self.y + centerX - self.lineLength - self.gapSize, centerY, + centerX - self.gapSize, centerY ) - -- Draw vertical lines playdate.graphics.drawLine( - self.x, self.y - self.lineLength - self.gapSize, - self.x, self.y - self.gapSize + centerX + self.gapSize, centerY, + centerX + self.lineLength + self.gapSize, centerY ) + playdate.graphics.drawLine( - self.x, self.y + self.gapSize, - self.x, self.y + self.lineLength + self.gapSize + centerX, centerY - self.lineLength - self.gapSize, + centerX, centerY - self.gapSize + ) + + playdate.graphics.drawLine( + centerX, centerY + self.gapSize, + centerX, centerY + self.lineLength + self.gapSize ) end