I think at least a few games could render that fast. I just looked into your game “Kong”:
Looks like it runs at 70fps while only using ~50% CPU. With only a slight focus on performance I’d bet it could easily render at 156 Hz.
Even if the sprites are on the FX chip it’s not too much of an issue. For this game I have my own sprite routines which sacrifice code size and flexibility (limited draw modes, height must be multiple of 8) for speed. The FX versions maintain the minimal 18 cycles/byte cadence which is competitive with the prog versions in the Sprites lib. Drawing lots of tiny sprites has a penalty due to the seek overhead so I keep the dialog font in prog for that reason and text rendering has its own specialized method as well.
The thing that’s less known is the value of Fosc for each oscillator setting. The Thumby community, which came up with the trick used to achieve frame sync without a vsync signal, have experimentally determined that for a setting of 15, Fosc=530kHz is a safe minimum value to assume that all SSD1306s will achieve.
My Arduboys seem to achieve about 570 kHz, which is the value my sim assumes. I’ve also put them through many battery drain tests rendering grayscale the entire time to ensure Fosc doesn’t begin to droop too low before brownout.
This game and ArduboyG reduce the precharge phase 2 to two cycles to speed up the row drive time:
My Arduboys tend to render at 165-170 Hz. However, if the value of Fosc were as low as 530 kHz, the frame rate would be
FPS = 530kHz / 1 / (50+1+2) / 64 = 156.25 Hz
So 156 Hz is the greatest allowable “safe” rate. I want to render as fast as possible to both avoid strobing and maximize effective brightness.
EDIT: If you only need one shade of gray (three shades total), you could try setting the precharge phase 2 back to 15 cycles (to try to maintain brightness) and rendering at
FPS = 530kHz/(50+1+15)/64 = 125 Hz
to give you more rendering time. With three levels the strobing is much less of a concern and you can afford higher frame times.
Yes Hopefully that doesn’t happen with Arduboy units. If it does I think only three shades gray will be visually acceptable and there will probably need to be some sort of calibration value stored in EEPROM.
The Arduboy having 64 rows vs the Thumby’s 40 already means frame times are much longer by necessity.
Note: the recordings are now taken from the sim instead of my windows port. The Arduboy version renders at 128x63 because the 64th row is used for the grayscale park row in the actual game. This is visible as a black line at the bottom of the recordings but isn’t noticeable on an actual Arduboy (unless you take the time to count the pixel height).
Movement mechanics turned out to be fairly involved. The world map is large and sometimes has complex collision structure so I wanted the movement to respond smoothly and not frustrate the player.
There are four bits of collision info per tile type, one per quarter tile.
I’m a little concerned if the need to navigate level design diagonally will be fun… or a chore!?.. This was also done in Team ARG’s Virus / zombie game; On a small d-pad it doesn’t feel great.
Are you referring to the d-pads of the official Arduboy or homemade ones? The official Arduboy is comfortable enough for me, but admittedly I haven’t been considering the ergonomics of other button types.
Currently some areas (such as the one shown above) do require diagonal movement to access. Taking yet more inspiration from @filmote’s dev process I think near completion there will be some sort of beta period for bug reporting and where game design choices can be molded to community preferences.
Homemade Arduboys using the usual tactile push buttons suck for d-pads. I’ve played Team Arg’s Virus-LQP (I forgot the number after the LQP) on my DIY Arduboy and it’s really uncomfortable. But anyway, I guess it’s just a hardware concern, nothing you can really do to fix it for those devices.
I’ve been working on a new synth library designed from the start for high performance and FX streaming – I’ll release it shortly.
I’m very happy with the result so far. In my use case, the new library frees about 90 bytes of RAM and 1300 bytes of prog, and allowed increasing the channel count from 2 to 4 while still providing a large reduction in CPU usage. Frame times now have a healthy margin at all times with music enabled.
One thing I wanted from ATMlib and added to the new lib is a master volume control. I plan to use this for fade out transitions when changing songs, so the overworld music doesn’t abruptly stop when entering a battle.
Right now I am using placeholder music from NES games. Eventually I’ll need to figure out new music or seek collaboration.
Brief explanation of what the lib does to save CPU from the lib's readme
There have primarily been two approaches to audio synthesis on the Arduboy.
The first types uses a timer that toggles a sound pin at the timer frequency, meaning the timer frequency is constantly adjusted to play different notes. This approach is extremely cheap on CPU usage as the work done in the ISR is minimal and interrupts only hit at the transitions of the square wave, but it is limited to full-amplitude square wave synthesis with one or two channels. This approach is used in ArduboyTones (one timer) and ArduboyPlaytune (two timers, one for each sound pin).
The second type uses timer4 to produce PWM analog values on the sound pins, with the PWM duty cycle controlled by another timer. In principle, this allows full control over the audio waveform. Existing solutions like ATMlib and ATMlib2 use a constant sample rate with a high frequency control timer. Each interrupt remixes the channels and sets the duty cycle. This produces a high quality synthesis and allows for many effects like vibrato and tremelo and precise volume control, but requires high CPU usage due to the continual remixing of the channels at a high rate.
SynthU attempts to allow for the benefits of the PWM approach while avoiding most of the performance downside. The high CPU usage in the PWM approach is due to the mixing interrupt triggering once per sample. If the waveform actually changes each sample, as it does for a noise channel, this is unavoidable. But if the mixing only involves square waves, there will be long sample sequences where the duty cycle doesn’t change because no wave transitions occur in any channel. Thus, the mixing ISR in SynthU dynamically schedules the next interrupt to occur on the sample following the next transition in any channel. The resulting waveform stays the same, and all effects (vibrato, tremelo, frequency/volume sweeps, etc) are still possible. However, noise channels are currently not implemented because their usage would defeat this optimization (this may be revisited later).