07-31-2004, 09:52 PM
I'm testing a terrain generation method in qbasic for a game I plan to program in C++ later.
The trick is to make the terrain's left edge fit with the right seamlessly height/slopewise
and I think I've figured out a method that seems to work, however it would take too much space
to explain in the same post but I will later if you ask me to...
The thing I need help with is "k" the variable defining the maximum slope/steepness
- A terrain segment can't be more than k pixels higher or lower than the ones beside it.
For now, it works perfectly unless k=1 then the above "law"
is often broken
The trick is to make the terrain's left edge fit with the right seamlessly height/slopewise
and I think I've figured out a method that seems to work, however it would take too much space
to explain in the same post but I will later if you ask me to...
The thing I need help with is "k" the variable defining the maximum slope/steepness
- A terrain segment can't be more than k pixels higher or lower than the ones beside it.
For now, it works perfectly unless k=1 then the above "law"
is often broken
Code:
RANDOMIZE TIMER
SCREEN 12
CONST screenw = 640
CONST screenh = 480
DIM mountains(0 TO screenw - 1) ' raw mountain array
DIM hills(0 TO screenw - 1) ' smoothed mountain array
FOR x = 0 TO screenw - 1 ' -1 shows that the particular part
mountains(x) = -1 ' of the raw mountain is unprocessed
NEXT
'k = INT(RND * 9) + 2 ' maximum steepness
k = 1 '<<< CAUSING ERRORS
min = 20 + INT(RND * 50) ' minimal height
max = screenh - (20 + INT(RND * 50)) ' maximal height
sv = INT(RND * 25) * 2 + 1 ' smoothing value
PRINT "Creating raw landscape ";
s = 512 ' step
DO
FOR x = 0 TO screenw - 1 STEP s
IF mountains(x) = -1 THEN ' if this particular mountain part
' is unprocessed...
'-----------------------------------------------------------------------------
l = x - s '\
IF x - s < 0 THEN l = l + screenw ' \
r = x + s ' | checking the height
IF x + s > screenw - 1 THEN r = r - screenw ' > to the left and
margin = k * s ' | right
left = mountains(l) ' /
right = mountains(r) '/
'-----------------------------------------------------------------------------
SELECT CASE left
CASE -1
IF right = -1 THEN ' If both are -1
high = max
low = min
ELSE ' If only left is -1
high = right + margin
low = right - margin
END IF
CASE ELSE
SELECT CASE right
CASE -1 ' If only right is -1
high = left + margin
low = left - margin
CASE IS < left ' If left > right
high = right + margin
low = left - margin
CASE ELSE ' If right >= left
high = left + margin
low = right - margin
END SELECT
END SELECT
'-----------------------------------------------------------------------------
IF high > max THEN high = max ' making certain that the
IF low < min THEN low = min ' values isn't out of bounds
mountains(x) = INT(RND * (high - low)) + low' and setting the mountains
' altitude
'-----------------------------------------------------------------------------
END IF
NEXT
s = s \ 2 ' halving the step NOTE:
LOOP UNTIL s = 0 ' INTEGER DIVISION: 1 \ 2 = 0
PRINT "FINISHED" + STRING$(2, 13) + "Smoothing landscape "
FOR x = 0 TO screenw - 1 'smoothing
LOCATE 4: PRINT INT(x / screenw * 100); "%" 'status meter
sum = 0
FOR p = -sv TO sv
p2 = p
IF x + p > screenw - 1 THEN p2 = p - screenw
IF x + p < 0 THEN p2 = p + screenw
sum = sum + mountains(x + p2)
NEXT
hills(x) = sum \ (sv * 2 + 1)
NEXT
CLS
FOR x = 0 TO screenw - 1
LINE (x, screenh - 1)-(x, screenh - mountains(x)), 8
NEXT
maxdiff = 0
FOR x = 1 TO screenw - 1
IF ABS(mountains(x) - mountains(x - 1)) > maxdiff THEN maxdiff = ABS(mountains(x) - mountains(x - 1))
NEXT
PRINT "k: "; k; " l/r diff: "; ABS(mountains(0) - mountains(screenw - 1)); " sv: "; sv
IF maxdiff > k THEN COLOR 4
PRINT "maxdiff: "; maxdiff; " (must be <= k or something's wrong)"
COLOR 15
LINE (0, screenh - 1 - max)-(screenw - 1, screenh - 1 - max), 1
LINE (0, screenh - 1 - min)-(screenw - 1, screenh - 1 - min), 4
SLEEP
CLS
FOR x = 0 TO screenw - 1
LINE (x, screenh - 1)-(x, screenh - hills(x)), 8
NEXT
LINE (0, screenh - 1 - max)-(screenw - 1, screenh - 1 - max), 1
LINE (0, screenh - 1 - min)-(screenw - 1, screenh - 1 - min), 4
maxdiff = 0
FOR x = 1 TO screenw - 1
IF ABS(hills(x) - hills(x - 1)) > maxdiff THEN maxdiff = ABS(hills(x) - hills(x - 1))
NEXT
PRINT "k: "; k; " l/r diff: "; ABS(hills(0) - hills(screenw - 1)); " sv: "; sv
IF maxdiff > k THEN COLOR 4
PRINT "maxdiff: "; maxdiff; " (must be <= k or something's wrong)"
COLOR 15
SLEEP
/post]