Follow the development of Rick Ardurous

(Alban Nanty) #25

Hello,

The episode 18 is out: stream replay

In this episode I’ve debugged and improved the crawling animation for the main character.

See you.

1 Like
(Alban Nanty) #26

Hello,

The episode 19 is out: stream replay

In this episode I explained how I finalized the crawl state, I’ve integrated the jump animation, and I’ve implemented the death state and animation for the main character.

See you.

2 Likes
(Alban Nanty) #27

Hello,

The episodes 20 stream replay and 21 stream replay are out.

In those episodes I worked on the platforms and ladders and implemented the climb ladder state for the main character.

See you.

2 Likes
(Simon) #28

They game is really coming along … do you have a finish date in mind?

(Alban Nanty) #29

Hi Simon,

No, not really. I guess I still have a lot to do :slight_smile:

1 Like
(Alban Nanty) #30

Hello,

The episode 22 is out: stream replay

In this episode I have fixed some bugs on the main character behavior, and I started to implement the support of drawing the main character in different screens.

See you.

4 Likes
(Alban Nanty) #31

Hello,

The episode 23 is out: stream replay

In this episode I continue to implement the support of drawing the main character in different screens.

See you.

1 Like
(Alban Nanty) #32

Hello,

The episode 24 is out: stream replay

In this episode I finished to implement the support of drawing the main character in different screens, and we have also fixed the drawing of all the items in different screens.

See you.

3 Likes
(Alban Nanty) #33

Hello,

The episode 25 is out: stream replay

In this episode I started to implement the AI for the walking enemies.

See you.

2 Likes
(Alban Nanty) #34

Hello,

The episode 26 is out: stream replay

In this episode I continue to implement the logic of the Enemy, integrating its walking animation, adding a state machine for walk, half turn, and fall, and implementing the logic for the enemy to do a half turn.

See you.

3 Likes
(Scott R) #35

I just realised it’s been a year already, how time flies. The game is really starting to take shape now. I’m looking forward to see how it progresses further.

2 Likes
(Alban Nanty) #36

Yes, time flies!! I made a long pause for a while, but these days, I tend to be more regular for the streaming periods. I hope I can keep on that steady progress.

2 Likes
(Pharap) #37

Personally I’m just waiting for the game itself (and the source code of course).
I’m one of those people who’s not very good at sitting around watching videos (especially hour-long ones).

2 Likes
(Alban Nanty) #38

Sure, I’ve no problem with that, actually, I’m happy to know that you find interest in the game itself.

The source code is already available, but of course, I update it after every stream, so you may want to wait for the final version of the code, if your goal is to modify it to create a similar game.

(Pharap) #39

I don’t have a bitbucket account so I’d have a hard time contributing unless I sent you and modifications directly.
I don’t really like bitbucket’s UI,
it was a bit of a struggle to actually find the source code from that link.

https://bitbucket.org/banban/rickardurous/src?at=default

Even then I can’t see a “download all source code” button anywhere.

I probably wouldn’t be doing that, but I would like to have a look to see if I could find some ways to save memory and/or spot potential issues.

My thoughts:

  • Your code could probably benefit from using some C++11 features like constepxr.
  • The signedness of char is actually implementation defined, so if anyone had any plans to port this then that could be an issue.
  • I think switching to Sprites rather than arduboy.drawBitmap might save you some memory, but I see you’re using a custom drawing function so that might not be possible.
  • Not using virtual would probably save quite a big chunk of memory, but you’re relying quite heavily on virtual functions so that would be a lot of effort to change.

It makes a nice change to see well-commented code, a lot of people just don’t bother.

(Alban Nanty) #40

Hello Pharap,

Here is a link to the download page (so you don’t need to create an account to have a snapshot of the repo): https://bitbucket.org/banban/rickardurous/downloads/

To answer your thoughts:

  • constexp seems indeed very interresting on such a tiny platform. I’m not sure however that the Arduino compiler can support it. I will try it, if I see a contant expression somewhere. However I don’t feel that I have a lot of functions that could benefit from it.
  • Because I develop on a such tiny platform, I cannot make my code portable. This will become worse and worse, I will later introduce more optimizations that will be thightly be linked to the Arduboy platform, such as the screen resolution for example. For example if I would develop on a “normal” platform I won’t bother at all to pack some values, or I won’t try to group several flags in one, just to limit the values of an enum to 8. I’m aware that this makes the code less readable, and less robust to changes.
  • I personally think that Arduboy 2 is gigantic. Sure it proposes many cool services and API for developing games quickly, but it also use too much progmem for those who don’t need those services (By the way, it would be cool, if the developers of the Arduboy API add a bunch of #define to enable or disable some parts of the code that the developers don’t use, knowing that everything could be enable by default). I also personally think that not proposing to draw a sprite in mirror (both x and y) is a huge miss in the API. So I do believe that if I use Arduboy 2, I won’t be able to fit my game in memory.
  • Sure, using virtual add a virtual table in each class. But so far, I use only 1 virtual function (Update) in the base class, and one in the PickUpItem class (PickUp). I guess the address of those virtual function use an int, therefore if I have 100 items in the final game, I will loose 200 bytes, which I think is reasonable for having a manageable implementation. But anyway, I’m aware of the weigth of the virtual, and I may remove them if I need to find some progmem.
  • Thank you for commenting on my code, I always code with comment, this was they way I learnt how to code, and now I’m used to it.
(Scott) #41

The compiler only includes library functions that you actually use. The Arduboy2 library could have 10 times as many functions and still wouldn’t make your particular sketch any bigger.

Take a look at the ArdBitmap library by @igvina if you want sprite mirroring.

(Pharap) #42

Before I get to the main part, here’s something to grab your attention:

Before making any changes to your code, I get:

Sketch uses 22052 bytes (76%) of program storage space. Maximum is 28672 bytes.
Global variables use 1906 bytes (74%) of dynamic memory, leaving 654 bytes for local variables. Maximum is 2560 bytes.

After replacing almost all the const variables that I could with static constexpr and replacing Arduboy with Arduboy2 I got:

Sketch uses 18992 bytes (66%) of program storage space. Maximum is 28672 bytes.
Global variables use 1744 bytes (68%) of dynamic memory, leaving 816 bytes for local variables. Maximum is 2560 bytes.

That’s 3060 bytes of progmem saved, and 162 bytes of RAM saved.

I haven’t actually run the game to make sure it all still works properly,
but I can’t think of any reason offhand why it wouldn’t.


What compiler are you using?

GCC has had C++11 support for several years now.
The Arduino IDE uses C++11 by default.

I was thinking more about your const variables:

const int BULLET_SPEED = 4;
const int BULLET_WIDTH = 3;
const int ARROW_SPEED = 2;
const int ARROW_WIDTH = 8;
const int SPARKS_ANIM_SPEED = 3;
const int NO_PIXEL_FOUND = 60000;

Those actually increase your class size.

Now I have access to the download I can prove it.
Before any changes, the compiler reports:

Sketch uses 22052 bytes (76%) of program storage space. Maximum is 28672 bytes.
Global variables use 1906 bytes (74%) of dynamic memory, leaving 654 bytes for local variables. Maximum is 2560 bytes.

Now, if I change that code I just highlighted to:

static constexpr int BULLET_SPEED = 4;
static constexpr int BULLET_WIDTH = 3;
static constexpr int ARROW_SPEED = 2;
static constexpr int ARROW_WIDTH = 8;
static constexpr int SPARKS_ANIM_SPEED = 3;
static constexpr int NO_PIXEL_FOUND = 60000;

The result is:

Sketch uses 21890 bytes (76%) of program storage space. Maximum is 28672 bytes.
Global variables use 1846 bytes (72%) of dynamic memory, leaving 714 bytes for local variables. Maximum is 2560 bytes.

Which is 163 bytes of progmem saved and 60 bytes of RAM saved (which is 2% of RAM).

(You should also avoid using ‘all caps’ for anything other than macros, but that’s just a style issue.)

That’s not necessarily the case.

I’ve been writing an implementation of Arduboy2 for the Pokitto and I’ve been able to port quite a few games with minimal effort.

Keeping code portable isn’t particularly difficult.
Especially these days with the availability of the fixed width types (int8_t, uint8_t, et cetera).

(That links to the C reference rather than the C++ reference because Arduino uses an implementation of the C standard library rather than the C++ standard library.)

As @MLXXXp said, in C++ you don’t pay for what you don’t use.
If you don’t use a function it isn’t included in the compiled .hex file.

Have you actually tested it?

I took a clean copy of your code, compiled it and got:

Sketch uses 22052 bytes (76%) of program storage space. Maximum is 28672 bytes.
Global variables use 1906 bytes (74%) of dynamic memory, leaving 654 bytes for local variables. Maximum is 2560 bytes.

Then I changed CustomArduboy.h to:

#ifndef _CUSTOM_ARDUBOY_H_
#define _CUSTOM_ARDUBOY_H_

#include <Arduboy2.h>

const uint8_t TRANSPARENT = 3;

class CustomArduboy : public Arduboy2
{
public:
	unsigned int drawBitmapExtended(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color, bool mirrorX);
	unsigned int CheckWhitePixelsInRow(uint8_t x, uint8_t row, uint8_t w);
	
	void beginNoLogo()
	{
		this->boot();
		this->display();
		this->flashlight();
		this->audio.begin();
	}
};

#endif

And now the compiler says:

Sketch uses 19522 bytes (68%) of program storage space. Maximum is 28672 bytes.
Global variables use 1882 bytes (73%) of dynamic memory, leaving 678 bytes for local variables. Maximum is 2560 bytes.

Thats’ a really big decrease in progmem usage.

It’s 2530 bytes of progmem saved (8% of progmem),
and 24 bytes of RAM saved (1% of RAM).

More specifically it’s one virtual table in progmem and one pointer in the actual object, so it uses both progmem and RAM.
There’s actually one virtual table per class, and then there’s additional code to load the virtual table pointer into the object and more code to call the virtual function, all of which adds up.

It’s a pointer, not an int, though they are the same size on the Arduboy.

2 Likes
#43

I recently discovered that by creating an Arduboy2 object the virtual functions bootLogoExtra and write will always be included and may take up some ~2K. Using Arduboy2Base object instead will save quite a bit of PROGMEM

Edit:
Here’s a simple test program:

#include <Arduboy2.h>

ARDUBOY_NO_USB

Arduboy2 arduboy;

void setup() {
 arduboy.boot();
}

void loop() {
  if (!arduboy.nextFrame()) return;
  
  arduboy.display(CLEAR_BUFFER);
}

When Arduboy2 is changed into Arduboy2Base the program size will decrease by rougly 2K

1 Like
(Scott) #44

Using the Arduboy2Base class instead of Arduboy2, to save memory if text functions aren’t required, is discussed in the Ways to make more code space available to sketches section, subsection Remove the text functions, on the main page of the Arduboy2 library documentation.