Pyoro! for the Arduboy

(Karim) #1


I just finished porting the game Pyoro (known as Bird and Beans in the US) to the Arduboy, and wanted to share the hex file (and code).

You can find the files here.


  • LEFT/RIGHT - Move Pyoro
  • A - Shoot tongue
  • UP+B (on main menu) - Clear save file


  • Add a pause menu

I added a Nintendo splash (sourced from GameBoy) because the game still is intellectual property of Nintendo.

Copyright Disclaimer
Under Section 107 of the Copyright Act 1976, allowance is made for “fair use” for purposes such as criticism, comment, news reporting, teaching, scholarship, and research. Fair use is a use permitted by copyright statute that might otherwise be infringing. Non-profit, educational or personal use tips the balance in favor of fair use.

(Scott) #2


  • Name your .ino file Pyoro.ino instead of Project.ino so people compiling using the Arduino IDE don’t have to rename it or put it in a folder named Project.

  • It would be a good idea to include arduboy.flashlight() after arduboy.boot(), to allow recovery if a version of the game ever causes the “bootloader magic key” problem.

  • Forcing audio on in setup() may annoy some people who wish to play the game with sound muted. You should use instead of

  • Along with the previous suggestion; since the game has no way for the user to toggle sound on and off, you could include arduboy.systemButtons() before so the mute state can be set during startup.

Or, instead of all the extra function calls in setup, you could just use arduboy.begin() instead of arduboy.boot() :wink:

(Karim) #3

i don’t wanna use the arduboy.begin() screen. Too many splashes and it starts to look like a Hollywood movie.
Pushing an update in minutes Done!

(Scott) #4

The first 16 bytes of EEPROM are reserved for system use (such as saving the mute state). Sketches must only use EEPROM locations starting at or after the defined value

(Karim) #5

Done! Used EEPROM_STORAGE_SPACE_START for the high score and EEPROM_STORAGE_SPACE_START+2 for the save magic number

(Scott) #6

Just to make things a bit cleaner, in setup() you can use


instead of

  do {
  } while(arduboy.buttonsState());

(Karim) #7

I actually saw that snippet on another post of yours, so I just used that. Will do, then!

(Karim) #8

Difficulty now increases for every 500 points you score. Beans go faster, spawn more often and Pyoro goes faster too.
Save magic changed since the difficulty and gameplay are different, so you will lose your high score.

(Pharap) #9

A bit of advice:

  • You don’t have to use itoa. arduboy.print can print integers, arduboy.print(score); would be fine. Because of this, scorebuf is essentially redundant.
  • aHeld looks like it could be replaced with using justPressed instead of pressed
  • sizeof(unsigned int) returns the size of unsigned int in bytes, not its maximum value, so when you call add(&val2u, margin, sizeof(unsigned int)) you’re actually doing add(val2u, margin, 2). That might be intentional, but it doesn’t seem to be.
  • You don’t need struct in front of bean and angel except for when they’re first declared. I.e. beans[i] = (struct bean){0,0,0,0} is redundant, you could just write beans[i] = (bean){0,0,0,0} or in fact beans[i] = {0,0,0,0} should work too

(Karim) #10

@Pharap Here are answers to your respective comments in order:

  • I’m using itoa because using the print(int) overload is super laggy. My code only calls itoa when score updates, instead of on every single frame. If I don’t redraw the score, it can get hidden by beans falling through.

  • aHeld works differently in that it uses aPressed's previous value, which goes through the validation of the A press (leading to the tongue having extended) which justPressed() does not do. I did try swapping out but it didn’t work.

  • Didn’t notice because req() was only used for small amounts

  • Nope. As per C convention, struct types can only be referred to by prefixing them with struct, unless typedef'd. And omitting the cast can create confusion for whoever reads the code afterwards.

(Pharap) #11

It shouldn’t be, usually it’s fairly quick.
If I can’t prove otherwise then fair enough.

I see, I hadn’t noticed that you set aPressed = false;.

This isn’t C, this is C++. In C++, the struct is optional.
(If this was C, you wouldn’t be able to do arduboy.display() because C doesn’t have a concept of member functions.)

The reason you are getting an error is because you named one of your images bean as well (i.e. PROGMEM const unsigned char bean[]), so the compiler can’t figure out whether you mean the struct bean or the array bean.
A simple fix would be to capitalise the type names to Bean and Angel.

That’s one of the reasons C++ tends to prefer constructors over C-style brace initialisation.
Personally I don’t think omitting the cast is particularly confusing, the array name is quite clear about what it contains, but fair enough.

(Karim) #12

I usually just code in C style, so I think I’ll stick with my (struct bean) cast, should it only be for aesthetic purposes. It doesn’t cause any problems AFAIK. (plus it allows me to have an image called bean[] next to it :stuck_out_tongue:)

Oh and print(int) might be superfast, but still, converting only on change leaves more cycles per frame, so more room for improvement.