Hello there !
I am using the latest (as of time of writing) Playdate SDK and I am making an app that requires to show a list of tracks to choose from. Unfortunately, when I need to scroll I can only do so if I explicitly say not to animate, otherwise it just doesn't work. It know it has to scroll but doesn't determine the position of the scroll...
It looks like this is happening because of the way I structured my code:
I have a main.lua file that uses a basic scene manager I made that just switches scenes. Each scene is stored in another Lua file which exports a Start and Update function that are being called in the playdate.update() function.
This is extremely weird as I am still calling the updateTimers correctly and clear the screen everytime. The rest of the scene works properly and the list still shows up.
I would appreciate help of any kind even if you aren't sure please tell me your thoughts
Here is some of the code (it's already a lot) :
The musicPlayerFileSelection.lua
file which is where the bug occurs
-- Home Scene - The Startup screen
-- Follows standard scene file definition
import "CoreLibs/graphics"
import 'CoreLibs/object'
import "CoreLibs/sprites"
import "CoreLibs/ui"
import "CoreLibs/timer"
import "CoreLibs/animation"
import "utils/AnimatedSprite.lua"
import "utils/UI/Button.lua"
import "Utils/SceneManager.lua"
import "Utils/FilesAndConfig.lua"
import "CoreLibs/crank"
local gfx <const> = playdate.graphics
local gui <const> = playdate.ui
local ds <const> = playdate.datastore;
-- Resources variables :
local logoImageTable
local logoImageTemp
local logoTilemap
local musicList
local musicListKeys = {}
local trackCovers = {}
local musicListUI = gui.gridview.new(300, 80)
function Preload()
print("Preloading resources for Music File Selection")
end
local scroll = 0
-- Start function called once when the scene is opened
function Start()
print("Initializing Music File Selection Scene")
musicList = GetMusicList()
printTable(musicList)
musicListUI:setNumberOfColumns(1)
musicListUI:setNumberOfRows(musicList.filesCount)
-- Storing only the indexes to use for the gridview
print("indexing for the gridview")
for index, trackInfos in pairs(musicList) do
print("index : " .. tostring(index))
if index == "filesCount" then
print("Ignoring filesCount")
else
table.insert(musicListKeys, index)
-- Preloading covers
if not trackInfos.coverPath == nil then
trackInfos.coverPath = Configuration.musicFolder .. "/" .. trackInfos.coverPath
end
print("Trying to load image : " .. trackInfos.coverPath)
local coverImage = gfx.image.new(trackInfos.coverPath)
table.insert(trackCovers, coverImage)
end
end
musicListUI:setCellPadding(2, 6, 2, 6)
printTable(musicListKeys)
end
-- Update function called every system update
function Update()
gfx.clear()
gfx.sprite.update()
-- Emulating a "window"
gfx.pushContext()
gfx.drawLine(0, 30, 400, 30)
gfx.setDitherPattern(0.5, gfx.image.kDitherTypeDiagonalLine)
gfx.fillRect(0, 0, 90, 30)
gfx.fillRect(310, 0, 90, 30)
gfx.setDitherPattern(1, gfx.image.kDitherTypeNone)
gfx.drawTextAligned("Music Player - File Selection", playdate.display.getWidth()/2, 5, kTextAlignment.center)
gfx.popContext()
-- Drawing the actual content
gfx.pushContext()
local crankTicks = playdate.getCrankTicks(2)
if crankTicks == 1 or playdate.buttonJustPressed(playdate.kButtonDown) then
musicListUI:selectNextRow(true, true)
-- musicListUI:scrollToRow(musicListUI:getSelectedRow())
print(musicListUI:getSelectedRow())
end
if crankTicks == -1 or playdate.buttonJustPressed(playdate.kButtonUp) then
musicListUI:selectPreviousRow(true, true)
-- musicListUI:scrollToRow(musicListUI:getSelectedRow())
print(musicListUI:getSelectedRow())
end
musicListUI:drawInRect(50, 40, 350, 200)
gfx.popContext()
end
function musicListUI:drawCell(section, row, column, selected, x, y, width, height)
local trackInfos = musicList[musicListKeys[row]]
gfx.pushContext()
-- For now, song covers are disabled as there is no way to load "normal" images
-- local coverImage = trackCovers[row]
-- coverImage = coverImage:scaledImage(0.5)
-- coverImage:drawCentered(x+10, y+height/2)
local radius = 5;
if selected then
playdate.graphics.setLineWidth(6)
radius = 10;
else
playdate.graphics.setLineWidth(3)
end
gfx.drawRoundRect(x, y, width, height, radius)
gfx.drawText("*" .. trackInfos.name .. "*", x+10, y+height/4-10)
gfx.drawText("_By : " .. trackInfos.author .. "_" , x+10, y+height/3)
gfx.popContext()
end
MusicFileSelectionScene = {
sceneID = 1,
sceneName = "Music Player File Selection",
preloadFunction = Preload,
startFunction = Start,
updateFunction = Update
}
The sceneManager.lua
file :
-- Scene Manager designed by Oxey405 based upon basic design recommendations from "SquidGod"
-- Library imports
import "CoreLibs/graphics"
import 'CoreLibs/object'
import "CoreLibs/sprites"
import "CoreLibs/timer"
-- Scene imports :
import "scenes/Home.lua"
import "scenes/MusicPlayerFileSelection.lua"
-- Other Imports
local gfx <const> = playdate.graphics
function SwitchToScene(sceneID)
print("Moving to Scene #" .. tostring(sceneID))
-- First tidy up everything fot the switch
gfx.sprite.removeAll()
local allTimers = playdate.timer.allTimers()
for _, timer in ipairs(allTimers) do
timer:remove()
end
gfx.setDrawOffset(0, 0)
-- Then switch the scene
if sceneID == 0 then
GameState.currentScene = { name = "home", id = 0, SceneObject = HomeScene}
elseif sceneID == 1 then
GameState.currentScene = { name = "musicfileselection", id = 1, SceneObject = MusicFileSelectionScene}
else
print("FATAL ERROR : CANNOT LOAD AN INVALID SCENE")
end
GameState.currentScene.SceneObject.startFunction()
end
The main.lua
file :
import "CoreLibs/graphics"
import 'CoreLibs/object'
import "CoreLibs/sprites"
import "scenes/Home.lua"
import "scenes/MusicPlayerFileSelection.lua"
import "utils/FilesAndConfig.lua"
import "CoreLibs/timer"
import "Utils/SceneManager.lua"
local gfx <const> = playdate.graphics
-- Global variables
-- See the SceneManager for scene switching
GameState = {
currentScene =
{
name = "home",
id = 0,
SceneObject = HomeScene
}
}
HomeScene.preloadFunction()
SwitchToScene(0)
InitializeFS()
print("Current scene : " .. GameState.currentScene.SceneObject.sceneName)
-- Main update function
function playdate.update()
GameState.currentScene.SceneObject.updateFunction()
playdate.timer.updateTimers()
end
-- Handling the app's lifecycle
function playdate.gameWillTerminate()
SaveConfiguration()
print("Goodbye !")
end
function playdate.deviceWillSleep()
SaveConfiguration()
end