PDA

View Full Version : Radial patterns in arrays



Whitt
10-04-2008, 08:21 AM
System: Windows XP, P4 2 GHz
Compiler/IDE: Delphi 7 for Win32
API: N/A
-----


Hi,

Been programming for a while during college and then got back into it recently. I'm a stuck trying to place a radial pattern in the centre of a array.

This is what I have so far
__
for l1:=1 to midpoint do

for l2:=1 to midpoint do
begin

cityd[midpoint+l1,midpoint-l2]:=(midpoint-l1);
cityd[midpoint-l1,midpoint+l2]:=(midpoint-l1);

cityd[midpoint+l1,midpoint+l2]:=(midpoint-l1);
cityd[midpoint-l1,midpoint-l2]:=(midpoint-l1);

cityd[midpoint+l1,midpoint]:=(midpoint-l1);
cityd[midpoint-l1,midpoint]:=(midpoint-l1);

cityd[midpoint,midpoint+l2]:=(midpoint-l1);
cityd[midpoint,midpoint-l2]:=(midpoint-l1);

end;

where cityd is a 2D array of dimensions 200,200
____
While this sort of works it give the highest values in the centre in a single column not a square of higher values expanding out to smaller values... I think the problem is how I am addressing the values in the code but I can't think of a way to address the values from the centre outwards that doesn't causes problems the further you move from the centre.

Model

1230321
1230321
1230321
1230321

Desired result

111111
122221
123321
122221
111111

The idea for this is to create levels for myself without adding thousands of buildings.... I know this is not as straght forward as I first thought after reading this post http://www.pascalgamedevelopment.com/viewtopic.php?t=4936.
I'm not looking to creating fractual cities as Im not that good a programmer, but If I can figure this out it would go a long way.

Any help would be most appreciated!

Whitt

jasonf
10-04-2008, 09:40 AM
sounds to me like you need an list of city blocks.
These would be cells, each cell has a link to the 8 cells around it as well as references to any models in that cell.

You'd be able to choose any of the cells and only render the models etc that can be seen from that cell and it's neighbors.

So in your situation, you have a 8x8 grid of cells. from 0 - 7

if you were to pick on cell 3x3 = cell #27 (3 * 8)+3


[18][19][20]
[26] [28]
[34][35][36]

and Cell 4x3 would be


[19][20][21]
[27] [29]
[35][36][37]

So you render your current cell and then any neighbors which haven't already been rendered using a recursive algorithm.

Using this mechanism, you can have extremely large maps, streamed off a disk or even an online source. Loading and unloading cells as needed because each cell knows what it's neighbors are, you don't have to keep all locations loaded in memory, you can get them when they're needed.

User137
10-04-2008, 01:34 PM
If i understood right, you would still need the entire map array to hold info wether or not it is part of a cell group, in this case 200x200 so we would be right where we started? :) With addition of more memory used.

Edit: To original question, i don't quite understand the midpoint variable and how do you want to convert a 7x4 grid to a 6x5? The function has to support skipping of numbers or?

jasonf
10-04-2008, 04:18 PM
Have you ever played dungeon siege?

The had a system of linking tiles (cells) together and getting cells from disk as they were needed. this allowed for a truly massive continuous landscape with no loading screens. In fact, after I beat the game, I then walked all the way back to the farm at the beginning (took me ages).. hoping to find an easter egg there..alas, there was none.

All you need is a starting cell. Pass that to your engine and it will get what it needs. As cells are no longer needed, they are unloaded. Sure, you need some process to load each cell from a file, and that file (or files) need to be arranged or named in such a way to facilitate dynamic loading of individual cells, but that's no problem. Certainly no need to load an array at the start.

Whitt
10-04-2008, 07:07 PM
Thanks for the help, but I'm not sure you understood what I wanted to do, that or its more complicated to do than I first thought.

Forgetting the ultimate aim of the game, all I'm trying to do is create a function which will place higher values in the centre of a 2D array which decrease outwards like a circle to 0. Is there a simple elegant way of doing this?
The idea I had on the way back from work was that as it looks at each cell in turn it applies a formula which is dependant on the distance from the centre which means that the values will be lower at the edges and higher in the center.

I've been trying to think this through for days but the ideas are helping!

Whitt

waran
10-04-2008, 08:13 PM
Your distance-idea is pretty good. Just use it.


const
min = -5;
max = 5;
var
map: array [min..max] of array [min..max] of byte;
x, y: integer;
maxz: byte = 0; // used to invert your circle;
begin
for x := min to max do
for y := min to max do
begin
map[x,y] := round(sqrt(x*x+y*y));
if map[x,y] > maxz then maxz := map[x,y];
end;

// print the map
for y := min to max do
begin
for x := min to max do write(maxz-map[x,y], ' ');
writeln;
end;

readln;
end.

Output:

0 1 1 2 2 2 2 2 1 1 0
1 1 2 3 3 3 3 3 2 1 1
1 2 3 3 4 4 4 3 3 2 1
2 3 3 4 5 5 5 4 3 3 2
2 3 4 5 6 6 6 5 4 3 2
2 3 4 5 6 7 6 5 4 3 2
2 3 4 5 6 6 6 5 4 3 2
2 3 3 4 5 5 5 4 3 3 2
1 2 3 3 4 4 4 3 3 2 1
1 1 2 3 3 3 3 3 2 1 1
0 1 1 2 2 2 2 2 1 1 0


Improvement:
You can also use the (float) distance as x for some fall-off function;
imagine the possibilites :)

User137
10-04-2008, 09:29 PM
Or if sphere is not what you need, square like distance between 2 points (where other could be map center) would go something like this

function SquareDist(p1x,p1y,p2x,p2y: integer): integer;
var dx,dy: integer;
begin
dx:=abs(p2x-p1x);
dy:=abs(p2y-p1y);
if dx>dy then result:=dx
else result:=dy;
end;

Using this (should) result a

2 2 2 2 2
2 1 1 1 2
2 1 0 1 2
2 1 1 1 2
2 2 2 2 2

To have it inverted, just decrease result from highest value
(ie. final = 100-result for a 200x200 map)

Whitt
10-04-2008, 09:37 PM
Thanks!

Perfect simple solutions...I knew there was one as I understood the logic just couldnt put it into code.

Whitt