Images Basics & Basic Parallaxing

 

Introduction:

One of the obvious things you'll need to do when making a game is load up images for display. Doing this with DirectX and C can be a real pain to figure out on your own, but fortunately BB saves us a lot of headache!

This article will touch on simple loading of images to more complex tiling and parallaxing effects. It's recommended that you download the source code so you can see all this in action.

 

A Really Simple Image Load

Loading an image, like say a splash screen, is quite simple. All you need to do is define a variable to point to the image, call the LoadImage function, check to make sure the image was loaded successfully (optional, but recommended), and then use DrawImage to display it. Here's a piece of sample code that does just that (source is in "loadimg.bb"):

 


  ; Initialize BB to run at 800x600
  Graphics 800,600

  ; Load the KrylarLogo.BMP file and point to it with the variable "imgKrylarLogo"
  imgKrylarLogo = LoadImage("graphics\krylarlogo.bmp")

  ; See if the image was loaded successfully (the "imgKrylarLogo" will be 0 if not)
  If imgKrylarLogo = 0 Then
     Text 100,100,"Invalid Image!"    ; tell the user it was invalid if 0
  Else
     DrawImage(imgKrylarLogo,250,100)     ; otherwise, draw the image around the center
  EndIf

  ; wait for the user to press a key
  WaitKey 
  
  ; end the program, return control to Windows
  End

Rotating an Image to Make Multiple Frames

One of the things that a lot of games do is have a 2D graphic that rotates around it's mid-point. For example, let's say that you're making a 2D space game (why not, everyone does!). You could make your player's ship by: a) drawing it at all the different angles by hand (ouch!), b) drawing it facing straight up and then use your graphics program to rotate each frame and then place the frames together (not too bad), c) draw it facing straight up, have BB load it and do all the rotations for you (ah...that's better).

Now this method isn't going to work in all situations. If, for example, you had the same image that either changed sizes real-time or had different light-sourcing depending on the angles (and that light-sourcing was not dynamic), you couldn't use this method. But I've used this for a number of demos and games without hesitation.

Just like the previous example, you're going to need to load the image you want to rotate and you're going to need a variable to point to it. From there, you'll use a combination of the CopyImage command and the RotateImage command. You may also need to use the MaskImage command if you have a mask color that is not black. Also, you should set BB's AutoMidHandle to True. This will ensure that your images are rotated at their center point. If you don't do this your images will rotate around the the top-left corner (at least that's what it looks like to me). Try yanking out the AutoMidHandle True section of the source to see what I mean.

Side Note: A mask color is used to tell BB NOT to draw any pixels (dots on the image) of that color. This is so your image will appear transparent. You wouldn't want to have this cool looking ship drawn with a big black rectangle all around it, so you'll need to tell BB to not draw certain colors. The default for transparency is black (or Red=0,Green=0, Blue=0), but a lot of people use a really ugly color (like bright magenta) to ensure they won't accidently use the transparent color as part of the actual art.

Even though the image I'll be loading will use black as the mask, the following source code will use the MaskImage function for demonstration purposes. Here's the code (source is in "loadimgrt.bb"):

 


  ; Initialize BB to run at 800x600
  Graphics 800,600

  Const iNumRotations=36               ;how many rotations do we want?

  Dim imgShipFrames(iNumRotations)     ;Holds the rotated images

  Global iCurrentFrame = 0             ;What is the current frame being displayed?

  ; tell BB to handle the centering of our images
  AutoMidHandle True

  ; Load the player image and point to it with "imgTemp"
  imgTemp = LoadImage("graphics\player.bmp")

  ; See if the image was loaded successfully (the "imgTemp" will be 0 if not)
  If imgTemp = 0 Then
     Text 100,100,"Invalid Image!"    ; tell the user it was invalid if 0
  Else
     ; set it's mask (transparent color)
     MaskImage imgTemp,0,0,0

     ; now run through the loop and rotate the image
     For iLoop=0 To iNumRotations-1

         ; first let's copy the original image into the current frame
   	 imgShipFrames(iLoop)=CopyImage( imgTemp )

         ; then rotate that frame the appropriate number of degrees
	 RotateImage imgShipFrames(iLoop),iLoop*360/iNumRotations
     Next
  EndIf

  ; loop until the player hits the ESC key
  While Not KeyHit(1)

    ; clear the screen
    Cls

    ; display the current Ship Frame in the center of the screen
    DrawImage(imgShipFrames(iCurrentFrame),400,300)

    ; change the current frame (spin it to the right)
    iCurrentFrame = iCurrentFrame + 1

    ; if the current frame counter goes past our number of
    ; allowable rotations, reset it to 0
    If iCurrentFrame > iNumRotations - 1
       iCurrentFrame = 0
    EndIf

    ; delay for 50 milliseconds so we can see the animation
    Delay 50 

  Wend
  
  ; end the program, return control to Windows
  End

So this basically loads in a ship and spins it around on the center of the screen. Mess around a bit with the delay speeds and the iNumRotations variables to see the weird things you can do ;)

 

Tiling Images and Basic Parallaxing

Let's say that you had an image that you wanted to paste all over the screen, side by side and top to bottom. You could write a routine that used a couple of for loops and that did some positioning calculations, or you could simply use BB's TileBlock command.

For fun, let's use that same little ship image to tile our background with. To do this we would simply call TileBlock with the image to use and optionally the x,y coordinates to start the drawing at. If you don't supply the x,y coordinates, BB will assume you want to start in the top-left corner.

Here's the code (source is in "tileblock.bb"):

 


  ; Initialize BB to run at 800x600
  Graphics 800,600

  ; Load the player image and point to it with "imgShip"
  imgShip = LoadImage("graphics\player.bmp")

  ; See if the image was loaded successfully (the "imgShip" will be 0 if not)
  If imgShip = 0 Then
     Text 100,100,"Invalid Image!"    ; tell the user it was invalid if 0
  Else
    ; Tile the ship image all over the screen 
    TileBlock imgShip
  EndIf

  ; wait for the user to press a key
  WaitKey   

  ; end the program, return control to Windows
  End

Now you probably want to see how they do those cool parallaxing starfields in most of those 2D space games (like Insectoids). It's actually a snap with BB. You simply use a combination of the TileBlock and the TileImage commands.

TileImage is basically the same thing as TileBlock with the primary difference being that TileImage draws the tile using transparency...thus it's a little slower. You'll need this, though, because you don't want to overwrite the backgrounds as you parallax over them.

Side Note: If you don't know what parallaxing is, here's the basic idea. Pretend you're in a car that's going down a highway with close hills and faraway mountains. The close hills will appear to be going past much faster than the faraway mountains. They're not, it just looks that way because of your proximity to them. Now look at a 2D starfield, the dim stars (way faraway) should appear to move more slowly than the bright stars (close up). It's just an illusion, really, but it adds a good amount of life to your game.

I borrowed the spacing of the starfields from Insectoids (thanks guys!), but I decided that having three actual images looked better. They're the exact same in layout, but they have different brightness and contrast values. This is so I could make the faraway stars look dimmer than the closer ones. The code piece for the calculations is straight out of Insectoids though, so the credit goes there.

One last thing, this example uses a couple of things that may seem foreign to you...the SetBuffer and the Flip commands. I'm going to touch on these in a future article, but for now I'm just using them to make the starfield scroll smoothly (without flicker).

Here's the code (source is in "prlxstars.bb"):

 


  ; Initialize BB to run at 800x600
  Graphics 800,600

  ; set up the drawing buffer to be the backbuffer
  SetBuffer BackBuffer()

  ; load up the star backgrounds (3 total)
  imgStarsFar=LoadImage( "graphics\starsfar.bmp" )
  imgStarsMid=LoadImage( "graphics\starsmid.bmp" )
  imgStarsClose=LoadImage( "graphics\stars.bmp" )

  ; create a variable to keep track of our drawing locations
  Global iStarsScroll

  ; loop until the player hits the ESC key
  While Not KeyHit(1)

    ; clear the screen/buffer
    Cls

    ; Fill the whole background with the 3 star layers
    ; in their current positions
    TileBlock imgStarsFar,0,iStarsScroll
    TileImage imgStarsMid,7,iStarsScroll*2
    TileImage imgStarsClose,23,iStarsScroll*3

    ; calculate the new position to start the next drawing cycle
    iStarsScroll=(iStarsScroll+1) Mod ImageHeight( imgStarsFar )

    ; flip the back drawing buffer to the display
    Flip
  Wend
  
  ; end the program, return control to Windows
  End

Conclusion:

Well that's the basics of images with a little cool stuff thrown in.

Until next time...cya!

This tutorial is by Christian Coders>