Latest Entries »

KEYBOX

KEYBOXThank you for visiting this blog site. I have moved over to iPhone development recently and have finally released my first iPhone app, KEYBOX! KEYBOX was originally a J2ME app for Vodafone Japan’s feature phones. The new iPhone version uses the full power of the iOS platform to fully secure your private life.

I welcome you to download the free lite edition and see for your yourself!

I haven’t done much in the way of J2ME development lately as I have taken up iPhone / Mac development.

While this blog will remain for some time I’d like to link to my more permanent home… http://www.jayfuerstenberg.com/blog

See you on the other side!

JammedUp Update

This is just a heads-up to let everybody know that JammedUp has been updated.

The latest and greatest version is “Version 1 Update 1” and comprises of localizations into Brazilian Portuguese, German, Hebrew and Simplified Chinese.

A big thank you goes to all the following people…
Yoav Shnel
Gibson Tang http://www.gibsontang.com
Pedro Miller Rabinovitch http://www.exodia.org
Juergen Lutz http://www.baby-soft.de/software

It can be downloaded at http://sourceforge.net/projects/jammedup

Information regarding its use can be found at https://j2medevcorner.wordpress.com/2007/03/22/jammedup-midlet-descriptor-updater-tool/

Scope of Article

This article introduces the general-purpose Animation class I have developed and used in some of my MIDlets with the intention of helping others avoid writing animation-related boilerplate code.

Real usage examples for various scenarios are also provided to demonstrate the class’ ease-of-use.

Introduction: What is an animation?

If you have a background in graphics you can skip this definition but for those who are just getting their feet wet here goes…

An animation is a transformation, over time, of one or more of an object’s properties. Common properties that can be animated include but are not restricted to position, color, sprite frame, translucency and visibility.

A Familiar Example: The Walking Hero

Anyone who has played an RPG game is no doubt familiar with “the walking hero”. He is the character who, regardless of moving or not, is always walking in stride. His animations usually consist of 3 separate animation frames (left foot front, both feet side-by-side, and right foot front). He typically walks in 4 directions but for the purposes of this article we’ll just focus on his downward facing frames. As I mentioned just a moment ago he never stops animating. His animation sequence looks like this…

1. frame 1 (left foot front)
2. frame 2 (both feet side-by-side)
3. frame 3 (right foot front)
4. frame 2 (both feet side-by-side)
... back to step 1

This is a linear cycling animation sequence. That is to say, the sequence goes from index 1 to 4 then back to 1 to keep cycling. From the player’s perspective this 1,2,3,4,3,2,1,2,3,4…. sequence is invisible. It just seems as if the hero is walking normally. There is another, perhaps better/more accurate way we could achieve this type of animation sequence without the player noticing any differences.

1. frame 1 (left foot front)
2. frame 2 (both feet side-by-side)
3. frame 3 (right foot front)
... rewind (step 2, step 1)

By rewinding the animation we better model the situation since walking is actually a reciprocal motion, like that of a pendulum. We also shorten the animation sequence by one frame. With such a trivial example it might be difficult to grasp the benefits of rewinding but as the properties become more complex it really simplifies the logic.

Animation Sequence Flows

There are 2 styles of animation sequence flows which I’ll now outline.

1. Linear

When the animation sequence reaches the end it stops there.

2. Rewinding

When the animation cycle reaches the end it rewinds back to the beginning after which it then stops.

Cycles

Animations can run through a sequence once, an arbitrary number of times or even forever. The decision is yours. Coupled with the sequence flow styles rich effects can be produced. For example our walking hero can be implemented as a forever cycling, rewinding animation sequence. Conversely, an explosion can be created with a one-time linear animation sequence.

The Animation Class

Without further ado allow me to list the Animation class…

Animation.java

/**
 * The Animation class represents the state of an object's view
 * in transition.  This transition is expressed through its current
 * index within a number of frames.  Additional control of this 
 * position index is offered to allow for rewinding and cyclical
 * progressions.
 * 
 * This class does not handle an object's rendering.  It is the
 * responsibility of the displayable object to use an Animation
 * instance to track the index which represents some form of
 * viewable state.
 *
 * For instance the index may reference images within an array
 * (animation cels) and/or it may reference x,y positions within a
 * different array (path-based animation).
 */
public class Animation {
	
	/**
	 * Flag indicating that the animation loops without end.
	 * @see Constructor.
	 */
	public static final int LOOP_FOREVER = -1;
	
	/**
	 * Flag indicating that the animation plays a single time only.
	 * @see Constructor.
	 */
	public static final int LOOP_DISABLE = 1;
	
	/*
	 * The current index in the animation.
	 */
	protected int index;
	
	/*
	 * The number of frames in the animation.
	 */
	protected int frameCount;
	
	/*
	 * The step in frames to progress.
	 */
	protected int step;
	
	/*
	 * Indicates whether the animation should rewind to the
	 * beginning upon completion.
	 */
	protected boolean rewind;
	
	/*
	 * Indicates whether the animation is currently rewinding.
	 */
	protected boolean inRewind;
	
	/*
	 * The number of times the animation should loop.
	 * Either LOOP_FOREVER, LOOP_DISABLE or any positive number.
	 */
	protected int loopCount;
	
	/*
	 * The current loop.
	 */
	protected int loopIndex;
	
	/*
	 * A flag indicating the Animation has completed.
	 */
	protected boolean finished;
	
	/*
	 * The time that must pass in order for a call to progress() to have any
	 * effect on the animation state.
	 */
	protected long progressInterval;
	
	/*
	 * The millisecond timestamp of the previous call to the progress method.
	 */
	protected long previousProgressCall;
	
	/**
	 * Instantiates an Animation.
	 * 
	 * @param frameCount The number of frames of which the animation consists.
	 * @param loopCount The number of loops to complete before terminating.  Either LOOP_FOREVER, LOOP_DISABLE or any positive number.
	 * @param rewinds A flag to indicate that the animation should rewind prior to completing a cycle.
	 */
	public Animation(int frameCount, int loopCount, boolean rewinds) {
		
		if(frameCount < 2) {
			throw new IllegalArgumentException("frameCount must be greater than 1.");
		}
		
		if(loopCount < LOOP_FOREVER || loopCount == 0) {
			throw new IllegalArgumentException("loopCount must be greater than 0 or LOOP_FOREVER.");
		}	
	
		this.frameCount = frameCount;
		this.loopCount = loopCount;
		rewind = rewinds;
		step = 1;
		
		previousProgressCall = -1L;
	
	}
	
	/**
	 * Resets the Animation to its starting position.
	 */
	public void reset() {
	
		index = 0;
		loopIndex = 0;
		inRewind = false;
		finished = false;
	}
		
	/**
	 * Indicates whether the Animation is finished or not.
	 * 
	 * @return true if finished, false otherwise.
	 */
	public boolean isFinished() {
		
		if(loopCount == LOOP_FOREVER) {
			return false;
		}
		
		return finished;
	}

	/**
	 * Returns the index.
	 *
	 * @return The index.
	 */
	public int getIndex() {
		return index;
	}
	
	/**
	 * Arbitrarily sets the index to any point in the animation.
	 *
	 * @param index The index to set.
	 */
	public void setIndex(int index) {
		
		if(index < 0 || index >= frameCount) {
			throw new IllegalArgumentException("index must be between 0 and frameCount.");
		}
		this.index = index;
	}
	
	/**
	 * Returns the Animation's progression step factor.
	 * 
	 * @return the step.
	 */
	public int getStep() {
		return step;
	}
	
	/**
	 * Sets the Animation's progression step factor.
	 * 
	 * @param step a number greater or equal to 1 and less than the frameCount.
	 */
	public void setStep(int step) {
		
		if(step < 1 || step >= frameCount) {
			throw new IllegalArgumentException("step must be greater or equal to 1 and less than the frameCount.");
		}
	
		this.step = step;
	}
	
	/**
	 * Progresses the Animation's state while enforcing that progression does
	 * not occur until the progress interval has elapsed.
	 *
	 * @param currentTimeMillis The current time in milliseconds.
	 */
	public int progress(long currentTimeMillis) {
		
		if (previousProgressCall == -1) {
			previousProgressCall = currentTimeMillis;
			return index;
		}
		
		if (currentTimeMillis - previousProgressCall &lt progressInterval) {
			return index;
		}
		
		previousProgressCall = currentTimeMillis;
		
		return progress();
	}
		
	/**
	 * Progresses the Animation's state.
	 * 
	 * The behavior of this method depends on the Animation's state.
	 * If rewinding is not used the last frame the index will reference will be
	 * the end frame.  However if rewinding is used the last frame will
	 * reference the beginning frame.
	 * 
	 * @return The Animation's current index after progressing.
	 */
	public int progress() {
		
		if (finished) {
			return index;
		}
		
		if (!inRewind) {
			index += step;
		}
		else {
			index -= step;
		}
		
		if(index >= frameCount) {
		
			// The Animation has reached the end frame.
			if(rewind) {
				// The Animation will now rewind...
				inRewind = true;
				index -= (step * 2);
			}
			else {
				// Begin the next animation cycle...
				loopIndex++;
				
				if(loopCount != LOOP_FOREVER && loopIndex >= loopCount) {
				
					// The Animation has finished.
					finished = true;
					loopIndex--;
					index -= step;
					return index;
				}
				
				index = 0;
			}
		}
		
		if(index <= 0 && inRewind) {
			/*
			 * The Animation finished rewinding.
			 * Begin the next animation cycle...
			 */
			loopIndex++;
			inRewind = false;
			
			if(loopCount != LOOP_FOREVER && loopIndex > loopCount) {
				// The Animation has finished.
				finished = true;
				return index;
			}

			index = 0;
		}
		
		return index;
	}

	/**
	 * Returns the number of frames in this Animation.
	 * 
	 * @return the frame count.
	 */
	public int getFrameCount() {
		return frameCount;
	}
	
	/**
	 * Returns the number of loops in this Animation.
	 * 
	 * @return the loop count.
	 */
	public int getLoopCount() {
		return loopCount;
	}
	
	/**
	 * Returns the Animation's current loop index.
	 * 
	 * @return the loop index.
	 */
	public int getLoopIndex() {
		return loopIndex;
	}
	
	/**
	 * Indicates whether the Animation rewinds upon reaching the end frame.
	 * 
	 * @return true if rewinding is supported, false otherwise.
	 */
	public boolean rewinds() {
		return rewind;
	}
	
	/**
	 * Indicates whether the Animation is currently in a rewind.
	 * A rewind is defined as a decrement in the index until the index equals
	 * 0 whereby the the Animation exists rewind mode and reenters normal mode.
	 * 
	 * @return true if currently rewinding, false otherwise.
	 */
	public boolean isInRewind() {
		return inRewind;
	}
	
       /**
	 * Sets the progression interval for use by the progress(long currentTimeMillis)  method.
	 * 
	 * @param progressInterval The time which must elapse between progressions in milliseconds.
	 */
	public void setProgressInterval(long progressInterval) {
		this.progressInterval = progressInterval;
	}
}

Synchronizing with the Game Loop

By coupling the Animation class with the FPS class an animation can be timed to advance with the flow of the game loop. But what if your animation wants to progress at a slower speed? With the animation class you can instruct it to progress only if a given milliseconds period has elapsed. This is extremely useful for creating dynamic progression schemes where a condition such as friction can cause a sprite to move slower like a golf ball flying against the wind.

How the Animation Class works

The Animation class is a general purpose number sequence and index/cursor maintainer. Unlike the MIDP 2.0 Sprite class, it isn’t tightly coupled to the property it is animating and in fact has no knowledge of any properties. Your objects use an Animation class instance for each animated property.

Our walking hero class, for instance, can have an instance of the Animation class that with each iteration of the game loop will advance the walking sequence to the next frame. The class will retrieve the current frame index from the animation instance at rendering time, draw the frame, then advance the frame index. For extra points let’s control the rate of progress so the animation does not occur too quickly.

The code might look something like this…

// A forever looping, and rewinding animation with 3 frames.
Animation walkAnim = Animation(3, Animation.LOOP_FOREVER, true);

// Make sure the animation progresses every 333ms (or 3 times per second)
walkAnim.setProgressInterval(333);

...

int walkFrame = walkAnim.getIndex();
Image walkImg = walkImages[walkFrame];
g.drawImage(walkImg, hero.getX(), hero.getY(), Graphics.LEFT | Graphics.TOP);

walkAnim.progress(System.currentTimeMillis());

Another class might utilize the Animation class to manage strobing color of a health indicator (like a heartbeat). Such an animation would cycles the red, green and blue elements of the health indicator’s color from 0 to 255 over and over again. This time lets make the animation run faster by setting the step to 4 instead of the
default 1.

// A forever looping, non-rewinding animation with 256 states.
Animation strobeAnim = Animation(256, Animation.LOOP_FOREVER, false);

// Set the step to 4 (index = 0, 4, 8, 12....)
strobeAnim.setStep(4);
...

int luminosity = strobeAnim.getIndex();
g.setColor(luminosity, luminosity, luminosity);

// draw health indicator using current color
strobe.draw();

strobeAnim.progress();

Pervasive Animation

By far the best case for using a dedicated Animation class is for implementing animations pervasively throughout your MIDlet. Weather conditions, sprite movements, projectile paths, etc… can all be easily managed in a declarative fashion by using the Animation class. Managing the various gears that drive an animation in a non-OOP fashion pervasively should be a last resort when trying to optimize your MIDlet’s performance/footprint.

Extending the Animation Class

To provide even richer animations it may be useful to extend or compliment the Animation class with an animation-scripting engine capable of managing multiple animations in tandem. Such an engine would provide an elegent and expressive means to time the animation progressions with respect to their states. Such facilities exist in other animation packages and could be easily integrated.

In closing

The Animation class listed in this tutorial is extremely general purpose and uncoupled from animatable properties for maximum flexibility. This tutorial cannot do the class justice however it serves as a starting point to adding an extra dimension of style to any MIDlet.

If you have feedback or questions please feel free to contact me at
j a y _ f u e r s t e n b e r g [AT MARK] y a h o o . c o . j p

Scope of Article

This article is intended for J2ME beginners and steps through every process of developing a MIDP compatible MIDlet. It is assumed that the reader has sufficient knowledge of general Java development using J2SE.

Java’s Original Promise

In the beginning Java was intended as a programming language that would power devices ranging from toasters to servers. This did not happen at first, but nearly a decade later Java found its way onto the mobile phones of millions of people and proved for the most part its ability to allow developers to “Write Once Run Anywhere”.

With this solid footing Java continues attempting to make inroads into other problem domains.

About J2ME

Programmers who have worked with J2SE expect that J2ME is its easier, little brother. Nothing could be further from the truth. J2ME development involves overcoming the limitations of mobile devices which do not exist on modern desktop let alone servers. In other words, the types of wastes you could get away with in J2SE will not be tolerated in J2ME and you’ll need to be mindful of every object instantiated and every byte used. Most of this site is dedicated to the topic of overcoming mobile device limitations and you’ll find much of the content useful in your future endeavours. In the end you’ll be able to take what you learn in J2ME and apply it in your J2SE projects to make them faster and leaner.

Getting Started: “Hello World” in J2ME

Whereas you write applications for the desktop and Applets for web browsers you write MIDlets for mobile devices.

Just as J2SE applications have an entry point (any class with a main() method) MIDlets have a class which extends the abstract MIDlet class. This class offers the startApp() method which will serve as the entry point to your MIDlet.

In J2SE, Hello World consists of merely System.out.println()-ing the static String “Hello World”. Unlike J2SE many J2ME devices do not have the concept of an on-screen console and as such we cannot avail ourselves of the System.out.println() method to print “Hello World” for us.

We must instead draw “Hello World” to a graphical canvas which we will then assign to be the currently displayed screen. If you’ve dabbled in AWT or Swing you likely have seen the Graphics object which acts as our paintbrush when painting to the Canvas. For those not familiar, the Graphics object is state-object with a current color, line-thickness, font etc…

Drawing Hello World :: The Rendering Process (in plain English)

Below are the steps required to draw “Hello World” on screen.

1. Set the current color to black
2. Fill the entire screen (using the current color)
3. Set the current color to white
4. Print “Hello World!” (using the current color and font)

So that Hello World’s font’s color is different from that of the screen we explicitly set both prior to filling the screen and printing our text.

The canvas code

Translating the steps above to Java code gives us this…

HelloWorldCanvas.java

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;

public class HelloWorldCanvas extends Canvas {

	protected void paint(Graphics g) {
		
		g.setColor(0, 0, 0);
		g.fillRect(0, 0, getWidth(), getHeight());
		g.setColor(255, 255, 255);
		g.drawString("Hello World!", 20, 20, Graphics.LEFT | Graphics.BOTTOM);
	}
}

Connecting the Canvas to the MIDlet.

Since the entry class of any MIDlet must extend the MIDlet class it cannot extend the Canvas class we just created (no multiple inheritence in Java).

We need a MIDlet implementor class like the one below…

HelloWorld.java

import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class HelloWorld extends MIDlet {
	
	public HelloWorld() {
		
	}
	
	protected void destroyApp(boolean conditional)
			throws MIDletStateChangeException {
		
	}
	
	protected void pauseApp() {
		
	}
	
	public void startApp() throws MIDletStateChangeException {
		
		Display.getDisplay(this).setCurrent(new HelloWorldCanvas());
	}
}

To recap, our entry class HelloWorld has its start method executed which sets our Canvas class HelloWorldCanvas to the currently displayed canvas (a MIDlet can have more than one Canvas). It then tells the canvas to begin drawing itself.


Fast forward :: The structure of a Completed MIDlet

Besides java files there are a minimum of 3 files required to build a MIDlet.

1. The JAR file

Anyone who has created a WebStart application or a server-side web application in Java will have come into contact with JAR files. They are essentially the same as ZIP archives and in the J2ME world they serve to compress the MIDlet as best as possible. They include the classes that constitute the MIDlet, and any resources such as images and data files used.

2. The JAD file

A JAD file is a lightweight proprties file in the which is offered to the target device prior to commiting to the full JAR download. It informs the device of the size of the MIDlet and any expectations and requirements it has of the device.

As the JAR files size must be mentioned and since it always changes during development it is advised to use JammedUp to automate this process with each build.

HelloWorld.jad

MIDlet-Name: HelloWorld
MIDlet-Version: 1.0
MIDlet-Vendor: VENDOR-NAME-HERE
MIDlet-Jar-URL: HelloWorld.jar
MIDlet-Jar-Size: 1523
MIDlet-1: HelloWorld,,HelloWorld
MicroEdition-Profile: MIDP-2.0
MicroEdition-Configuration: CLDC-1.1
MIDlet-Data-Size: 0
build: 1
Last-Modified: 2007-04-09 08:17:25

3. The Manifest

All MIDP compatible MIDlets must include a MANIFEST.MF file residing in the META-INF directory of the JAR file. This file reasserts some of the basic settings found in the JAD file for validation purposes and is provided in the properties file format.

MANIFEST.MF

MIDlet-Name: HelloWorld
MIDlet-Version: 1.0
MIDlet-Vendor: VENDOR-NAME-HERE
MicroEdition-Profile: MIDP-2.0
MicroEdition-Configuration: CLDC-1.1
MIDlet-1: HelloWorld,,HelloWorld

At this point you don’t need to worry too much about the contents of the JAD and manifest files. I’ll be devoting an article to their maintenance in the near future. For the purposes of this article you need only know that they are essential files for running any MIDlet.

Directory Structure

If you are intending on using the ANT build script I provide below to automate your project’s build then all of these files must appear in a particular hierarchy. Below is an image of that hierarchy. Ensure that the files are placed in the proper directories.

The Directory Structure
helloworld-folder-layout.png

Although I discuss each of build steps in detail below I want to briefly explain the directory structure’s purpose.

The src directory is where the two java files are located.

When compiled the resulting class files will be placed in the build directory along with the MANIFEST.MF file which is copied from the META-INF directory.

The lib directory houses the two main J2ME library JAR files that are needed for our project.

Upon JARring the project, the files located in the build folder will be archived and the resulting JAR files will be placed in the dist folder where the JAD file is normally housed. It is here that preverify and JammedUp process the JAR file and update the JAD file.

This is by no means the only way to layout your project’s files but it’s a basic one that has worked well for me many times.

Rewind :: The Build Process

Compilation

Either performed automatically by an IDE or done by hand or automated via ANT. The end result is a set of class files. In this example there should be two files: HelloWorld.class, and HelloWorldCanvas.class.

JARing

The project classes, the manifest and resource files are bundled into one file: HelloWorld.jar.

Preverification

Unlike J2SE classes J2ME classes must have their contents preverified prior to execution on the device. This is compensation for the limited processing power of mobile devices. This stage includes checks for illegal bytecode or constructs not supported by J2ME.

The preverify tool comes with most emulators and for Mac users the MPowerPlayer offers an OS X compatible binary.

JAD Updating

The JAD file has its contents updated to reflect the properties of the JAR file.

To download JammedUp click here.
(Learn more about JammedUp…)

Automating the build process with ANT

ANT can be used to perform all of the build steps in sequence saving you much time and effort. The source code download also includes a sample ANT build script.

build.xml

<project name="helloworld" default="dist" basedir="." >
	<property name="app.name" value="helloworld" />
	<property name="app.path" value="/${app.name}"  />
	<property name="build.home" value="${basedir}/build" />
	<property name="lib.home" value="${basedir}/lib" />
	<property name="dist.home" value="${basedir}/dist" />
	<property name="src.home" value="${basedir}/src" />
	<property name="compile.debug" value="true" />
	<property name="compile.deprecation" value="false" />
	<property name="compile.optimize" value="true" />

	<target name="all" depends="dist" description="Clean build and dist directories, then compile" />
	
	<target name="clean" description="Delete old build directory">
		<delete dir="${build.home}" />
	</target>
	
	<target name="compile" description="Compile Java sources">
		<javac srcdir="${src.home}" destdir="${build.home}" debug="${compile.debug}" deprecation="${compile.deprecation}" optimize="${compile.optimize}">
			<classpath>
				<fileset dir="${lib.home}" includes="*.jar,*.zip" />
			</classpath>
			<include name="**/*.java"/>
		</javac>
	</target>
	
	<target name="bundle" depends="compile" description="Takes the built objects and makes a JAR file.">
		<mkdir dir="${build.home}/META-INF"/>
		<copy todir="${build.home}/META-INF">
			<fileset dir="META-INF" includes="**/*.MF" />
		</copy>
		<jar jarfile="${dist.home}/HelloWorld.jar" basedir="${build.home}" includes="**/*.class" />
	</target>
	
	<target	name="preverify" depends="bundle" description="Preverifies the JAR file.">
		<exec dir="${dist.home}" executable="<path-to-project>/dist/preverify">
			<arg line="-d ${dist.home} -classpath ${lib.home}/cldcapi11.jar:${lib.home}/midpapi20.jar ${dist.home}/HelloWorld.jar"/>
		</exec>
	</target>
	
	<target
		name="dist"
		depends="preverify"
		description="Create binary distribution">

		<exec dir="${dist.home}" executable="java">
			<arg line="-cp %CLASSPATH%;.;.. -jar JammedUp.jar HelloWorld.jad -b -d -s"/>
		</exec>
		
	</target>
	
</project>

Running HelloWorld

If the build worked perfectly you now have a HelloWorld.jar and a HelloWorld.jad file pair in your dist directory. Using your emulator, instruct it to open the JAD file and you should see something similar to the below image…

Image of Hello World running in MPowerPlayer
helloworld-emulator.png

In Closing

In this article you learned how to develop, deploy and test your first MIDlet. But this is just the beginning of your journey to become a great J2ME developer. This site continues to grow and provide tips and techniques for both beginners and experts alike and I also recommend the J2MEForums for finding quick answers from programmers of all calibres.

Scope of Article

A supporting feature for any serious game, collision detection provides tangibility and depth to your game world’s objects. This article explores in brief the common types of collision detection you can employ in your games to add a sense of realism and interactivity.

The 3 Approaches

1. Grid-based Detection

This is by far the simplest form of collision detection. Essentially a grid is setup whereby the player is only allowed to stand on certain tiles. This is similar to chess where each piece occupies only a single square.

To implement this form of collision detection you need only use an array to represent each tile. This array can be as simple as a collection of booleans (false = empty, true = solid) or you can repurpose a tiled graphics layer to also store this information. Such layers store integers as indices into a tile array and it is typical to use 0 as the no tile value which is also useful for saying there is nothing with which to collide.

This approach is useful for board games like chess and for simulation games.

2. Bounding Boxes

Bounding boxes are imaginary, invisible boxes that surround solid objects. In this case collision detection involves ensuring that no two bounding boxes intersect. In the case of 3D games boxes are replaced by 3D cubes.

While easy to process this technique is not accurate unless the objects in question are rectangular and the same size as their bounding boxes. A workaround to this problem is the use of smaller bounding boxes. Since bounding boxes are invisible their size has no impact on the display of objects. This is at best a workaround and not a full solution however. Even smaller bounding boxes will not provide perfect results and in the worst cases may exhibit situations where two objects which appear to be colliding visually are not detected as a true collision.

This approach is useful for games with a large quantity of objects which can collide with the player or each other.

One caveat regarding bounding box testing

When using this technique in 3D or 2.5D games avoid floating point comparisons as bounds values can become skewed and are generally slower to compare than integer values.

3. Pixel-level collision detection

Introduced in MIDP 2.0, the Sprite class’ doPixelCollision/collidesWith methods offers pixel-level collision detection which involves detecting overlap between two objects’ visible pixels. This method is only applicable to 2D games and is more costly as the pixels from masks of both images must be tested for overlap. The larger the images, the more costly this approach becomes. There are cases, however, where this approach is the only viable one. Good examples would include testing whether a spaceship with a non-rectangle shape were really hit by an enemy
missile or one ball hit another on a billiard board.

The Need for Collision Detection

Without effective collision detection there would be nothing preventing gravity from dragging you through the ground or from walking through walls. Games like golf, tennis, and pinball simply wouldn’t work with collision detection.

When to Apply Collision Detection: Preventative VS Corrective Collision Detection

Collision detection is either applied before or after an object moves. If applied before, the object’s soon to be occupied position is used in the test and should a collision be detected the move is denied. If the collision detection is applied after the object move and a detection occurs the object
is moved back to its prior position. Both methods incur the same performance costs and which one you employ will largely be based on the ease of integration with the rest of your game logic.

Performance Costs

The time it takes to test for object collision in a scene is proportionate to the number of objects in that scene. If only two objects exist only one test need occur. If three objects exist three tests must occur. In grid based collision detection a simple lookup to see if the slot is occupied or not will suffice. With free-range 3D games each object’s moves are in need of testing.

Results of a Position Collision

When a sprite collides with an object it typically stops moving and prevent further incursions in the interest of maintaining the illusion of solidity. This, however, is not the only possible result of collision.

Fighting games often cause the injured player to be pushed back upon being punched or kicked to impress upon the player the amount of force that was just used. Billiard balls that collide transfer a portion of the kinetic energy to each other while retaining some which is used to move in a refracted direction. In these cases stopping motion is not desirable. The take away here is that each game can have its own appropriate response to collision.

In Closing

Collision detection, while a must for most games if not all games comes at a cost and decisions during the design phase need to take into account this performance impact. There are various techniques for providing solidity in game environments and they can be used singularly or in tandem.

Introducing JammedUp, the MIDP and DoJa MIDlet descriptor updater.

>> Download JammedUp.zip <<

Introduction

MIDlets are typically separated into a JAR executable file and another file, the descriptor, which offers a brief but accurate description of the JAR file’s contents prior to download.

As JAR files are updated with each build there arises the need to also update the descriptor. Neglecting this step will result in MIDlets which cannot be installed to either an emulator or an actual J2ME-enabled device.

JammedUp (short for: JAM and JAD Update) is the tool which will automate this updating with each build of the JAR file. Since JammedUp runs on Java 1.4 it works on any Java capable host computer and has been localized to support the following languages:

· Brazilian Portuguese
· English
· French
· German
· Hebrew
· Japanese
· Simplified Chinese
· Spanish

How it Works

JammedUp updates, according to the specified options, the JAR size, the build date, and the build counter.

The update options are…
-b Updates the build counter
-d Updates the build date
-s Updates the JAR size

How to Execute

JammedUp can be executed 3 ways. For manual execution one need only to execute the following command…

java -jar JammedUp.jar descriptor.jad midlet.jar -b -d -s

(where descriptor.jad and midlet.jar are replaced by your project’s filenames, if for DoJa substitute jad with jam)

This command can be issued by a shell script as shown above but if the ANT build tool is used the following target should be integrated into your project’s build.xml file.

<target name="jammedup" depends="preverify" description="Update descriptor">
    <exec dir="${dist.home}" executable="java">
        <arg line="-cp %CLASSPATH%;.;.. -jar JammedUp.jar helloworld.jad helloworld.jar -b -d -s"/>
    </exec>
</target>

Lastly, if you have a customized build system that is built in Java you can leverage the classes in the JammedUp.jar from your application as demonstrated in the code below.

JammedUp ju = new JammedUp();

try {
    // Call JammedUp
    ju.execute(descriptorFilename, jarFilename,
        isDojaDescriptor, updatesSize, updatesBuild,
        updatesDate, null);
} catch (JammedUpException jue) {
    // An exception occured!
    System.out.println(jue.getMessage());
}

Call for assistance

JammedUp needs localizations. If you natively speak a language that has not been listed and would like to have your contribution mentioned in the product please contact me at the address below…

    j a y _ f u e r s t e n b e r g [AT MARK] y a h o o . c o . j p

Scope of Article

Although the tips in this article are not specific only to J2ME, they are essential for maintaining the performance of MIDlets in spite of the limitations of mobile devices.

In most cases, optimizing for speed comes at the cost of increased space usage. Developing for MIDlets is a careful balance of these 2 optimization concerns. Early optimization can render code difficult to read and maintain and the most of the tips found here should be taken towards the end of the development phase and not from the beginning.

1. Avoid synchronization when possible

It is said that code within synchronized contexts is roughly 4 times slower than ordinary code. Regardless of Java VM implementation a lock must be inspected and acquired upon an object each time the synchronized context is entered and must be unlocked upon exit. Threads which cannot acquire a lock must wait for the lock to be released. These factors should be compelling reasons to avoid synchronization where possible.

2. Using pre-computing

If your MIDlet uses 3D/2.5D graphics you will no doubt be using sines, cosines and possibly tangents along with angles. These operations are processing intensive so why not create pre-computed lookup arrays in your code? Your CPU will thank you for it.

There are cases besides 3D graphics that benefit from pre-computing but all take the form of lookup tables/arrays where values known at design-time are spared computation at runtime.

3. Array-spreading

Accessing arrays comes at a performance penalty and multi-dimension arrays are even worse. They can be optimized by making them uni-dimensional.

Example:


// Before
int[][] table; // a 4x4 table

// After
int[] table; // a 1x16 table

As a bonus uni-dimensional arrays consume less heap memory!

4. For-Loop Unrolling

Loops are a convenient feature but the bytecode they generate is wasteful. Iterating 15 times over a block of logic means also executing a 15 comparisons and 15 increments.

Example:


void printMsg() {
	for (int loop = 0; loop < 15; loop++) {
		System.out.println(msg);
	}
}

Is functionally the same as…


void printMsg() {
	int loop = 0;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;
	
	System.out.println(msg);
	if (loop >= 15) {
		return;
	}
	loop++;	
}

I apologize for making you scroll so far, but it was necessary to impress upon you how loops make our lives easier but also abstract the inner workings so well that many programmers don’t realize their costs.

If, at design time, you know the number of iterations it can be beneficial to unroll your loop like such…


void printMsg() {
	
	for (int loop = 0; loop < 15; loop += 5) {
		
		System.out.println(msg);
		System.out.println(msg);
		System.out.println(msg);
		System.out.println(msg);
		System.out.println(msg);
	}
}

Do you see what has improved? This for-loop will only iterate 3 times. The message will still be printed out 15 times as it was before but there will be only 3 comparisons and 3 additions upon the ‘loop’ variable. The output is the same but it takes less instructions to accomplish because there was less loop management.

One caveat about loop-unrolling

You might be tempted to apply this trick on all your for-loops but you must keep one thing in mind before doing so. Loop-unrolling generates larger code and can cause the body of the loop to be so big that it cannot fit entirely within the CPU’s cache. When instructions cannot entirely fit within the cache, the cache contents have to swapped in and out and this will render your MIDlet’s performance probably worse than had you not unrolled it at all. Refrain from going overboard with loop-unrolling.

5. For-loop tightening

The goal of for-loop tightening is to remove logic that does not require repeated execution from appearing within the loop body.

Example:


// Bad
for (int loop = 0; loop < 10; loop++) {
	
	int a = 5;
	int b = 10;
	
	int c = a * b + loop;
}

// Good
int a = 5;
int b = 10;

for (int loop = 0; loop < 10; loop++) {
	
	int c = a * b + loop;
}

In the good example a and b are assigned once only. That’s a total of 20 assignments that were avoided.

A lesser known tightening technique

Unless absolutely necessary, never call a method in the conditional portion of a loop. It will be called with each iteration. A common example and an easy optimization is given below.


//Bad
for (int loop = 0; loop < msgs.size(); loop++) {

	System.out.println(msgs.get(loop));
}

// Good
int msgCount = msgs.size();
for (int loop = 0; loop < msgCount; loop++) {

	System.out.println(msgs.get(loop));	
}

In the bad example msgs.size() is called with each iteration. In the good example it is called once. This is of course assuming msgs doesn’t grow or shrink during the execution of our loop.

6. Avoiding interface method calls

In Java bytecode there are 4 types of method invocations. Below they are listed in fastest-to-slowest order.

  • invokestatic
  • Static method invocation does not use an instance and therefore does not need to abide by the rules for polymorphism and this means an instance type lookup is not required when calling it. The reference type is used instead and this is known at compile time.

  • invokevirtual
  • Calls a normal method.

  • invokespecial
  • Special invocations are calls to constructors, private methods and super class methods.

  • invokeinterface
  • Requires a search for an appropriate implementation of the interface method prior to invocation and is therefore the slowest.

    What types of methods you call can have an impact on your application design so it is a good idea to keep these facts in mind during the development cycle.

    Calling static methods offers the best performance as there is no lookup at runtime for the method that will be invoked. In contrast, calling interfaces requires two lookups.

    7. Avoiding unnecessary array lookups

    Indexing an array isn’t the fastest of actions. If there’s a value you can reuse, place it in a plain variable and refer to that instead.

    8. Avoiding argument usage

    When you call a non-static method you are implicitly passing the “this” reference to it along with any other parameters. Since the Java VM is a stack-based one these arguments need to be pushed and then popped from that stack upon each method invocation. In some cases you can place these parameters in instance variables and avoid stack operations altogether.

    Example:

    
    // Bad
    return multiply(int a, int b) {
    
    	return a * b;
    }
    
    
    // Good
    int result;
    int a;
    int b;
    
    void multiply() {
    
    	result = a * b;
    }
    

    From a high-level perspective there is very little difference between these two styles but the Good one is actually faster. It gets even better if all the variables and the method are declared “static”. This way the “this” reference isn’t sent to the multiply method.

    9. Avoid local variables

    Local variables are instantiated on and removed from the stack with each method call. Where possible use (and reuse) instance variables which are allocated from the heap upon object instantiation and garbage collected at a later time.

    10. Avoiding getters/setters

    For reasons mentioned above calling getter/setter methods is wasteful. I don’t usually recommend breaking from Java Beans calling conventions but towards the end of my development cycles I usually trim these methods from my code. This is a rare case where optimizing for speed also optimizes for space.

    11. Strength Reduction

    Performance-wise, not all mathematical operations are equal. While additions are subtractions are fast, multiplications, divisions, and modulus are slow. Sometimes bitwise operators can make operations even faster as we’ll see.

    
    // Bad
    int a = 5 * 2;
    
    
    // Good
    int a = 5 + 5;
    
    
    // Better
    int a = 5 << 1; // Shift 5 (0000 0101) 1-bit to the left to become 10 (0000 1010).
    
    
    // Best
    int a = 10; // Trick question, if you know the result at design-time don't compute it!
    

    Strength reduction techniques have been in practice since at least the DOS game programming days and are perhaps one of the only optimizations that one might care to make early on as it can impact the overall design of the MIDlet.

    In closing

    This is just a sample of optimizations that can be easily applied to just about any MIDlet with minimal effort. While it might be difficult to guage their effectiveness (especially across various mobile devices), properly used they cannot have a negative impact on performance. The value in these tips comes mostly from the gained understanding of the bytecode that results from our programming styles and how it is up to us to keep it optimal.

    Low-level Debugging in J2ME

    Scope of Article

    Debugging MIDlets can be challenging to say the least. This article
    aims to show programming techniques that can reduce the need to debug and then best practices when debugging as well as the top tool for that task.

    Debugging as is commonly done in J2SE with breakpoints is not discussed as it is not always available in J2ME. In other words the reader is assumed to have working knowledge of System.out.println() method.

    Preventative VS Corrective Maintenance

    “An ounce of prevention is worth a pound of cure” certainly rings true when developing applications for mobile devices. When creating a class or method it is worth creating an accompanying Unit Test (UT) which can expose any flaws early in the development process. JUnit (bundled with the Eclipse IDE) and J2MEUnit are two testing frameworks that perform tests on the development host PC and the target device respectively. Unit testing deserves an article all by itself and cannot be done justice here, but certainly keep it in mind if you’re aiming for robustness.

    Developing Defensively

    Applications invariably fail from time to time. The reason is often human error. As applications grow bigger and bigger their complexity becomes a thriving environment for bugs. It has been the goal of many programming languages to reduce these complexities through enhancing expressiveness (accomplishing tasks in fewer instructions/steps).

    For this reason a line of hand-written Java code is less likely to contain a bug then its assembly language equivalent. However expressiveness alone is not enough to keep our applications bug-free. It also helps to program defensively where assertions are sprinkled around the code like traps waiting for bugs. A simple example is that of validators at the beginning of key methods.

    Defenseless method

    
    void setAge(int age) {
        this.age = age;
    }
    

    Defensive method

    
    void setAge(int age) {
        if (age < 0) {
            StringBuffer msg = new StringBuffer();
            msg.append("The negative age (");
            msg.append(age);
            msg.append(") is not permitted.  age must be 0 or higher.");
            throw new IllegalArgumentException(msg.toString());
        }
    
        this.age = age;
    }

    Defenseless method

    
    void setDayOfWeek(int dayOfWeek) {
        this.dayOfWeek = dayOfWeek;
    }

    Defensive method

    
    void setDayOfWeek(int dayOfWeek) {
        switch (dayOfWeek) {
        case SUNDAY:
        case MONDAY:
        case TUESDAY:
        case WEDNESDAY:
        case THURSDAY:
        case FRIDAY:
        case SATURDAY:
            break;
        default:
            StringBuffer msg = new StringBuffer();
            msg.append("The dayOfWeek (");
            msg.append(dayOfWeek);
            msg.append(") is not recognized. dayOfWeek must be one of ");
            msg.append("SUNDAY, ");
            msg.append("MONDAY, ");
            msg.append("TUESDAY, ");
            msg.append("WEDNESDAY, ");
            msg.append("THURSDAY, ");
            msg.append("FRIDAY, ");
            msg.append("SATURDAY.");
            throw new IllegalArgumentException(msg.toString());
        }
    
        this.dayOfWeek = dayOfWeek;
    }
    

    While these above examples illustrate argument filters/validators throwing the IllegalArgumentException near the top of the method body, using traps at various locations in source code is also highly recommended.

    The goal is to have logic perform a sanity check on the state of objects before relying on them.

    Which of the below pseudo code samples looks cleaner?

    
    void methodName() {
        // check all
        sanityCheck1();
        sanityCheck2();
        sanityCheck3();
    
        // do all
        doSomething1();
        doSomething2();
        doSomething3();
    }
    
    
    void methodName() {
        // check 1
        sanityCheck1();
    
        // do 1
        doSomething1();
    
        // check 2
        sanityCheck2();
    
        // do 2
        doSomething2();
    
        // check 3
        sanityCheck3();
    
        // do 3
        doSomething3();
    }
    

    The second example is slightly more complex than the first in that it requires the developer to constantly switch attention back and forth from “checking” and “doing”. These examples are trivial and it might be difficult to understand how either could cause a bug but performing all checks in advance lets the developer focus on the task at hand (the core logic) later and also lends well to exporting the validation task to an external class at some later point for performance and code clarity reasons.

    Using Descriptive Exceptions

    Exceptions are a powerful feature in Java and give developers a chance to gracefully recover/fail in the face of errors. A lot of developers don’t realize however the opportunity for exceptions to automate the process of bug-fixing by simply being descriptive.

    I’m a firm believer that computers and people are better at different things and that we should offload the things that we cannot do quickly and accurately or with much interest onto computers. The infinitely mundane task of bug-hunting, in my opinion, should be no different. Bugs ARE there and in order to keep them from occurring twice we need to know their causes, the conditions that got us in this situation. This is something most computers don’t do so well and need somebody at the helm to fix things.

    But what we’re used to seeing is this…

    
    IllegalArgumentException at line 123
    

    Wouldn’t it be nicer to see…

    IllegalArgumentException at line 123
    Cannot withdraw the negative amount (-50.00) from (My Savings) account.
    Amount must be 1.00 or higher and must not exceed the amount saved in the account.
    

    This more descriptive exception tells the programmer not only what went wrong but what the method contract expects and even gives an example of how to do the right thing.

    If the method was simply passed a value from the user then we know that input validation is the solution. If, on the other hand, a different method called this withdrawal method then we know that it was programmer error that is the cause. And we figured this all out without having to scour the code. The stack trace tells us who the caller is.

    MPowerPlayer

    The MPowerPlayer is a MIDP 2.0 compliant multi-platform Java-based emulator. What distinguishes it from the rest, and why I recommend it, is its ability to print the line number of offending code the same as J2SE VMs. All other emulators I have tried only show byte offset numbers which are not useful but are unfortunately the norm in J2ME. As I develop MIDlets from a Mac there aren’t many emulators to choose from and I have come to depend on MPowerPlayer and can vouch for its quality.

    What might throw one off at first is that this emulator does not have a graphical window pane for outputting messages/exceptions and instead relies on the console for its output. That output looks like this…

    j2me-debug-exception.gif

    Debugging on Devices

    Lastly I’d like to discuss the issue of debugging with devices. Sometimes a bug can only be reproduced within the environment of a mobile device and this is usually the case with errors regarding networks, storage, and threading. In these cases we need a means to output the exception and/or some information about the environment prior to failure.

    In the past I have written custom canvas classes to break up large Strings into smaller ones that could be output with the drawString() method. I have also heard others uploading the exception information in a HTTP request to their servers and even some people saving the data to external storage (SD cards).

    The take away is that there are many ways to collect this data and the point about being descriptive really pays off (literally if your carrier charges you for data downloads).

    With this information I wish you happy debugging!

    Scope of Article

    This article begins by giving a general introduction to the concept of FPS and illustrates its everyday use before diving into the specifics of how it is employed in J2ME applications. Lastly, the FPS code is discussed and offered for inclusion in your MIDlet.

    Terminology

    FPS = Frames Per Second
    fps = the measuring unit for FPS
    Hz = Hertz (cycle frequency used in electronic devices)

    What is FPS?

    FPS stands for “Frames Per Second” and is a measure of full-screen updates that occur within a single second. FPS is used everywhere screens/monitors are used. Your TV uses it to show you exactly 25 or 30fps (actually 29.97fps) depending where in the world you live. Movie theatres use it to show films at 24 fps.

    Why is FPS used?

    Without FPS a screen would playback video at unstable speeds.

    If you’ve watched a silent motion picture where actors walk fast one second then slow the next you have a good idea of the effects of no-FPS video playback. FPS keeps the screen synchronized with the video’s original recording speed.

    How does FPS differ from Hz?

    If you’ve ever tuned your PC monitor’s settings you’ve likely come into contact with the Hz (short for Hertz) setting. Hz is the measurement of screen refreshes to the monitor. It usually coincides with the Hz of the electricity flow, for instance 60Hz in North America/Japan and 50Hz in most of Europe.

    FPS and Hz are similar but not identical. North American TVs for instance refresh
    the screen 60 times per second (60Hz) but have a 30fps.

    What is happening is that only half of the screen is being updated in a 1Hz cycle and the other half in the next 1Hz cycle. This is referred to as interlacing. First the odd lines are rendered to screen then the even lines. This way it takes 2Hz to update the entire screen and at 60Hz it can render 30fps.

    Remember FPS counts full-screen updates whereas Hz counts screen refreshes, which are not required to be full refreshes.

    Still images and the illusion of motion.

    The video seen on your TV is really comprised of still images that, displayed fast enough, provide the illusion of motion. But you already knew that. What you might not know is that your eyes have their own FPS! At 18 fps or higher your eyes are incapable of distinguishing the still images that make up a segment of video. This is why TVs and movie theatres display video at rates higher than 18.


    FPS in J2ME

    Now that you understand FPS and why it is needed let’s look at FPS’ role in J2ME applications.

    Much like video, games render scenes to the screen. If these scenes are rendered too slow the player loses interest. If rendered too fast keeping up with the action might prove difficult. In this sense FPS is more important in games than it is in TV because the player is interacting with and being immersed in the game.

    With regards to J2ME, FPS is paramount to providing a consistent experience across a wide range of devices. Each device vendor is free to use any CPU and component configuration and part of the power of J2ME is maintaining functional operation while lacking a reference hardware configuration. If the device were a reference hardware configuration like that of the GameBoy Advance the maximum FPS would be a known number.

    Unfortunately, performance may vary wildly from device to device. While applying an FPS setting cannot make a game render scenes faster it can ensure that the game will not render more frames than are specified within one second.

    So what is the ideal FPS setting?

    There is no one correct answer for this. If the goal is to provide a consistent experience across many devices, testing will be required to gauge the result and to find that sweet spot that balances performance with consistency.

    The resulting number may even be lower than the eye’s FPS of 18fps. This is acceptable to some degree by most players depending on the gameplay. It is advised that any game should be tested with FPS settings as low as 5fps if only to define the absolute minimum acceptable FPS rating.

    A note about sample video distribution

    If you are planning on providing a sample video capture of your game in action to others you may wish to use 15fps as it can be played back smoothly on TVs supporting 30fps and computer monitors supporting 60Hz or 75Hz as 30, 60 and 75 are multiples of 15.

    The FPS class

    For my own purposes I have created a FPS controller class that integrates well within any framework. The code is as follows…

    /*
    	Copyright 2007 Jason Fuerstenberg
    	
    	Licensed under the Apache License, Version 2.0 (the "License");
    	you may not use this file except in compliance with the License.
    	You may obtain a copy of the License at
    	
    		http://www.apache.org/licenses/LICENSE-2.0
    		
    	Unless required by applicable law or agreed to in writing, software
    	distributed under the License is distributed on an "AS IS" BASIS,
    	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    	See the License for the specific language governing permissions and
    	limitations under the License.
     */
    import java.lang.Math;
    
    /**
     * Utility class for exposing FPS related functionality to a J2ME application.
     * 
     * @author Jason Fuerstenberg
     */
    public class FPS {
    	
    	/*
    	 * The millisecond timestamp of the current render frame if used.
    	 */
    	private static long frameTime;
    	
    	private FPS() {
    		// singleton implementation
    	}
    	
    	/**
    	 * Returns the best delay given the specified FPS.
    	 * The delay is used in application loops and is typically provided to the
    	 * Thread.sleep() method.
    	 * 
    	 * 
    	 * The basic formula for this calcuation is as below:
    	 * 
    	 * delay = 1000 / fps
    	 * 
    	 * The delay in millseconds, is the product of 1000 milliseconds divided
    	 * by the desired FPS.
    	 * 
    	 * Note: To be compatible with the CLDC 1.0 specification this method
    	 * makes no use of floating point math and therefore the returned delay
    	 * is always an integral number and may not be the precise result.  The
    	 * results are precise to within 0.5ms.
    	 * 
    	 * For example an FPS of 3 should produce a delay of 333.33333ms
    	 * however this method will return a delay of 333ms.
    	 * 
    	 * Alternately an FPS of 6 would produce a 166.66666ms delay.  The actual
    	 * returned delay is 167ms.
    	 * 
    	 * @param fps The desired frames per second.
    	 * @return A delay (in milliseconds) within 0.5ms accuracy.
    	 * @throws IllegalArgumentException if fps does not fall within 1-60.
    	 */
    	public static int getDelayFromFPS(int fps) {
    		
    		if (fps < 1 || fps > 60) {
    			// invalid fps
    			throw new IllegalArgumentException("fps must range from 1 to 60.");
    		}
    		
    		// determine the delay
    		int delay = 1000 / fps;
    		
    		// determine the duration of a cycle if the above delay were applied
    		int cycleDuration = delay * fps;
    		
    		
    		if (cycleDuration == 1000) {
    			/*
    			 * Found the perfect delay!
    			 * Return it now.
    			 */
    			return delay;
    		}
    		
    		/*
    		 * The calculated delay, if applied, will not result in the desired FPS.
    		 * Find the delay which will produce the closest FPS cycle from the
    		 * following choices:
    		 * 
    		 * 1. the calculated delay
    		 * 2. the calculated delay - 1ms
    		 * 3. the calculated delay + 1ms
    		 */
    		int delayMinusOne = delay - 1;
    		int cycleDuration2 = delayMinusOne * fps;
    		
    		int delayPlusOne = delay + 1;
    		int cycleDuration3 = delayPlusOne * fps;
    		
    		int diff1, diff2, diff3;
    		
    		diff1 = Math.max(cycleDuration, 1000) - Math.min(cycleDuration, 1000);
    		diff2 = Math.max(cycleDuration2, 1000) - Math.min(cycleDuration2, 1000);
    		diff3 = Math.max(cycleDuration3, 1000) - Math.min(cycleDuration3, 1000);
    		
    		if (diff1 < diff2) {
    			return (diff1 < diff3 ? delay : delayPlusOne);
    		}
    		
    		return (diff2 < diff3 ? delayMinusOne : delayPlusOne);
    	}
    	
    	/**
    	 * Enforces a cycle delay on behalf of the application while using
    	 * an internally managed frame time.
    	 * 
    	 * @param delay The delay to apply to this cycle.
    	 */
    	public static void enforceCycleDelay(int delay) {
    		enforceCycleDelay(frameTime, delay);
    	}
    	
    	/**
    	 * Enforces a cycle delay on behalf of the application.
    	 * 
    	 * @param frameTime The millisecond timestamp of the current frame's
    	 * 			start time. 
    	 * @param delay The delay to apply to this cycle.
    	 */
    	public static void enforceCycleDelay(long frameTime, int delay) {
    		
    		long sleepTime = delay - (System.currentTimeMillis() - frameTime);
    		
    		if (sleepTime > 0) {
    			
    			try {
    				Thread.sleep(sleepTime);
    			} catch (InterruptedException ie) {
    				/*
    				 * There is no appropriate course of action to recover from
    				 * an InterruptedException and therefore only the fact that it
    				 * occurs is output to the stack trace.
    				 */
    				ie.printStackTrace();
    			}
    		}
    		
    		// Set the current frame-time.
    		FPS.frameTime = System.currentTimeMillis();
    	}
    	
    	/**
    	 * Returns the interally managed frame-time.
    	 * The value may or may not be set depending on the previous usage of
    	 * this class.
    	 * 
    	 * @return The internal frame-time.
    	 */
    	public static long getFrameTime() {
    		return frameTime;
    	}
    }
    

    How does the class work?

    The class has 2 purposes:

  • Determine the most appropriate delay for a given FPS setting. Remember, Java doesn’t understand FPS. The Thread.sleep() method expects a millisecond delay setting. The getDelayFromFPS() method will determine the best delay to within 0.5 ms accuracy given a FPS setting.
  • To provide an easy-to-use fps controller which integrates into any MIDlet and is callable from multiple locations.
  •  

    Where does the invocation to this class belong?

    The game loop!

    Since each game loop iteration can be thought of as a cycle a game can use a call to the enforceCycleDelay() method to signal the end time of the previous frame and the start time of the next frame. To achieve the desired the FPS it calculates the remaining time it should attempt to sleep, if any.

    Managing the frame’s start time.

    The FPS class has an internal frame start time but will also accept an external start time when provided one. In addition, the internal frame start time can be retrieved via the getFrameTime() method for general consumption by the caller.

    A word about Java’s thread scheduling

    Java does not provide its own threading functionality but merely abstracts the OS’ thread scheduler with a consistent API. As such, different devices will offer different responsiveness. As the FPS class is dependent upon this functionality there is a chance that the requested FPS setting may not be honored at all times.

    Multithreaded considerations

    Each thread that executes on a mobile device can consume significant amounts of CPU time. In fact many embedded OSes do not support the concept of pre-emptive multithreading where each thread is forced to play fair and only uses a small slice of the CPU’s time. In this case each thread might be allowed to “hog” the CPU. The FPS class can still adjust since it is aware of the accurate passage of time but it cannot prevent a game loop iteration from taking longer than the FPS setting to complete.

    Please read my article on Multithreading in J2ME for more in depth information.