Untitled Grayscale RPG Dev Log

Current Version (6/29)

Play online here. This game is in development. Please feel free to report issues, feedback, or suggestions at the GitHub repo.

ReturnOfTheArdu.arduboy (180.9 KB)


Inspired by @filmote’s thread, I want to share progress of an FX-powered RPG I’ve been working on. Hopefully this will produce design feedback or story ideas to make it a better game.

The working title that I’m not entirely happy with is “Return of the Ardu”.
recording_20230214202500

The story so far is full of tropes: it features a boy who discovers that he is descended from an ancient people called the Ardu (so he is an “Ardu boy”, right??) who had magic/technology that only a fellow Ardu is able to interface with. The big bads are the Old Dark empire, who is slowly conquering the area and seeking to acquire Ardu items.

The game story is controlled by a bytecode interpreter that executes scripts stored on the flash chip. The scripts are stored alongside map data, and execute every frame, controlling sprites, dialog, tiles, party, battle encounters, items, story flags, etc.

Battle encounters are turn based, up to 4v4. They are not random, but happen by running into an enemy on the map or as a part of the story. Most encounters are avoidable, though many have rewards for defeating them. There is a philosophy of no RNG in the battle mechanics themselves (all damage is deterministic). Attack order is determined by a speed stat. Actions are:

  • Attack a specific enemy. If an enemy is defending, only the defender may be targeted.
  • Defend until your next turn. While defending, all enemies target you, but you take half damage from all attacks.
  • Use item: use a defensive or offensive consumable item.

recording_20230214213353

19 Likes

You made a bytecode interpreter just to run story elements? That is ridiculously impressive; I guess you didn’t trust the logic to fit in the basic space? Gosh… such dedication

This is … next level.

Fantastic! Please post regular updates as things progress, I really want to see how this evolves.

I have found that by posting up something (anything!) and getting some feedback keeps you motivated.

1 Like

This is exactly the sort of thing I’d been hoping to make but could never find the time (or effort/enthusiasm) for.

Glad to see someone’s finally going to be able to pull this off.

The greyscale is an unexpected bonus.


That’s exactly what Pokemon and Mother 3 did. (And what I’d been hoping to do.)

It’s more flexible, frees up progmem, and means the game script is restricted by the FX chip rather than the on-board progmem.

It’s also more or less necessary for the script to be able to do things like set story flags, give the player items, heal the player et cetera.

There are ways to do it other than bytecode, e.g. a graph-based approach would also work, but bytecode is probably more compact.

2 Likes

‘Return of the Ardu’ makes me imagine a little dude waving around a little light stick :grin:

Great to see a dev log of your game and interesting to know that your using a byte code VM. will be perfect for FX.

Also nice to see your using Tiled.

1 Like

Oh my gawd. I honestly despise RPGs because I find them super boring, but this is one I’ll definitely play! Fantastic job! :slightly_smiling_face:

Dungeons

A major element of the game will be rewarding exploration. Dungeons, some puzzle-based, some reflex-based, and some combat-based, offer rewards when completed.

Examples:

recording_20230215111409

recording_20230215112020

Yes – now that the fun stuff (engine coding and optimization) is pretty much done, making the game content is proving to be much more monotonous. I don’t want to let up in quality however.

9 Likes

Are the dungeon games scripted using the byte code? If so, there would appear to be no limits to how big you can make this game!

Yes, all interactivity, whether dungeon behavior, enemies, looting items, storyline… is entirely from scripts.

The scripts can react to a bunch of stuff: what tile the player is standing on or selecting, what direction he’s facing, what sprite he is contacting or selecting, what items are equipped, etc.

Then the scripts can modify game state in response: change a tile, spawn/remove a sprite, start a battle, teleport/heal/kill the player, grant items, perform dialog, etc.

The way things are organized is the map is divided into chunks the size of the screen, and each chunk has a script that runs each frame. Only visible chunks run their scripts, so up to four chunks can execute. At the beginning of each frame, the chunk is reset to its default state, and then its script executes, which can modify stuff. This allows chunks to react to the game state continuously.

5 Likes

This sounds incredible for a little Arduboy. Great work!

1 Like

As someone enjoying Arduventure a lot recently, I’m super stoked for this game. Keep it up!

1 Like

CPU Usage

The primary reason I wanted to develop an Arduboy profiler was for grayscale dev. This game really stretches the Arduboy’s performance limit.

The game renders at 156 Hz and all graphics except for the font are stored on the FX chip. Music is played using a stripped down ATMlib2 modified to stream from the FX chip and compute two channels instead of four. The music ISR tends to take up 10-15% of CPU time.

Interestingly enough, the title screen is the most CPU-intensive. This is because everything that normally happens during gameplay (map/sprite rendering, map script processing, game logic updates) is still happening, as it merely simulates a game running in the background. But also, there are two large masked sprites rendering for the title and blinking “Press A”.

With music enabled the frame times are near the breaking point:
Animation2

With music disabled:
Animation3

Saves

I modified the save system to use Mr. Blinky’s new FX save methods. They are much better than my old version – less code and a kind of built-in “wear leveling” on the save block.

Since pretty much all graphics reside on the FX chip, nothing can be rendered while erasing/programming. Normally, a monochrome game could just leave the display buffer untouched. But with grayscale, it would be jarring to briefly leave a monochrome image of one of the grayscale planes on the display while saving. Thus saving involves a fade to black to smooth it over:
recording_20230305114051

Pause Menu Darken Effect

Speaking of which, the pause menu renders the background darkened.

recording_20230305115012

This effect comes easily with grayscale, as grayscale is accomplished with a kind of PWM on each pixel:

Plane 0 Plane 1 Plane 2
Black . . .
Dark Gray X . .
Light Gray X X .
White X X X

While rendering the pause menu, the map’s plane 0 is skipped:

Plane 0 Plane 1 Plane 2
Black . . .
Dark Gray . . .
Light Gray . X .
White . X X

This effectively causes all pixels to be rendered one shade darker: white pixels as light gray, light gray pixels as dark gray, and dark gray and black as black.

11 Likes

My kingdom for a vsync pin

This is just mind blowing stuff !! :exploding_head:
It’s great to read more of these technical details.

1 Like

Every time I see the grey scale I’m amazed. This is just awesome.

And I see the sim has a CPU meter now too :smiley:

If you want a second pair of eyes looking at that modified ATMlib code :wink:

2 Likes

I might take you up on that. However, I’ve been considering just doing a rewrite of the whole command/synth logic on top of the base osc code. That was also my motivation for supporting timer4 and sound in the sim.

The original design intent seems to have been optimizing the song encoding to save prog, which isn’t a concern anymore. Stuff like looping and subroutines aren’t needed. Performance-wise, I wanted to investigate changing the ISR from a constant 16 kHz to a scheduling based approach to save CPU: assuming only additive square waves, schedule the next interrupt for the next transition in any channel. I also want to make the FX data transfer more robust.

1 Like

Next level stuff! This amazes me every time I look at it!

This game is worthy of a special release like Arduventure was.

I wonder if many games could be rendered at this rate? I would love to render Prince of Persia in grey scale but would be surprised if it will work.

2 Likes

Thanks :smiley:

I think at least a few games could render that fast. I just looked into your game “Kong”:
Animation4
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.

OK … that’s interesting. I am trying to recall whether Kong has lots of little sprites or less, big ones.

Is your game using tile sheets to render the landscape? If so, this would be similar to Prince of Persia and probably give me some confidence that it might be achievable.

Yes, 8x4 map chunks of 16x16 tiles, and sprites are also 16x16.

EDIT: The demo in the ArduboyG thread is just over 50% cpu rendering only the tiles, though they are in prog, not FX:
Animation5