Ok, just wrote this up, maybe it'll help. Its an extremely basic 3D game with a third person camera, a textured matrix, and matrix collision. Movement is with the arrow keys.
Its not a lot of code at all, almost all of it is comments, paste it into DBP and you'll see all of the grey
.
Untested but it should work, not on a computer with DBP ATM;
`Set the main program settings.
`"SYNCing" refers to refreshing the screen. Normally, DBP will automatically sync the screen
`every time something is drawn, moved, made, etc. This isnt good, its better to have DBP
`sync the screen once every loop for every object in the game. To do this, we turn SYNC ON,
`allowing us to later call the SYNC command ourselves to sync the screen manually.
`The "SYNC RATE" is the maximum frame rate we allow the program to have. The frame rate
`(measured in frames per second) is how many times we refresh the screen per second.
`If we set the sync rate to 60, then the computer would only allow DBP to refresh at a maximum
`of 60 times per second. Setting it to 0 allows the computer to refresh the screen as many times
`as it possibly can, which makes a drastic speed increase.
`AUTOCAM is a built-in function of DBP, whereby whenever a new 3D entity is made, DBP will orient
`the current camera as best it can so that we can see the newly made object. Since we're handling
`all camera positioning ourselves, we dont need this function, so we turn it off with the AUTOCAM
`OFF command.
`HIDE MOUSE just hides the mouse. Later on, you could hide the mouse and then position your own mouse
`sprite at the mouse coordinates (retrieved from the MOUSEX() and MOUSEY() commands) for a custom
`cursor.
`Lastly, we disable the escapekey. In DBP, by default, when the escapekey is pressed,
`all loops are exited and the program ends. This isn't good, because what if instead
`we wanted to display a pause menu when the escape key is pressed, or write a log file, or something
`else? To do this, we DISABLE ESCAPEKEY, and later on Ill explain how we handle ending the program.
SYNC ON:SYNC RATE 0:AUTOCAM OFF:HIDE MOUSE:DISABLE ESCAPEKEY
`This mini section of code will draw a picture to the screen, 64 by 64 pixels, of random colour.
`The LOCK PIXELS command is used to help DBP draw the image. When pixels are locked, DBP can draw
`faster, but disables you from viewing what is being drawn in real-time.
`Then, we have 2 nested for loops. Each going from 1 to 64. You'll notice the first loop has
`x for it's counter variable, and the second has y. These 2 loops output an X and Y coordinate on the screen.
`The DOT command will draw a single pixel on the screen. The syntax is DOT x,y,colour value. The Colour Value
`is the computer-code for whatever colour we want. Luckily, there is a command with DBP that returns
`a colour value based on 3 integers. The command is RGB(red, green, blue). Each of the parameters can be from
`0 to 255. The RND command will give us a random number between 0 and the number we specify in the brackets.
`Putting all of this together, we draw pixels using the DOT command, specifying the colour as a random red, green, and
`blue value between 0 and 255.
LOCK PIXELS
FOR x = 1 TO 64
FOR y = 1 TO 64
DOT x,y,RGB(RND(255),RND(255),RND(255))
NEXT y
NEXT x
UNLOCK PIXELS
`After drawing the image, we unlock the pixels, and call the GET IMAGE command. This command will copy any image
`data currently on the screen into an image, that we can use later. DBP stores images just like objects, every
`image has a unique number. The same goes with sounds, cameras, lights, and lots more. The GET IMAGE command has 5
`parameters. The first is the image number we want to save the image to, the next to are the x and y location of the
`top left corner of the area we want to grab the image from, and the last 2 are the x and y location of
`the bottom right corner. We use image number 1, getting an image in a boxed area from 1,1 to 512, 512.
`Why we need this image will be apparent in the next section.
GET IMAGE 1,1,1,64,64
`Matrices in DBP are a fast way to make a 3D terrain (but dont be mistaken, they are not true terrains).
`Matrices are built up of a grid, and each grid's square can have a position and rotation. To make a matrix,
`we first call the MAKE MATRIX command, giving it a matrix number of 1, a width of 1000, a length of 1000, and then
`the last 2 parameters specify how many grid slots there are to be widthwize and lengtwize. So this will make a
`matrix 1000x1000, with 100 grid slots (10 x 10).
`After making the matrix, we call the RANDOMIZE MATRIX command. This command is pretty useful, what it does is goes through
`every single vertex of the matrix, and set's it's height to a random height between 0 and the maximum height you specify.
`The syntax is matrix number, max heighr. We've specified a height of 30 to be the maximum height.
`The next command, we call the PREPARE MATRIX TEXTURE command. This command will "texture" the matrix with
`an image. The image we're going to use is the image we created earlier, but you could use any image, sand, water,
`anything. (Note: to load external images, call the LOAD IMAGE command).
`The syntax of the command is PREPARE MATRIX TEXTURE matrix number, image number, across, down. matrix / image number
`should be self-explanatory. Across and Down refers to how many times the image will be tiled. If we specify 1 for
`the across and down value, then the entire matrix will be textured with the 1 image. We use 10 for the across and
`down value, making every single grid square be textured with the image we made earlier.
`Lastly, we call the UPDATE MATRIX command, which essentially updates all of the changes we've made to the matrix
`visually.
MAKE MATRIX 1,1000,1000,10,10
RANDOMIZE MATRIX 1,30
PREPARE MATRIX TEXTURE 1,1,10,10
UPDATE MATRIX 1
`Now we'll make our player object. Right now, we call the MAKE OBJECT BOX command, with an object number of 1,
`and dimensions 10x30x20. Its important to remember that seperate entities dont share ID numbers. That means, you can
`have a light with an ID number of 1, an object with an ID number of 1, and a matrix with an ID number of 1, all at the
`same time. However, you can not have 2 of the same entities with the same ID number. If you do, you'll get a "Runtime Error:
`Object Already Exists" error report, which basically means you've used that object number elsewhere already.
`After making the box, we call the COLOR OBJECT command. This command is a quick way to colour your objects
`made inside of DBP. It takes 2 parameters, the object number, and then the colour value. The object is our player (1),
`and the colour value Ive chosen is red. Remember the RGB command? We can use that here as well to get the colour value
`for red. Remember the RGB command takes 3 parameters, a red value, a blue balue, and a green value. Ive given red its maximum value
`(255), and green / blue 0, making the object completely red.
MAKE OBJECT BOX 1,10,30,20
COLOR OBJECT 1,RGB(255,000,000)
`Now comes the most important part of the program, the main loop. Almost every program you make in basic will have a main
`loop. A main loop is what constantly loops, forever, until the program ends. Inside the loop you might check for 3D collisions,
`send battle information to other players, allow the user to shoot, etc, all usually dozens of times per second. The more times your
`loop executes per second, the smoother your program will run.
`You'll notice in a lot of code snippets / tutorials for DBP, the main loop is a DO....LOOP structure. DO...LOOPS have
`no determined end, which is fine if you're relying on the escapekey system in DBP to end the game for you, but if, like we
`have, you've disabled the escape key, its better to use a WHILE...LOOP. WHILE the ESCAPEKEY() = 0 (is not pressed), the
`loop will execute. Once the escapekey is pressed, the loop exits.
`Ill point out now DBP's great key input system. There are keywords for almost every special key on your keyboard that you can call
`to check if it's pressed or not. For example, SPACEKEY(), ESCAPEKEY(), RETURNKEY(), LEFTKEY(), RIGHTKEY(), etc.
`The commands will return a 1 if the key is pressed, or a 0 if not.
`For any keys that dont have special commands (like the numbers, letters, symbols, etc.), theres the KEYSTATE() command. The KEYSTATE
`command takes 1 parameter, the scancode of the key you want to check for. Every key on your keyboard has a unique scancode (do a
`search for scancode on the forums to find scancode images that show every key's scancode). For example, the "W" key's
`scancode is 17. To check if the W key is pressed, you'd check IF KEYSTATE(17) = 1.
WHILE ESCAPEKEY() = 0
`Here is where we control our player in the 3D world.
`Hopefully you understand IF structures before this.
`I just made reference to the key commands in DBP right? Well for this program, we'll control our player object (1) with
`the arrow keys. Luckily for us, there are special commands for those keys, so we wont need to use the KEYSTATE command.
`The MOVE OBJECT command is used here. Basically, every object, in the entire 3D world, has an x, y, and z angle.
`This angle determines where the object is pointing. The MOVE OBJECT command will move whatever object we want forwards
`by whatever speed we want, based on it's angles. The syntax is MOVE OBJECT object number, speed. The speed can be any
`value, with or without decimals, postive or negative. If we specify a positive value, the object will move forward. If we
`give a negative value, it'll move backward. So, we check IF the UPKEY() = 1 (is pressed), THEN MOVE the OBJECT 1 (our player)
`forward 0.5 units.
`The same is done for the DOWNKEY, except we set the move value to -0.5, causing the object to move backwards.
IF UPKEY() = 1 THEN MOVE OBJECT 1,0.5
IF DOWNKEY() = 1 THEN MOVE OBJECT 1,-0.5
`Thats movement covered, but what about rotation? Rotation is a bit more complex, but nothing to get confused about.
`DBP does have nifty commands for rotation, like TURN OBJECT LEFT/RIGHT, PITCH OBJECT UP/DOWN, ROLL OBJECT LEFT/RIGHT, etc.
`But, these commands tend to mess up the object's internal xyz angles if we need them later on (which we do).
`Instead, we can use the ROTATE OBJECT command. The ROTATE OBJECT command takes 4 parameters; the object number, the x angle,
`the y angle, and the z angle. Keep in mind that each angle is between 0 and 360 degrees. You can specify a value above 360 or below 0,
`DBP will handle it appropriately. For example if you give an x value of -90, DBP will rotate the object on the x axis 270 degrees.
`Thats not important though.
`You would think, if you called the ROTATE OBJECT command like so:
`ROTATE OBJECT 1, 1,0,0
`Constantly, that object 1 would rotate around it's x axis continually by 1 unit per loop. Right? Nope. The ROTATE OBJECT command
`rotates an object TO the specified angle, not BY the specified angle. So, the object would be rotated to 1,0,0, and left there.
`So how would be make an object constantly rotate about it's x axis? Simple. You just add it's current x angle to the rotation
`speed. To get an object's angles you can call the OBJECT ANGLE X(), OBJECT ANGLE Y(), and OBJECT ANGLE Z() commands.
`Each command takes the object number, and returns the angle.
`Lastly, for convenience, if you want to rotate an object only around 1 axis, DBP has axis-specific commands. Those being
`XROTATE OBJECT, YROTATE OBJECT, and ZROTATE OBJECT. Theyre exactly the same as ROTATE OBJECT, except it only takes
`a single angle, since you're only rotating about 1 axis.
`Rotating on the Y axis will cause our object to turn right or left. A negative value will turn it left, a positive will
`turn it right.
`So, we check if the leftkey is pressed, and if so, we YROTATE OBJECT 1 (our player) to it's OBJECT ANGLE Y(1)
`minus - 0.5. This will spin our player left as we hold the leftkey, and vice versa for the rightkey.
IF LEFTKEY() = 1 THEN YROTATE OBJECT 1, OBJECT ANGLE Y(1) - 0.5
IF RIGHTKEY() = 1 THEN YROTATE OBJECT 1, OBJECT ANGLE Y(1) + 0.5
`Now its time for some variables. We have 2 variables below, x#, and z#. Hopefully you know by now how DBP handles
`different variable types, and that variables with a hash sign (#) at the end are floats (can have decimals).
`x# will store our player's X position, and z# will store it's z. Object positions can be retrieved by calling
`the OBJECT POSITION X(), OBJECT POSITION Y(), and OBJECT POSITION Z() commands, just like the angles.
`So, we store the x position in x#, and then the z position in z#.
x# = OBJECT POSITION X(1)
z# = OBJECT POSITION Z(1)
`Now, what about collision? Remember we made a matrix, and we made it "bumpy" by using the
`RANDOMIZE MATRIX command. At the current state of the program, the object will just move through the matrix as if it
`weren't there. We want the object to follow along the surface of the matrix. How?
`Luckily, theres a GET GROUND HEIGHT() command. This command takes 3 parameters; matrix number, x, and z. What does it return?
`Well, based on the x and z coordinate we specify, it will tell us the height of the matrix at that point. That height value
`is where we want to position our player's feet.
`So, we fill the y# variable with the height returned from the get ground height command.
y# = GET GROUND HEIGHT(1,x#,z#)
`Now that we've got the object's xyz position, and the height our feet should be at, we need to move the object onto the surface
`of the matrix. We'll need to use the POSITION OBJECT command. This command takes an object number, and an xyz position.
`It'll then position the object at the specified xyz. Simple, right?
`You'll notice one last thing we do below, is add on half of our player's y size, to the y position. Why? Well,
`the POSITION OBJECT command positions the object based on it's centre, which would make our player follow
`along the matrix with half of it below the surface and half above. To compensate, we add half of our y height,
`retrieved from the OBJECT SIZE Y() command, to the y# value.
POSITION OBJECT 1,x#,y# + (OBJECT SIZE Y(1) / 2),z#
`Here we store the object's y angle in ya#
ya# = OBJECT ANGLE Y(1)
`Now we need to handle orienting our camera. Just like object positioning, there is a POSITION CAMERA command.
`Before I go on, DBP has a useful feature where it has a "CURRENT CAMERA". The current camera is set with the
`SET CURRENT CAMERA command. By default, the current camera is 0. NOTE: I know I said you cant have 0 for ID
`numbers, this isnt the case for entities pre-made like the default camera and light, which both have an ID of 0.
`Because of this "CURRENT CAMERA" feature, any command that requires a camera number, can have the camera
`number omitted if you want to use the current camera. So, calling POSITION CAMERA 0,x#,y#,z#, is exactly the same as
`calling POSITION CAMERA x#,y#,z#.
`Also note, this program will have a "third person camera" style, whereby the camera follows behind the player as they move.
`Step 1 is to position the camera at the player's position. We add 40 to the y# value to make the camera position
`itself above the player a bit.
`Step 2, we need to rotate the camera on it's y axis to the object's y angle. We stored the object's y angle in ya#
`previously, so we call the ROTATE CAMERA command, giving the ya# variable for the y angle. Unfortunately, for some
`reason, there aren't axis specific rotation commands for the camera, you have to call the ROTATE CAMERA command.
`To avoid effecting a specific axis, just provide the camera's angle on that axis for the axis parameter. For example if
`you wanted to rotate the camera on the y axis, but leave it on the x and z axis, you would do ROTATE CAMERA CAMERA ANGLE X(),
`y angle,CAMERA ANGLE Z().
`We use 0 for the x and z axis because we know the camera wont be rotating on the x and z axis, so it will always be 0.
`Step 3, we move the camera backwards by -150 units.
`Step 4, we call the POINT CAMERA command to make the camera point directly at our player. For future reference, there is
`also a POINT OBJECT command. Both commands take an ID number, and a 3D world coordinate of where to point to.
`Thats it, 4 lines of code, and we've got a third person camera routine working.
`Take a look at whats happening if you dont understand why it works;
`The camera is positioned at the player's position, but a bit higher. , then the camera is made to face the same direction as the player,
`then the camera moves backward, and then points towards the player. The camera is pointed to the player afterwards because remember,
`its not directly behind the player, it's up in the air a bit as well.
POSITION CAMERA x#,y# + 40,z#
ROTATE CAMERA 0,ya#,0
MOVE CAMERA -150
POINT CAMERA x#,y#,z#
`Now we use the TEXT command to display some 2D text on the screen. The text command takes 3 parameters,
`an x location, a y location, and a string. The TEXT command has a lot of other commands to change how it looks, you can change
`the text colour using the INK command, you can center the text on the position by adding the word CENTER before the TEXT, and a lot more.
`Look in the index for help.
`First we display a title "My First Game".
`Then, we display the FPS of the game. FPS is the Frame Rate per Second the game is running at. The higher the FPS, the faster the game.
`DBP has a command to get the FPS, called SCREEN FPS(). IMPORTANT: Calling SYNC more than once will cause SCREEN FPS() to return
`inaccurate results. Thats why we only call it once at the very end of the loop.
`The STR$ command converts a float or integer into a string. The text command can only display strings, so we need to use
`the STR$ command to convert SCREEN FPS() to a string.
TEXT 0,0,"My First Game"
TEXT 0,30,"FPS: "+STR$( SCREEN FPS() )
`Lastly, we call the SYNC command to refresh the screen, drawing all of the 3D/2D entities.
SYNC
`The ENDWHILE command is hit, and the program loops back up to the top where the WHILE command is. It checks if the escapekey isn't pressed,
`and if so, loops again. If it is pressed, it exits the loop.
ENDWHILE
`This line of code will only ever be hit, when the escapekey is pressed. You could replace this with code that runs through the program properly
`deleting any data, writing a log, or displaying a pause menu. Whatever you want. Right now, we'll leave it at calling the
`END command, which will close the program completely.
END
`- RUCCUS
Copy it into DBP, run it, see what it does, then examine the code. Feel free to change anything.