Monday, August 20, 2007

Toggle Fullscreen Mode

Purpose

To show how you can switch a window between being windowed and fullscreen with the press of a button.


Diving Right In

Ok, so in a previous post I showed how you can start a JFrame in fullscreen mode by removing decorations on the frame and also by changing the screens display mode. Well now I am going to use that code modify it so that you can toggle or switch between windowed and fullscreen modes just by pressing a single key.


Windowed Mode

The following code will change a fullscreened JFrame back to windowed mode.

//set the display mode back to the what it was when
//the program was launched.
device.setDisplayMode(dispModeOld);

//hide the frame so we can change it.
setVisible(false);

//remove the frame from being displayable.
dispose();

//put the borders back on the frame.
setUndecorated(false);

//needed to unset this window as the fullscreen window.
device.setFullScreenWindow(null);

//make sure the size of the window is correct.
setSize(800,600);

//recenter window
setLocationRelativeTo(null);

//reset the display mode to what it was before
//we changed it.
setVisible(true);
There are a couple of key function calls here, one is the dispose call since it allows us to add the decorations back onto the window. Without it right before the call to setUndecorated we would get a java.awt.IllegalComponentStateException with the message "The frame is displayable". We could however remove the call to setUndecorated but then there would be no Border (i.e no title bar, minimize, maximize, or exit buttons) around the window when in windowed mode.
Another nice call that you could remove without any problems is the setLocationRelativeTo(null); this call centers the window on screen. You need to make sure you call this only after the size has been reset since it won't be centered if you do that.

One of the most important calls is the first one displayModeOld is a member variable that we must set in the JFrame's constructor and anytime before we switch to a custom screen mode. Idea: What would be a good idea is to check to see if the current screen mode is what we want and if not then save the old one and change to one we want.

Fullscreen Mode

Ok, so now that we can switch back to windowed here again is the code for changing to fullscreen mode there are a couple of things that needed to be added since we need to be doing this while the window is already being displayed.
//save off the old display mode.
dispModeOld = device.getDisplayMode();

//hide everything
setVisible(false);

//remove the frame from being displayable.
dispose();

//remove borders around the frame
setUndecorated(true);

//make the window fullscreen.
device.setFullScreenWindow(this);

//attempt to change the screen resolution.
device.setDisplayMode(dispMode);

//show the frame
setVisible(true);

Notice that we first save the current screen mode so the next time the window is changed we can reset the screen mode back to what it was before we changed it.


Encapsulation

Alright, now we need to put it all in one nice easily managable function.

/**
 * Method allows changing whether this
 * window is displayed in fullscreen or
 * windowed mode.
 *
 * @param fullscreen true = change to fullscreen,
 *                   false = change to windowed
 */
public void setFullscreen(boolean fullscreen) {
   //are we actually changing modes.
   if( this.fullscreen != fullscreen ) {

      //change modes.
      this.fullscreen = fullscreen;

      // toggle fullscreen mode
      if(!fullscreen) { 

         //change to windowed mode.

         //...windowed mode code.

      }else{
         //change to fullscreen.

         //...fullscreen mode code.

      } // end if

      //make sure that the screen is refreshed.
      repaint();
   }
}


We only want to actually change display modes if we are switching from fullscreen to windowed or vice versa, since trying to set some of the properties will cause exceptions to be thrown.


Seeing Is Believing

Thursday, July 12, 2007

Timed Animation

Switching Images


Ok so one of the things that you might want to do after figuring out how to draw images on the screen that were loaded from a file is to animate a bunch of images. One of the main concepts to making animation is switching between images. To do this we simply use an indexed array of images to represent our animation.
// A collection of frames used for animation.
private ArrayList frames = new ArrayList();
This means that each frame or image has an integer position in the array. We can use this to position to move to the next frame or even to wrap around to rewind to the first frame. So we'll need to keep track of our current frame.
// An integer representing the current frame to display.
private int animation_frame = 0;
Likewise we will need the first frame of our animation and also the last. The first frame in this case will be zero or the beginning index in the Array you could actually create another variable for the beginning position so that you can randomize it for explosions or other effects. The last frame is of course the last index in the ArrayList and that will be frames.size()-1. We will be checking to make sure that our animation_frame variable value stays within zero and frames.size()-1 other wise an ArrayIndexOutOfBounds exception will be thrown.

Drawing The Current Frame


So now that we have a list of images (frames) that will become our animation we want to be able to draw the current image in the list that corresponds to the index animation_frame. This is how we would draw it using a Graphics object.
g.drawImage((Image)frames.get(animation_frame), 10, 150, null);
As you can see its pretty simple. We can substitute the second and third parameters for the x and y position respectively. In another post I will show how to vary these two parameters over time in order to obtain certain movement and physics effects. There are also additional methods for drawImage within the graphics object one in particular allows you to set the width and height of the image you are drawing which allows for a lot more effects in game.

Changing The Frame


Ok so we are displaying the current image in the list of frames for our animation now we want to cycle or loop through the entire list but we only want to change a frame at a fixed interval of time. For this we will use a timer. And so we create a java.util.TimerTask which will increment the animation_frame variable thus moving to the next image in the list.

We need to check after we change the variable to make sure that we have not reached the last frame if we have then we want to loop back to the first image in the list.
TimerTask animationTask = new TimerTask() {
   public void run() {
      //move the animation to the next frame.
      animation_frame++;

      //check to see if we have finished all frames.
      if( animation_frame >= frames.size() ) {
     
         //rewind to the beginning of the animation.
         animation_frame = 0;
      }
    }
};
Now we can schedule the TimerTask with the java.util.Timer and give it an interval on which to change frames.
// set the animation to run at 2 frames per second.
timer.schedule(animationTask,0,500);
So that is pretty much all you need to create animations.

Seeing Is Believing

Wednesday, July 11, 2007

Drawing An Image

Back To Basics

On of the first things that you need to be able to do when creating a game is to simply draw an image to a particular location within a window. Its relatively simple to draw the image to the screen, for that you would just use the following call:
//this call draws the image on the JFrame.
g.drawImage(imgToRender, 0, 50, null);
Well now that is if you already have created a valid image and assigned it to 'imgToRender'. Well unfortunately in Java there is no one accepted way to load an image. And of course you are probably thinking about loading an image from a file so that anyone who has Paint or Photoshop skills can go in an create or update art for your game. Well here is one way:
// This is one method to load images
imgToRender = (new ImageIcon("pictures/redX.png")).getImage();
You can replace the "pictures/redX.png" with the path to your own image. In the path string if you do not specify a drive or protocol type meaning file:///, C:/ or http://) then you can put in the relative path from the execution directory.

I will discuss loading resources such as image and sound files from different location in another post but essentially the basics of drawing an image are really all you need to do tons of cool things in your game.

Seeing Is Believing

Friday, June 29, 2007

Game State Machine

Uses and Purpose:


A state machine has a context which holds the current state. Each state knows which states come next and when to transition to those states. There are many different ways of implementing a state machine. A lot of people like to use a State Manager class that knows which state to transition to and hold concurrent states, however this couples the Manager with each new state you create. This violates extensibility and abstraction principles of good design. The example state machine I have included is very extendable and abstracts the Conext (or State Manager) from the States themselves such that the Context only knows a bare minimum about the States that are running.

Design And Implementation Choices:


One of the concerns that must be addressed when creating a State Machine is whether your application is Multi-threaded or not. Since this example was created in Java your application most likely will have multiple threads. In C++ the code for a State Machine is trivial because most games are not multithreaded. Another concern is will you need substates my example code does not allow for substates but the State class can easily be sub-classed to hold substates or can also be done for concurrent states.


Code Speaks For Itself:


This example also includes Rendering Loop And Double Buffering example.

Friday, June 22, 2007

Double Buffering and Timed Rendering



A Backbuffer

First thing you need before creating a flicker free environment is to have a buffer to draw to. Basically the concept is, draw everything to an offscreen image the same size as the window you are going to be displaying it on. Once the drawing of a single frame is complete then swap or in this case draw the backbuffer onto the screen. And of course you want to do this every 16-33 milliseconds or between (30-60 fps, frames per second) So we need a backbuffer to use for drawing. You want to use a BufferedImage which has a method to get the Graphics object which is what you use to draw to any component or Image in Java.


Timer and TimerTask's

Ok! Now that we have a backbuffer we need a way of timing each frame and rendering (drawing) that frame onto the window. So we need a timer something that will execute after a specified period of milliseconds. There is a Timer class already in the Java API java.util.Timer. This class allows you to schedule TimerTask's which are simply a separate thread with a run method that you need to overload. A typical rendering loop is something like this:
// create the Timer and schedule it with the timer.
TimerTask renderTask = new TimerTask() {
   public void run() {

      // check to see if the backbuffer needs to be
      // initialized. this will help when window is resized.
      if (backbuffer == null wndResized) {
         // create a BufferedImage the size of the JFrame.
         backbuffer = new BufferedImage(getWidth(), getHeight(),
         BufferedImage.TYPE_INT_ARGB);
         wndResized = false;
      }

      // get the Graphics object from the backbuffer.
      Graphics g = backbuffer.getGraphics();

      // TODO: draw things to the screen.
      // example
      g.drawString(DoubleBuffering.DISPLAY_STRING, 100, 100);

      // now we do our page flipping to display the image on the
      // window. So we need the windows Graphics object.
      getGraphics().drawImage(backbuffer, 0, 0, null);

      // after we have drawn what we need on the screen we can clear
      // the backbuffer.
      g.clearRect(0, 0, backbuffer.getWidth(),
      backbuffer.getHeight());
   }
};
Now scheduling the TimerTask is very easy and is done like so:
// start rendering at 60 fps.
timer.schedule(renderTask, 100, 16);
That would be the guts of things you just extends this as you need and make your game.

Resizing Windows

What to do with resizing windows. Whenever a window is resized you need to recreate the backbuffer since the width and height of the image has changed. This really is not a problem if you are in fullscreen mode or you lock the windows resizable property but still in case you really need to do it here is a way to determine if the window has been resized.
// add a listener to detect when the window has been resized by the
// user.
addComponentListener(
new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
wndResized = true; // resize the backbuffer.
}
}
);

That’s about it here is the single file code snippet for you to use:

Thursday, June 21, 2007

Fullscreen & ScreenModes in Java Games

Setting up a JFrame in Fullscreen

To make a JFrame fullscreen you need to first get a valid graphics device which can be obtained from the GraphicsEnvironment object in java.awt package. Here is a quick example call,
GraphicsDevice gd =
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();

The GraphicsDevice object has a method called setFullScreenWindow it has one parameter which is a Window object and JFrame is a subclass of Window so you can pass it as an argument to the method.


Changing Display Modes

Ok so now we have a window that takes up the whole screen but what if you want to change the Screen Resolution to work best with your game. No problem!

The GraphicsDevice object has another method for doing just that. The name of the method is setDisplayMode that takes a single parameter. The parameter is a DisplayMode object. An example creation of a DisplayMode object is shown below:

DisplayMode dm = new DisplayMode(640,480,32,60);

When passed to the GraphicsDevice.setDisplayMode will attempt to change your current default monitors screen resolution to 640 pizels in width by 480 pixels in height with 32 bits of space for storing the color of each pixel on screen and a screen refresh rate of 60 hertz.

Warnings:
1) You cannot change the DisplayMode without a fullscreened window.
2) Changing the DisplayMode to something that is not supported by your monitor or display can cause an exception to be thrown.

Notes:
To get a full listing of supported DisplayModes you can use the GraphicsDevice.getDisplayModes() method which will return an array of valid DisplayMode objects. (good for settings option in Games)

Stripping The JFrame Decorations

Well now you can make a fullscreen window but what about that border thats no good for games. All you need to do is the following:

this.setUndecorated(true);
This call is made on any java.awt.Frame object.

How to Escape

Just add a keyListener to the frame. This may be a problem later on if you include other awt or swing components.

Example: Seeing is Believing

Tuesday, June 19, 2007

Start of Game Programming Snippets

This blog is dedicated to showing quick snippets of Game Programming code from a variety of different languages as well as articles on Game Programming practices and algorithms.

Also there will be current news and game reviews. So stay tuned!