[Game]CastleBoy (Direct Port)

This is a direct port of dir3kt/JLauener’s CastleBoy for Arduboy.

Please note that this is a work-in-progress.
Prereleases are available, but there will be bugs.

1

The original GItHub page is here.

Source Code

Releases

Licence


Also, please be aware that this game expects the first 16 bytes of your EEPROM to be in Arduboy format.

The format is as thus:

  • Byte 0 - EEPROM Version (which I think is unused)
  • Byte 1 - System Flags
    • Bit 0 - 1 to display the username on startup
    • Bit 1 - 1 to display the logo on startup
    • Bit 2 - 1 to flash the LED on startup
    • Bit 3-7 - Reserved
  • Byte 2 - Audio
    • 0 is “off”
    • anything else is “on”
  • Byte 3-7 - Reserved
  • Byte 8-9 - A 16 bit unit ID number
  • Bytes 10-15 - A 6 character unit name
    • Must not contain 0xFF
    • Names less than 6 characters should be padded with 0x00
6 Likes

How does the eeprom thing affect is

I’ve had a dig around the Arduboy2 library and aparently the EEPROM data is laid out as thus:

  • Byte 0 - EEPROM Version (which I think is unused)
  • Byte 1 - System Flags
    • Bit 0 - 1 to display the username on startup
    • Bit 1 - 1 to display the logo on startup
    • Bit 2 - 1 to flash the LED on startup
    • Bit 3-7 - Unused/Reserved
  • Byte 2 - Audio
    • 0 is “off”
    • anything else is “on”
  • Byte 3-7 - Unused/Reserved?
  • Byte 8 and 9 - A 16 bit unit ID number
  • Bytes 10-15 - A 6 character unit name
    • Must not contain 0xFF
    • Names less than 6 characters should be padded with 0x00

Basically the Audio byte and the system flags are the most important parts.
The audio byte is the only thing that would normally affect gameplay,
but this game doesn’t have sound yet anyway.

I’ll make a note to compile the SetSystemEEPROM example at some point so people can toggle these.

Yes, it’s currently unused. If, in the future, a different, incompatible, system EEPROM layout is defined, this byte is intended to indicate this.

Recently, bytes 6 and 7 have been tentatively reserved for calibration information for battery voltage monitoring and low battery detection.

Bytes 8 and 9, the Unit ID, can be read and written by a program using available library functions. It’s intended to uniquely identify units linked in some way for multi-player games. I don’t think there are currently any games using this but could in the future.

Bytes 10-15, the Unit Name, will generally be displayed during the boot sequence, if set. Like the Unit ID, library functions are available to read and write it. It could be used by a program to pre-fill an ID, such as in a high score table or the name of the player in a text adventure. Also, like the Unit ID, I don’t think any programs are currently using it.

1 Like

The game is not working for me :frowning:

It starts but then no player in the level. Not sure this could be related to the EEPROM thing.

One thing that can easily be improved is the pause button. Currently pressing A + down (I think) will pause the game. Let’s switch that to Pokitto’s C button!

Oops, that’s my fault, I uploaded the wrong .bin.
I uploaded an earlier one from when I forgot to implement drawPlusMask.

(I wish someone had pointed this out earlier. :P)

Here’s the working one:
CastleBoy.bin (60.6 KB)

I’ll replace the one in the main post.

To be clear, at the moment I haven’t actually made any alterations to the game code other than renaming the .ino to main.cpp and commenting out all the sound-related code (basically all of the uses of the sound variable and the definition of the sound variable itself).

Apart from that it’s basically the same as the code from my local branch of the original (the one I made the PR with).

The real voodoo is my Arduboy2 port (which is still unfinished unfortunately).

Will try the new bin tonight! Maybe you should share the repo :wink:

My biggest issue with the port is the resolution. A 128x64 game need to fit into a 110x88 canvas.

Horizontally it’s tempting to cut 16 pixels horizontally (and leave 1 pixel on both side) which would work for ‘normal levels’. The problem is boss rooms as they would not fit and the game will scroll a bit which will look strange. The boss rooms could be redesigned to accomodate the new screen size though.

Vertically it’s not much an issue as some area could be simply left empty, or the UI could be displayed higher than in the original version. This could be good because UI was sometime hidding the player on the Arduboy version.

110x88 is the half-resolution. Abbaye des Morts, for example, runs at 220x176

1 Like

As @jonne said, the screen is actually 220x178. (Technically it’s actually 178x220 and it’s tilted on its side.)
There was some discussion about the options on the thread that started it all.

Would it be alright if I migrated the posts to that thread so we can discuss ideas about the ‘colour remake’ over there?

@Pharap : never mind the graphics resolution. Have you considered how limited the gameplay mechanics are, given that there is 4x more screen space on Pokitto than Arduboy. The screen of canyon or some other feature that barely fits on Arduboy will be sparse on Pokitto.

IDK if you understand what I mean. Let’s say movement across a given screen is 8 times right and a jump. We will have to do big graphics on Pokitto to compensate for the lack of resolution in the gameplay mechanics OR we will have to redesign the levels.

1 Like

Yes I understand about the fact that 110x88 is half resolution. But that’s kind of my point. If you want to port CastleBoy mostly “as is” to Pokitto you have two choices:

  1. Use full Pokitto resolution and display the full Arduboy game. This is what is currently made using Arduboy display mode. But the issue is that the game frame is very small. We want to play full screen!
  2. Use the resolution that is the closest to the original game -> Pokitto half resolution, and make the game fit within it. This way you can play full screen!

@jonne I understand what you say. If you want to fully use Pokitto’s hi-res, then you would have to make a completly new CastleBoy (CastleBoy 2?) game with new graphics, new physic and new mechanics. The scope of this project is completely different.

@jonne, @dir3kt,
This has already been discussed a long time ago.
Let’s flash back to March for a moment:


When I talk about a ‘scaled up, full colour remake’ is ending up with something like this (from the same post that I just linked to):

Scaled

By editing the game to reveal more of the world and possibly use slightly bigger tiles, you can make more of the existing game.

(See also this post where I discuss changing the tile size.)

What I am aiming to do at the moment is:

  1. Fix that text bug in the ‘direct port’
  2. Move on to the scaled up/colour port
  3. Then consider whether it’s worth making a sequel

I think this is a problem for the Arduboy2 library port to solve,
rather than this port in particular.

Personally I think the current approach of having a 128x64 block in the middle of a 220x176 screen is alright for now.

I don’t hold up much hope for being able to scale it up to full resolution without the graphics looking stretched or distorted,
and I refuse to use 110x88 and cut off 18 pixels, because those pixels are important for a lot of games.

Also there needs to be at least some space around the gameplay area so there’s room to fit the LED indicator sprite that I’m planning to add.

1 Like

I was planning to wait, but I’ve uploaded it all to GitHub (see the first/main post).
There’s not much to see though, it’s only slightly edited from the original.

I tried to keep the commit history nice and neat so people can see just how little I had to change to get it working with the Arduboy2 port.


(Aparently rebasing now removes the ‘verified’ tag… that’s an annoying bug.)

Good news, I’ve solved the number printing bug.

Castleboy is using ltoa to convert numbers into strings and I haven’t implemented that yet,
currently I’m just returning the input, so it’s a nop, which explains the zeroes.

The original CastleBoy is actually slightly incorrect here.
It should be using utoa because value is uint16_t which is unsigned int (not long).

I’ve got a fix that uses sprintf, which is actually a bonus because it means I can get rid of strlen,
and just use one O(n) complexity function instead of two.

2 Likes

Not sure. I mean at best Arduboy2-Pokitto can take the game as is, with the same resolution, and display it in a bigger frame. Cropping the width of the game to make it fit Pokitto’s half resolution needs redesign of the game.

The mockup you posted is exactly what I meant. Slightly increasing the map height, adding 2 extra tiles at the bottom of all stages. Editing the maps to add the extra tiles at the bottom. I think it would be the best way to have a proper CastleBoy port on Pokitto.

Speaking of coding actually I think the best would be to replace all Arduboy calls by Pokitto calls. From there it would be possible to do anything such as adding colored sprites, changing resolution, etc…

Oops. Don’t hesitate to make a pull request for this improvement. I’m not sure why I didn’t used sprintf though. It seems so obvious…

That’s a job for the remake:

Again, that’s the sort of stuff that would be happening with the colour remake, not the direct port.

That is the general idea, I wasn’t planning to use the Arduboy2 library for the colour remake.

I wanted to get the direct port working so that people who don’t have an Arduboy have chance to play the original to know what we’re working with.

(When I say ‘slightly incorrect’ I mean it’s not so much an error as a case of being a bit ‘overkill’.)

I was assuming it was a progmem constraint and/or you didn’t realise that sprintf returned the length.

A lot of people aren’t aware of what the str family of functions return.


This reminds me of the ‘Shlemiel the painter’ algorithm mentioned in one of Joel Spolsky’s articles.

For people who can’t be bothered to read the whole article, here’s the short version.

The Schlemiel the painter joke is as thus:

Shlemiel gets a job as a street painter, painting the dotted lines down the middle of the road. On the first day he takes a can of paint out to the road and finishes 300 yards of the road. “That’s pretty good!” says his boss, “you’re a fast worker!” and pays him a kopeck.

The next day Shlemiel only gets 150 yards done. “Well, that’s not nearly as good as yesterday, but you’re still a fast worker. 150 yards is respectable,” and pays him a kopeck.

The next day Shlemiel paints 30 yards of the road. “Only 30!” shouts his boss. “That’s unacceptable! On the first day you did ten times that much work! What’s going on?”

“I can’t help it,” says Shlemiel. “Every day I get farther and farther away from the paint can!”

Most sensible programmers will agree that Schlemiel is being very naive.

Some of those same programmers will write code like this:

char buffer[100];
std::strcat(buffer, "Some text.");
std::strcat(buffer, " Some more text.");
// ad nauseum

But what those programmers don’t realise is that std::strcat actually returns a value.
That value happens to be a pointer to the place in the buffer just after where the new text has been copied.

Congratulations ‘sensible’ programmers, you’re all Schlemiels. :P

Instead, what they should have written was this:

char buffer[100];

char * output = &buffer[0];
output = std::strcat(output, "Some text.");
output = std::strcat(output, " Some more text.");
// ad nauseum

Now, instead of doing an O(n) scan to find the end of the string, the function starts at the end.
Just think of how much processing power that saves.

(Of course, the really bright sparks out there would actually be yelling "no, don’t use std::strcat, use std::strncat", but that’s an entirely different story.)

1 Like

Yeah but then there is also the context. I mean when writing code for Pokitto/Arduboy this matters. At my work, we do soft real-time system among other stuffs. We have a huge (but I really mean huuuuuge) codebase and rather quick turnover of coders so we always favor code simplicity over optimization. Then in practice if we see an issue and track it down to a performance problem, we start optimizing. But only when needed. This is critical to reduce the cost of code maintenance. But again, context…

This isn’t really a question of simplicity, both examples are quite simple.
This is more a question of knowing and understanding one’s tools,
and understanding algorithms and computational complexity.

If someone was holding a hammer upside down then you’d tell them.

It might look harmless enough on this scale, but if the text being operated on is especially large then this is a serious problem - the kind of thing that at best will cause a few seconds of lag and at worst will lock up the program.

And yes, that would come up when the code was profiled,
but it wouldn’t come up at all if the code was written correctly the first time around.

At any rate, if you were writing for desktop then you’d probably be using std::string or std::stringstream so this probably wouldn’t come up anyway,
and if you were using char arrays, you’d possibly be better off using std::copy anyway.
(All of which are simpler to use might I add.)


Also, to be clear, the ‘schlemiel the painter’ thing wasn’t a jab at what you’d ended up doing by accident, it just reminded me of that story because of the use of the str-family.

When it comes to code, I’m a firm believe in always asking “is there a better way of doing this?”.