Ref/pointer to sprites

Is there a way that I can have a variable point to a sprite? The reason I want to do this is to use just one variable name, but have it point to different sprites depending on what is happening in the game.
example:

unsigned char const heart[] PROGMEM =
{
  8, 7,
  // 0
  0x0e, 0x1f, 0x3f, 0x7e, 0x7e, 0x3f, 0x1f, 0x0e, 
};

const unsigned char& myHeart = heart;  //here using ref?
            Sprites::drawOverwrite(100,52,myHeart,BLACK);
            arduboy.display();

Later in the game I want to point myHeart to a different sprite.

I’m not great with references & pointers so getting very confused in how to do this? any help greatly appreciated

References can’t be rebound to other objects, you can only bind them once, so you won’t be able to use references for this.

If you need to have a variable that you can ‘repoint’ to another sprite, you’d have to use a pointer.
E.g.

constexpr unsigned char heart1[] PROGMEM
{
	8, 7,

	// 0
	0x0E, 0x1F, 0x3F, 0x7E, 0x7E, 0x3F, 0x1F, 0x0E,
};

constexpr unsigned char heart2[] PROGMEM
{
	8, 7,

	// 0
	0x0E, 0x1F, 0x3F, 0x7E, 0x7E, 0x3F, 0x1F, 0x0E,
};

const unsigned char * heart = heart1;

And then:

// x, y, sprite (pointer), frame index
Sprites::drawOverwrite(100, 52, heart, 0);
arduboy.display();

However, if you’re using Sprites for drawing and your heart sprites are all the same dimensions or could all fit in the same dimensions then you’d probably be better off using the sprites format’s ‘frame’ feature, which allows you to pack multiple frames into a single sprite and then provide a frame index to select the correct frame.

E.g.

constexpr unsigned char heart[] PROGMEM
{
	8, 7,

	// Frame 0
	0x0E, 0x1F, 0x3F, 0x7E, 0x7E, 0x3F, 0x1F, 0x0E,

	// Frame 1
	0x7E, 0x3F, 0x1F, 0x0E, 0x0E, 0x1F, 0x3F, 0x7E,
};

unsigned char heartFrame = 0;

And then

Sprites::drawOverwrite(100, 52, heart, heartFrame);
arduboy.display();

Note that this means the last argument of drawOverwrite is actually a frame index, not a colour.

If you’d used WHITE (which is a macro with a value of 1) instead of BLACK (which is a macro with a value of 0) then your sprite wouldn’t have drawn properly because drawOverwrite would be trying to draw a frame that didn’t exist.


I’d offer to type up an explanation, but it’s late here so instead I’ll just drop you a few links:

The latter two are less important, but I left them in case you’re curious.

Note that usually you should prefer references when possible because they can’t be null. Sometimes you have to use pointers because you have no choice (e.g. when you need to change the object being referenced/pointed to) but generally references are safer and better.


Does that all make sense?
If you have any other questions, feel free to ask.

4 Likes

Thank you Pharap, that all makes perfect sense, I’ve used sprite sheets before, and that would be a much better approach, so I’ll use that.
I’ve just ordered a book on C++, so going to work through that when it comes & try to get a better understanding of pointers & references.
I notice you use constexpr instead of const - is that a better approach for the graphics?

1 Like

In the vast majority of cases it doesn’t make a difference, but I would argue that yes, it is better to use constexpr.

For truly constant data, constexpr is a better option in general in the situations where you can use it. It ensures that the object (integer, array, et cetera) can be constructed at compile time.

The odd thing about const is that it doesn’t actually mean ‘constant’, it only means ‘read-only’. (In fact, const was originally called readonly.) This means that when making a const global variable, the variable might actually be initialised when the program starts rather than at compile time. (On Arduboy that would be quite rare though.)

The one difference constexpr has on sprites is that it makes it possible to inspect the sprite’s data at compile time (because it’s guaranteed to be initialised at compile time, unlike with const). This is rarely ever useful though.

The best way to understand pointers, in my opinion, is to understand how computer memory (e.g. RAM, flash, EEPROM) works.

If you can understand what an array is (and what bytes are) then you can understand how computer memory works, because memory is effectively just a big array of bytes.

What programming languages term ‘pointers’ are actually memory addresses, and if you think of memory as an array of bytes then by analogy a memory address is an index into that array (i.e. pointers are in fact integers, with some compiler magic to make them look and behave specially).

(Different kinds of memory have different characteristics though. E.g. being read-only, or being volatile or non-volatile.)

References are (in most (but not all) cases) secretly pointers with a bit of compiler magic to ensure that:

  • You have to make them refer to an actual object
  • You can’t reassign them
  • You can use normal object syntax with them
    • I.e. using . to refer to member variables/function instead of -> as required for pointers.
    • E.g. Arduboy2 & reference = arduboy; reference.display(); versus Arduboy2 * pointer = &arduboy; pointer->display();

Not that I think that’s necessarily a bad thing, but be aware that you can learn pretty much everything about C++ online if you know where to look. (I can safely say I’ve only ever read one physical C++ book.)

  • Learn C++ (the tutorial I linked to parts of before) is great for actually learning the language.
  • The ISO C++ FAQ is good for learning a few things many tutorials won’t tell you.
  • cppreference is good for when you’re able to understand the more technical stuff and/or need to check the rules (including language syntax).
  • C++ Core Guidelines is good if you care about best practice and writing clean code.

(These and more helpful links can be found in my Resource Collection.)

Note that learning to write for the Arduboy is actually a lot quicker than learning to write dekstop/general C++ because you don’t need to know as much as you would for a desktop program.

For one thing, most Arduino boards (the Arduboy included) don’t have access to the C++ standard library, they use the C standard library instead, so anything you might learn about the C++ standard library is only partly useful (because only parts of it overlap the C standard library).

2 Likes

4 posts were split to a new topic: Learning resources for C#?