Main Loop

Traditionally games (action and time-dependent games in particular) are written as a loop that runs as fast as possible continuously updating the graphics, physics, AI and such. This is because in C that is how applications with a GUI were written, a loop which updates the UI and then sleeps for a while.

Multiple Event Listeners

This method is specific to ActionScript and it’s fancy listeners. Rather than having a main loop that updates all of the objects, the objects have event listeners attached to themselves. Listeners are used a lot in ActionScript this is mainly because there isn’t blocking like in Java. For example in Java reading a line from a network Socket would block until the socket had something to read (or timed out), but in ActionScript you have to add a Listener that is triggered when the Socket has something to read.

In the case of the ENTER_FRAME event however all of the multiple Listeners are responding to the same event and are therefore adding to the amount of computation required.

Code

The code for this test is split into two parts, one of the documents classes uses a main loop and the other uses a class called ParticleSpecial which handles it’s own ENTER_FRAME events.

Main Loop Document Class:

package {

	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.utils.getTimer;

	public class MainLoop extends MovieClip {
		private var fps:FPS=new FPS();
		private var particles:Array=new Array(1000);

		public function MainLoop() {
			for (var i:uint = 0; i<particles.length; i++) {
				particles[i] = new Particle();
				addChild(particles[i]);
			}

			addEventListener(Event.ENTER_FRAME, update);
		}

		private function update(e:Event) {
			for (var i:uint = 0; i<particles.length; i++) {
				particles[i].x=275+100*Math.cos(getTimer()*0.001);
				particles[i].y=200+100*Math.sin(getTimer()*0.001);
			}
		}
	}
}

Multiple Event Listeners Document Class:

package {

	import flash.display.MovieClip;

	public class Listeners extends MovieClip {
		private var fps:FPS=new FPS();
		private var particles:Array=new Array(1000);

		public function Listeners() {
			for (var i:uint = 0; i<particles.length; i++) {
				particles[i] = new ParticleSpecial();
				addChild(particles[i]);
			}
		}
	}
}

ParticleSpecial  Class used by Multiple Event Listeners Document Class:

package {

	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.utils.getTimer;

	public class ParticleSpecial extends MovieClip {

		public function ParticleSpecial() {
			addEventListener(Event.ENTER_FRAME, update);
		}

		private function update(e:Event) {
			x=275+100*Math.cos(getTimer()*0.001);
			y=200+100*Math.sin(getTimer()*0.001);
		}
	}
}

Results:

Test MainLoop (fps) Listeners (fps)
1 59.9 29.8
2 59.9 29.7
3 60.0 30.5
4 59.8 29.3
5 60.0 30.7
6 59.8 29.0
7 59.9 30.8
8 59.9 29.2
9 60.0 30.6
10 59.3 29.3
Average 59.8 29.9

Conclusion

Although using multiple event listeners can make your code neater and more organized, the technique is far too slow in performance critical fast paced games.

Preamble

ActionScript 3 despite the hype of the AVM2 still can be very slow, particularly when writing games because games often push your hardware ways that other applications simply will not. A form or image gallery for example will for a lot of the time be doing nothing waiting for the user to interact e.g. click a button. A game on the other hand will constantly be drawing, calculating physics, responding to collisions for a number of objects and then there’s AI on top of those.

Although this series is most relevant to games the findings can be applied to most programming projects especially in languages such as Java and ActionScript. After all performance and efficiency is important predominantly when memory or processing power is limited i.e. on handheld devices.

Object Recycling

Object recycling is reusing memory that has already been allocation by modifying variables rather that allocating more memory using the new statement. Modifying the variables such that the object is effectively a new object but in the same memory. Here’s an explanatory example:

var lc:LovelyCharacter = new LovelyCharacter("David", "17-02-1902", 10, 0.5);

// not recycling and bad
lc = new LovelyCharacter("Terry", "03-05-2004", 14, 0.1);

// recycling and good
lc.name = "Terry";
lc.dob = "03-05-2004";
lc.numOfChildren = 14;
lc.interest = 0.1;

// or for convenience  define a reset function
lc.reset("Terry", "03-05-2004", 14, 0.1);

As you can see the instance lc is the same after either process however the recycling process didn’t allocate more memory. Allocating more memory also means that the old memory is released which results in the garbage collector (gc) having to do some work ultimately slowing down the game since this process takes time.

Read more: Code, Results and Conclusion

Acara Catch

December 29th, 2009

Here we are approximately 1800 lines of code my first flash game Acara Catch! It’s a fishing game with an online highscore table.

Acara Catch

Play the game

Multi-client
Icons: Macbook Pro – jasonrm, Server – visualpharm.

Handling multiple clients in Java is relatively easy and painless compared to C for example. This is because Java hides a lot of the complexities of writing your application to make use of multiple threads.

Basically all that needs to be written is a class, ClientHandler say, the implements Runnable and handles the client. ClientHandler‘s constructor takes the client Socket as an input, so that it has something to act upon. And, the run() method does whatever needs to be done (i.e. reading and writing to the Socket) and then close()s the Socket.

ClientHandler Implementation

package uk.co.hejp.Server;

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;

public class ClientHandler implements Runnable {
	Socket socket;
	PrintStream out;

	ClientHandler(Socket s) {
		socket = s;
	}

	@Override
	public void run() {

		try {
			out = new PrintStream(socket.getOutputStream());
		} catch (IOException e) {
			System.out.println("PrintStream Error");
		}

		out.println("Hello");

		try {
			socket.close();
		} catch (IOException e) {
			System.out.println("Failed to close, oddly...");
		}
	}

}

This particular implementation of ClientHandler just writes ‘Hello’ to the Socket and close()s.

And just for completeness here is an implementation of a Server that uses ClientHandler:

package uk.co.hejp.Server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
	static ServerSocket socket;
	static int port = 7999;

	public static void main(String[] args) {

		try {
			socket = new ServerSocket(port);
			System.out.println("Bound to port: " + port);
		} catch (IOException e) {
			System.out.println("Cannot bind to port: " + port);
			System.exit(0);
		}

		while (true) {
			try {
				Socket s = socket.accept();
				System.out.println("New Client: "+s.getInetAddress().toString());
				(new Thread(new ClientHandler(s))).start();
			} catch (IOException e) {
				System.out.println("Failed to accept client");
			}
		}

	}
}

To test this Server you can use telnet (telnet 127.0.0.1 7999) or in your favourite browser goto ‘http://localhost:7999/’ the result should be just a line to text ‘Hello’ assuming you have the Server running.

Getting the URL variables can be using when writing AJAX applications, here is a little snippet of a function.

Method Detail:

String[] getURLVars(url)

Parameters:

url – string e.g. http://hejp.co.uk?name=joe&sister=sally

Returns:

An associative array containing the URL variables.

Code:

function getURLVars(url){
	var urlStr = new String(url);
	var vars = new Object();
	var tempArr = new Array();

	urlStr = urlStr.substring(urlStr.indexOf('?')+1);
	tempArr = urlStr.split('&');

	for(var i=0;i<tempArr.length;i++){
		var equalsPos = tempArr[i].indexOf('=');
		var key = tempArr[i].substring(0, equalsPos),	value = unescape(tempArr[i].substring(equalsPos+1));
		vars[key] = value;
	}

	return vars;
}

Example:

/* window.location is the url of 'this' page */
var vars = getURLVars(window.location); // e.g. window.location = 'http://hejp.co.uk?name=joe&sister=sally'

document.write(vars['name'] + '<br/>' + vars['sister']);
/* Prints:
      joe
      sally
*/

HEJPBézier Library

August 31st, 2009

Bézier Curve
Bézier curves are named after a French engineer Pierre Bézier, who used them to design smooth automobile bodies.

Today, them are most commonly used in computer graphics because of their smoothness and aesthetics.

Bézier curves are typically cubic, i.e. described by two anchor points and two control points but can be any degree that is computational possible in the time restraints of a particular application. HEJPBézier is a library for generating the series of points that compose a n-th degree Bézier curve.

Download Download HEJPBézier (24.8KB)
Documentation is included in the jar file.

Example

import uk.co.hejp.Bezier.*;
import java.awt.Point;

Point[] p1 = null, p2 = null;

void setup(){

  /* initialise */
  size(360, 200);
  strokeWeight(2);
  background(255);
  smooth();
  noFill();

  /* generate the curve */
  p1 = Bezier.bezierPoints(20, new Point(10,100), new Point(123,0), new Point(236,200), new Point(350,100));
  p2 = Bezier.bezierPoints(20, new Point(10,100), new Point(123,200), new Point(236,0), new Point(350,100));

  /* draw the curves with circles at each point */
  beginShape();

  stroke(135,170,222); /* pale blue */
  for(int i=0;i<p1.length;i++){
    vertex(p1[i].x, p1[i].y);
    ellipse(p1[i].x, p1[i].y,10,10);
    ellipse(p1[i].x, p1[i].y,4,4);
  }

  endShape();

  beginShape();

  stroke(255, 85, 85); /* salmon */
  for(int i=0;i<p2.length;i++){
    vertex(p2[i].x, p2[i].y);
    ellipse(p2[i].x, p2[i].y,10,10);
    ellipse(p2[i].x, p2[i].y,4,4);
  }

  endShape();

  /* export the image */
  save("bezier-example.png");
}

This example is written in Processing, which is basically Java + a few libraries + a simple quick IDE. Comes in handy for small pieces on code.

Evaluating a infix expression (e.g. “3+6^9″) is both a complex and frequently occuring problem in programming projects. Here is a library to evaluate infix expression.

Usage

package test;

import hejp.RPN.*;

public class Test {
	static public void main(String[] args){
		String expression = "tanh(10)";

		try {
			System.out.print(RPN.process(expression).toString() + "\n"); //prints 0.9999999958776927
		} catch (Exception e) {
			if (e.getMessage().equalsIgnoreCase("Malformed Expression")) {
				System.out.print("Malformed Expression");
			}
		}
	}
}

The RPN class only has one method called process this takes an infix expression as a String and returns the result as a Double or throws an Exception whose message is equal to “Malformed Expression”.

The method ‘process(String infix)’ is static therefore there is no need to make an instance of the class RPN. So process is called like so RPN.process(infix) rather than like RPN r = new RPN(); r.process(infix).

Download (4.2KB)

List of Functions

Read the rest of this entry »