Im storing a 2d array of bytes in progmem because its pretty huge (4kb) If i want to read from this 2d array can someone give me an example of how to do this?

(storing the array in progmem because the rest of the game isnt likely to take up too much space and because I want more detail to my map than the bit array i used before)

``````constexpr uint8_t arrayWidth = 10;
constexpr uint8_t arrayHeight = 5;

uint8_t arrayOfBytes[arrayHeight][arrayWidth] PROGMEM =
{
// ...
};

{
}
``````

(Strictly speaking `arrayWidth` and `arrayHeight` should be `size_t`, but `size_t` is 16 bits on the Arduboy, so using `uint8_t` should produce less code. I’m not completely sure though, I’ve never actually tested - it’s possible that it doesn’t make a difference because it’s `constexpr` or because it has to get promoted anyway.)

2 Likes

Oh that easy? Nice one. Just as an aside question, say I have converted a bitmap image into an array, this array was produced by going left to right along each “row” of pixels on the image and assigned them a byte (so a 2x2 pixel image might look like {0, 0, 0, 0}) If i want to convert this to a 2d array I should just be able to do arrayofbytes[2,2] right?

So basically you’re generating your maps by drawing them in an image editor and then treating each colour as a different tile type?

If so, a 2x2 image (when converted) would look like:

``````constexpr uint8_t arrayWidth = 2;
constexpr uint8_t arrayHeight = 2;

uint8_t arrayOfBytes[arrayHeight][arrayWidth] PROGMEM =
{
{ 0, 0 },
{ 0, 0 },
};
``````

(Assuming the image was all one colour, and that colour corresponded to `0`.)

You don’t have to use `constexpr` variables,
but it’s easier to do that than to extract the dimensions from the array (especially a 2D array).

I’ve got two more bits of advice…

Firstly,
I recommend using an `enum class` (‘scoped enumeration’) for map tiles instead of using number types.
It makes the code more readable.

E.g.

``````enum class Tile
{
Empty,
Tree,
};

constexpr uint8_t mapWidth = 2;
constexpr uint8_t mapHeight = 2;

Tile mapData[mapHeight][mapWidth] PROGMEM =
{
{ Tile::Empty, Tile::Empty },
{ Tile::Empty, Tile::Tree },
};

{
}
``````

Then your code becomes more readable, because you can write things like:

``````bool isSolid(Tile tile)
{
switch(tile)
{
case Tile::Empty:
return false;
case Tile::Tree:
return true;
default:
return true;
}
}
``````

And in case you haven’t encountered a `switch` statement before, think of it like this:

``````bool isSolid(Tile tile)
{
if(tile == Tile::Empty)
return false;
else if(tile == Tile::Tree)
return true;
else
return true;
}
``````

If you’ve only got 16 tiles or less then you can pack more than one tile per byte.
You’d need to do some bitshifting to pack and extract the data.

It’s possible to do this as well as using an `enum class` for the tile types,
but you’d need to know how.

I can explain it if you want, but if you don’t plan to do this then I don’t want to overload you with info.

And if you haven’t stumbled upon it yet, you might find this useful:

2 Likes

Thanks for the useful advice, I know I could squeeze more data into each byte but Im doubting if i NEED to for this particular application. If I did I would probably just draw the map in bits using the function i used in my roguelike wip and then modify what it displays based on when on the array a tile is drawn, would squeeze the map well below 1kb but im being lazy for reasons of getting more done.

1 Like

Depending on how big your game gets you might have to eventually.
That progmem runs out really quickly.

If you do end up packing your bits and using your map code, make sure to replace your `#define`s with `constexpr` variables.
Also, try `using MapStorage = unsigned char;` instead of `#define MAP_STORAGE unsigned char`.

Macros are evil and should be avoided whenever possible.

1 Like