# Accessing tiles in a tilemap

## Recommended Posts

coderWalker    127
I am having a hard time understanding how to access tiles in a 3d tile-map.

I have the tile map split into sections. Each section is 16x16x16 tiles.

In the game there is a 3d ptr array (section) that is 11x11x11;
Each of these positions contains a pointer to one of the sections.

So it's like this:

TileMap
-Sections
-Tiles

At the bottom I have some code I am currently using.

This routine to find the targeted tile is called hundreds to thousands of times per frame.
Meaning I think this code is a major slowdown in my game.

There has to be a faster way to access tiles in the map.
Has anyone tried implementing something like this?
Any ideas?

I know there has to be a faster-way.
I had an idea the other day, but have forgotten it.
Something with %16 ? Then using the Offset?

Is the current method the best possible or ridiculously slow?

Thanks
CoderWalker

[code]
/*
ChunkOffset is the amount of sections away from the center section the players on 5x5x5.
tmpChunk is the Section that the target tile is in.
tmpPoint is the position the tile is in that section.
*/

//Get full offset in blocks not chunks
x-=(xChunkOffset*16);
y-=(yChunkOffset*16);
z-=(zChunkOffset*16);
//Round to closest Block
tmpPoint.z=align(z);
tmpPoint.y=align(y);
tmpPoint.x=align(x);
//Get X Chunk
tmpOffset.x=0;
while (tmpPoint.x>=16)
{
tmpPoint.x-=16;
tmpOffset.x+=1;
}
while (tmpPoint.x<0)
{
tmpPoint.x+=16;
tmpOffset.x-=1;
}
//Get Y Chunk
tmpOffset.y=0;
while (tmpPoint.y>=16)
{
tmpPoint.y-=16;
tmpOffset.y+=1;
}
while (tmpPoint.y<0)
{
tmpPoint.y+=16;
tmpOffset.y-=1;
}
//Get Z Chunk
tmpOffset.z=0;
while (tmpPoint.z>=16)
{
tmpPoint.z-=16;
tmpOffset.z+=1;
}
while (tmpPoint.z<0)
{
tmpPoint.z+=16;
tmpOffset.z-=1;
}
//Apply the Offsets
tmpOffset.x+=HALFCLIPDIST;
tmpOffset.y+=HALFCLIPDIST;
tmpOffset.z+=HALFCLIPDIST;
[/code]

##### Share on other sites
JTippetts    12970
For some reason, I highly doubt this is the main cause of your slowdown. Have you profiled yet, or are you just making random guesses?

##### Share on other sites
[b]Note:[/b] I may be misunderstanding what you are saying. It sounds like you want to get an element (a tile) out of a 3 dimensional array, and your X,Y,Z relative to the center of the array (That is, the position 0,0,0 is in the center of the array in every dimension).

This is easy enough to do, once you realize that even though you are [i]pretending[/i] it's a 3D array, the computer's memory isn't 3D, nor is it 2D, it's only 1D, and so your 3D array is actually [b]only a 1D array[/b]. So let's treat it like one. [img]http://public.gamedev.net/public/style_emoticons/default/smile.gif[/img]

Let's simplify this first, by doing it one dimension at a time. If you have a tile array, called oneDimensionalArray, and you want to get the tile 'x' out of it, you do it like this:
[b]oneDimensionalArray[ x ][/b]
Easy!

For two dimensions, we need to also take into account the width of the array, because the array [b]is not[/b] stored like this:
[img]http://img838.imageshack.us/img838/6831/pic0x.png[/img]

It's actually stored like this: (spaces between rows added for easier reading - in actual memory, there are no gaps between the rows)
[img]http://img40.imageshack.us/img40/9077/pic1jx.png[/img]

So to access the two dimensional array, all we really need to do is still use the same method as before ( [b]oneDimensionalArray[ x ][/b] ), but offset it by the width of the array multiplied by the row we want to access.
[b]twoDimensionalArray[ (y * width) + x ][/b]

For example, to access the third row (y = 2 since it starts at 0), and the 3rd column, we get [b]twoDimensionalArray[ (1 * width) + 2 ][/b], which gets us:
[img]http://img812.imageshack.us/img812/6787/pic2o.png[/img]

[hr]

So let's move on to the third dimension.
For the first dimension when we use 'X', think of this as [b]X times the size of the cell[/b], which in your case, each cell is 1, so we just exclude that multiplication.

First dimension, to get the cell: [b]X times size of Cell[/b]
Second dimension, to get the row: [b]Y times size of Row[/b]
Third dimension, to get the layer: [b]Z times size of Layer[/b]

So we have:
[b]threeDimensionalArray[ (z * width * height) + (y * width) + x ][/b]

Or to simplify through additional variables:
[b]threeDimensionalArray[ (Layer * LayerSize) + (Row * RowSize) + (Cell * CellSize)][/b]

Where the variables are:
Layer = Z, Row = Y, and Cell = X
LayerSize = Width * Height
RowSize = Width
CellSize = 1

And since we can omit the cell size (since X times 1 is still X):
[b]threeDimensionalArray[ (Layer * LayerSize) + (Row * RowSize) + Cell][/b]

This scales up to however many dimensions you want, whether it be three dimensions or three hundred.

[hr]

Since you start at the center of the array, you can just resolve the actual position before getting the index of the array:

[code]Tile &GetTile(int x, int y, int z)
{
//Convert the position from the center of the map to the upperleft corner, like it's stored in memory.
int realX = (MapWidth / 2) + x;
int realY = (MapHeight / 2) + x;
int realZ = (MapDepth / 2) + x;

int tileIndex = (realZ * MapWidth * MapHeight) + (realY * MapWidth) + realX;
return map[ tileIndex ];
}[/code]

[hr]

[b]Note:[/b] For the formulas I showed you to work, DO NOT have C++ create a Three-Dimensional array. Have C++ create a One-Dimensional array, and treat it like a 3D one. Because C++ might think the data is being stored one way (for example, row first and then column) and you might think it's being stored another way (for example,. column first and then row).

[b]Don't do this:[/b]
MyArray = new Tile[Depth] [Height] [Width];

[b]Do this:[/b]
MyArray = new Tile[ (Width * Height * Depth) ];

[hr]

Ofcourse, when you are [i]looping over the entire array[/i] you don't want to waste time with the function call overhead, for every iteration of the loop, so for actual looping, you do it all in one run:

[code]//The outer loops go: z, y, x, instead of x, y, z, because I prefer the game to loop over
//the tiles in the same order that I mentally think of the tiles. If you take a moment
//and think about the difference between the inner loop being 'x', you'll see what I mean.
for(int z = 0; z < MapDepth; z++)
{
for(int y = 0; y < MapHeight; y++)
{
for(int x = 0; x < MapWidth; x++)
{
int tileIndex = (z * MapWidth * MapHeight) + (y * MapWidth) + x;

Tile &tile = map[ tileIndex ];

tile.Draw(...);
}
}
}[/code]

This can even be further optimized by avoiding the resolving of the index of the array on every loop (all the multiplications), by doing pointer arithmetic. But we don't need to do that, because now I'll tell you an even cooler secret: Remember that our array is actually just a 1-dimensional array [i]pretending[/i] to be a 3-dimensional array? Well, for hard loops, we can just treat it like a one-dimensional array. Observe:

[code]int TotalSize = (MapDepth * MapHeight * MapWidth);

for(int index = 0; index < TotalSize; index++)
{
Tile &tile = map[ index ];

tile.Draw(...);
}[/code]

Because after all, it [i]is[/i] just an array, [img]http://public.gamedev.net/public/style_emoticons/default/wink.gif[/img]

##### Share on other sites
coderWalker    127
Servant of the Lord, thanks for all the information! That explains alot and helps alot to speed things up with the individual array access.

However the main concern is how to access the elements when thier spead across multiple arrays.

I must split the map and use pointers because it would take to long to shift an array that contains (16^3*25^3) tiles.

I'll try to explain better, lets work with just a 2d tile map this time.

Refer to the image attached.
[attachment=2402:grid.png]

Each of the Black squares is a section of the map.
Each of the Orange squares is a tile in the map.

Basically the map is split into sections.
I have pointers to each of the sections and 16x16 arrays inside of each of them.

What would be the easist way to access each of the tiles in the arrays.
I need to access them to change them, instead of just read them.

Right now I am using offsets from the center of the map to move to other positions,
however this can be dropped if [i]Absolute positions[/i] would be faster[i] [/i]than [i]absolute positions.[/i]

##### Share on other sites
You can use relative or absolute positions, it doesn't matter what - just use whichever is easier for you. Just convert it to absolute positions when you need to access the tiles.

Your problem is the same as what I mentioned above, with one minor difference: You have (logically) two separate 3D arrays: The [size="2"][color="#1c2837"][b]SectionArray [/b]that holds pointers to each section, and each section has a [b]TileArray [/b]that holds pointers to each Tile. [/color][/size]It's the same concept, just apply it twice.

To draw every tile, or whatever you are doing, go like this: (for when you need to loop over every section or tile - much faster)
[code]int TotalMapSize = (NumSectionsDeep * NumSectionsHigh * NumSectionsWide);

int TotalSectionSize = (NumTilesDeep * NumTilesHigh * NumTilesWide);

for(int section = 0; section < TotalMapSize; section++)
{
Section *section = SectionArray[ section ];

//WARNING: I'm assuming that your 'section' is not NULL, or your program will crash.

for(int tile = 0; tile < TotalSectionSize; tile++)
{
Tile *tile = section->TileArray[ tile ];

tile.Draw(...);
}
}[/code]

Or like this: (For getting a single section or tile when you need it, much more precise)
[code]Section *GetSection(int x, int y, int z)
{
//WARNING: I'm assuming that your 'x', 'y', and 'z' are not out of bounds, or your program will crash.
//They should be between negative '(NumSectionsWide / 2)' and positive '(NumSectionsWide / 2)'.

int realX = (NumSectionsWide / 2) + x;
int realY = (NumSectionsHigh / 2) + y;
int realZ = (NumSectionsDeep / 2) + z;

int tileIndex = (realZ * NumSectionsWide * NumSectionsHigh) + (realY * NumSectionsWide) + realX;
return SectionArray[ tileIndex ];
}

Tile &GetTileFromSection(Section *section, int x, int y, int z)
{
int realX = (NumTilesWide / 2) + x;
int realY = (NumTilesHigh / 2) + y;
int realZ = (NumTilesDeep / 2) + z;

int tileIndex = (realZ * NumTilesWide * NumTilesHigh) + (realY * NumTilesWide) + realX;
return section->TileArray[ tileIndex ];
}[/code]

##### Share on other sites
coderWalker    127
The only problem is I still have to use the slow code above to figure out which Chunk and what Tile.
Wait, does your code do that?

Basically I want a get tile function that basically returns a pointer to that specific tile.
ex:
tile* get_tile(int x, int y, int z);

call to:
get_tile(40,20,15)

would return:
Section[2][1][0]->tile[8][4][15];

just how to calculate these positions?

Also, even just calculating a tile position takes a lot of math.
Would there be a faster-way of doing this? ( I mean anything faster, even totally diffrent)

*just using 3d arrays in the example to simplify the pseudo code.

This is the code I'm trying to replace:
[code]
/*
ChunkOffset is the amount of sections away from the center section the players on 5x5x5.
tmpChunk is the Section that the target tile is in.
tmpPoint is the position the tile is in that section.
*/

//Get full offset in blocks not chunks
x-=(xChunkOffset*16);
y-=(yChunkOffset*16);
z-=(zChunkOffset*16);
//Round to closest Block
tmpPoint.z=align(z);
tmpPoint.y=align(y);
tmpPoint.x=align(x);
//Get X Chunk
tmpOffset.x=0;
while (tmpPoint.x>=16)
{
tmpPoint.x-=16;
tmpOffset.x+=1;
}
while (tmpPoint.x<0)
{
tmpPoint.x+=16;
tmpOffset.x-=1;
}
//Get Y Chunk
tmpOffset.y=0;
while (tmpPoint.y>=16)
{
tmpPoint.y-=16;
tmpOffset.y+=1;
}
while (tmpPoint.y<0)
{
tmpPoint.y+=16;
tmpOffset.y-=1;
}
//Get Z Chunk
tmpOffset.z=0;
while (tmpPoint.z>=16)
{
tmpPoint.z-=16;
tmpOffset.z+=1;
}
while (tmpPoint.z<0)
{
tmpPoint.z+=16;
tmpOffset.z-=1;
}
//Apply the Offsets
tmpOffset.x+=HALFCLIPDIST;
tmpOffset.y+=HALFCLIPDIST;
tmpOffset.z+=HALFCLIPDIST;
[/code]

##### Share on other sites
[quote name='coderWalker' timestamp='1306106040' post='4814373']
The only problem is I still have to use the slow code above to figure out which Chunk and what Tile.
Wait, does your code do that?[/quote]
No it doesn't, but it's easy for you to adapt, if you put in the effort. [img]http://public.gamedev.net/public/style_emoticons/default/smile.gif[/img]

[quote]Basically I want a get tile function that basically returns a pointer to that specific tile.
ex:
tile* get_tile(int x, int y, int z);[/quote]

If you're calling 'get_tile()' many times in a for() loop, you need to be accessing the array directly instead of calling 'get_tile()'. If you're calling 'get_tile()' for every tile in the map or even just one section, you're doing it wrong, and it will go ridiculously slow.

[quote]Section[2][1][0]->tile[8][4][15];[/quote]
Don't use the myArray[x][y][z] format of array access. Treat it as a single array, like I've explained above. It's easier to work with.

[quote]just how to calculate these positions?[/quote]

[code]int sectionX = (originalX / 16);
int sectionY = (originalY / 16);
int sectionZ = (originalZ / 16);

int tileX = (originalX % 16);
int tileY = (originalY % 16);
int tileZ = (originalZ % 16);[/code]
Do you understand how modulus works? If not, now's a good time to learn!
[b]Don't[/b] just copy and use my code, but [b][i]learn how it works[/i][/b]. [img]http://public.gamedev.net/public/style_emoticons/default/smile.gif[/img]

If the above code is still too slow for you, then it's because you are calling [b]get_tile()[/b] too many times, and you need to access the array directly and properly as I've explained in previous posts. If you still don't understand (after making an honest and actual attempt to figure it out based on the information I already posted), then you need to post [b]how[/b] you are planning on using the code, and not just what you expect the code to do.

##### Share on other sites
coderWalker    127
I totally understand how this works.

However when I replaced the following with the new version the game starts thowing errors.
Showing a tile is a certain one when it's not, etc.

The question is why?
I thought they would return the same results?

[code]
//Get X Chunk
tmpOffset.x=0;
while (tmpPoint.x>=16)
{
tmpPoint.x-=16;
tmpOffset.x+=1;
}
while (tmpPoint.x<0)
{
tmpPoint.x+=16;
tmpOffset.x-=1;
}
//Get Y Chunk
tmpOffset.y=0;
while (tmpPoint.y>=16)
{
tmpPoint.y-=16;
tmpOffset.y+=1;
}
while (tmpPoint.y<0)
{
tmpPoint.y+=16;
tmpOffset.y-=1;
}
//Get Z Chunk
tmpOffset.z=0;
while (tmpPoint.z>=16)
{
tmpPoint.z-=16;
tmpOffset.z+=1;
}
while (tmpPoint.z<0)
{
tmpPoint.z+=16;
tmpOffset.z-=1;
}

[/code]

[code]
int sectionX = (originalX / 16);
int sectionY = (originalY / 16);
int sectionZ = (originalZ / 16);

int tileX = (originalX % 16);
int tileY = (originalY % 16);
int tileZ = (originalZ % 16);
[/code]

##### Share on other sites
[quote name='coderWalker' timestamp='1306111155' post='4814390']
I totally understand how this works:
[code]
int sectionX = (originalX / 16);
int sectionY = (originalY / 16);
int sectionZ = (originalZ / 16);

int tileX = (originalX % 16);
int tileY = (originalY % 16);
int tileZ = (originalZ % 16);
[/code]

However I implemented this and it's giving incorrect answers?
Is something in this math incorrect?
[/quote]

Well, have you debugged it to find out under what circumstances it gives incorrect answers?
What have you done to problem-solve this problem? [img]http://public.gamedev.net/public/style_emoticons/default/mellow.gif[/img]

Which numbers give you the wrong results, and what results are you expecting?

Two hints: The modulus and divide operators aren't broken. Neither is your compiler.
This means either I made a mistake in the math (which is possible) or you made a mistake implementing it (also possible), or there's some circumstance that we're overlooking or not thinking through (like what happens when 'originalX' is 0).

So the question is, what are you doing to isolate the problem? Programming is not about knowing the right information to type in to the computer, programming is about problem-solving when that information wasn't as right as originally thought.

Since I'm not the one trying to run your program, I can't answer the question "[i]Is something in this math incorrect?[/i]". [b]You [/b]have to tell [b]me [/b]that. [img]http://public.gamedev.net/public/style_emoticons/default/wink.gif[/img]

##### Share on other sites
coderWalker    127
[quote name='Servant of the Lord' timestamp='1306112206' post='4814396']
Since I'm not the one trying to run your program, I can't answer the question "[i]Is something in this math incorrect?[/i]". [b]You [/b]have to tell [b]me [/b]that. [img]http://public.gamedev.net/public/style_emoticons/default/wink.gif[/img]
[/quote]

Man thanks again for all that info, also the inspiration.

I honestly could not see the problem earlier.
So i decided to run a test and compare all the variables because there seemed to be no correlation , however there is.

Remember the [color="#0000FF"]first [/color]number the chunk Offset is where the chunk is relative to the center chunk so can be negative or positive.
Then the [color="#0000FF"]second [/color]number is the position in the array in that chunk so has to be from 0 to 15.
[b]Below [/b]why I am getting the wrong answers becomes very apparent.
*Scroll down to see it

Its shown with The [b]Relative [/b]Chunk , pos in the array with the new and old methods numbers.

Now a huge decision,
Rewrite the entire engine... again to make everything reletive to chunk 0,0 removeing negatives.
or Find a way to get the correct results here, without adding more computing time.

The only Perfect solution I see is,
[b]**EDIT[/b]: This routine is not always Correct!!! -16, -32 are wrong now
After performing the routine:
[code]
if (x<0)
{
Chunk-=1;
Tile+=16;
if (y<0)
{
Chunk-=1;
Tile+=16;
if (z<0)
{
Chunk-=1;
Tile+=16;
[/code]
however this would [b]slow [/b]it down and I don't want to turn to this.
[b]
Analysis Results:[/b]
[code]
world0->setPos Analysis:
----------------------------------
number Old New
X: -32 SAME
X: -31 -2 , 1 -1 , -15
X: -30 -2 , 2 -1 , -14
X: -29 -2 , 3 -1 , -13
X: -28 -2 , 4 -1 , -12
X: -27 -2 , 5 -1 , -11
X: -26 -2 , 6 -1 , -10
X: -25 -2 , 7 -1 , -9
X: -24 -2 , 8 -1 , -8
X: -23 -2 , 9 -1 , -7
X: -22 -2 , 10 -1 , -6
X: -21 -2 , 11 -1 , -5
X: -20 -2 , 12 -1 , -4
X: -19 -2 , 13 -1 , -3
X: -18 -2 , 14 -1 , -2
X: -17 -2 , 15 -1 , -1
X: -16 SAME
X: -15 -1 , 1 0 , -15
X: -14 -1 , 2 0 , -14
X: -13 -1 , 3 0 , -13
X: -12 -1 , 4 0 , -12
X: -11 -1 , 5 0 , -11
X: -10 -1 , 6 0 , -10
X: -9 -1 , 7 0 , -9
X: -8 -1 , 8 0 , -8
X: -7 -1 , 9 0 , -7
X: -6 -1 , 10 0 , -6
X: -5 -1 , 11 0 , -5
X: -4 -1 , 12 0 , -4
X: -3 -1 , 13 0 , -3
X: -2 -1 , 14 0 , -2
X: -1 -1 , 15 0 , -1
X: 0 SAME
X: 1 SAME
X: 2 SAME
X: 3 SAME
X: 4 SAME
X: 5 SAME
X: 6 SAME
X: 7 SAME
X: 8 SAME
X: 9 SAME
X: 10 SAME
X: 11 SAME
X: 12 SAME
X: 13 SAME
X: 14 SAME
X: 15 SAME
X: 16 SAME
X: 17 SAME
X: 18 SAME
X: 19 SAME
X: 20 SAME
X: 21 SAME
X: 22 SAME
X: 23 SAME
X: 24 SAME
X: 25 SAME
X: 26 SAME
X: 27 SAME
X: 28 SAME
X: 29 SAME
X: 30 SAME
X: 31 SAME
X: 32 SAME
[/code]

Again thanks for all the help and explanations!
We should build a tutorial using all this, not sure what it would be specifically about though.

##### Share on other sites
Trienco    2555
Those results aren't really surprising when you're using % instead of /.

edit: Unless of course the column labels are in the wrong place and it simply means you're not handling negative numbers correctly.

##### Share on other sites
[quote name='coderWalker' timestamp='1306120567' post='4814434']
however this would [b]slow [/b]it down and I don't want to turn to this.[/quote]
Anything you do will slow down something. The question is whether it is [i]too [/i]slow.

How many times are you calling it, and why?
What are you calling it for? How are you calling it?

##### Share on other sites
JTippetts    12970
[quote name='Servant of the Lord' timestamp='1306125823' post='4814454']
[quote name='coderWalker' timestamp='1306120567' post='4814434']
however this would [b]slow [/b]it down and I don't want to turn to this.[/quote]
Anything you do will slow down something. The question is whether it is [i]too [/i]slow.

How many times are you calling it, and why?
What are you calling it for? How are you calling it?
[/quote]

This.

Seriously, unless you profile to know for sure, there is a very real chance that you are merely wasting your time and disrupting your code for something that might not make a difference.

##### Share on other sites
kdmiller3    178
Important safety tip: the [url="http://en.wikipedia.org/wiki/Modulo_operation"]modulo operator[/url] in C and C++ (%) returns a negative value for a negative dividend.

Since you're using power-of-two sizes, you can use bitwise operations instead:
[list][*](x / 16) becomes (x >> 4), though the compiler most likely performs that optimization on its own[*](x % 16) becomes (x & 15), without the aggravation of dealing with negative values[/list]

##### Share on other sites
coderWalker    127
[quote]
Seriously, unless you profile to know for sure, there is a very real chance that you are merely wasting your time and disrupting your code for something that might not make a difference.
[/quote]

This is called a large amount of times per frame.
So any speedup in this code would definitely help.

Do you mean use a Code Profiler?

I am making a game where every tile is an element and reacts with other elements, so this is largely contributing to the speed of the game.

Basically I am about to rewrite how the engine accesses the tiles with this % algorithm opposed to the while statements which is thousands of lines with hundreds needing changing.

Is there a faster routine to access the tiles then this?
I need to decide now, to prevent me from having to rewrite it again.

##### Share on other sites
[quote name='coderWalker' timestamp='1306184787' post='4814750']
This is called a large amount of times per frame.
So any speedup in this code would definitely help.[/quote]
Most of the time the fastest speedups are not optimizing one piece of code, but rethinking on a larger scale why and how you use that code.

[quote]I am making a game where every tile is an element and reacts with other elements[/quote]
Does every tile really need to react every frame? I seriously doubt it. Why can't each element react once a second, with the elements' updating being spread out over that second? That'll instantly be about 30 times faster.

Example: (pretending your game only runs at 10 frames a second, and that you only need to update 1000 tiles)
[b]Frame 1: [/b]Tiles 1 through 100 update and react.
[b]Frame 2: [/b]Tiles 101 through 200 update and react.
[b]Frame 3: [/b]Tiles 201 through 300 update and react.
[b]Frame 4: [/b]Tiles 301 through 400 update and react.
[b]Frame 5: [/b]Tiles 401 through 500 update and react.
[b]Frame 6: [/b]Tiles 501 through 600 update and react.
[b]Frame 7: [/b]Tiles 601 through 700 update and react.
[b]Frame 8: [/b]Tiles 701 through 800 update and react.
[b]Frame 9: [/b]Tiles 801 through 900 update and react.

[b]Frame 10: [/b]Tiles 901 through 1000 update and react.

[b]Frame 11: [/b]Tiles 1 through 100 update and react.

This is just one quick thought that pops into my mind, there are many many more ways you can resolve your problem. Optimizing that one piece of code only saves minuscule amounts of time. Optimizing things on a larger scale saves larger chunks of time. Think outside the function - how can the process of each frame as a whole be faster?

[quote]Basically I am about to rewrite how the engine accesses the tiles with this % algorithm opposed to the while statements which is thousands of lines with hundreds needing changing.[/quote]
Never do the same thing in more than one or two spots. Make it so you do it once, and re-use that code in a function or class. Don't copy and paste the code a hundred times; just use the function a hundred times. You can then change the inside of the function all you want without having to rewrite the areas that use the function.

[quote]I need to decide now, to prevent me from having to rewrite it again.[/quote]
What you ought to do is write it in a way that changing one area does not force you to change 100 other areas.

##### Share on other sites
coderWalker    127
[quote]Does every tile really need to react every frame?[/quote]
No. When a tile is modified I add that and the 6 touching tiles to a "Watch List".
Then when updating it just goes threw the list.
So basically lets say you light wood on fire.
The wood and fire would be added.
When updating 1 frame would just change the wood to fire and add an adjacent wood.
And would repeat until stops reacting.
Thats the best method I can think of, know of a better one?

[quote]
[b]Frame 1: [/b]Tiles 1 through 100 update and react.
[b]Frame 2: [/b]Tiles 101 through 200 update and react.
[b]Frame 3: [/b]Tiles 201 through 300 update and react.
[b]Frame 4: [/b]Tiles 301 through 400 update and react.
[b]Frame 5: [/b]Tiles 401 through 500 update and react.
[b]Frame 6: [/b]Tiles 501 through 600 update and react.
[b]Frame 7: [/b]Tiles 601 through 700 update and react.
[b]Frame 8: [/b]Tiles 701 through 800 update and react.
[b]Frame 9: [/b]Tiles 801 through 900 update and react.
[/quote]
I have considered this, but wont this make it look like scanlines going across the multiple chunks?
I mean if a wood path is going back and forth between chunks when burning then one chunk may be behind

Again thanks! All of this is making me have new ideas of how it should work to be optimal!

##### Share on other sites
I use the speed trick Servant suggested in batching updates across multiple frames for my NPCs AI and it works really great. Basically I separated the functions into periodic and constant AI. Constant = Needs to update on every frame such as movement, animation and sensory input. Periodic = Goal and Need driven AI and Pathfinding. I've read if from the book AI Game Programming Wisdom. If you didn't know it, you would think that I update the AI on every frame but I only update 20 NPCs per frame and i have a couple of hundreds of them. But then again, it largely depends on how often you really need to update.