@all others: Thanks for the comments.
Here is the last chapter to this series: collision.
Collision is definately one of the stumpers for those who haven't conquered it yet.
To be able to do collision in an FPS style game like this There needs to be two objects to collide. At the moment, we move the camera around with the arrow keys, and seing that the camera does not get involved in collision we need an object to act like a player object. This is easy, because all we need to do is make a sphere, just insert this code in our pre-game precedures:
As we all know this will make a sphere 10 units in diameter. Next we need to set up a variable that will control the angle that the object facing. Insert this code with the other variable setup:
This creates a variable for the angle named a# and its value is set to 0. Now we have those things set up we need to be able to control the sphere, or player object. To do this all we need to do is replace:
if upkey()=1 then move object 9,2
if downkey()=1 then move object 9,-2
if leftkey()=1 then a#=a#-2
if rightkey()=1 then a#=a#+2
The move object command is exactly like the "move camera" command although this moves 3d objects, the first parameter is the object nmber that you wish to move and the second is how far you want to move it. The "a#=a#-2" command simply subtracts two from the a# variable, and vice-versa for the "a#=a#+2" command. The updated code should look like:
sync on
sync rate 50
hide mouse
load object "simplegun.x",1
position object 1,3,-3.5,7
yrotate object 1,255
lock object on 1
make object box 2,200,40,10
make object box 3,200,40,10
make object box 4,10,40,200
make object box 5,10,40,200
make object box 6,200,10,200
make object box 7,200,10,200
position object 2,0,0,100
position object 3,0,0,-100
position object 4,100,0,0
position object 5,-100,0,0
position object 6,0,20,0
position object 7,0,-20,0
make object sphere 8,1
position object 8,0,50,0
make object sphere 9,5
shoot#=0
a#=0
do
if upkey()=1 then move object 9,2
if downkey()=1 then move object 9,-2
if leftkey()=1 then a#=a#-2
if rightkey()=1 then a#=a#+2
if spacekey()=1 and shoot#=0
position object 8,camera position x(),camera position y(),camera position z()
set object to camera orientation 8
shoot#=1
endif
if shoot#=0 then position object 8,0,50,0
if shoot#=1 then move object 8,2
if object collision(8,0)>0 then shoot#=0
sync
loop
Now that will move the sphere back and forth but not rotate, nor does the camera follow the player object. The code below does just that:
a#=wrapvalue(a#)
position camera object position x(9),object position y(9),object position z(9)
yrotate object 9,a#
yrotate camera a#
The first line is a command that keeps a variable between 0 and 360, before the = sign you put the destination variable and between the brackets you place the variable you wish to be converted. The "position camera" command will merely position the camera in 3d space. We are using the "object position x()" etc. command to return the currnt position of the specified object along each axis. You know about the third line except we're using a variable as the angle parameter instead of a strait number. The "yrotate camera" command rotates the cam along its y axis (vertical), once again we are using the a# variable as a parameter instead of a fixed number. The latest code should look like:
sync on
sync rate 50
hide mouse
load object "simplegun.x",1
position object 1,3,-3.5,7
yrotate object 1,255
lock object on 1
make object box 2,200,40,10
make object box 3,200,40,10
make object box 4,10,40,200
make object box 5,10,40,200
make object box 6,200,10,200
make object box 7,200,10,200
position object 2,0,0,100
position object 3,0,0,-100
position object 4,100,0,0
position object 5,-100,0,0
position object 6,0,20,0
position object 7,0,-20,0
make object sphere 8,1
position object 8,0,50,0
make object sphere 9,5
shoot#=0
a#=0
do
if upkey()=1 then move object 9,2
if downkey()=1 then move object 9,-2
if leftkey()=1 then a#=a#-2
if rightkey()=1 then a#=a#+2
if spacekey()=1 and shoot#=0
position object 8,camera position x(),camera position y(),camera position z()
set object to camera orientation 8
shoot#=1
endif
if shoot#=0 then position object 8,0,50,0
if shoot#=1 then move object 8,2
if object collision(8,0)>0 then shoot#=0
a#=wrapvalue(a#)
position camera object position x(9),object position y(9),object position z(9)
yrotate object 9,a#
yrotate camera a#
sync
loop
Now for our collision code to work we need some more variables set up the first set is:
oldx#=object position x(9)
oldy#=object position y(9)
oldz#=object position z(9)
These variables will store the old position of the player object before any repositioning is done. These variables need to be placed at the start of the main loop as they need to be constantly updated.
The second set is:
newx#=object position x(9)
newy#=object position y(9)
newz#=object position z(9)
These variables will store the position of the player object after the repositioning is done so this set should be put after those if...then statements. The code should now look like this:
sync on
sync rate 50
hide mouse
load object "simplegun.x",1
position object 1,3,-3.5,7
yrotate object 1,255
lock object on 1
make object box 2,200,40,10
make object box 3,200,40,10
make object box 4,10,40,200
make object box 5,10,40,200
make object box 6,200,10,200
make object box 7,200,10,200
position object 2,0,0,100
position object 3,0,0,-100
position object 4,100,0,0
position object 5,-100,0,0
position object 6,0,20,0
position object 7,0,-20,0
make object sphere 8,1
position object 8,0,50,0
make object sphere 9,5
shoot#=0
a#=0
do
oldx#=object position x(9)
oldy#=object position y(9)
oldz#=object position z(9)
if upkey()=1 then move object 9,2
if downkey()=1 then move object 9,-2
if leftkey()=1 then a#=a#-2
if rightkey()=1 then a#=a#+2
newx#=object position x(9)
newy#=object position y(9)
newz#=object position z(9)
if spacekey()=1 and shoot#=0
position object 8,camera position x(),camera position y(),camera position z()
set object to camera orientation 8
shoot#=1
endif
if shoot#=0 then position object 8,0,50,0
if shoot#=1 then move object 8,2
if object collision(8,0)>0 then shoot#=0
a#=wrapvalue(a#)
position camera object position x(9),object position y(9),object position z(9)
yrotate object 9,a#
yrotate camera a#
sync
loop
To keep things tidy the "gosub" command is used. This command makes the program skip to another place in the code. The syntax for using this command is:
gosub boris
boris:
[commands go here]
return
The place that the program skips to must be marked with a colon (
at the end of the label. The return command defines the end of that sub, this command simply makes the program go back to where it left and continue on normally.
To make our code happen there needs to be an if statement in the middle of our code that looks like this:
if object collision(9,0)>1 then gosub collision
I set it so that it would work when it returned a value greater than 1 because the gun is object no. 1. If it was collisiong with this then you wouldn't be able to move.
Also this code needs to go after the main loop:
The new code should look like this:
sync on
sync rate 50
hide mouse
load object "simplegun.x",1
position object 1,3,-3.5,7
yrotate object 1,255
lock object on 1
make object box 2,200,40,10
make object box 3,200,40,10
make object box 4,10,40,200
make object box 5,10,40,200
make object box 6,200,10,200
make object box 7,200,10,200
position object 2,0,0,100
position object 3,0,0,-100
position object 4,100,0,0
position object 5,-100,0,0
position object 6,0,20,0
position object 7,0,-20,0
make object sphere 8,1
position object 8,0,50,0
make object sphere 9,5
shoot#=0
a#=0
do
oldx#=object position x(9)
oldy#=object position y(9)
oldz#=object position z(9)
if upkey()=1 then move object 9,2
if downkey()=1 then move object 9,-2
if leftkey()=1 then a#=a#-2
if rightkey()=1 then a#=a#+2
newx#=object position x(9)
newy#=object position y(9)
newz#=object position z(9)
if object collision(9,0)>1 then gosub collision
if spacekey()=1 and shoot#=0
position object 8,camera position x(),camera position y(),camera position z()
set object to camera orientation 8
shoot#=1
endif
if shoot#=0 then position object 8,0,50,0
if shoot#=1 then move object 8,2
if object collision(8,0)>0 then shoot#=0
a#=wrapvalue(a#)
position camera object position x(9),object position y(9),object position z(9)
yrotate object 9,a#
yrotate camera a#
sync
loop
collision:
return
Now, time for the heart of the collision the code that makes everything happen is this:
if object collision(9,0)>1
position object 9,oldx#,newy#,newz#
if object collision(9,0)>1
position object 9,newx#,oldy#,newz#
if object collision(9,0)>1
position object 9, newx#,newy#,oldz#
if object collision(9,0)>1
newx#=oldx#
newy#=oldy#
newz#=oldz#
else
newz#=oldz#
endif
else
newy#=oldy#
endif
else
newx#=oldx#
endif
endif
I know it might seem baffaling but what it does is it repositions the object to its original x position and if that doesn't work it'll try the y posision and so on. The else statements mean that if an if command results in a false it will do the things between the else and the endif statements instead. This code may take a while to study. This needs to be placed between the collision: and the return commands.
Finally we need to update the position of the object, all we need to do is insert this code into our main loop:
position object 9,newx#,newy#,newz#
Also, to fix a shooting problem that occurs insert this code into the "if spackey()" set:
The code should look like this:
sync on
sync rate 50
hide mouse
load object "simplegun.x",1
position object 1,3,-3.5,7
yrotate object 1,255
lock object on 1
make object box 2,200,40,10
make object box 3,200,40,10
make object box 4,10,40,200
make object box 5,10,40,200
make object box 6,200,10,200
make object box 7,200,10,200
position object 2,0,0,100
position object 3,0,0,-100
position object 4,100,0,0
position object 5,-100,0,0
position object 6,0,20,0
position object 7,0,-20,0
make object sphere 8,1
position object 8,0,50,0
make object sphere 9,5
shoot#=0
a#=0
do
oldx#=object position x(9)
oldy#=object position y(9)
oldz#=object position z(9)
if upkey()=1 then move object 9,2
if downkey()=1 then move object 9,-2
if leftkey()=1 then a#=a#-2
if rightkey()=1 then a#=a#+2
newx#=object position x(9)
newy#=object position y(9)
newz#=object position z(9)
if object collision(9,0)>1 then gosub collision
if spacekey()=1 and shoot#=0
position object 8,camera position x(),camera position y(),camera position z()
set object to camera orientation 8
move object 8,7
shoot#=1
endif
if shoot#=0 then position object 8,0,50,0
if shoot#=1 then move object 8,2
if object collision(8,0)>0 then shoot#=0
position object 9,newx#,newy#,newz#
a#=wrapvalue(a#)
position camera object position x(9),object position y(9),object position z(9)
yrotate object 9,a#
yrotate camera a#
sync
loop
collision:
if object collision(9,0)>1
position object 9,oldx#,newy#,newz#
if object collision(9,0)>1
position object 9,newx#,oldy#,newz#
if object collision(9,0)>1
position object 9, newx#,newy#,oldz#
if object collision(9,0)>1
newx#=oldx#
newy#=oldy#
newz#=oldz#
else
newz#=oldz#
endif
else
newy#=oldy#
endif
else
newx#=oldx#
endif
endif
return
And thats it! I'd like to thank Lost In Thought and G-Man for that collision code, it is brilliant.
Anyway, keep programming!
If I were you and you were me, then you'd be yourself 'cos you are me and I am you.