For all beginner DarkBASIC Professional programmers, Mike S is back with the second and final part of his series of tutorials covering developing a complete 2D side scrolling game with tile map system. This is a monster sized tutorial! The download runs to over 10MB, but it's worth it for all the media, example code and EXEs you get. Building on what you learnt last issue you now get to make media for your game, add in scrolling backgrounds and even a hero. The zip file contains the DBPro source code, media, EXE and tutorial in Microsoft Word format.

by Micheal Shah

Download project and media from the newsletter:

http://www.thegamecreators.com/data/newsletter/newsletter_issue_35.html#16

Language: 
Dark Basic Pro
Code: 
`Didn't see last months tutorial? Get it here.
`http://www.thegamecreators.com/data/newsletter/newsletter_issue_34.html#14


`Here is our basic setup, the same as in our tile editor.
flush video memory
sync on : sync rate 60
backdrop on
set display mode 640,480,32
set window size 640,480

`Set the window title to whatever you want, for now we'll use "The Game Engine"
set window title "The Game Engine"


`Now we get to load our level into our game engine. We've had to make a few simple changes
`from our previous load function, but the base of this is just the same.
filename$="Level1"
if file exist(filename$) then open to read 1,filename$
  read string 1,_Dimensions$
  read string 1,_TileSize$
  read string 1,_MapSize$


`Once we read the Dimension, TileSize, and MapSize variables, we store their values in
`an integer.
_Dimensions=val(Dimensions$)
_TileSize=val(TileSize$)
_MapSize=val(_MapSize$)

`Re-assign our constants, in case they've changed from our new variables..
#Constant Dimensions _Dimensions
#Constant TileSize _TileSize
#Constant MapSize _MapSize

`Now we create our Grid array which stores the whole level data, and the Display array,
`which displays what's currently on screen.
dim Grid(MapSize,MapSize)
dim Display(Dimensions,Dimensions)

`Read our values from the text file, then convert the values from a string
`variable, to a integer. Then, once it's an integer, we assign it back to our
`array.
  for x = 0 to MapSize
  for y = 0 to MapSize
    read string 1,temp$
    Grid(x,y)=val(temp$)
    `Determines the starting position of our little hero.
    `Whichever tile is number 4, will be designated our starting spot for our hero
    `character.  So we assign the startx/starty values with the proper x and y values.
    `from their, we can also assign our hero's x and y position.
    if Grid(x,y)=4
      startx=x+1: herox=startx
      starty=y: heroy=starty
    endif
  next x
  next y

close file 1 `Close our file now that we're done with it.


`Now we get to load our media that we created.
load image "media/2.bmp",2
load image "media/3.bmp",3
load image "media/4.bmp",4
load image "media/5.bmp",5
load image "media/6.bmp",6



`For now, image one will just be black.
cls rgb(0,0,0)
get image 1,0,0,32,32

`Our Hero
#Constant Hero 10
load image "media/hero.bmp",Hero
`Our background: We'll need two of the same images for this.
#constant backgroundimage 11
#constant backgroundimage2 11
load image "media/background.bmp",backgroundimage,1
load image "media/background.bmp",backgroundimage2,1

`Our main loop
do
`cls `clear the screen.


`The base of this collision code works by getting the boundaries and making sure that
`your hero player doesn't cross them. I've also setup the basis for which we'll be able
`to do tile to tile collisions. The basis of this works in that our hero is just a mobile
`tile. However, this will be okay for now, and you can tweak it to your protection, although
`next month the whole tutorial will be dedicated to pixel-perfect collision. :)

if leftkey()=1 and currentx>0
  if RelativeTileX>0 `and Display(relativeTileX,relativeTileY)=1
    currentx=currentx-1
    herox=herox-1
  endif
endif

if rightkey()=1 and currentx<MapSize `and Display(relativeTileX,relativeTileY)=1
  currentx=currentx+1
  herox=herox+1
endif

if downkey()=1 and currenty<(MapSize-1)
  if RelativeTileY>0 `and Display(relativeTileX,relativeTileY)=1
    currenty=currenty+1
    heroy=heroy+1
  endif
endif

if upkey()=1 and currenty>0 `and Display(relativeTileX,relativeTileY)=1
  currenty=currenty-1
  heroy=heroy-1
endif


`This ensures that our hero doesn't go outside our screen. If he does, then the hero
`character will be reset back to the front of the screen.
if herox>Dimensions
  herox=0
endif
if heroy>Dimensions
  heroy=0
endif
if herox<0 then herox=Dimensions
if heroy<0 then heroy=Dimensions



`Here we'll paste our scrolling background.
`The way this works is we have two images 1024x768 in size. The y position will always
`be relative to the player. Meanwhile, both images are scrolling, but they're set their
`width apart so they're side by side. Once the backgroundx variable gets larger than 1024,
`it resets, and the process restarts to give you an infinitly scrolling background.
paste image backgroundimage,backgroundx,currenty
paste image backgroundimage,-1024+backgroundx,currenty
backgroundx=backgroundx+1
if backgroundx>1024 then backgroundx=0




`Here is the simple for-next loop that breaks everything down.
`For the current dimensions, the GRID array data is applied to our DISPLAY array.
`This is then the array that we use to paste the various images to the screen with.
for x = 0 to Dimensions
for y = 0 to Dimensions
  if currentx+x>MapSize or currenty+y>MapSize `Ensure we're not out of bounds on our array.
    Display(x,y)=Grid(150,150)                `If we are, just assign the last GRID value.
  else                                        `If we're not out of bounds, shift values
                                              `to the DISPLAY array.
    Display(x,y)=Grid(x+currentx,y+currenty)
  endif
  `if Display(x,y)=1 then paste image 1,x*TileSize,y*TileSize,1
  if Display(x,y)=2 then paste image 2,x*TileSize,y*TileSize
  if Display(x,y)=3 then paste image 3,x*TileSize,y*TileSize
  if Display(x,y)=4 then paste image 4,x*TileSize,y*TileSize
  if Display(x,y)=5 then paste image 5,x*TileSize,y*TileSize
  if Display(x,y)=6 then paste image 6,x*TileSize,y*TileSize
next x
next y

`Here we paste onto the screen based on its position and the TileSize for our level.
HeroPositionx=herox*TileSize
HeroPositiony=(heroy*TileSize)
paste image Hero,HeroPositionx,HeroPositiony,1


`This is just a simple text statement to help show us the values of each tile in the
`DISPLAY array. This will become especially useful when we get really in-depth with our
`collisions, to make sure that everything is working properly.
if spacekey()=0
for x=0 to Dimensions
for y=0 to Dimensions
 text x*TileSize,y*TileSize,str$(Display(x,y))
next x
next y
endif

`Our current TileX and TileY the mouse is over.
position mouse (HeroPositionx+TileSize),(HeroPositiony+TileSize)

TileX=((mousex()+(currentx*32))/TileSize)*1.0
TileY=((mousey()+(currenty*32))/TileSize)*1.0
`The relative TileX and TileY we're over in our Display array.
relativeTileX=(mousex()/TileSize)*1.0
relativeTileY=(mousey()/TileSize)*1.0

`Here's a little bit of debugging, showing the tiles our mouse is over.
text 580,0,str$(currentx+relativeTileX)+","+str$(currenty+relativeTileY)
text 580,40,str$(relativeTileX)+","+str$(relativeTileY)
text 580,80,str$(Dimensions) `Shows the map dimensions
text 580,100,str$(TileSize)  `Shows the TileSize
text 580,120,str$(MapSize)   `Shows the mapsize.
text 580,140,str$(startx)+","+str$(starty) `Starting x and y positions
text 580,160,str$(herox)+","+str$(heroy)   `Heroes current position
text 580,180,str$(screen fps())            `The Frames per second our program is running.

sync ` refresh our screen.
loop ` Go back to our do, and start all over!
0
No votes yet