Quote: "Yeah friend !! I thought that it ends around Australia .
Nice terraing...you use your own perling noise to generate the terrain. You could apply the same to an Advanced terrain as matrix use to slow down PCs, but good work .
Cheers."
Thanks ^^
The algorithm is roughly based on the diamond-square algorithm, with some small modifications.
As far as making it faster on slow computers, I also made a memblock version, that generates the terrain in almost the same way. It's a lot faster but I couldn't get it into 20 lines if I tried :p
I'm going to quickly modify it(the code posted above) to export to a bitmap and see what it looks like
edit:
export_bitmap function:
/////////add this after the generate_terrain function is called:
global size = 10
global chunk_size = 64
export_bitmap("test.bmp")
///////////add this at the bottom:
function export_bitmap(file_name$)
sync off
s = size*chunk_size
create bitmap 1,s,s
set current bitmap 1
lock pixels
dim bitmap(s,s)
//moves the heights of the matrices into a single array
for x = 1 to chunk_size : for z = 1 to chunk_size
bitmap(x,z) = get matrix height (matrix_no(1,1),x,z)
next z : next x
for n = 2 to size : for x = 1 to chunk_size : for z = 1 to chunk_size
bitmap(x,((n-1)*chunk_size)+z) = get matrix height (matrix_no(1,n),x,z)
next z : next x : next n
for n = 2 to size : for x = 1 to chunk_size : for z = 1 to chunk_size
bitmap(((n-1)*chunk_size)+x,z) = get matrix height (matrix_no(n,1),x,z)
next z : next x : next n
for m = 2 to size : for n = 2 to size : for x = 1 to chunk_size : for z = 1 to chunk_size
bitmap(((m-1)*chunk_size)+x,((n-1)*chunk_size)+z) = get matrix height (matrix_no(m,n),x,z)
next z : next x : next n : next m
//finds the maximum and minimum height from this array
max_hight = -1000
min_height = 1000
for x = 1 to s : for z = 1 to s
if bitmap(x,z) > max_height then max_height = bitmap(x,z)
if bitmap(x,z) < min_height then min_height = bitmap(x,z)
next z : next x
range = max_height-min_height
//makes all the values > 0
tmp = min_height*-1
for x = 1 to s : for z = 1 to s
bitmap(x,z) = bitmap(x,z) + tmp
next z : next x
k# = (range+tmp) / 255 //constant
for x = 1 to s : for z = 1 to s
c = bitmap(x,z)/k#
dot x,z,rgb(c,c,c)
next z : next x
unlock pixels
get image 1,1,1,s,s
save image file_name$,1
set current bitmap 0
delete bitmap 1
sync on
wait 2000
endfunction
The full, uncompressed code:
Rem Project: Simple Terrain
Rem Created: Wednesday, February 08, 2012
// Rem ***** Main Source File *****
sync on
sync rate 60
set display mode desktop width(),desktop height(),32
maximize window
position camera 0,50,0
make object cube 1,0.1
hide object 1
`used in the genorator, this is the starting number for the matrix numbers, but It is changed a lot within the function as well >.<
global matrix_ID = 0
`basic lighting, follows the camera
set ambient light 30
hide light 0
make light 1
position light 1,0,1000,0
set light range 1,3000
global size = 10
global chunk_size = 64
`This calls the generate world function
`generate_world(seed,size,scale,chunk_size,wireframe)
`seed = used for the randomize command
`size = the width+height of the world (in chunks)
`note: the actual size of the generated world = chunk_size
`scale = the scale of the features
`chunk_size = the ammount of x and y segments in each matrix(chunk). It must be a power of 2 (2^n)
`wireframe = turns wireframe on/off, 1 = on
generate_world(timer(),size,6,chunk_size,1)
`note: you might get errors if the scale is too high for the chunk_size
`the maximum is the power used for the chunk size (lg(chunk_size))
`note: you can add a texture to all the matrices at the bottom :P
export_bitmap("test.bmp")
```````````main loop``````````````
do
`basic flying movement
`- mouse = look around
`- wasd = move
`- shift = down
`- space = up
`look around
rotate camera camera angle x ()+MouseMoveY( )/2.5,camera angle y ()+MouseMoveX( )/2.5,camera angle z ()
rotate object 1,camera angle x (),camera angle y (),camera angle z ()
position mouse 0,0
`movement
if keystate (17)=1 then move object 1,2
if keystate (30)=1 then move object left 1,2
if keystate (31)=1 then move object 1,-2
if keystate (32)=1 then move object right 1,2
if keystate (57)=1 then move object up 1,2
if keystate (42)=1 then move object down 1,2
`moves camera
position camera object position x(1),object position y(1),object position z(1)
`moves the light to above the camera
position light 1,object position x(1),object position y(1)+1000,object position z(1)
sync
loop
``````````Functions`````````````
`generates the world
function generate_world(seed,size,scale,chunk_size,wireframe)
`based of the idia of the diamond-square algorithm, to an extent >.<
`It's not very optimised, but seems to work ok for me :s
randomize seed
`this array holds the matrix numbers for every chunk
dim matrix_no(size,size)
`calculates the first chunk :)`
make matrix matrix_ID + 1,chunk_size*10,chunk_size*10,chunk_size,chunk_size
matrix_ID = matrix_ID + 1
position matrix matrix_ID,0-(chunk_size*10*size)/2,-20,chunk_size*10*n-(chunk_size*10*size)/2
matrix_no(0,0) = matrix_ID
set matrix height matrix_ID,0,0,rnd(100)-50
s=scale
`generates the main point on the line z=0 for the first matrix
for x=2^s to chunk_size step 2^s
set matrix height matrix_id,x,0,get matrix height (matrix_id,x-2^s,0) + rnd((2^s)*10)-((2^s)*10)/2
next x
`generates the main point on theline y=0 for the first matrix
for y=2^s to chunk_size step 2^s
set matrix height matrix_id,0,y,get matrix height (matrix_id,0,y-2^s) + rnd((2^s)*10)-((2^s)*10)/2
next y
`generates the rest of the main points for the first matrix
for y = 2^s to chunk_size step 2^s
for x=2^s to chunk_size step 2^s
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x-2^s,y) + get matrix height (matrix_id,x,y-2^s))/2 + rnd((2^s)*10)-((2^s)*10)/2
next x
next y
`calculates the rest of the points based on the main points
for o = 1 to s
p=s-o+1
for y = 0 to chunk_size step 2^p
for x=2^p/2 to chunk_size step 2^p
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x-(2^p/2),y) + get matrix height (matrix_id,x+(2^p/2),y))/2 + rnd(2^p*2)-2^p
next x
next y
for y = 2^p/2 to chunk_size step 2^p
for x=0 to chunk_size step 2^p
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x,y-(2^p/2)) + get matrix height (matrix_id,x,y+(2^p/2)))/2 + rnd(2^p*2)-2^p
next x
next y
for y = 2^p/2 to chunk_size step 2^p
for x = 2^p/2 to chunk_size step 2^p
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x,y-(2^p/2)) + get matrix height (matrix_id,x,y+(2^p/2)) + get matrix height (matrix_id,x-(2^p/2),y) + get matrix height (matrix_id,x+(2^p/2),y))/4 + rnd(2^p*2)-2^p
next x
next y
next o
update matrix matrix_id
// `calculates all of the chunks on x=0
for n = 1 to size
make matrix matrix_ID + 1,chunk_size*10,chunk_size*10,chunk_size,chunk_size
matrix_ID = matrix_ID + 1
position matrix matrix_ID,0-(chunk_size*10*size)/2,-20,chunk_size*10*n-(chunk_size*10*size)/2
matrix_no(0,n) = matrix_ID
`takes row z=0 from above matrix
for x=0 to chunk_size
set matrix height matrix_id,x,0, get matrix height (matrix_no(0,n-1),x,chunk_size)
next x
`calculates row x=0
for y=2^s to chunk_size step 2^s
set matrix height matrix_id,0,y,get matrix height (matrix_id,0,y-(2^s)) + rnd(2^s*10)-(2^s*10)/2
next y
for y = 2^s to chunk_size step 2^s
for x=2^s to chunk_size step 2^s
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x-2^s,y) + get matrix height (matrix_id,x,y-2^s))/2 + rnd(2^s*10)-(2^s*10)/2
next x
next y
for o = 1 to s
p=s-o+1
for y = 2^p to chunk_size step 2^p
for x=2^p/2 to chunk_size step 2^p
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x-(2^p/2),y) + get matrix height (matrix_id,x+(2^p/2),y))/2 + rnd(2^p*2)-2^p
next x
next y
for y = 2^p/2 to chunk_size step 2^p
for x=0 to chunk_size step 2^p
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x,y-(2^p/2)) + get matrix height (matrix_id,x,y+(2^p/2)))/2 + rnd(2^p*2)-2^p
next x
next y
for y = 2^p/2 to chunk_size step 2^p
for x = 2^p/2 to chunk_size step 2^p
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x,y-(2^p/2)) + get matrix height (matrix_id,x,y+(2^p/2)) + get matrix height (matrix_id,x-(2^p/2),y) + get matrix height (matrix_id,x+(2^p/2),y))/4 + rnd(2^p*2)-2^p
next x
next y
next o
update matrix matrix_id
next n
````calculates all of the chunks on z=0
for m = 1 to size
make matrix matrix_ID + 1,chunk_size*10,chunk_size*10,chunk_size,chunk_size
matrix_ID = matrix_ID + 1
position matrix matrix_ID,chunk_size*10*m-(chunk_size*10*size)/2,-20,0-(chunk_size*10*size)/2
matrix_no(m,0) = matrix_ID
// `takes row x=0 from left matrix
for z=0 to chunk_size
set matrix height matrix_id,0,z, get matrix height (matrix_no(m-1,0),chunk_size,z)
next z
`calculates row z=0
for x=2^s to chunk_size step 2^s
set matrix height matrix_id,x,0,get matrix height (matrix_id,x-2^s,0) + rnd((2^s)*10)-((2^s)*10)/2
next x
for y = 2^s to chunk_size step 2^s
for x=2^s to chunk_size step 2^s
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x-2^s,y) + get matrix height (matrix_id,x,y-2^s))/2 + rnd((2^s)*10)-((2^s)*10)/2
next x
next y
for o = 1 to s
p=s-o+1
for y = 0 to chunk_size step 2^p
for x=2^p/2 to chunk_size step 2^p
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x-(2^p/2),y) + get matrix height (matrix_id,x+(2^p/2),y))/2 + rnd(2^p*2)-2^p
next x
next y
for y = 2^p/2 to chunk_size step 2^p
for x=2^p to chunk_size step 2^p
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x,y-(2^p/2)) + get matrix height (matrix_id,x,y+(2^p/2)))/2 + rnd(2^p*2)-2^p
next x
next y
for y = 2^p/2 to chunk_size step 2^p
for x = 2^p/2 to chunk_size step 2^p
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x,y-(2^p/2)) + get matrix height (matrix_id,x,y+(2^p/2)) + get matrix height (matrix_id,x-(2^p/2),y) + get matrix height (matrix_id,x+(2^p/2),y))/4 + rnd(2^p*2)-2^p
next x
next y
next o
update matrix matrix_id
next m
`generates the rest of the chunks
for m = 1 to size ` z co-ord
for n = 1 to size ` x co-ord
make matrix matrix_ID + 1,chunk_size*10,chunk_size*10,chunk_size,chunk_size
matrix_ID = matrix_ID + 1
position matrix matrix_ID,chunk_size*10*m-(chunk_size*10*size)/2,-20,chunk_size*10*n-(chunk_size*10*size)/2
matrix_no(m,n) = matrix_ID
`takes row z=0 from above matrix
for x=0 to chunk_size
set matrix height matrix_id,x,0, get matrix height (matrix_no(m,n-1),x,chunk_size)
next x
`takes row x=0 from left matrix
for z=0 to chunk_size
set matrix height matrix_id,0,z, get matrix height (matrix_no(m-1,n),chunk_size,z)
next z
for y = 2^s to chunk_size step 2^s
for x=2^s to chunk_size step 2^s
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x-2^s,y) + get matrix height (matrix_id,x,y-2^s))/2 + rnd((2^s)*10)-((2^s)*10)/2
next x
next y
for o = 1 to s
p=s-o+1
for y = 2^p to chunk_size step 2^p
for x=2^p/2 to chunk_size step 2^p
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x-(2^p/2),y) + get matrix height (matrix_id,x+(2^p/2),y))/2 + rnd(2^p*2)-2^p
next x
next y
for y = 2^p/2 to chunk_size step 2^p
for x=2^p to chunk_size step 2^p
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x,y-(2^p/2)) + get matrix height (matrix_id,x,y+(2^p/2)))/2 + rnd(2^p*2)-2^p
next x
next y
for y = 2^p/2 to chunk_size step 2^p
for x = 2^p/2 to chunk_size step 2^p
set matrix height matrix_id,x,y,(get matrix height (matrix_id,x,y-(2^p/2)) + get matrix height (matrix_id,x,y+(2^p/2)) + get matrix height (matrix_id,x-(2^p/2),y) + get matrix height (matrix_id,x+(2^p/2),y))/4 + rnd(2^p*2)-2^p
next x
next y
next o
update matrix matrix_id
next n
next m
if wireframe = 1
for j = 1 to matrix_id
set matrix wireframe on j
next j
else
for j = 1 to matrix_id
set matrix wireframe off j
`if you want to texture the all the matrices, it's easyer to do it here ^-^
next j
endif
endfunction
function export_bitmap(file_name$)
sync off
s = size*chunk_size
create bitmap 1,s,s
set current bitmap 1
lock pixels
dim bitmap(s,s)
//moves the heights of the matrices into a single array
for x = 1 to chunk_size : for z = 1 to chunk_size
bitmap(x,z) = get matrix height (matrix_no(1,1),x,z)
next z : next x
for n = 2 to size : for x = 1 to chunk_size : for z = 1 to chunk_size
bitmap(x,((n-1)*chunk_size)+z) = get matrix height (matrix_no(1,n),x,z)
next z : next x : next n
for n = 2 to size : for x = 1 to chunk_size : for z = 1 to chunk_size
bitmap(((n-1)*chunk_size)+x,z) = get matrix height (matrix_no(n,1),x,z)
next z : next x : next n
for m = 2 to size : for n = 2 to size : for x = 1 to chunk_size : for z = 1 to chunk_size
bitmap(((m-1)*chunk_size)+x,((n-1)*chunk_size)+z) = get matrix height (matrix_no(m,n),x,z)
next z : next x : next n : next m
//finds the maximum and minimum height from this array
max_hight = -1000
min_height = 1000
for x = 1 to s : for z = 1 to s
if bitmap(x,z) > max_height then max_height = bitmap(x,z)
if bitmap(x,z) < min_height then min_height = bitmap(x,z)
next z : next x
range = max_height-min_height
//makes all the values > 0
tmp = min_height*-1
for x = 1 to s : for z = 1 to s
bitmap(x,z) = bitmap(x,z) + tmp
next z : next x
k# = (range+tmp) / 255 //constant
for x = 1 to s : for z = 1 to s
c = bitmap(x,z)/k#
dot x,z,rgb(c,c,c)
next z : next x
unlock pixels
get image 1,1,1,s,s
save image file_name$,1
set current bitmap 0
delete bitmap 1
sync on
wait 2000
endfunction
(when the program runs, it saves a (compressed) heightmap called "test.bmp" in the same directory as the exe)
Right, so it's similar to perlin noise, but it has the same flaw as the diamond-square algorithm, there are sometimes seams in the heightmap. ^^
Also, because some of the positions in the matrix are higher than 255, and some are lower than 0, the values need to be compressed, so a lot of detail is lost in the heightmap.
(one of the heightmaps is attached)