DarkBASIC Development Materials (Assembled from DarkBASIC FPS Tutorial)
Source Code in (if you installed it the way that I did, otherwise find \Dark Basic Professional\ and drill down from there.)
C:\Program Files\The Game Creators\Dark Basic Professional\Help\Tutorials
TUTORIAL ONE
Designing Your Game
The first step in creating a large program is understanding exactly what you need to do. There are different ways to know what this is, and one of the traditional methods is a pen and a piece of paper. You already have an idea what you want to create, and its amazing how many details surface when you apply those thoughts to paper.


The above illustration demonstrates the kind of things that surfaced for the programmer who wrote these tutorials when faced with the
challenge of writing an FPS Game.
TUTORIAL TWO
Collecting Your Media
The next step is locating and preparing all your media. Media can be any file
that adds into your main program, usually in the form of 3D worlds, 3D models,
sounds, music, images and pictures. We will require most of these types of
media to create our FPS Game. Though you would resource these media files
yourself from Model, Audio and Resource collections, we have prepared the media
you will require for this tutorial.

The media includes a BSP World file for the game level. A sky sphere model for
the sky backdrop. A gun model for the player view. An enemy model for the foe
we must vanquish. A selection of sounds to bring the game to life including a
large looping wave file for our in-game music. A fire image for our particle
bullet and a few miscellaneous items to make the game look nicer.
All these media files were sourced from the Dark Basic Professional Resources
collection and are all royalty free. It is important that all the media you use
is likewise copyrighted to owners who have given express permission before you
use their work. The media files once collected are arranged in suitable folders
and renamed for easy reference when we focus on our program and away from the
names of all our media files.
TUTORIAL THREE
The Program Skeleton
The skeleton of the program is the first thing you will be thinking about after
the design stage. Most game skeletons are very similar and include the
following. A setup stage to load and prepare your objects. A main loop to run
your game logic and a cleanup stage where all the loaded media is released.

In Dark Basic Professional you only have to concern yourself with the first two
in most cases. All media loaded is released automatically when you leave a Dark
Basic Professional program. The first and second stages are very easy to
visualise and can be coded in the following two steps. You must first create
your setup stage:
rem TUT3Arem Initial settingssync on : sync rate 100backdrop off : hide mouse rem Load all media for gamegosub _load_game rem Setup all objects for gamegosub _setup_game
You then create the main loop and any calls you will make
over and over again to control the elements within your game:
rem TUT3Brem Game loopdo rem Control game elements gosub _control_player gosub _control_gunandbullet gosub _control_enemies rem Update screen sync rem End looploop
The last step is to create all the subroutines that the
first two stages call. Subroutines are blocks of code you can jump to in order
to execute instructions that achieve a subtask. A subtask could be something
like loading the player, controlling the player, deleting the player and so on.
It is easier to understand what a subroutine does when given a useful name:
rem TUT3C_control_player:return _control_gunandbullet:return _control_enemies:return _control_stats:return _setup_game:return _load_game:return
As you
can see, each subroutine has a name that describes what it does. At the moment
they are all empty and contain no code. Later on in the tutorial we shall fill
these subroutines with commands.
TUTORIAL FOUR
Loading The World
The first order of business is to create a world in which our game will be set.
Once upon a time this was a very difficult proposal and would often become the
first major stumbling block for many would be game writers. With the built in
BSP commands however, such a task is mind bogglingly simple.

With a single command we can load an entire BSP world. The BSP file contains
information about polygons, collision, textures and even special effects also
known as shaders. With a second command we can create a skysphere to provide an
enclosed environment for our world:
rem TUT4Arem Load BSP world and sky modelload bsp "world\ikzdm1.pk3","ikzdm1.bsp"SkyObj=1 : load object "models\sky\am.x",SkyObj
When the BSP world and sky are loaded, we must setup the
camera and ensure the autocam does not start moving around without our direct
control. We must also scale down the size of the sky to bring it closer so we
bring it within the maximum distance of our 3D universe and switch off sky
culling so polygons that would normally show from the outside of the sky sphere
will now show on the inside as well:
rem TUT4Brem Setup cameraset camera range 1,10000autocam off rem Setup sky modelset object SkyObj,1,0,0,0,0,0,0scale object SkyObj,20,20,20
In order that the user stay informed, we will provide a
text prompt when the BSP is loading. Sometimes BSP worlds can be very large and
can take minutes to fully load, so an onscreen prompt is very important. In
order to make our game as presentable as possible, we will choose a nice large
font:
rem TUT4Crem Select fontset text font "arial" : set text size 16set text to bold : set text transparent rem Loading promptsync : center text screen width()/2,screen height()/2,"LOADING" : sync
The
reason for the pre and post additions of the SYNC command is that we have
initialised our program with the SYNC ON command. This tells the computer that
we would like to update the screen ourselves; manually. In order to see the
loading prompt, a sync must be made after we have drawn the text.
TUTORIAL FIVE
Adding A Player
After the world has been loaded, we must create a player for our game. As a
first person shooter, the player is essentially the camera. You move the camera
and are treated to a view of the world in the first person.

So that we can re-use our player initialization code, we will place the code
somewhere we can trigger it by the simple switching of a variable value. So
that the player is initialized the first time we run the game, we will set the
trigger variable first:
rem TUT5Arem Trigger player initializationrestart=1
We then provide the code that will setup the player when
this variable is set to one. By using BSP collision on the camera, we
completely automate the handling of collision within the 3D world. This not
only provides sliding collision on any surface, but does so at great speed:
rem TUT5Brem In case of restartif restart=1 restart=0 set bsp collision off 1rotate camera 0,0,0
position camera 2,2,2 set bsp camera collision 1,0,0.75,0endif
After the player has been setup, we can start to control
it. We will first need to provide control of the players rotation, movement and
gravity:
rem TUT5Crem Control player directionrotate camera camera angle x(0)+(mousemovey()/2.0),camera angle y(0)+(mousemovex()/2.0),0 rem Control player movementcx#=camera angle x(0) : cy#=camera angle y(0)if upkey()=1 then xrotate camera 0,0 : move camera 0,0.2 : xrotate camera 0,cx#if downkey()=1 then xrotate camera 0,0 : move camera 0,-0.2 : xrotate camera 0,cx#if leftkey()=1 then yrotate camera 0,cy#-90 : move camera 0.2 : yrotate camera 0,cy#if rightkey()=1 then yrotate camera 0,cy#+90 : move camera 0.2 : yrotate camera 0,cy#if wrapvalue(camera angle x(0))>40 and wrapvalue(camera angle x(0))<180 then xrotate camera 0,40if wrapvalue(camera angle x(0))>180 and wrapvalue(camera angle x(0))<280 then xrotate camera 0,280 rem Apply simple gravity to playerposition camera camera position x(),camera position y()-0.1,camera position z()
In addition, we must ensure the player is always at the
center of the universe. To that end, when ever the player moves we must adjust
the position of the sky and the 3D listener which represents the player in our
game:
rem TUT5Drem Player is always focal point of skyposition object SkyObj,camera position x(),camera position y(),camera position z() rem Position listener at player for 3D soundposition listener camera position x(),camera position y(),camera position z()rotate listener camera angle x(),camera angle y(),camera angle z()
TUTORIAL SIX
Adding A Gun
It would be a very short shooter game if our player did not have a gun, and
bullets to fire. In traditional first person style, the gun protrudes from the
base of the screen and the bullets fire into a crosshair fixed to the center of
the screen.

The first step is to load all the models, sounds and images we will need to
create the visual effect. We must load a gun model, some appropriate sounds,
some sniper music and a crosshair for the screen:
rem TUT6Arem Load model for gunGunObj=2 : load object "models\gun\gun.x",GunObj rem Load all soundsGunSnd=1 : load sound "sounds\gun.wav",GunSndImpactSnd=2 : load 3dsound "sounds\impact.wav",ImpactSndDieSnd=3 : load sound "sounds\die.wav",DieSnd rem Load music (WAV best for looping)MusicSnd=101 : load sound "sounds\ingame.wav",MusicSndloop sound MusicSnd : set sound volume MusicSnd,80 rem Load imagesFireImg=1 : load image "images\fire.bmp",FireImgCrossHairImg=2 : load image "images\crosshair.bmp",CrossHairImg
Once the media has been loaded, we can setup the objects
before the game begins. The gun needs to be locked to the screen as it is part
of the player camera now. We also need to create a bullet object and the
crosshair for the screen:
rem TUT6Brem Setup gun for playerlock object on GunObjscale object GunObj,2,2,4rotate object GunObj,270,0,0position object GunObj,0.5,-1,2disable object zdepth GunObj rem Create object for bulletBulletObj=3 : make object cube BulletObj,0.1 rem Create simple sprite based crosshairsprite 1,320-16,240-16,CrossHairImgset sprite 1,0,1
When the user presses the mouse button, the gun must be
fired. In firing the gun we must first make sure the gun has cooled down enough
to allow another shot. This is a storyline to cover for a technical limitation
as our tutorial game allows only one bullet to be fired at any one time. When
the gun is fired, a sound is played and the bullet is created at the players
position and rotated to face the target:
rem TUT6Crem Control gun firingif mouseclick()=1 and bullet=-50 bullet=100 play sound GunSnd position object BulletObj,camera position x(0),camera position y(0),camera position z(0) rotate object BulletObj,camera angle x(0),camera angle y(0),0 set bsp object collision 2,BulletObj,0.1,1 move object BulletObj,0.2endif
During the life of the bullet, we must move it forward and
ensure it is destroyed when it hits a wall. We use the built in BSP collision
setup in the previous code segment to make this task simple:
rem TUT6Drem Control life of bulletif bullet>0 rem If bullet collides with BSP world if bsp collision hit(2)=1 or bulletimpact=1 rem End bullet on wall position sound ImpactSnd,object position x(BulletObj), object position y(BulletObj), object position z(BulletObj) play sound ImpactSnd bulletimpact=0 bullet=0 else rem Move bullet dec bullet move object BulletObj,0.5 endif rem Bullet dies if bullet=0 set bsp collision off 2 endif else rem Gun recharge phase if bullet>-50 then dec bulletendif
TUTORIAL SEVEN
Adding Enemies
All shooters need something to shoot at. In this case we opt for those poor
aliens again. They may have come to visit us with a message of peace, but our
player is interested only in target practice.

The first step is to load the models for our enemy objects:
rem TUT7Arem Load models for enemiesEneObj=11for ene=EneObj to EneObj+4load object "models\enemy\H-Alien Psionic-Idle.x",ene
append object "models\enemy\H-Alien Psionic-Die.x", ene, total object frames(ene)+1 position object ene,2,2,4 loop object ene,0,25next ene
Not forgetting the sounds we will need to give our enemies
a realistic presence within the game. With additional use of 3D sounds and a
scary alien breathing sound we can create the creepy effect of 'what's just
around the corner' for our game:
rem TUT7BEnemySnd=11 : load 3dsound "sounds\enemy.wav",EnemySndEnemygunSnd=12 : load 3dsound "sounds\enemygun.wav",EnemygunSndEnemydieSnd=13 : load 3dsound "sounds\enemydie.wav",EnemydieSnd
Now we have loaded our enemy media, we must control them
within our game. We must control each enemy, ensuring we can move, rotate,
handle gravity and play 3D sound for them:
rem TUT7Crem Variable for finding closest enemycdist#=9999.99 rem Handle enemies within worldfor ene=EneObj to EneObj+4 rem If enemy alive
if object visible(ene)=1 rem Kill this enemy killenemy=0 rem Move enemy on a slow curve for appearance of intelligence if object angle z(ene)=0 yrotate object ene,wrapvalue(object angle y(ene)+2) endif if object angle z(ene)=1 yrotate object ene,wrapvalue(object angle y(ene)-2) endif if object angle z(ene)=2 move object ene,0.05 else move object ene,0.02 endif rem Switch direction of curve based on a random value if rnd(200)=1 then zrotate object ene,rnd(1) rem Handle gravity for enemy position object ene,object position x(ene),object position y(ene)-0.01,object position z(ene) rem Work out angle and distance between enemy and player dx#=camera position x(0)-object position x(ene) dy#=camera position y(0)-object position y(ene) dz#=camera position z(0)-object position z(ene) dist#=abs(sqrt(abs(dx#*dx#)+abs(dy#*dy#)+abs(dz#*dz#))) viewa#=wrapvalue(atanfull(dx#,dz#)) obja#=wrapvalue(object angle y(ene)) if viewa#>180 then viewa#=viewa#-360 if obja#>180 then obja#=obja#-360 rem Closest enemy emits the enemy sound if dist#26+25 and object visible(ene)=1 killenemy=1 endif if killenemy=1 set bsp collision off 3+(ene-EneObj) hide object ene : dec aliensleft killenemy=0 endif rem If enemy alive ENDIF endif next ene
To make sure that our aliens appear creepy, we will
constantly play their presence sound effect, and scale the 3D sound listener so
you only hear them when they are very close to the player:
rem TUT7Drem Start the enemy presence soundloop sound EnemySndscale listener 0.1
TUTORIAL EIGHT
Adding Logic
Logic is the cornerstone of every game, no matter what kind of game it is.
Logic is responsible for everything that happens in the game. In this sense,
logic is the code to control when you kill an alien, when the alien kills you,
when you win the game and when you lose the game. As this tutorial does not
attempt to write a complete game, we will add the logic to restart when the
player dies and the logic to move the aliens around the world and allow the
player to shoot them.

We can give our aliens the appearance of intelligence by letting them move
towards the player when they are looking in the right direction, and the player
is close enough:
rem TUT8Arem If enemy 'facing player' and 'on similar height' and 'close', zoom inif abs(viewa#-obja#)<10.0 and abs(dy#)<5.0 and dist#<30.0 if object angle z(ene)<>2 then play sound EnemygunSnd rotate object ene,0,viewa#,2 set object speed ene,2else set object speed ene,1endif
When the player gets too close to the enemy, the player
must die. As we wish the game to continue, we shall reset the players position
and in order to avoid the enemy constantly attacking the player, we remove the
alien from the game:
rem TUT8Brem If enemy gets too close to player, player diesif dist#<2.0 play sound DieSnd for x=0 to 100 point camera object position x(ene), object position y(ene)+(x/20.0), object position z(ene) sync next x restart=1 killenemy=1endif
When the bullet gets too close to an enemy, both the enemy
and the bullet die. The bullet will of course live again when the player fires
the gun, but the enemy alas will not be so fortunate this game:
rem TUT8Crem If enemy and bullet in same space, enemy diesif bullet>0 if object collision(BulletObj,ene)>0 play sound EnemydieSnd play object ene,26,26+50 set object speed ene,1 bulletimpact=1 endifendif
Having all the enemies in front of you does not make for a
very good game, so adding logic to space them out and give them collision so
they don't move through walls provides good enemy logic for the game:
rem TUT8Drem Place enemies throughout world and set BSP collision for themaliensleft=0restore EnemyPosDatafor ene=EneObj to EneObj+4read ex#,ey#,ez#
position object ene,ex#,ey#,ez# set bsp object collision 3+(ene-EneObj),ene,0.75,0 yrotate object ene,180 : fix object pivot ene inc aliensleftnext ene
As the above code uses the RESTORE and READ commands, we
must provide some DATA statements containing coordinates to place the enemies
throughout the world. These coordinates were calculated by walking around with
the player and writing down the coordinate of the player:
rem TUT8Erem Enemy position data within levelEnemyPosData:data -9.27,9.98,-2.78data -16.54,-0.22,19.18data 2.0,9.0,25.0data -2.0,-9.0,25.0data 2,4.0,10.0
TUTORIAL NINE
Adding Shine
Shine is the fine layer of detail that turns a good game into a great game.
Shine is why you like the latest model of car, stereo and washing machine. It’s
the six coats of polish you pay for through the nose.

We could add shine forever. For this tutorial we shall add just two coats of
shine. Some statistical shine and particle bullet shine. For our stats, we
shall inform the user how many aliens remain in the level, when the level is
complete and how far away the player is to the nearest alien. The function
below does all this:
rem TUT9Arem Distance to next alienif aliensleft>0 then text 20,screen height()-40,"DISTANCE READING:"+str$(abs(cdist#*100)) rem Aliens Left Stats$=str$(aliensleft)+" ALIENS LEFT"if aliensleft=0 then s$="LEVEL COMPLETE!" : stop sound EnemySndtext 640-20-text width(s$),screen height()-40,s$
To add
our particle bullet shine, we simply have to create and control a particles
object and use the position of the bullet object as our guide. There are three
areas of code we must modify. The creation, control and destruction of the bullet.
Bullet creation:
rem TUT9Bif particles exist(1)=1 then delete particles 1make particles 1, FireImg, 50, 0.5set particle emissions 1,10set particle speed 1,0.01
Bullet
control:
rem TUT9Crem Update particle using bullet object positionset particle emissions 1,1+(bullet/10)rotate particles 1,90-object angle x(BulletObj),object angle y(BulletObj)+180,0position particles 1,object position x(BulletObj),object position y(BulletObj),object position z(BulletObj)
Bullet
destruction:
rem TUT9Dset particle emissions 1,0