--- -- An abstract scene class. -- Do not copy this file as a template for your scenes. Instead, your scenes will extend this class. -- See templates/SceneTemplate.lua for a blank scene that you can copy and modify for your own scenes. -- If you are using NobleEngine-ProjectTemplate, -- see `scenes/ExampleScene.lua` for an implementation example. -- @usage -- YourSceneName = {} -- class("YourSceneName").extends(NobleScene) -- local scene = YourSceneName -- -- @classmod NobleScene -- NobleScene = {} class("NobleScene").extends(Object) --- Properties -- @section properties --- The name of this scene. Optional. -- If you do not set this value, it will take on the scene's `className`. NobleScene.name = "" --- This is the background color of this scene. -- NobleScene.backgroundColor = Graphics.kColorWhite --- Tables -- @section tables --- All scenes have a default inputHandler which is made active when the scene starts. -- If you do not define your scene's `inputHandler`, it is `nil` and input is disabled when this scene -- starts. -- @see Noble.Input.setHandler -- -- @usage -- YourSceneName.inputHandler = { -- AButtonDown = function() -- // Your code here -- end, -- AButtonHold = function() -- // Your code here -- end, -- -- ... -- -- ... -- } -- -- OR... -- -- Use a non-scene-specific inputHandler, defined elsewhere. -- YourSceneName.inputHandler = somePreviouslyDefinedInputHandler -- -- OR... -- -- Reuse another scene's inputHandler. -- YourSceneName.inputHandler = SomeOtherSceneName.inputHandler NobleScene.inputHandler = {} --- When you add a sprite to your scene, it is put in this table so the scene can keep track of it. -- -- This is intended as `read-only`. You should not modify this table directly. -- @see addSprite NobleScene.sprites = {} --- Methods -- @section Methods --- Use this to add sprites to your scene instead of `playdate.graphics.sprite:add()`. -- -- If your sprite is a `NobleSprite`, using `NobleSprite:add()` will also call this method. -- -- Sprites added with this method that are tracked by the scene. Any not manually removed before transitioning to another scene are automatically removed in @{finish|finish}. -- @tparam playdate.graphics.sprite __sprite The sprite to add to the scene. -- @see NobleSprite:add -- @see removeSprite function NobleScene:addSprite(__sprite) if (__sprite.isNobleSprite == true) then __sprite:superAdd() else __sprite:add() end if (table.indexOfElement(self.sprites, __sprite) == nil) then table.insert(self.sprites, __sprite) end end --- Use this to remove sprites from your scene instead of `playdate.graphics.sprite:remove()`. -- -- If your sprite is a `NobleSprite`, using `NobleSprite:remove()` will also call this method. -- -- Sprites not manually removed before transitioning to another scene are automatically removed in @{finish|finish}. -- @tparam playdate.graphics.sprite __sprite The sprite to add to the scene. -- @see NobleSprite:remove -- @see addSprite function NobleScene:removeSprite(__sprite) if (__sprite.isNobleSprite == true) then __sprite:superRemove() else __sprite:remove() end if (table.indexOfElement(self.sprites, __sprite) ~= nil) then table.remove(self.sprites, table.indexOfElement(self.sprites, __sprite)) end end --- Callbacks -- @section callbacks --- Implement this in your scene if you have code to run when your scene's object is created. -- -- @usage -- function YourSceneName:init() -- YourSceneName.super.init(self) -- --[Your code here]-- -- end -- function NobleScene:init() self.name = self.className self.sprites = {} end --- Implement if you want to run code as the transition to this scene begins, such as UI animation, triggers, etc. -- -- @usage -- function YourSceneName:enter() -- YourSceneName.super.enter(self) -- --[Your code here]-- -- end -- function NobleScene:enter() end --- Implement if you have code to run once the transition to this scene is complete. This method signifies the full activation of a scene. If this scene's `inputHandler` is defined, it is enabled now. -- @see inputHandler -- @usage -- function YourSceneName:start() -- YourSceneName.super.start(self) -- --[Your code here]-- -- end -- function NobleScene:start() Noble.Input.setHandler(self.inputHandler) end --- Implement to run scene-specific code on every frame while this scene is active. -- NOTE: you may use coroutine.yield() here, because it only runs inside of playdate.update(), which is a coroutine. -- -- @usage -- function YourSceneName:update() -- YourSceneName.super.update(self) -- --[Your code here]-- -- end -- function NobleScene:update() end --- Implement this function to draw background visual elements in your scene. --- This runs when the engine need to redraw a background area. --- By default it runs every frame and fills the background with self.backgroundColor. All arguments are optional. --- Use `Graphics.sprite.setAlwaysRedraw(false)` after `Noble.new()` to optimize partial redraw. -- -- @usage -- function YourSceneName:drawBackground(__x, __y, __width, __height) -- YourSceneName.super.drawBackground(self) -- optional, invokes default behavior. -- --[Your code here]-- -- end -- function NobleScene:drawBackground(__x, __y, __width, __height) __x = __x or 0 __y = __y or 0 __width = __width or Display.getWidth() __height = __height or Display.getHeight() -- Cache the currently set color/pattern. local color = Graphics.getColor() local color_type = type(color) -- Draw background. Graphics.setColor(self.backgroundColor) Graphics.fillRect(__x, __y, __width, __height) -- Reset color/pattern from cache. if color_type == 'number' then Graphics.setColor(color) elseif color_type == 'table' then Graphics.setPattern(color) end end --- Implement this in your scene if you have "goodbye" code to run when a transition to another scene -- begins, such as UI animation, saving to disk, etc. -- -- @usage -- function YourSceneName:exit() -- YourSceneName.super.exit(self) -- --[Your code here]-- -- end -- function NobleScene:exit() for _, sprite in ipairs(self.sprites) do sprite:setUpdatesEnabled(false) sprite:setCollisionsEnabled(false) end end --- Implement this in your scene if you have code to run when a transition to another scene -- is complete, such as resetting variables. -- -- @usage -- function YourSceneName:finish() -- YourSceneName.super.finish(self) -- --[Your code here]-- -- end -- function NobleScene:finish() for _, sprite in ipairs(self.sprites) do if (sprite.isNobleSprite) then sprite:superRemove() else sprite:remove() end end end --- `pause()` / `resume()` -- -- Implement one or both of these in your scene if you want something to happen when the game is paused/unpaused -- by the system. The Playdate SDK does not require you to write pause logic, but these are useful if you want a -- custom menu image (see Playdate SDK for more details), want to obscure game elements to prevent players from -- cheating in a time-sensitive game, want to count the number of times the player pauses the game, etc. -- -- @usage -- function YourSceneName:pause() -- YourSceneName.super.pause(self) -- --[Your code here]-- -- end function NobleScene:pause() end --- -- @usage -- function YourSceneName:resume() -- YourSceneName.super.resume(self) -- --[Your code here]-- -- end function NobleScene:resume() end