Godar's Game Development Package Tutorial.


Game Application/Applet Framework.

The first of many tutorials. To start off the tutorials I will outline a few classes that I created that give a basic framework to build our Java projects upon. When I started programming Java code I found out that it was really handy to have the code run as an applet or an application. Both have their negatives and positives but if no major system access occurs (like reading/writing files, DB access) during the programs execution we can switch between both execution types. First I will explain what I mean by the use of a UML class diagram. If you are not familiar UML don't panic I only use it to graphically explain how a program executes. (You will see..) The main thing to remember no matter how daunting the code looks is DON'T PANIC! just have fun with the code until you feel comfortable using it. I would Highly suggest downloading the Java API found HERE for your version of the JDK. I find it invaluable in locating what a class or method does. Now lets get to it.

 

Fig1.1

Fig 1.1 shows how the basic system communicates. The first two classes "GApplet" and "GFrame" will be first up for discussion. I will not be discussing details on how to program an applet or a JFrame please refer to the java.sun.com site for that information. The four main problems that need to be tackled in this design are image, sound loading and keyboard, mouse events. All images and sounds are loaded into two arrays found in the class Global where any other class can access them, this is why they are declared as static arrays.


	/** Holder for all the required images */
    public static Image imgs[];
    /** Holder for all the required sounds. */
    public static AudioClip snds[];

These arrays are then filled with the required images and sounds and can be accessed globally using the "Global' class. How do we load images into the arrays well lets explain the method loadImages() first.


	/**
     * Loads all the required images into the snds array.
     */
    Private boolean loadImages() {
        // Load all media.
        MediaTracker t = new MediaTracker(this);
        URL url = getDocumentBase();
        
        // ShowStatus("Loading Images!");
        if(Global.imgNames != null) {
            try {
                // Load the image files.
                Global.imgs = new Image[Global.imgNames.length];
                for(int i = 0; i < Global.imgNames.length; i++) {
                    Global.imgs[i] = getImage(url, "images/" + Global.imgNames[i]);
                    t.addImage(Global.imgs[i],0);
                }
                // Wait for all images to finish loading.
                
                t.waitForAll();
            }  catch (InterruptedException e) { System.out.println(e); }
        }
        
        // check for errors //
        if (t.isErrorAny()) {
            // ShowStatus("Error Loading Images!");
            return false;        // Return false on error.
        }
        else if (t.checkAll()) {
            // ShowStatus("Images successfully loaded");
        }
        
        return true;        // Return true if all went well.
    }

This piece of code is not all that complex all it really does is read a String array if image filenames and then loads those images into the imgs array. This is a good place to introduce the "Global" class I use it to hold all the global variables needed in an application it is also good for placing static methods that help with debugging or are just useful throughout a program this is why I put the image and sound arrays here. To access any of the "Global" values the class DOES NOT have to be initiated, all that is required is to call the Class.method or Class.var like so:


	i = Global.imgNames.length;		// To access a variable in the "Global" class.
	OR
	Global.printArray(int[] i);		// To access a method in the "Global" class.

Cool hey!

So all that is left to do is fill in the imgNames array in the "Global" class and the images will be loaded into the imgs array.

The loading of the sounds is very similar in that all that is needed is to fill the sndNames array with the required filenames. Take a look at the code and you will notice that the loading of images and sounds slightly differs although I have kept the algorithm the same.

The next major problem is how to capture the users input and filter it to our program. In my introduction to UML I found a class pattern called a "controller" that inspired this design. The GMainPanel would become our controller and it then conceals out any dependency on the Applet or JFrame because they simply send all events to the "GMainPanel". All the listeners are set up as inner classes and simply send the event to the corresponding "GMainPanel" method where we can access these event for our application.

If you have any experience with Java events you will see what I mean, if not, don't be too concerned just concentrate on how we can use these events in the "GMainPanel" class. The "GMainPanel" has a number of methods that allow us access to the user events we will start of by looking at mouseMoved(e) and mouseDragged(e). They basically do the same thing accept for the obvious (one is for not dragged movement and one is for dragged movement... for the newbes) and that is they allow us to track the mouse's location on our screen. You will notice that I have included offset values for the x(-4), and y(-23) of the mouse location this is basically to fix a problem I found when using a JFrame as it includes the top window bar(where you min and max the screen) and the border around the window in the mouses location and an applet does not. This simply allows us to receive the same mouse locations regardless if it was sent by an Applet or JFrame.

Next we have the mousePressed(e) and mouseReleased(e) functions. You will notice that each if statement has a constant like BUTTON1_MASK, BUTTON2_MASK, and BUTTON3_MASK and these relate to ........ you guessed it, the mouse buttons. The code us wish to execute goes in these if statements. Experiment and get a feel of how it works.

The last lot of event is the keyboard events keyPressed(e) and keyReleased(e) this is a fairly straight forward way of handling keyboard events. Again it requires little explanation just experiment with it.

Now that's over you should understand how we get the user events and the media to the class "GMainPanel". The next thing to outline with this code is how to draw to the screen and the thread that is implemented. There is a constant called REFRESH_RATE in the class this controls how many times the screen is repainted in Frames Per Second (fps) it is currently set to 15fps which should be fine for most applications. The class's run() method shows how the time is used to keep the frame rate as constant as possible.(Depending on the system it is run on)


    public void run() {
        long tm = System.currentTimeMillis();
        
        while(true) {
            update();
            // TODO: any updates
            
            Thread.currentThread().yield();     // Allow other threads to run (if any)
            // Make the thread sleep for a duration.
            // Delay depending on how far we are behind.
            try {
                TM += delay;
                Thread.sleep(Math.max(0, TM - System.currentTimeMillis()));
            } catch (Exception exc) { };
        }   
    }

Last but not least for this tutorial is the paintComponent() method where all the magic happens. All elements that need to be drawn to our panel can be drawn here. The SWING API is used to draw to the screen. It does not need to be double buffered because SWING implements double buffering.

Executing the application is just a simple case of creating an applet tag in selected web page:

<APPLET CODE = "GApplet.class" WIDTH = 600 HEIGHT = 450>
</APPLET>

If you use a jar archive:

<APPLET CODE = "GApplet.class" ARCHIVE = "FileName.jar" WIDTH = 600 HEIGHT = 450>
</APPLET>

 

To execute the program as an application I have created a bach file called go.bat it simply contains the command:

java GFrame

To execute the program as an application in a .jar file use this command:

java -cp FileName.jar GFrame

As you can see, if you have not noticed by now, that applet tags call the the GApplet.class and java commands call the GFrame.class.

To create a .jar file all I do is use winzip to create a zip file of all the selected classes and media (images and sounds) and rename it to a .jar file.

Currently it draws the data of the mouse(locations button states) and an image. Experiment with loading your own images and adding other shapes etch. Try implementing a square that is drawn when you drag the mouse all the tools are here for that.

Have fun with the code !!!


That wraps up the first of my tutorials I hope you found it useful. It is important to note that the "GMainPanel" class will be our main useful panel other panels can be added to t. If you go back to the UML diagram you can see that there is 3 user defined panels linking to "GMainPanel" this is the key to letting our programs run as an Applet or Application.

Download Source: Framework
View The Applet

 


Copyright ©2000-2003 Michael Mifsud. All rights reserved.
godar@cairns.net.au