I would like some help with a map for a game

I have been thinking about making a little adventure game that would use a colour LCD and buttons/touch for input. I don't know how best to approach the problem and I'm hoping you can help me.

The game will have a player roam a 2D map. They will have 8 degrees of freedom, N, NE, E, SE, S, SW, W, NW. The player will stand in a tile and will move to an adjacent tile when movement occurs.

Each tile would have properties like condition, weather, terrain type (for description and look).

I was thinking the map could be stored as a two dimensional array. This seems like a good way to do a map because you have basic Cartesian coordination abilities and each element in the array could be called upon and interrogated to give the player some feedback about the tile. I imagine the contextual information will be pulled from a lookup table after masking the array cell data.

Does this sound feasible? Have I gone in to this without seeing the obvious flaw? I was thinking about using external EEPROM(s) to store the 'map', lookup tables and descriptive wordbanks. I know I can store and recall a lot of data from external storage but maybe this will be slow? I was hoping to display maybe 100 tiles (10*10) at a time from a larger map. When the player moved it would shift the map one row or column to keep the player in the centre of the map.

Thanks!

Hi,
Welcome to the forum.

Can you tell us your electronics, programming, Arduino, hardware experience?

Thanks… Tom… :slight_smile:

Hello Tom,

No problem, I'm an electronics engineer however for my work I don't deal with software development at all. I have developed hardware/software systems before (in C#, ~8 years ago) however this is a little different from my previous experiences.

Because I have not done anything like this on this platform before I have no feel for the viability and pitfalls (speeds, methods) so I think my post here (and an almost mirror post on Reddit) is an idiot check of my approach and hopefully will spark some useful pointers.

Cheers,

Tom

I don't have a lot of experience with game design but some things to consider could be:

Will you be designing the map and storing it or auto generating it as the player explores?

You only have 100 tiles loaded (and saved in ram?) at a particular time, and loading 10 for a N,S,E or W movement, or 19 for a NE, NW, SE, SW movement so it shouldn't be time intensive to iterate through coordinate arrays. You may run short of RAM if your map gets too big so external storage (eg SD card) might be an option.

You can do it using Arduino. I'm not clear why you would though. Rather than external EEPROM, consider a shield with an SD card. Speed will likely be an issue, so consider a Due which gives you more memory in addition to increased clock speed. Of course, once you're at that price point, you might as well look at a Raspberry Pi.

If your purpose is to build a game, Arduino is probably not the optimal choice of hardware. The game will likely evolve to outgrow its capability.

If your purpose is to learn to use Arduino with external hardware, why not?

SamIAm93: I don't have a lot of experience with game design but some things to consider could be:

Will you be designing the map and storing it or auto generating it as the player explores?

You only have 100 tiles loaded (and saved in ram?) at a particular time, and loading 10 for a N,S,E or W movement, or 19 for a NE, NW, SE, SW movement so it shouldn't be time intensive to iterate through coordinate arrays. You may run short of RAM if your map gets too big so external storage (eg SD card) might be an option.

Thanks, I would have a small part of each of the 100 tile loaded in RAM (the part that tells us what the tile type is so I can put the right image for it on the map). The full tile information would be loaded when the player moves on to a new tile. This would save some RAM.

100 tiles = 10 by 10 grid?

So 10 can be represented by 4 bits.
You can represent a full tile co-ordinate, like (x = 6, y = 4) in a single byte.
100 bytes would give the entire board co-ordinates.
You could then have it so that you have a second set of 100 bytes in RAM for “properties” of the tiles…

I.e. Tile (8,3) = 1111 0011 Properties = 0B10011011 (where each bit is like a property…)

This sort of what you want?

You could even just index the tiles…
So co-ordinate (1,0) is held in array[1] with the byte of “property” data.
co-ordinate (5,2) is held in array[25] with the byte of “property” data. ie. 2 tiles up and fifth across = 25th
co-ordinate (8,1) is held in array[81] with the byte of “property” data. i.e. 8th tile up and 1st across = 81st.

Then a bit of vector maths...

Move 1 NW = current position(x-1),current position (y+1)

If you are displaying say 9 "tiles" on the GUI, then you just want to load the properties for the surrounding tiles using your current positon as the centre tile..

Tile to north = current co-ordinate(+0 , +1) Tile to NE = current co-ordinate(+1 , +1) etc. etc.

then manage the "empty" or out of bounds tiles with some "if statements". You could always have a 12x12 grid where the movement is rectricted to the 10x10 and the outer tiles are all blanks (i.e. 0B00000000).

Johnny010: 100 tiles = 10 by 10 grid?

So 10 can be represented by 4 bits. You can represent a full tile co-ordinate, like (x = 6, y = 4) in a single byte. 100 bytes would give the entire board co-ordinates. You could then have it so that you have a second set of 100 bytes in RAM for "properties" of the tiles...

I.e. Tile (8,3) = 1111 0011 Properties = 0B10011011 (where each bit is like a property...)

This sort of what you want?

Yes I think we are on the same page. I was wanting to have 100 tiles visible on the screen but many more tiles in storage. I am starting to put it together with a NodeMCU but I'm not tied to that.

Johnny010:
Then a bit of vector maths…

Move 1 NW = current position(x-1),current position (y+1)

Really interesting. This is where my knowledge of C drops right off. If there is a current position variable that is holding the current position, how would you use that variable to point to the correct array?

Cheers!

The NodeMCU is like 80MHz and can be OCd to 160MHz :). Also has more RAM than arduio I believe. This should be more than possible as far as I can tell (depending on what you are then doing with the tiles once you have their property bytes loaded in RAM...)

TomAskew:
Really interesting. This is where my knowledge of C drops right off. If there is a current position variable that is holding the current position, how would you use that variable to point to the correct array?

Cheers!

Well seeming as the entire 10 by 10 grid can be stored in a byte…

A byte = 2 nibbles.

[0000] and [0000]

So x = [0000] y = [0000]

Say (6,8), [0110][1000] = a byte.

You can XOR and shift bytes and whatever to get the bits you need…

For example…the above is:

byte current_location = 01101000 //(6,8)

get_x_coord = current_location >> 4 //Just shift the bits 4 to the right to have the value of 0110 = 6
get_y_corod = current_location << 4 >> 4 // Shift left 4 to knock the highest bits out then shift back = 1000 = 8

the y one can be done with XOR or some addition/subtraction or something but I have had about 4 pints too much to think right now!

You have helped a lot, thanks! The idea of the array and the values inside relating to the coords is fantastic, thanks! (I understand what you mean since you edited in the pics)

PS I have realised I have cocked my binary counting up…but the method is there :P.

You can encode a co-ordinate like this where x,y = [0000][0000] = 1 byte of 2 nibbles…one nibble is x and one is y.

new_co-ordinates = (x << 4) + y

so say it was a new co-ordinate of 9,3…

using the above…

x = 9 = 1001
y = 3 = 0011

the “empty” variable new_co-ordinates currently contains “0000 0000”
So we firstly add x (1001) to it…

new_co-ordinates = 0000 1001

then we shift it 4 bits left…

new_co-ordinates = 1001 0000

then we just add y (0011)

new_co-ordinates = 1001 0011

Sorry to go on. Pint 5.

But then you can make functions to do the vector calculations to adjust the “current co-ordinates”.

If you want to add 1 to the x co-ordinate and 1 to the y…, it would simply be:

current_co-ordinate = current_co-ordinate + (change_in_x << 4) + change_in_y;

Using an example of say where current = (6,3) = [0110][0011] = B 0110 0011

If we want to go North East (add one to x and y)…then…

current + (change_in_x << 4) + change_in_y

current + (00000001 << 4) + 00000001

current + 0001000 + 00000001 = current + 0001001

current =[0111][0100]

= (7,4)

Johnny010:
Sorry to go on. Pint 5.

But then you can make functions to do the vector calculations to adjust the “current co-ordinates”.

If you want to add 1 to the x co-ordinate and 1 to the y…, it would simply be:

current_co-ordinate = current_co-ordinate + (change_in_x << 4) + change_in_y;

Using an example of say where current = (6,3) = [0110][0011] = B 0110 0011

If we want to go North East (add one to x and y)…then…

current + (change_in_x << 4) + change_in_y

current + (00000001 << 4) + 00000001

current + 0001000 + 00000001 = current + 0001001

current =[0111][0100]

= (7,4)

Thanks!

I was thinking that if I did a 100*100 map with a 10000 long array I could use a full byte for x pos and y pos. You have given me enough to get started but I will most certainly be back with my errors.

In the 10000 array each position would ideally be one hex or 16 bits. How would you implement this type of array?

byte map = {0x4, 0x1, 0xF,…

Like that?

Thanks a lot

Get those pints in!!

What is the advantage of keeping all the coordinates in an array?

Your program really only needs to know the player's position and any object's position if it's within 5 spaces. I imagine it will draw the player in the center and then objects relative to it.

If you use an unsigned int, this will allow a full grid of 256x256 (0,0)->(255,255) where 0,0 is the bottom left square.

Example:

Co-ordinate 78,255 = (78,255) = [1001110][11111111]

The maximum number of tiles is the size of an int... 2^16 = 65536 256*256 = 65536

Do you really need a 16 bit value held in each "array slot"? How many "properties" for a tile are you wanting? If you just have 8 properties...then each index in the array of 65536 values need only hold 1 byte...

SamIAm93:
What is the advantage of keeping all the coordinates in an array?

Your program really only needs to know the player’s position and any object’s position if it’s within 5 spaces. I imagine it will draw the player in the center and then objects relative to it.

I assume so that prior changes are kept as a history is the player moves back to the squares…

But that position will still have the same coordinates. You already know the coordinates of each position, you need to keep a list of objects at each position.