Okay, here's the final version. Arum Knight, I took your advice and added more enemies. And I gave them better AI.
Here's the game rules.
Use the W A S D keys to move the hovertank. You won't have to fire the weapon, it's always on.
If you brush the beam up against one of the blue globes, you score a kill. But if the globe is too close to you, your tank takes some damage.
If you drive too close to the globes, they will veer towards you and explode against you.
In each corner is a laser that tracks you and will fire at you if you get too close.
If your hull integrity reaches zero, you lose. If you last for two minutes, you get a score, based on how many kills you made, and modified by the damage you took.
You can use the numpad keys to change the camera viewpoint, and the "5" key in the center will cycle through various camera angles.
Rem Project: Brave Badger
Rem Created: Tuesday, October 13, 2009
Rem The Game Creators Forum code challenge
Rem **************************************
Rem Use W A S D to move the Badger vehicle.
Rem Num pad keys control the camera view.
Rem Use "5" key to cycle camera presets.
set display mode 800,600,32
disable escapekey
set ambient light 60
color backdrop 0
randomize timer()
gosub DeclareVariables
gosub DrawGraphics
gosub MakeObjects
sync on
sync rate 60
do
gosub PlayGame
if nTankHealth < 1 then gosub EndSimulation else gosub ShowScore
outlinetext("Continue? y/n",400,360,30)
sync
nWaitingForAnswer=1
while nWaitingForAnswer
if keystate(21) then nWaitingForAnswer=0
if keystate(49) then end
if keystate(1) then end
endwhile
loop
` game loop ***************************
PlayGame:
set text size 20
ink cWhite,cBlack
nStartTime=timer()
nGameLength=120000
nTankHealth=200
position object nTankBody,0,5,0
yrotate object nTankBody,0
for t = 1 to 3
position object nTarget(t),rnd(800)+50,20,rnd(800)+5
rotate object nTarget(t),0,rnd(359)+1,0
next t
do
` movement controls
nTurn = 0
nKeyDriftFlag = 1
if keystate(1) ` the ESC key
for x = 1 to nObject
delete object x
next x
end
endif
if keystate(17) ` "w" key - moving forward
nSpeed# = nSpeed# + .1
if nSpeed# > 5 then nSpeed# = 5
nKeyDriftFlag = 0
endif
if keystate(31) ` "s" key - backward movement
nSpeed# = nSpeed# - .1
if nSpeed# < -5 then nSpeed# = -5
nKeyDriftFlag = 0
endif
` slow down to zero movement if no movement keys are pressed
if nKeyDriftFlag
if nSpeed# < .1 and nSpeed# > -.1 then nSpeed# = 0
if nSpeed# < 0 then nSpeed# = nSpeed# + .1
if nSpeed# > 0 then nSpeed# = nSpeed# - .1
endif
if keystate(30) ` "a" key - turning left
nTurn = -1
endif
if keystate(32) ` "d" key - turning right
nTurn = 1
endif
` camera controls
if keystate(72) ` "8" key on numpad - camera closer to tank
dec camDistance
if camDistance < 40 then camDistance = 40
endif
if keystate(80) ` "2" key on numpad - camera farther from tank
inc camDistance
if camDistance > 300 then camDistance = 300
endif
if keystate(75) ` "4" on keypad - camera turn left
camAngleOffset = wrapvalue(camAngleOffset-2.5)
endif
if keystate(77) ` "6" key on numpad - camera turn right
camAngleOffset = wrapvalue(camAngleOffset+2.5)
endif
if keystate(73) ` "9" on numpad - camera higher
inc camHeight
if camHeight > 300 then camHeight = 300
endif
if keystate(81) ` "3" on numpad - camera lower
dec camHeight
if camHeight < 27 then camHeight = 27
endif
if keystate(76) ` "5" on numpad - cycle camera views
if timer() > nCameraTimer + 500
nCameraTimer = timer()
inc camShot
if camShot = 7 then camShot = 1
select camShot
case 1
camAngleOffset = 0
camDistance = 60
camHeight = 27
endcase
case 2
camAngleOffset = 90
camDistance = 95
camHeight = 27
endcase
case 3
camAngleOffset = 270
camDistance = 95
camHeight = 27
endcase
case 4
camAngleOffset = 180
camDistance = 117
camHeight = 27
endcase
case 5
camAngleOffset = 30
camDistance = 200
camHeight = 68
endcase
case 6
camAngleOffset = 0
camDistance = 200
camHeight = 100
endcase
endselect
endif
endif
` flash tank laser
if timer()>nTankLaserTimer+50
if object visible(nTankBeam)
hide object nTankBeam
nTankLaserTimer=timer()
else
show object nTankBeam
nTankLaserTimer=timer()
endif
endif
` check tank collision
if nSpeed#<0 then nMovement = -1
if nSpeed#>0 then nMovement = 1
if nTurn = 1 and checkcollision(nTankBumper2) then nTurn = 0 : nSpeed# = 0
if nTurn = -1 and checkcollision(nTankBumper1) then nTurn = 0 : nSpeed# = 0
if nTurn = 1 and checkcollision(nTankBumper3) then nTurn = 0 : nSpeed# = 0
if nTurn = -1 and checkcollision(nTankBumper4) then nTurn = 0 : nSpeed# = 0
if nMovement = 1 and checkcollision(nTankBumper1) then nMovement = 0 : nSpeed# = 0
if nMovement = 1 and checkcollision(nTankBumper2) then nMovement = 0 : nSpeed# = 0
if nMovement =-1 and checkcollision(nTankBumper3) then nMovement = 0 : nSpeed# = 0
if nMovement = -1 and checkcollision(nTankBumper4) then nMovement = 0 : nSpeed# = 0
` move and turn tank
yrotate object nTankBody, wrapvalue(object angle y(nTankBody)+nTurn)
move object nTankBody, nSpeed# * abs(nMovement)
position object nTankBeam,object position x(nTankBody),object position y(nTankBody),object position z(nTankBody)
set object to object orientation nTankBeam,nTankBody,1
move object nTankBeam,163
move object up nTankBeam,15
for t = 1 to 3
` check distance from target to tank
d#=getdistance(object position x(nTankBody),object position y(nTankBody),object position z(nTankBody),object position x(nTarget(t)),object position y(nTarget(t)),object position z(nTarget(t)))
` if the target is close to the tank, chase it down
if d#<200
point object nTarget(t),object position x(nTankBody),20,object position z(nTankBody)
endif
` check for tank beam hitting target
if object collision(nTankBeam,nTarget(t)) and nTargetStatus(t) = 0
inc nHits
nTargetStatus(t)=1
texture object nTarget(t),tFire
if d# < 150.0
dec nTankHealth, rnd(5) + 7
if nTankHealth < 1 then gosub EndSimulation
endif
endif
` move the target
if nTargetStatus(t)=0
move object nTarget(t), 3
else
set alpha mapping on nTarget(t), 100 - (nTargetStatus(t) * 20)
scale object nTarget(t), 100 + (nTargetStatus(t) * 40),100 + (nTargetStatus(t) * 40),100 + (nTargetStatus(t) * 40)
inc nTargetStatus(t)
if nTargetStatus(t) = 6
position object nTarget(t), rnd(909)+90,20,rnd(909)+90
scale object nTarget(t),100,100,100
texture object nTarget(t),tNeon
set alpha mapping on nTarget(t),100
rotate object nTarget(t),0,rnd(259)+1,0
nTargetStatus(t)=0
endif
endif
` check for target near boundary
if object position z(nTarget(t)) > 900 then rotate object nTarget(t),0,wrapvalue(90+rnd(179)),0
if object position z(nTarget(t)) < -900 then rotate object nTarget(t),0,wrapvalue(90-rnd(179)),0
if object position x(nTarget(t)) > 900 then rotate object nTarget(t),0,wrapvalue(0-rnd(179)),0
if object position x(nTarget(t)) < -900 then rotate object nTarget(t),0,wrapvalue(0+rnd(179)),0
next t
` move camera
set camera to follow object position x(nTankBody),object position y(nTankBody),object position z(nTankBody),wrapvalue(object angle y(nTankBody)+camAngleOffset),camDistance,camHeight,1,0
point camera object position x(nTankBody), object position y(nTankBody), object position z(nTankBody)
` update and fire defensive lasers
for laser = 1 to 4
point object nLaser(laser), object position x(nTankBody), 15, object position z(nTankBody)
nDistance = getdistance(object position x(nTankBody),object position y(nTankBody),object position z(nTankBody),object position x(nLaser(laser)),object position y(nLaser(laser)),object position z(nLaser(laser)))
if nDistance<600
if rnd(30)=1 and object visible(nLaserBeam(laser))=0
scale object nLaserBeam(laser),100,100,(nDistance*100)+10
position object nLaserBeam(laser),0,0,(nDistance/2) + 10
show object nLaserBeam(laser)
laserTimer(laser) = timer()
endif
endif
` take damage from defensive lasers
if object visible(nLaserBeam(laser)) then dec nTankHealth, 1
if nTankHealth < 1 then return
` end defensive laser fire
if timer() > laserTimer(laser) + 50
hide object nLaserBeam(laser)
position object nLaserBeam(laser),0,0,0
scale object nLaserBeam(laser),100,100,100
endif
next laser
` calculate the clock
nElapsedTime=timer()-nStartTime
nTimeLeft=nGameLength-nElapsedTime
nSeconds=nTimeLeft/1000
nMinutes=nSeconds/60
nSeconds=nSeconds-nMinutes*60
sTime$="0"+str$(nMinutes)+":"
if nSeconds<10 then sTime$=sTime$+"0"
sTime$=sTime$+str$(nSeconds)
` display status, score, and clock
text 0,0," Vehicle Integrity: " + str$(nTankHealth/2) + "% Targets Destroyed: " + str$(nHits) + " Time Left: " + sTime$
if nSeconds=0 AND nMinutes=0 then return
sync
loop
return
`****************************
DeclareVariables:
` color assignments
#constant cBlack=rgb(0,0,0)
#constant cWhite=rgb(255,255,255)
#constant cRed=rgb(255,0,0)
#constant cDarkRed=rgb(100,0,0)
#constant cLightBlue=rgb(150,150,255)
#constant cBlue=rgb(0,0,255)
#constant cDarkBlue=rgb(0,0,100)
#constant cDarkYellow=rgb(100,100,0)
#constant cYellow=rgb(255,255,0)
#constant cGreen=rgb(0,255,0)
#constant cDarkGreen=rgb(0,100,0)
#constant cGrey=rgb(200,200,200)
#constant cLightGray=rgb(225,225,225)
#constant cMediumGray=rgb(150,150,150)
#constant cDarkGray=rgb(50,50,50)
#constant cBrown=rgb(255,128,0)
#constant cDarkBrown=rgb(125,75,0)
#constant cDarkerBrown=rgb(65,25,0)
#constant cTan=rgb(160,120,70)
#constant cMediumTan=rgb(155,115,65)
#constant cDarktan=rgb(150,110,50)
#constant cNeon=rgb(87,87,255)
` texture assignments
tBackdrop=1
tFloorGrid=2
tBodyTop=3
tBillboard=4
tID=5
tBlack=6
tBarrel=7
tBodyFront=8
tLaser=9
tTankSkirt=10
tWallGrid=11
tNeon=12
tFire = 13
` camera assignments
camAngleOffset=0
camDistance=200
camHeight=100
camShot=6
` globals for collision function
global nCollisionStart, nCollisionEnd, nTankBody, nKeyTimer
nSeconds as integer
nMinutes as integer
dim nLaser(4)
dim nLaserBeam(4)
dim laserTimer(4)
dim nTarget(3)
dim nTargetStatus(3)
` misc variables
nTankHealth as integer = 200
return
`*********************************
DrawGraphics:
` tank shadow and other black parts
cls cBlack
get image tBlack,0,0,10,10,3
` laser beam
cls cRed
get image tLaser,0,0,7,7
` neon for marble
cls cNeon
get image tNeon,0,0,7,7
` tank skirts
cls cBlack
ink cYellow,cBlack
for x = 5 to 20
line x,5,x+15,40
next x
get image tTankSkirt,0,0,45,45
box 100,100,300,300,cRed,cYellow,cRed,cYellow
get image tFire,100,100,300,300
` camo background
ink cTan,cBlack
box 0,0,800,600
for b = 1 to 5000
r=rnd(2)
select r
case 0: c=cTan : endcase
case 1: c=cDarkTan : endcase
case 2: c=cMediumTan : endcase
endselect
ink c,cBlack
bx=rnd(800)
by=rnd(600)
box bx,by,bx+10,by+10
next b
` tank body parts
get image tBodyTop,1,1,200,340,3
` back billboard on tank <=============== draw a hatch cover!
set text font "ariel"
set text to bold
set text size 28
ink cBlack,cBlack
text 10,202,"BADGER MARK IV MOD 5"
ink cWhite,cBlck
text 8,200,"BADGER MARK IV MOD 5"
get image tBillboard,1,1,300,240,3
` tank ID number
cls
set text size 100
ink cDarkBrown,cBlack
text 5,5,"5"
ink cWhite,cBlack
text 0,0,"5"
get image tID,0,10,50,90
` floor tiles
ink cMediumGray,cBlack
box 0,0,127,127
ink cLightGray,cBlack
box 2,2,124,124
get image tFloorGrid,0,0,127,127,3
get image tWallGrid,0,0,127,127,3
return
`*************************************
MakeObjects:
` make the walls
inc nObject
make object plane nObject,2000,20
position object nObject,0,10,1000
texture object nObject,tWallGrid
scale object texture nObject,20,1
nCollisionStart=nObject
inc nObject
make object plane nObject,2000,20
position object nObject,0,10,-1000
texture object nObject,tWallGrid
scale object texture nObject,20,1
inc nObject
make object plane nObject,2000,20
rotate object nObject,0,90,0
position object nObject,-1000,10,0
texture object nObject,tWallGrid
scale object texture nObject,20,1
inc nObject
make object plane nObject,2000,20
rotate object nObject,0,90,0
position object nObject,1000,10,0
texture object nObject,tWallGrid
scale object texture nObject,20,1
inc nObject
make object box nObject,100,10,100
texture object nObject,tWallGrid
position object nObject,100,5,100
` put all the other colliding terrain before this line:
nCollisionEnd = nObject
`make the floor
inc nObject
make object plane nObject, 2000,2000
rotate object nObject, 90, 0, 0
position object nObject, 0,0,0
texture object nObject, tFloorGrid
scale object texture nObject, 20, 20
set object collision off nObject
` the laser poles
inc nObject
make object box nObject,2,50,2
position object nObject,-1005,25,1005
texture object nObject,tWallGrid
inc nObject
make object box nObject,2,50,2
position object nObject,1005,25,1005
texture object nObject,tWallGrid
inc nObject
make object box nObject,2,50,2
position object nObject,-1005,25,-1005
texture object nObject,tWallGrid
inc nObject
make object box nObject,2,50,2
position object nObject,1005,25,-1005
texture object nObject,tWallGrid
` the laser bases
inc nObject
make object box nObject,10,20,10
position object nObject,-1005,10,1005
texture object nObject,tWallGrid
inc nObject
make object box nObject,10,20,10
position object nObject,1005,10,1005
texture object nObject,tWallGrid
inc nObject
make object box nObject,10,20,10
position object nObject,-1005,10,-1005
texture object nObject,tWallGrid
inc nObject
make object box nObject,10,20,10
position object nObject,1005,10,-1005
texture object nObject,tWallGrid
` make the laser guns
for laser = 1 to 4
inc nObject
nLaser(laser) = nObject
make object box nLaser(laser),7,7,20
next laser
` make the laser beams
for beam = 1 to 4
inc nObject
nLaserBeam(beam) = nObject
make object box nLaserBeam(beam),2,2,1
glue object to limb nLaserBeam(beam),nLaser(beam),0
position object nLaserBeam(beam),0,0,0
texture object nLaserBeam(beam),tLaser
hide object nLaserBeam(beam)
next beam
` put the lasers on the poles
position object nLaser(1),-1005,50,1005
position object nLaser(2),1005,50,1005
position object nLaser(3),-1005,50,-1005
position object nLaser(4),1005,50,-1005
` make the tank
` this is the main body, root limb
inc nObject
nTankBody = nObject
make object box nTankBody,55,3,85
` these are the four bumpers used to check for collisions
inc nObject
nTankBumper1 = nObject
make object box nTankBumper1,26,1,40
inc nObject
nTankBumper2 = nObject
make object box nTankBumper2,26,1,40
inc nObject
nTankBumper3 = nObject
make object box nTankBumper3,26,1,40
inc nObject
nTankBumper4 = nObject
make object box nTankBumper4,26,1,40
` these are the rest of the tank parts
inc nObject
nTankBody1 = nObject
make object triangle nTankBody1,25,20,-40,-25,20,-40,25,5,40
inc nObject
nTankBody2 = nObject
make object triangle ntankBody2,25,5,40,-25,20,-40,-25,5,40
inc nObject
nTankSide1 = nObject
make object triangle nTankSide1,25,20,-40,25,5,-40,25,5,40
inc nObject
nTankSide2 = nObject
make object triangle nTankSide2,-25,20,-40,-25,5,-40,-25,5,40
inc nObject
nTankFront = nObject
make object plane nTankFront,50,5
inc nObject
nTankBack = nObject
make object plane nTankBack,50,5
inc nObject
nTankBillboard = nObject
make object plane nTankBillboard,50,15
inc nObject
nTankSkirt1 = nObject
make object plane nTankSkirt1,80,5
inc nObject
nTankSkirt2 = nObject
make object plane nTankSkirt2,80,5
inc nObject
nTankBarrel1 = nObject
make object box nTankBarrel1,3,3,60
inc nObject
nTankBarrel2 = nObject
make object box nTankBarrel2,8,5,6
inc nObject
nTankBarrel3 = nObject
make object sphere nTankBarrel3,3
inc nObject
nTankShadow = nObject
make object plane nTankShadow,60,90
inc nObject
nTankIDPanel1 = nObject
make object plane nTankIDPanel1,8,10
inc nObject
nTankIDPanel2 = nObject
make object plane nTankIDPanel2,8,10
inc nObject
nTankBeam = nObject
make object box nTankBeam,2,2,400
` glue all tank parts together
glue object to limb nTankBumper1,nTankBody,0
glue object to limb nTankBumper2,nTankBody,0
glue object to limb nTankBumper3,nTankBody,0
glue object to limb nTankBumper4,nTankBody,0
glue object to limb nTankBody1,nTankBody,0
glue object to limb nTankBody2,nTankBody,0
glue object to limb nTankSide1,nTankBody,0
glue object to limb nTankSide2,nTankBody,0
glue object to limb nTankFront,nTankBody,0
glue object to limb nTankBack,nTankBody,0
glue object to limb nTankBillboard,nTankBody,0
glue object to limb nTankSkirt1,nTankBody,0
glue object to limb nTankSkirt2,nTankBody,0
glue object to limb nTankBarrel1,nTankBody,0
glue object to limb nTankBarrel2,nTankBody,0
glue object to limb nTankBarrel3,nTankBody,0
glue object to limb nTankShadow,nTankBody,0
glue object to limb nTankIDPanel1,nTankBody,0
glue object to limb nTankIDPanel2,nTankBody,0
` scale and rotate some tank parts
scale object nTankBarrel3,100,100,1
rotate object nTankSkirt1,0,90,0
rotate object nTankSkirt2,0,90,0
rotate object nTankBarrel1,0,0,45
rotate object nTankShadow,90,0,0
rotate object nTankIDPanel1,0,90,0
rotate object nTankIDPanel2,0,-90,0
` position tank parts
position object nTankBumper1,-17,0,25
position object nTankBumper2,17,0,25
position object nTankBumper3,-17,0,-25
position object nTankBumper4,17,0,-25
position object nTankFront,0,2.5,40
position object nTankBack,0,2.5,-40
position object nTankBillboard, 0,12.5,-40
position object nTankSkirt1,25,2.5,0
position object nTankSkirt2,-25,2.5,0
position object nTankBarrel1,0,15,0
position object nTankBarrel2,0,15,30
position object nTankBarrel3,0,15,33
position object nTankShadow,0,-4.9,0
position object nTankIDPanel1,25.1,12,-33
position object nTankIDPanel2,-25.1,12,-33
` texture the tank parts
texture object nTankBody,tBodyTop
texture object nTankBody1,tBodyTop
texture object nTankBody2,tBodyTop
texture object nTankSide1,tBodyTop
texture object nTankSide2,tBodyTop
texture object nTankFront,tTankSkirt
texture object nTankBack,tTankSkirt
texture object ntankBillboard,tBillboard
texture object nTankSkirt1,tTankSkirt
texture object nTankSkirt2,tTankSkirt
texture object nTankBarrel1,tBodyTop
texture object nTankBarrel2,tBodyTop
texture object nTankBarrel3,tBlack
texture object nTankShadow,tBlack
texture object nTankIDPanel1,tID
texture object nTankIDPanel2,tID
texture object nTankBeam, tLaser
set alpha mapping on nTankShadow,30
scale object texture nTankFront,8,1
scale object texture nTankBack,8,1
scale object texture nTankSkirt1,12,1
scale object texture nTankSkirt2,12,1
set object transparency nTankIDPanel1,2
set object transparency nTankIDPanel2,2
set object ambience nTankBody,cMediumGray
set object ambience nTankSide1,cMediumGray
set object ambience nTankSide2,cMediumGray
set object ambience nTankBillboard,cDarkGray
set object ambience nTankBarrel1,cBlack
` hide the bumpers
hide object nTankBumper1
hide object nTankBumper2
hide object nTankBumper3
hide object nTankBumper4
` make the targets
for t = 1 to 3
inc nObject
nTarget(t) = nObject
make object sphere nTarget(t),25,36,36
texture object nTarget(t),tNeon
inc nObject
make object sphere nObject,30,36,36
texture object nObject,tBlack
set alpha mapping on nObject,30
glue object to limb nObject, nTarget(t),0
scale object nObject,120,0,120
position object nObject,0,-19.9,0
next t
return
`*************************************
function checkcollision(nObjectToCheck as integer)
nCollisionFlag=0
for nCheck = nCollisionStart to nCollisionEnd
if object collision(nObjectToCheck,nCheck)
nCollisionFlag = 1
endif
next nCheck
endfunction nCollisionFlag
`*************************************
function getdistance(x1 as float,y1 as float,z1 as float,x2 as float,y2 as float,z2 as float)
xd=x1-x2
yd=y1-y2
zd=z1-z2
nDistance#=sqrt((xd*xd)+(yd*yd)+(zd*zd))
endfunction nDistance#
`*************************************
function outlinetext(text$ as string, x as integer, y as integer, tsize as integer)
set text size tsize
ink cBlack,cBlack
center text x+3,y,text$
center text x-3,y,text$
center text x,y-3,text$
center text x,y+3,text$
center text x-3,y-3,text$
center text x+3,y+3,text$
center text x+3,y-3,text$
center text x-3,y+3,text$
ink cWhite,cBlack
center text x,y,text$
endfunction
`*************************************
EndSimulation:
outlinetext("VEHICLE DESTROYED",400,200,50)
outlinetext("SIMULATION TERMINATED",400,240,50)
return
`*************************************
ShowScore:
nFinalScore = ceil((nHits*50)*(nTankHealth*.01))
outlinetext("STAGE COMPLETED",400,200,50)
outlinetext("SCORE: "+str$(nFinalScore),400,240,50)
return
Rich
EDIT: Well, crud. I just realized that my "ink" commands don't work in vanilla DBPro. They don't have the background color paramater. I have IanM's matrix dlls, and his ink command supercedes the DBPro one. It doesn't require the background color. I didn't realize this until I compiled the source on a machine that doesn't have IanM's utils. So, I've edited the above code to include the second parameter. I believe that's the only thing in my code that's non-vanilla DBPro.