`Real-time Matrix/Canyon generator (intemediate tutorial) `====================== `©CPU `====================== `*note* many times I will refer to a matrix with x,y coordites, the `help files refer to them as x,z coordintes. If you were looking at `a matrix from the top this is what you would see: ` help files Me ` ____z____ ____y____ ` | | | | | | ` | | | | | | ` -----------x -----------x ` | | | | | | ` |____|____| |____|____| rem this will go to a subroutene that will set up our display mode rem fonts, system optitions and other things that belong at the rem very begining of our code gosub startup rem general varibles #constant camera_matrix_collision = 1 #constant camera_radius = 15 #constant fogYN = 1 #constant fogcolor = RGB(188,165,129) #constant fogdis = 2000 rem some matrix specific numbers #constant matrix_tilex = 50 #constant matrix_tiley = 50 #constant matrix_number = 1 #constant matrix_image = 1 #constant matrix_wire_num = 2 #constant matrix_offsetx = 0 #constant matrix_offsety = 0 #constant matrix_offsetz = 0 #constant matrix_width = 1000 #constant matrix_height = 1000 rem initialize some vaibles and constants used in the terrain #constant turnchance = 3 #constant turn_base = 8 #constant turn_dev = 5 #constant hillchance = 7 #constant hill_base = 10 #constant hill_dev = 5 #constant hill_sharpness = 5 #constant narrow_chance = 10 #constant narrow_base = 3 #constant narrow_dev = 4 #constant spikechance = 100 #constant spikeheight = 25 #constant height_min = 50 #constant height_max = 300 #constant width_min = 5 #constant width_max = 25 #constant roughness = 0 `build an initial canyon so we don't start out with a flat matrix... gosub initialCanyonBuild repeat rem control mouse, if control key is pressed move 7 units at a time rem instead of moving 3 units normaly if controlkey() = 1 MouseControl(7) else MouseControl(3) endif rem if shiftkey is pressed then shift the matrix down and update the canyon if shiftkey() = 1 shift matrix down matrix_number gosub canyon equate_matrix(matrix_number, matrix_wire_num, matrix_tilex, matrix_tiley) update matrix matrix_number update matrix matrix_wire_num endif rem position the wireframe overlay if the returnkey is pressed if returnkey() = 1 position matrix matrix_wire_num, matrix_offsetx, matrix_offsety + 0.5, matrix_offsetz else rem unfortunatly there is no "hide matrix" command position matrix matrix_wire_num,-100000,-100000,-100000 endif rem display some text and update screen gosub ScreenPrompts sync rem exit on escapekey until escapekey() = 1 end startup: rem housecleaning set display mode 800,600,32 sync on sync rate 0 hide mouse rem makes it so that the camera doesn't intstantly zoom to newly created objects autocam off color backdrop rgb(0,0,0) set text size 10 rem turn on fog if fogYN = 1 and fog available() = 1 fog on fog color fogcolor fog distance fogdis endif rem set the random seed so that the canyon is different every time randomize timer() return `the first time we go through our code we need to initaly setup the canyon initialCanyonBuild: rem these are varibles used to turn, vary the height and narrow or rem widen the matrix canyon global turn as integer = 0 global narrow as integer = 0 global hill as integer = 0 rem these are some varibles that hold what height, width, and rem position(offset) the matrix is updating at global tilex as integer = 0 global tiley as integer = 0 global offset as integer = 20 global canyon_width as integer = 10 global canyon_height_factor as integer = 100 rem create the ground matrix `load image "ground.jpg", matrix_image,0 GroundTexture(matrix_image) make matrix matrix_number, matrix_width, matrix_height ,matrix_tilex, matrix_tiley prepare matrix texture matrix_number,matrix_image, 1, 1 set matrix texture matrix_number, 1, 1 position matrix matrix_number, matrix_offsetx, matrix_offsety, matrix_offset rem make the overlay wireframe matrix make matrix matrix_wire_num, matrix_width, matrix_height, matrix_tilex, matrix_tiley position matrix matrix_wire_num, matrix_offsetx, matrix_offsety + 0.5, matrix_offsetz set matrix wireframe on matrix_wire_num set matrix priority matrix_wire_num, 1 rem this generates a canyon so you don't start with a flat matrix for tiley = 0 to matrix_tiley - 1 gosub canyon next tiley rem update the matrixs so that you can see the changes update matrix matrix_number equate_matrix(matrix_number, matrix_wire_num, matrix_tilex, matrix_tiley) update matrix matrix_wire_num rem tiley is the varible that tells the computer which matrix square rem to update in the y direction tiley = matrix_tiley - 1 rem set the initial position of the camera position camera 0,150,-500 return canyon: rem handel the canyon turning gosub turn_canyon rem hande the changing the height of the canyon gosub hill_canyon rem hande the matrix narrowing and widening gosub narrow_canyon rem randomize the matrix for tilex = 0 to matrix_tilex - 1 set matrix height matrix_number, tilex, tiley, rnd(roughness) next tilex rem handel the canyion turning rem form the canyon tmp_angle_inc = 180/(canyon_width) for tilex = offset to offset + canyon_width rem apply basic curve to the height height = -1*(sin((tilex - offset)*tmp_angle_inc) * canyon_height_factor) rem apply spike chance if rnd(spikechance) = 1 height = height + (spikeheight/2.0) + rnd(spikeheight/2.0) endif rem apply roughness height = height + rnd(roughness) if tilex <= matrix_tilex and tiley <= matrix_tilex and tilex >= 0 and tiley >= 0 set matrix height matrix_number, tilex, tiley, height endif next tilex rem make the far end a "wall" for tilex = 0 to matrix_tilex set matrix height matrix_number,tilex,matrix_tiley,0 next x return turn_canyon: rem make bends in the canyon if turn <> 0 if turn > 0 rem turn right if turn mod 2 = 0 inc offset endif dec turn else rem turn left if turn mod 2 = 0 dec offset endif inc turn endif else rem if turnchance = 1 then turn canyon if rnd(turnchance) = 1 rem if it equals 1 it's a right turn if it equals 0 its a left one if rnd(1) = 1 turn = turn_base + rnd(turn_dev) if offset + turn + width_max > matrix_tilex - 1 rem if the turn will "exit" the matrix then turn the oposite way turn = turn * -1 endif else turn = -1 * turn_base - rnd(turn_dev) if offset + turn < 1 rem if the turn will "exit" the matrix then turn the oposite way turn = turn * -1 endif endif endif endif return hill_canyon: rem make rises and falls in the height of the canyon if hill <> 0 if hill > 0 rem go down inc canyon_height_factor, hill_sharpness dec hill else rem go up dec canyon_height_factor, hill_sharpness inc hill endif else rem if hillchance = 1 then raise or lower the canyon if rnd(hillchance) = 1 rem if it equals 1 it goes down, 0 it goes up if rnd(1) = 1 hill = hill_base + rnd(hill_dev) if (hill * hill_sharpness)+ canyon_height_factor > height_max rem if the hill will go to low or to high then flip rem the direction of the slope hill = hill * -1 endif else hill = -1 * hill_base - rnd(hill_dev) if (hill * hill_sharpness)+ canyon_height_factor < height_min rem if the hill will go to low or to high then flip rem the direction of the slope hill = hill * -1 endif endif endif endif return narrow_canyon: rem narrow or widen the canyion if narrow <> 0 if narrow > 0 rem widen inc canyon_width dec narrow else rem narrow dec canyon_width inc narrow endif else if rnd(narrow_chance) = 1 rem if it equles 1 it gets narrower, 0 it gets wider if rnd(1) = 1 narrow = -1 * narrow_base - rnd(narrow_dev) if narrow + canyon_width < width_min rem if its going to get to small then make it get bigger narrow = narrow * -1 endif else narrow = narrow_base + rnd(narrow_dev) if narrow + canyon_width > width_max rem if it's going to get to wide then make it get smaller narrow = narrow * -1 endif endif endif endif return ScreenPrompts: text 0,0,"Screen FPS = " + str$(screen fps()) text 0,15,"Press Enter to overlay wireframe" text 0,30,"Press Shift to scroll matrix" text 0,45,"Use Left Mouse button to move forward" text 0,60,"Use Right Mouse button to move backwards" text 0,75,"Look using mouse" return function equate_matrix(matrix_a, matrix_b, xsize, ysize) rem this function makes matrix b equal to in form to matrix a for n = 0 to xsize for m = 0 to ysize set matrix height matrix_b, n, m, get matrix height(matrix_a, n, m) next m next n endfunction function MouseControl(Speed as float) xrotate camera camera angle x()+(mousemovey()/2.0) yrotate camera camera angle y()+(mousemovex()/2.0) if mouseclick()=1 then move camera Speed if mouseclick()=2 then move camera (0-Speed) rem this handels camera matrix collision if camera_matrix_collision = 1 if camera position y() < get ground height(matrix_number, camera position x(), camera position z())+1 position camera camera position x(), get ground height(matrix_number, camera position x(), camera position z())+camera_radius, camera position z() endif endif endfunction function GroundTexture(imgNum as integer) local xSize as integer local ySize as integer local tmpXa as integer local tmpYa as integer local tmpXb as integer local tmpYb as integer local extream as integer xSize = 255 ySize = 255 cls rgb(120,90,70) for n = 1 to (xSize+ySize)*50 extream = -60 + rnd(100) ink rgb(110+rnd(20)+extream,80+rnd(20)+extream,60+rnd(20)+extream),0 circle rnd(xSize), rnd(ySize),3 next n for n = 1 to (xSize+ySize)*3 extream = -60 + rnd(100) ink rgb(110+rnd(20)+extream,80+rnd(20)+extream,60+rnd(20)+extream),0 tmpXa = rnd(xSize) tmpYa = rnd(ySize) tmpXb = rnd(xSize) tmpYb = rnd(ySize) line tmpXa, tmpYa, tmpXb, tmpYb extream = -60 + rnd(100) ink rgb(110+rnd(20)+extream,80+rnd(20)+extream,60+rnd(20)+extream),0 tmpXa = rnd(10) for x = 1 to 5 circle rnd(xSize), rnd(ySize),5+tmpXa+x next x next n blur bitmap 0,5 get image imgNum,xSize/4,ySize/4,(xSize*3)/4,(ySize*3)/4,0 endfunction