Creating a Blackberry Game – Part 5

Looking for part 4?

Let’s See Our Game

Now that our logic is done, we have a few holes in the program where calls are made to graphics and sound processing. By isolating (for the most part, as much as our program allows) graphics and sound processing from the rest of the program, it offers for a little more portability. In general, this isn’t too big of an issue in Java since Java itself is cross platform, but even so we run into areas where certain libraries might be available for one setup and not for others (for example, our program in which we use Blackberry specific libraries, wouldn’t be valid in a non-Blackberry environment). For systems where processor speed and memory are in ample supply (which are most systems these days – as compared to an MCU or retro environment when you’re dealing with 64K of RAM), it’s a good practice to isolate things out like this – it makes porting a lot easier (Think Windows -> Mac & Linux, or PS3 -> XBox & Wii, that kind of thing).

Anyway, game programming philosophy aside, let’s dig into the graphics functionality of GFX. GFX is actually fairly simple since most of the low level graphic processing is done by the Blackberry itself. We don’t have a lot of ways to get close to the hardware, which is a good and bad thing – but for us here, the built in graphics functionality of the Blackberry is good enough and saves us work.

Besides some initialization routines, the GFX class consists mainly of the process method, which takes a handle to the graphics of the current screen from Gameplay. This handle indirectly allows us to write to the screen memory through simple graphic methods like drawBitmap and drawText. The overall algorithm is to first write the background (aligned properly, it moves every update) to the screen, then draw all objects, then the score and our hero’s health meter. There is some math for doing coordinate and dimension calculations, but everything is fairly straightforward.

GFX.java

package com.synthdreams.GalacticBlast;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.*;
import java.util.Vector;

// The GFX class is our game's graphics engine with all the drawing routines
class GFX 
{
    int _backPos, _backSpeed; // Background position and speed
    Bitmap _backgroundBM; // The bitmap for the background
    Bitmap _healthBM; // The bitmap for the health meter
    Font _gameFont; // The font used for drawing score and lives
    
    GFX() 
    {
        // First see if we can get the BBCondensed font at size 16 for our game font.
        // If not, we just go with the default, but all Blackberrys should have this font.
        try
        {
            _gameFont = FontFamily.forName("BBCondensed").getFont(FontFamily.SCALABLE_FONT,16);
        }
        catch (Exception e) { }
        
        // Load the health bitmap from health.png
        _healthBM = Bitmap.getBitmapResource("health.png");
    }
    
    // Get current background position
    public int getBackPos() { return _backPos; }
    
    // Method that sets the bitmap for the background and sets the scroll speed
    public void initBackground(String passBackground, int passSpeed)
    {
       _backgroundBM = Bitmap.getBitmapResource(passBackground);
       _backPos = 0;
       _backSpeed = passSpeed;
    }
    
    // Primary function for the graphics engine, draws all the objects, text, health, etc
    public void process(Graphics passGraphics, Vector passObjects, int passScore, int passLives)
    {
        // Draw our background at the correct position
        passGraphics.drawBitmap(0,0, Graphics.getScreenWidth(), Graphics.getScreenHeight(), _backgroundBM, 0, _backPos);
        
        // Move our background.  
        _backPos -= _backSpeed;
        
        //If we're at the beginning of our bitmap, reset to end
        if (_backPos < 0)
        {
           _backPos = _backgroundBM.getHeight() - _backSpeed;
        }
        
        // If we're within screenheight of the end of our bitmap, we need to draw another copy to fill in the blank
        if (_backgroundBM.getHeight() - _backPos < Graphics.getScreenHeight()+_backSpeed)
        {
           passGraphics.drawBitmap(0, _backgroundBM.getHeight() - _backPos - _backSpeed, Graphics.getScreenWidth(), Graphics.getScreenHeight(), _backgroundBM, 0, 0);
        }
        
        // Now draw each of our objects to the screen
        for (int lcv = 0 ; lcv < passObjects.size() ; lcv++)
        {
            passGraphics.drawBitmap(((OBJ) passObjects.elementAt(lcv)).getX(),
                                    ((OBJ) passObjects.elementAt(lcv)).getY(),
                                    ((OBJ) passObjects.elementAt(lcv)).getBitmap().getWidth(),
                                    ((OBJ) passObjects.elementAt(lcv)).getBitmap().getHeight(),
                                    ((OBJ) passObjects.elementAt(lcv)).getBitmap(),
                                    0, 0);
        }
        
        // Draw score
        String zeroPad;
        
        // We want to pad the score with 0s
        zeroPad = "";
        if (passScore < 10000)
          zeroPad += "0";        
        if (passScore < 1000)
          zeroPad += "0";
        if (passScore < 100)
          zeroPad += "0";
        if (passScore < 10)
          zeroPad += "0";
          
        // Draw score and lives in white with the game font
        passGraphics.setColor(0xFFFFFF);
        passGraphics.setFont(_gameFont);
        passGraphics.drawText("Score: " + zeroPad + passScore, Graphics.getScreenWidth()-93, 2);
        passGraphics.drawText("Lives: " + passLives, 7, Graphics.getScreenHeight() - 20);
        
        //Draw health, with width dependent on hero's life
        if (((OBJ) passObjects.elementAt(0)).getLife() > 0)
            passGraphics.drawBitmap(7, 7, _healthBM.getWidth() * ((OBJ) passObjects.elementAt(0)).getLife() / 5, _healthBM.getHeight(), _healthBM, 0, 0);
    }

}

As can be seen, nothing major happening here. The only weird part is how we draw the background. We basically have a long bitmap that scrolls in the background. When it hits the end of the bitmap, it needs to repeat it. It does this by continuing to scroll the original bitmap, and then filling in the whitespace with a second bitmap, placed flush to the first bitmap. Since we’re dealing with random stars, its hard to make out any seams on the screen. If you were doing something with a more ordered/textured background, you’d need to make sure the top of the bitmap flowed well with the bottom of the bitmap.

Graphics are done – you should be able to disable your audio calls and get a playable game at this point! It should look something like this (only with your graphics, of course)

Onto our final part, audio…

5 Responses to Creating a Blackberry Game – Part 5

  1. Abhinav says:

    HI

    Thanks for this detailed tutorial. I was trying ti create this game, but was not able to find these graphics files, health.png stars.jpg herogame.png enemygame.png.
    Do you have them on this site. please tell us.

    Thanks
    Abhinav

  2. Javi says:

    Same problem, can’t find the graphics files, Do you have a link to download it?

    Thanks

    Javi

  3. Toni says:

    Hi Javi (and Abhinav, sorry I missed your post) –

    There is a link on this page to one of the images, and some more explanation there. Thanks!

  4. Rav says:

    Is there any gaming engine is available for blackberry?

  5. Srinivas says:

    Hi,
    Toni
    I need all image files please…

Leave a Reply

Your email address will not be published.