Below you will find the devlog, where I will go into technical detail of various aspects of developing this game.
Original topic start below
A port of Crazy Gravity Portable I made some 12 years ago in my stereotypical bedroom.
The original game was made for the PlayStation Portable, which had a lively homebrew scene. Only C++ was available as a toolchain, but my game ran in a Lua interpreter. It achieved some 20fps.
With the original system having a resolution of 480x272, porting is a matter of resizing the viewport, replacing all the game engine calls and converting the sprites to 1-bit. I also found out that not all Lua functions are available, but found a way to probably repackage and load level files faster than before. Thanks @Nic
I used Canvas Dither to convert the colored sprite to 1-bit using atkinson. Still thinking about how to translate the color-coded gate keys to this platform
Great, thanks. There is ample room for optimization, so no worries. Worst case I'll aim for a solid 20fps, since that is the original speed. Somewhat surprised to not see the framerate go up when there is no sound playing, as the docs warn that's heavy on cpu.
Thanks, that's great news. So the 20fps target is achieved and the the 30fps may be in reach. Note that the level 03 that gets loaded by default might be the heaviest, along with 10.
todo:
profile impact of audio: disable as test; and compress to adpcm audio
DONE optimize the OptimizeLevel() function further so render code skips over empty spaces in both directions (currently only one direction). Really this should be baked into the level files, but doing it on level load is practical for experimentation for now.
replace all pgeDraw calls by sprite:draw calls
perhaps limit the maximum player or camera velocity in such a way that the player will only move 1 tile (8px) per frame. This rate-limits the amount that needs to be drawn.
It really doesn't make sense for me to do this work, since I cannot profile on my own. So if anyone wants a challenge: have at it and create a pull request
Is there a way to drill down in the profiler, like only keep the samples for the 10% slowest frames or even better: the frames where the target was not achieved?
Did some checking on whether bits are actually on screen before drawing
optimized the level format so that more empty areas can be ignored by render calls
Fixed out of memory by garbage collecting before loading a level
do not redraw the HUD when a lot of tiles were drawn in the current frame
disabled debug mode, so that more realistic scenarios are tested. (Flying full speed diagonal without crashing will be difficult)
pre-calculated some math (cos and sin)
Questions:
Let's say I have 20 8x8 pixel cannonballs to draw. Half of those are offscreen. Will it benefit performance to check their pixel coordinates before drawing, or can I draw them all and let the clipRect cull the offscreen draws?
Would love to know what the current fps stats are
Could you give me some gameplay feedback?
Can an out of memory situation be created by switching levels 10 times? Not on the 16MB simulator. (press menu button)
That makes me really happy @matt , thanks so much!
Runs at a steady 30fps. At unlimited setRefreshRate(0) it's at 34–40fps! could be locked 35 easily. let's push for 40!
Don't tempt me! I spent a bit more time already, and if 40 is the max right now, a solid 40 would be very difficult. Also, the game physics is frame-based, not time based. So increasing fps would require re-tuning physics etc. Also, we humans are very accustomed to 30, 40 might feel weird. In addition, pushing the display past it's recommended fps might introduce ghosting or whatever.
I'd expect the scrolling to continue and the craft to explode dramatically into pieces or particles or something?
YES. I know the collision point, so could break up the sprite at that point and animate some parts to continue their momentum. This could be very cool.
feels unfair to be able to die when taking of by turning too soon.
Yeah, You'll get used to it, but I don't want to set a bad first impression. I'll revert the landing tolerance to the previous value
Levels take ~1–3 seconds to load depending on complexity/size. Did you consider saving their fully-loaded Lua state back to disk and loading that instead? I'll be doing that with my cars soon.
Which gets compiled into binary lua by pdc. Note that it's very inefficient: most numbers could have been 8-bit, but lua only has 32-bit numbers. level 3 takes about 7MB of ram. Im thinking about a feature request for a more efficient playdate-level-format which can be loaded with a progress update callback
According to the docs, pdxinfo is only read by the system, not displayed to the user in the launcher.
In the meantime, I did make a simple card though.
Had a blast implementing a nice explosion effect, thanks for the inspiration @matt
Hope the framerate is not too terrible, but maybe I could sell it as a slow-mo crash cam?
Also:
level loading should be quite a bit faster.
simple game card
converted some globals into locals for performance
changed some 2-bit images to 1-bit. Perhaps it'll improve performance
This is great! I had never played the original, but I've beaten all the levels twice now on my playdate and it is great fun. The easier levels are very meditative.
I have three questions.
Have you considered making the strength of gravity a changeable parameter? Maybe as an achievement you could need to explore a level while the gravity was a strong as Jupiter or null gravity.
I read somewhere the original had twenty levels. Any plans to update the game to include the other 10?
In level 3, off to the right, there's a platform with a bonus crate. If you take the crate it makes the same sound as the +1 life box, but it doesn't increment your lives when you take it, nor does it increase your carrying capacity. Is this a bug or does the box do something I'm missing?
Seriously, though, this is a great addition to my playdate and has given me several hours of enjoyment already. The game has been very stable for me. It crashes sometimes when I re-load the same level I'm currently on, but otherwise I've had no crashes.
Reading that my work entertained you for more than an hour made my day!
Great suggestion! I might add a 1.5x gravity challenge.
I have the source code for loading the original levels, in c++. I'll have a crack at using that. If someone reads this and wants to take the challenge: let me know
VERY valuable feedback. I'll look into giving all pickups their own sound. In this case a turbo whoosh. I think you've been playing an older version, because the sprites for pickups are redone, and also the HUD icon for speed blinks and gets replaced by a fast forward symbol. Please let me know whether this is clear to you.
Crash: I would like to get to the bottom of this. Can you make sure you are using version 0.5 and tell me the steps to reproduce? If it is not too much effort, I'd like to know whether you can reproduce it in the simulator and what the error message is in the console. @metafish I will upload a pdx this evening.
btw, I noticed I forgot to actually prevent you from starting a locked level
Anyways, that would be trivial to add later. For now it's convenient for playtestesting. @metafish@karljpsmith
cgpd_0_5_1.pdx.zip (2.5 MB)
edit: actually made a change to properly reset the game state when selecting retry, which might possibly fixes the crash. Calling this v0.5.1.