EDIT
The code looks weird in different browsers. It\'s tabbed all funny and sometimes there are no carriage returns so the code runs all together. I don\'t know why it\'s happening but it makes the code hard to understand.
Quote: "I would like to see an endless terrain demo in action.
"
The following code shows the concept. This will indeed be an endless terrain - limited only by the size of integers on DBC. I'm using a random generator based on the one used in libnoise. However, this example doesn't use any fancy noise functions to make things pretty. This is bare bones. What makes it endless, is the random number generator's ability to create the same values based on the same seeds.
If we use the X and Z locations as our seeds, then we get our endless terrain. You can come back to locations and it will be the same as it was on first visit etc.
The example can be expanded upon - use a nice noise function instead of random jaggies, use memblock matrix objects instead of the built in matrix commands, add texturing and handle the normal changes (can also be procedurally done similar to the landscape).
This example also needs a little smoothing out of the movement. Also, I'm updating and drawing everything every iteration. It should really only be updated when there is a change, like the camera has crossed a tile border.
Use UP DOWN arrows to move. Mouse to steer
REMSTART
==============================================================
= TITLE : Endless Matrix using random seed
= Author : latch
= Date : 07/13/2013
= UPDATE :
= Version: .02
==============================================================
Comments
==============================================================
REMEND
REM =============================================================
REM = SET UP DISPLAY
REM =============================================================
AUTOCAM OFF
SET DISPLAY MODE 1152,864,32
SYNC ON
SYNC RATE 60
HIDE MOUSE
REM =============================================================
REM = MAIN
REM =============================================================
_main:
gosub _init
DO
TEXT 0,0,"Matrix z = "+STR$(MATRIX POSITION z(mat))
TEXT 0,20,STR$(SCREEN FPS())
gosub _calculate_heights
SYNC
LOOP
END
REM =============================================================
REM = SUBROUTINES - PROCEDURES
REM =============================================================
_init:
rem make a matrix that will be scrolled and altered
mat=1
tilex=31
tilez=31
matx#=2000
matz#=2000
vertcount=tilex*tilez
maxht#=20
rem get the number of units per tile
xpertile#=matx#/(tilex+.)
zpertile#=matz#/(tilez+.)
centerx#=matx#/2
centerz#=matz#/2
make matrix mat,matx#,matz#,tilex,tilez
rem let's get a start position for our camera. We'll have it
rem somewhere in the world
randomize timer()
xpos#=rnd(10000)
zpos#=rnd(10000)
sync
rem set the camera speed
cspeed#=10
position camera centerx#,50,centerz#
return
`================================================================
_calculate_heights:
remstart
We keep the camera stationary and move the matrix. We do,
however, keep track of the virtual distance the camera has moved.
When the matrix has moved the distance of a tile in either the
x or z directions,we put the matrix back to it's original
position by the -length of the direction it has moved. We
then recalculate the heights of the matrix based on this new
virtual camera position.
We need a fairly robust random number generator that will always
return the same set of values based on it's current seed. We
calculate the seed based on the virtual camera position.
This example recalculates all of the point on the matrix. We could
just recalculate the outer edges and 'SHIFT' the matrix up or down
or left or right. This might be a little faster for DBC - but I'm
not sure. The slowdown would come from the custom random number
generator running from DBC code. This example performs pretty
well.
remend
rem keep camera in the center and move the matrix
cangy#=wrapvalue(camera angle y()+mousemovex())
yrotate camera cangy#
ud=upkey()-downkey()
movex#=newxvalue(0,cangy#,cspeed#*ud)
movez#=NEWZVALUE(0,cangy#,cspeed#*ud)
dec mx#,movex#
DEC mz#,movez#
rem keep track of virtual camera position
inc xpos#,movex#
INC zpos#,movez#
rem figure out current tile
oldx1=x1
oldz1=z1
x1=int((xpos#/xpertile#))
z1=int((zpos#/zpertile#))
vx1=vx1+x1
vz1=vz1+z1
rem move the matrix by mx and mz
POSITION MATRIX mat,mx#,MATRIX POSITION Y(mat),mz#
rem if we've moved passed a tile size, move matrix back
if x1!oldx1
position matrix mat,matrix position x(mat)-mx#,matrix position y(mat),matrix position z(mat)
mx#=0
xpos#=0
endif
if z1!oldz1
position matrix mat,matrix position x(mat),matrix position y(mat),matrix position z(mat)-mz#
mz#=0
zpos#=0
ENDIF
text 0,60,"vx1 = "+str$(vx1)
TEXT 0,80,"vz1 = "+STR$(vz1)
rem now, update the heights on the matrix
for z=0 to tilez
for x=0 to tilex
ht#=maxht#*random(x+vx1,z+vz1,0)
set matrix height mat,x,z,ht#
next x
next z
UPDATE MATRIX mat
`cht#=get ground height(mat,camera position x()-mx#,camera position z()-mz#)
`position camera camera position x(),cht#+100,camera position z()
return
`================================================================
`================================================================
REM =============================================================
REM = FUNCTIONS
REM =============================================================
function random(x,z,seed)
if seed=0 then seed=1045437251
r=((1619*x)+(31337*z)+(seed*1013))&2147483647
temp=r/(2^14)
r=xor(temp,r)
result#=1.0-(((r*(r*r*60493+1376312589))&2147483647)/1073741824.0)
endfunction result#
function xor(a,b)
rem latch 03/28/2010
result=(a|b)-(a&b)
endfunction result
REM =============================================================
REM = DATA STATEMENTS
REM =============================================================
@BN2
Load time for a terrain could be basically eliminated. However, if you change the texturing, you might have to do some loading.
Programmatically, you could use a perlin noise function to generate other things - houses, trees, walls, textures, - depending on the depth/extent of the procedural generations, the trade off might be performance. However, if you have stored "pieces" of objects that can be assembled into whatever you need, then you could use short iterations of noise functions to assemble aspects of your world. You can return values in 3 dimensions from perlin noise. These values could be the same flags/triggers you were talking about storing in a memblock or bitmap - the difference being the structured noise would be calculated on the fly.
Enjoy your day.