Use this freely if it helps you! Fixes/improvements welcome. There are lots of ways this could be made more sophisticated, but I wanted something super simple to implement with just a few lines of code—while being as friendly as possible to the end user.
Here's how it works
1. The Playdate game reads its build number from the pdxinfo
file and makes a URL with that number as a parameter. This is presented as a QR code to scan with a phone. That's how the user checks for updates. (The QR code takes time to generate, so a "please wait" message appears if needed.)
2. The developer website, with just a few lines of JavaScript (nothing server-side), compares that build number with the latest one, and displays a message letting the user know that they are up to date—or that there's a new version available.
3. The user downloads and sideloads the game as usual, wherever it may be hosted. Then, as long as you keep updating the build number for each new release, it should automatically replace any prior pdx on the Playdate. There should be no need to delete the old version manually.
I have sample code here for both the Playdate and website ends of the process.
Here are all the pieces
Make a 105x105 square "placeholder"/"please wait" PNG image to show in case the QR code isn't ready yet. In this example, the filename is qr-placeholder.png.
Run the following Lua code at launch—so the QR code starts asynchronously generating early, not waiting for the user to view whatever Check for Updates screen you make. That way there's a good chance it's already ready when they do go there.
import "CoreLibs/graphics"
import "CoreLibs/sprites"
import "CoreLibs/timer"
import "CoreLibs/qrcode"
local pd <const> = playdate
local gfx <const> = pd.graphics
local updateQRimage = gfx.image.new("qr-placeholder")
function QRDone(image, errorMessage)
updateQRImage = image
end
gfx.generateQRCode("yourdomain.com/anyaddress?build="..pd.metadata.buildNumber, 105, QRDone)
Replace yourdomain.com/anyaddress
with the URL of an update page where you control the HTML. No http/https:// needed. Add ?build= to the end.
It's OK if your page URL has other parameters! Just include build= at the end. (In that case it's &build= instead of the question mark.)
In my experience, 105x105 is a good size that fits a pretty long URL, and takes about 11.5 seconds to generate the code on Playdate hardware. (You could use another size—or even pre-generate a PNG. But with this system, you don't have to! Maintain your build number and the rest is automatic.)
Then on your game's Check for Updates screen, include the following code:
local updateQRSprite = gfx.sprite.new(updateQRImage)
updateQRSprite:moveTo(200, 120) --Or wherever you want the QR code
updateQRSprite:add()
And in the update loop (OK to setRefreshRate to a low value) while on that screen do this:
updateQRSprite:setImage(updateQRImage) --Ready for whenever the QR code is done
playdate.timer.updateTimers() --Needed for QR code generator
gfx.sprite.update()
You're done on the Playdate side!
On the web page, include an empty element with the ID update-status
somewhere up high and very visible (<p>
, <div>
, <span>
, or whatever you wish, styled as you see fit):
<p id="update-status"></p>
And some JavaScript at the end of the page (or anywhere after that element):
<script>
var latestBuildNumber = 1234;
var appName = "My Game Title";
var lastParameter = window.location.search.substr(1).split("&").slice(-1)[0];
if (lastParameter.substr(0, 6) == "build=") {
var buildNumber = parseInt(lastParameter.substr(6));
var statusMessage = "You have " + appName + " build " + buildNumber + ".";
if (buildNumber == latestBuildNumber) {
statusMessage += "<br><strong>You are up to date!</strong>";
} else if (buildNumber < latestBuildNumber) {
statusMessage += "<br><strong>A new version (build " + latestBuildNumber + ") is available!</strong>"
}
document.getElementById("update-status").innerHTML = statusMessage;
}
</script>
That's it! Customize the message text to say what you want.
EDIT: If you'd like dots displayed to the user ("1.0.5") to make the build number look like a traditional version number, here's JS code to handle that.
Now just remember to keep your buildNumber up to date: both in your game's pdxinfo
file and in the JavaScript of the page. (The "version"—as displayed in Settings—is not what matters. You need to include a buildNumber in your pdxinfo
. Update it manually if you don't have it automated.)
Edge case: if for some reason the app has a build number greater than the one declared as the latest in the JavaScript, thats's OK: the page simply informs you of the build number you have installed, without offering any further message about that being up to date or not.
There's no need for the URL to be a special web page just for updates—it could be any existing page you already use. The "Up to date" or "New version available" message is ADDED to the page when you include the build= parameter. But if you don't include that, the element update-status
remains empty and the rest of the page still works without error.
You probably do want to include a download link, so people can easily obtain the current version.
For example, the page for my Playtime clock is just a note linking to the itch.io page, plus some links to help with sideloading. But above that info, I display the update status in bright red—as long as that build parameter is added to the URL.
Try it out
As a demo, edit the following address in your browser to see what happens with different build numbers (which in reality would come automatically from your pdxinfo
via QR code):
https://adamsimmersive.com/apps/playdate/playtime-clocks/?build=102
The latest version coded into that page is higher than the "102" in the QR URL. So you get notified of the new version.
But change that "102" in the URL to match the current version number (no dots), and you'll see the "Up to date" message.
And if you remove the ?build= parameter from the URL entirely, you'll see that the page still works on its own, without trying to perform an update check.
Hope this is useful!