Arduboy2 - The now recommended alternative to the Arduboy Library

(Ignacio Viña) #42

@JO3RI Yes, I called you! :wink:

Thanks for answering! My encoder is created based on some improvements after analyzing RLE encoding used in Cabi. I cannot be 100% sure but I think that my function creates images with 10-30% less size (based on my tests). (Ex. @TEAMarg logo is compressed on 517 bytes (vs 640 bytes on Cabi).
Draw speed is 50% faster and I have implemented vertical/horizontal mirroring with no performance penalty,I think mirroring feature could be useful for some games that now use 2 different images to draw.
I hope to publish the code as soon as possible, this way people can test it and give me feedback.
Anyway, I have released a preview version of the encoder if someone wants to check it now:

Bitmap encoder post

Also, thanks for the idea of the pre-recorded numbers for the voice library, I think it is perfect. I have to write a tool to convert from wav to the encoded byte array. I will work more in this after I finish the image encoder/decoder.

(Scott) #43

The thing about standard libraries, like Arduboy2, is that if you remove a documented API function that has been used in a sketch, then that sketch will break when compiled with the new library release. It’s better to leave the old function there even if the new function is improved in a way that leaves no reason to use the old one for new development.

In the specific case of drawCompressed(), one could argue that there are currently very few sketches using Arduboy2 so far, and the chances that any are using drawCompressed() is very likely zero, so nothing would break by removing it.

However, it’s unknown if there are some games in development and are near completion in which the author has chosen to use Arduboy2 with drawCompressed(). If the function were removed it may cause the release of a game to be delayed because the developer would have to spend time recompressing the bitmaps and switching to the new function.

It’s also possible that someone may wish to modify or extend a Team A.R.G. game but wants to take advantage of something that Arglib can’t do but Arduboy2 can, such as playing multi-tone effects using the ArduboyTones library instead of the simple single tone function in Arglib. Since I’ve made Arduboy2 highly Arglib compatible, replacing Arglib with Arduboy2 is generally quite easy (as I found with the 4 that I quickly converted). If drawCompressed() were removed, it may make doing this kind if thing a more difficult.

If it turns out that drawCompressed() has no benefit whatsoever over the new function then I would note that fact in the documentation, recommending the new function be used for all new development.


Perfect, I only wanted you both to know, I don’t mind drawCompressed() getting ditched or replaced.

(Blob Attack is our only game using it …)

Now the vertical/horizontal mirroring sound like something interesting, even more for uncompressed stuff

(Holmes) #45

We discussed this before… I think there should be a drawBitmap overload that includes a parameter that can be flipped, rotated, or both. We can define a few keywords for this parameter, too.

(Ignacio Viña) #46

Thanks for all the feedback. I almost have finished the draw function optimizations, I hope to publish it tomorrow, then @MLXXXp could tell me the best way to integrate it on Arduboy2 library.

About the parameters (mirroring, rotation, resize) all could be included on uncompressed staff also. This is what I have found about the complexity:

  • Horizontal mirror: Trivial, almost no more code (in fact I did this on my game Bangi).
  • Vertical mirror: Easy, extra work is to flip all the bytes of the image.
  • Rotation: 90º and 270º could be slow to apply in real-time in games running at 30/60 fps.
  • Resize: Similar or even a bit more complex than rotation.

Anyway, I hope that people use compressed staff also during the gameplay. :sunglasses:

(Scott) #47

This will depend on how fast it runs and how much code space is saved. It will probably end up to be a decision made for each game, depending on its requirements. In some cases it might not be obvious if using compressed or uncompressed bitmaps is better, so just experimenting and observing the results will be required. Some people may also wish to use the dedicated Sprites class in the Arduboy2 library due to its masking and frame handling capabilities.

The compiler can produce some pretty strange output sometimes. For instance, the following sketch will compile to 7670 bytes but if you uncomment the second arduboy.display(CLEAR_BUFFER); so that there are now two identical calls in a row, the code size is REDUCED by 10 bytes to 7660! Huh?? :confounded:

#include <Arduboy2.h>

Arduboy2 arduboy;

void setup() {
//  arduboy.display(CLEAR_BUFFER);

void loop() {

(Ignacio Viña) #48

You are right, it depends a lot of the type of game. It works better if the game has big images/sprites and no masks (you need to decode 2 images).

My draw method is about 500 bytes (it depends of the compiler optimizations), using this could be worth even for a game with only a 128x64 (1 Kb) splash screen image.

I’m working on a demo to test the performance of my decoding/encoding code. I think that a good pixel artist/animator could do better stuff to play in the great Arduino! :wink:

(Stephen Lavelle) #49

Thanks so much for this library - it’s been really helpful. (But it was a bad/inconsiderate idea to call it arduboy2 - it’s unnecessarily stomping on the name of the official library. Also I was confused when I got the arduboy first what library to install - I would have called it something like “arduboy_plus” - it’s too late to rename now I guess, but I would recommend making it clear in its description in the arduino database that it’s an unofficial fork, not just a fork - people may not know what ‘fork’ means. But, to reiterate, I’m grateful that it’s out there, and I’m using it in several WIP projects, so thank you!)

(Scott) #51

Arduboy2 library version 3.1.0 has been released and is available through the Arduino Library Manager.

What’s New:

  • Added new functions writeUnitName(), readUnitName(), writeUnitID() and readUnitID(). These allow a 6 character (or less) unit name and a 16 bit unit ID to be saved to and retrieved from a reserved location in system EEPROM.
  • Added a new example sketch, SetNameAndID, which allows the unit name and unit ID to be set or changed.
  • The Arduboy2 class’s bootLogo() function will display the unit name at the bottom of the screen after the logo stops scrolling. This feature is not available when using the Arduboy2Base class because it doesn’t include the text functions.
  • The boot logo sequence can now be bypassed by holding the RIGHT D-pad button when powering up or by pressing it when the logo is scrolling down.
  • Added function audio.toggle() to toggle the audio mute state.
  • Made the display buffer, sBuffer[], public for easier and more efficient direct access, instead of using a pointer obtained from getBuffer().
  • Made the frameCount variable public so that a local counter may not be required for the purpose.
  • Added function nextFrameDEV() for use in place of nextFrame() during sketch development. This works the same as nextFrame() but additionally will light the yellow TX LED whenever a frame takes longer to render than the time allotted per frame.

The documentation has been updated with all the details:

Nicknames and Arduboy
Disable Boot Animation
Distinguishing one Arduboy from another in software?
(Mike McRoberts) #52

Great work. Thanks Scott.

has anyone used the sBuffer[] command in their game yet? I’d be interested to see how people are implementing it.

(Scott) #53

External display libraries can use it. For instance, ArdBitmap needs to be given an expression to access the screen buffer. Previously, for ArdBitmap you would use:

#define ARDBITMAP_SBUF arduboy.getBuffer()

but now you could use

#define ARDBITMAP_SBUF arduboy.sBuffer

which would create less code and be a bit more efficient.

My ArduboyLife sketch directly accesses the screen buffer, though it does it via a pointer obtained using getBuffer(). I haven’t yet updated it to use sBuffer directly. (I haven’t even switched it over from Arduboy to Arduboy2 :astonished: It’s on my todo list. )

(Josh Goebel) #54

Doesn’t this also mean it can be modified? Probably should have a function to return a read-only copy.

(Scott) #55

Yes, but it doesn’t really matter. frameCount is only used by everyXFrames(), so if a developer wants to mess with writing to frameCount (for reasons that are beyond me) then that’s on them. Other than affecting everyXFrames() it won’t cause any other problems with library frame handling.

(spinal) #56

How do I switch off the RX/TX LEDs?

(Scott) #57

When are they coming on? Are you trying to control them?

(spinal) #58

Not trying to control them in any way right now, they seem to be on by default, with or without the sub connected.

(Scott) #59

@spinal, Sounds like a hardware problem or a bad sketch has been loaded. Does it happen with all sketches?

(spinal) #60

my mistake, I was building for micro instead of leonardo.

(Scott) #61

Arduboy2 library version 4.0.0 has been released and is available through the Arduino Library Manager. The complimentary sound library ArduboyPlaytune has also been updated to release 1.0.3, which has changes to help achieve some of the memory size reductions described below.

Release notes:

The main purpose of this release is to reduce code produced by the library, leaving more code space for the sketch itself. The overall size of a sketch will be reduced by around 600 to 1100 bytes, with around 1000 bytes being typical. The actual operation of the sketch will not be affected. This size reduction was mainly achieved by directly controlling the I/O pins and on chip peripherals, instead of using pinMode(), digitalWrite() and other Arduino library functions. Also, existing functions were optimized to reduce size.

  • nextFrame(), drawChar(), drawPixel(), readUnitName(), writeUnitName() and Sprites::drawPlusMask() functions have been optimized to reduce size. Thanks to @Dreamer3 for this.
  • The initRandomSeed() function uses a different technique which produces less code.
  • New functions bootLogoCompressed(), bootLogoSpritesSelfMasked() and bootLogoSpritesOverwrite() can be used in place of bootLogo() to reduce code size in cases where their drawing functions are shared with the same functions used by the sketch. Also, a bootLogoText() function was added that renders the logo as text instead of a bitmap, which can reduce code size at the expense of showing a logo that doesn’t look as good.
  • delayShort() function added for delays up to 65535 milliseconds. Using it in place of the Arduino delay() function will save a few bytes.

Other additions and changes:

  • drawPixel() function optimized for speed. Thanks to @Dreamer3 for this.
  • In addition to the current version of digitalWriteRGB(), which takes 3 parameters to control all 3 of the LEDs simultaneously, a new 2 parameter version has been added to allow controlling each individual LED by specifying the LED color and whether to turn it on or off.
  • The displaying of the unit name at the end of the boot logo sequence has been made optional, controlled by a flag set in the system EEPROM area. Functions writeShowUnitNameFlag() and readShowUnitNameFlag() have been added to read and write this flag. The SetNameAndID example sketch has been modified to allow setting the flag.
  • The flashlight() function has been improved to do a better job of allowing a new sketch to be uploaded when the current sketch causes bootloader “magic key” issues. It no longer allows the Down button to be used to continue the sketch, so the unit must now be rebooted after use. Also, function safeMode() has been made available as a lower memory replacement for flashlight().
  • New function SPItransfer() added to be used instead of the SPI library SPI.transfer() function.
  • displayOff() and displayOn() functions added to allow putting the display in a blanked low power state.

(Boti Kis) #62

Amazing, thank you for your work!