You have a good knowledge of commands, the only problem is your structure.
If I was grading your program I'd give you:
Commands: A
Structure: D
Presentation: B
Remarks: B
OVERALL: B-
Commands - Very good. Lots of different commands used well, good to see things like NewValue and CurveValue being used.
Structure - I gave you a D because you have a subroutine inside the main loop, this is probably why your program isn't working because it is executing your subroutine every loop, just like any other code, whether you call it or not. There is also no return statement at the end of your "subroutine", this is a problem because when you call a subroutine with gosub the program remembers the place it called the subroutine from so it can return there when the routine is finished (unlike goto). If there's no return statement you will keep calling your subroutine and storing the position it was called at over and over again until there is a stack overflow (which means you run out of memory) and your program will crash. If you put a return statement then the program will return to the right spot and remove the record of the return position from the stack.
A minor problem with your structure is that your main loop isn't in the best order, this wont cause a crash but it's better to get the right order. I've labeled each process with the subsection it should be in; I've removed the subroutine as we now know this shouldn't be there.
rem yay we're in the main loop!
Do
rem // PROCESS \\
Rem Position Camera
Position Camera X#,Y#,Z#
rem // INPUT \\
Rem Control input for our camera
If Upkey()=1 rem forward
XTest# = Newxvalue(X#,cAY#,7)
ZTest# = Newzvalue(Z#,cAY#,7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
rem // INPUT \\
If Downkey()=1 rem backwards
XTest# = Newxvalue(X#,Wrapvalue(cAY#-180),7)
ZTest# = Newzvalue(Z#,Wrapvalue(cAY#-180),7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
rem // INPUT \\
If Leftkey()=1 rem rotate to the left...
XTest# = Newxvalue(X#,Wrapvalue(cAY#-90),7)
ZTest# = Newzvalue(Z#,Wrapvalue(cAY#-90),7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
rem // INPUT \\
If Rightkey()=1 rem rotate to the right...
XTest# = Newxvalue(X#,Wrapvalue(cAY#+90),7)
ZTest# = Newzvalue(Z#,Wrapvalue(cAY#+90),7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
rem // PROCESS \\
Rem Rotate camera
cTestX#=WrapValue(cAX#-180)
if cTestX# > 225 then cAX#=45
if cTestX# < 135 then cAX#=315
YRotate camera CurveAngle(cAY#,oldcAY#,24)
XRotate camera CurveAngle(cAX#,oldcAX#,24)
Y# = Get ground height(1,X#,Z#)+35
rem I just tested it and it just displays a black screen... No idea why.
rem But I'll continue, because my code is atleast partly correct.
rem // INPUT \\
if spacekey()=1 and BulletLife<60 then gosub playershoot
rem // PROCESS \\
Position object 2,10,7,15
Loop
If you read my coding guidelines you'll know what I'm talking about here, if not there is a link on the first post of this thread.
Here is your code re-organised so all the same types are together; these blocks can be made into subroutines later.
Do
rem // INPUT \\
rem Fire bullet
if spacekey()=1 and BulletLife<60 then gosub playershoot
rem // INPUT \\
Rem Control input for our camera
If Upkey()=1 rem forward
XTest# = Newxvalue(X#,cAY#,7)
ZTest# = Newzvalue(Z#,cAY#,7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
rem // INPUT \\
If Downkey()=1 rem backwards
XTest# = Newxvalue(X#,Wrapvalue(cAY#-180),7)
ZTest# = Newzvalue(Z#,Wrapvalue(cAY#-180),7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
rem // INPUT \\
If Leftkey()=1 rem rotate to the left...
XTest# = Newxvalue(X#,Wrapvalue(cAY#-90),7)
ZTest# = Newzvalue(Z#,Wrapvalue(cAY#-90),7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
rem // INPUT \\
If Rightkey()=1 rem rotate to the right...
XTest# = Newxvalue(X#,Wrapvalue(cAY#+90),7)
ZTest# = Newzvalue(Z#,Wrapvalue(cAY#+90),7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
rem // PROCESS \\
Rem Rotate camera
cTestX#=WrapValue(cAX#-180)
if cTestX# > 225 then cAX#=45
if cTestX# < 135 then cAX#=315
YRotate camera CurveAngle(cAY#,oldcAY#,24)
XRotate camera CurveAngle(cAX#,oldcAX#,24)
Y# = Get ground height(1,X#,Z#)+35
rem // PROCESS \\
Rem Position Camera
Position Camera X#,Y#,Z#
rem // PROCESS \\
rem Position object 2,10,7,15 : I assume this is a mistake
Loop
You may wonder why there is are no output blocks, that's because when you use 3D Dark Basic does all the output for you! We might want to switch to manual sync'ing though because DB is not very good at judging when to refresh the screen.
Now we can begin to group these blocks into subroutines. If you look at your comments you've already recognized blocks that do a specific job, now you just need to make subroutines of them. Your comment headings are:
* Control input for our camera
* Rotate Camera
* Position Camera
I'd add a fourth: Fire Bullet. The two camera routines can be merged because they both deal with the camera. You might then say "why don't I just put Fire Bullet in with the Camera Input?", well we don't want vague subroutines like "Input" because that doesn't tell us what's in there and we can't execute a specific bit when needed, so it defeats the point of having a subroutine. We could just as well put the entire program into one big subroutine but again this would be pointless.
A clue to which routines you can group together is the variables they use; if they use the same variables, like the camera routines, you can put them in the same routine because the fact they use the same variables means they are dependent on each other already so they might as well be in the same place. However, there may be circumstances where you want to execute only part of the routine, in this case split it up into two.
That's enough waffling about that. Here's the edited program with subroutines:
Hide mouse : rem I always put this before sync on so it is hidden straight away.
Sync on
Sync rate 60
set camera range 1,3000
Autocam off
Fog on
Fog distance 3000
Fog color RGB(128,128,128)
Color Backdrop RGB(128,128,128)
rem Making matrix...
make matrix 1,10000,10000,25,25
rem texture it...
remstart
Load image "image.bmp",1
prepare matrix texture 1,1,1,1
fill matrix 1,0,1
remend
rem Making a gun. I only know how to make a bazooka at the moment :P
Make object cylinder 1,2
XRotate Object 1,90
Scale object 1,10,5,10
position object 1,10,7,15
Lock object on 1
rem making Boolet :P
make object sphere 2,2
rem hiding it for now, since it won't show till we shoot it.
hide object 2
rem make 5 cubes and place randomly. I already used numbers 1 and 2, and I want to use numbers 5 to 10 for cubes. So I do.
For x = 5 to 10
Make object cube x,10
Position object x,Rnd(10000),0,Rnd(10000)
Next x
rem === MAIN ===
Do
rem Fire bullet
if spacekey()=1 and BulletLife<60 then gosub playershoot
gosub control_camera
gosub update_camera
Loop
rem === SUBROUTINES ===
control_camera:
If Upkey()=1 rem forward
XTest# = Newxvalue(X#,cAY#,7)
ZTest# = Newzvalue(Z#,cAY#,7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
If Downkey()=1 rem backwards
XTest# = Newxvalue(X#,Wrapvalue(cAY#-180),7)
ZTest# = Newzvalue(Z#,Wrapvalue(cAY#-180),7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
If Leftkey()=1 rem rotate to the left...
XTest# = Newxvalue(X#,Wrapvalue(cAY#-90),7)
ZTest# = Newzvalue(Z#,Wrapvalue(cAY#-90),7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
If Rightkey()=1 rem rotate to the right...
XTest# = Newxvalue(X#,Wrapvalue(cAY#+90),7)
ZTest# = Newzvalue(Z#,Wrapvalue(cAY#+90),7)
If XTest#>0 and XTest#<10000 and ZTest#>0 and ZTest#<10000
X#=XTest#
Z#=ZTest#
Endif
Endif
return
`//
playershoot:
Position object 2,10,7,15
Set object to camera orientation 2
BulletLife =120
show object 2
Dec BulletLife
Move object 2,12
return
`//
update_camera:
rem Rotate Camera
cTestX#=WrapValue(cAX#-180)
if cTestX# > 225 then cAX#=45
if cTestX# < 135 then cAX#=315
YRotate camera CurveAngle(cAY#,oldcAY#,24)
XRotate camera CurveAngle(cAX#,oldcAX#,24)
Rem Position Camera
Y# = Get ground height(1,X#,Z#)+35
Position Camera X#,Y#,Z#
return
`//
I've taken out a few of your comments, while they were useful to show me what you understand I've only left the ones in that would be in a normal program. Everything before the main loop is fine.
Presentation - On the whole good. There were no markers to show the different sections of the program (e.g. "=== SUBROUTINES ===") but there was enough white space to make it easy to follow. Indentation was mainly consistent with one or two errors (most people use two spaces instead of a tab so you can have more layers without it running off the page).
Remarks - Good. In some parts there was not enough commenting, in others there was too much. Try to be more to the point with your explanations and focus on the bits of code that would take time to understand without comments.
Sidenote - The gun still wont fire properly, can you tell why? The only routine that deals with bullets is the playershoot sub, which is only called when spacekey() is pressed. So the bullet will only be moved once. The bulletlife will only dec once so it will never be below 60 for the sub to be called again! What you need to do is to turn this sub into two subs, one that creates bullets (fires them), and one that moves bullets and reduces their life. The second routine is called every loop of the main but the first is only called when the user presses the fire key.