Playground: HEJP ColourPicker

February 3rd, 2010

Just been messing around with the Robot class, which is designed for automated testing of applications but has other uses. Here I have used it to write an application to get the pixel colour of any pixel on the screen. The GUI consists of a Canvas magnifying the area around the mouse pointer and a text field to display the pixel hex value.

How to Use

Move the mouse pointer to the pixel you’d like to know the colour of and hit Enter.

Source and Jar

Source (zip)

Jar

Notes Regarding the Robot Class

getColorPixel is very slow as I found out as soon as using it, the solution is to use createScreenCapture to get the pixels around the mouse pointer then read the colours from the BufferedImage.

Flash Socket Programming

What is a Socket?

A Socket is a mechanism used to send data over a network (e.g. the Internet), it is the combination of an IP address and a port. The IP address is used to specify the computer (on the network) to connect to and the port (which is not a physical port just a software construct represented by a number) specifies which port on the computer to connect to. There are multiple ports to allow multiple distinct connections to a single IP address, certain ports traditionally have certain uses for example HTTP servers use 80 and POP3 servers use 110.

Restrictions and Security

ActionScript has many restrictions that (to be brutally honest) cripple, but not entirely, the usefulness of Sockets.

Firstly, there are security issues, for a Flash application to connect to a particular server that server must host a policy file defining what ports Flash is allowed to connect to. This restricts Flash from connecting to most of the servers on the Internet although it isn’t too much trouble to put a policy file on your server.

Secondly, Flash isn’t allowed to create server sockets (sockets that clients can connect to) either, so to make a multiplayer game would require that the game is hosted on a server which all of the clients connect to. The server would have to constantly send data to all of the clients; this could potentially use a lot of bandwidth.

Finally, only one type of transportation protocol is supported that is TCP. Although TCP is very good for sending data like webpages and such it is not so good at sending real-time data. This means that multiplayer real-time games are slower than they could be or infeasible.

Never mind all that though, Flash Sockets are still useful.

Creating a Socket

Creating a socket is fantastically straight forward, since there are no decisions to make about the type of Socket. Here is an example with all of the event listeners added:

import flash.net.Socket;
import flash.events.*;

var socket:Socket = new Socket();

Security.allowDomain("*");

socket.addEventListener(Event.CONNECT, onConnect);
socket.addEventListener(Event.CLOSE, onClose);
socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
socket.addEventListener(ProgressEvent.SOCKET_DATA, onResponse);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecError);

socket.connect("hejp.co.uk", 80);

It is wise to connect after adding the event listeners because an event could be dispatched without any code to respond to it, or something strange like that. This example connects to hejp.co.uk using port 80 i.e. my web server.

Quick description of the Events:

  • CONNECT: dispatched when the connection is established
  • CLOSE: dispatched when the connection is closed
  • IO_ERROR: dispatched when an error occurs
  • SOCKET_DATA: dispatched when socket can be read
  • SECURITY_ERROR: dispatched when security gets in the way

Using the Socket

Using the socket involves implementing the listener functions. In this example we’ll make a request for the index page of hejp.co.uk and trace the response.

Doing so involves writing a HTTP request to the port and then reading the response.

function onConnect(e:Event):void {
	socket.writeUTFBytes("GET / HTTP/1.1\n");
	socket.writeUTFBytes("Host: hejp.co.uk\n");
	socket.writeUTFBytes("\n");
}

function onClose(e:Event):void {
	// Security error is thrown if this line is excluded
	socket.close();
}

function onError(e:IOErrorEvent):void {
	trace("IO Error: "+e);
}

function onSecError(e:SecurityErrorEvent):void {
	trace("Security Error: "+e);
}

function onResponse(e:ProgressEvent):void {
	if (socket.bytesAvailable>0) {
		trace(socket.readUTFBytes(socket.bytesAvailable));
	}
}

Notes

A Flash app running the Flash IDE runs in a completely different security sandbox to a Flash app running in the browser, therefore even though an works running in the IDE errors (usually security errors) can crop up while running in the browser.

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: Details

December 29th, 2009

Silver Scat

Silver Scat Points: 300
Speed: 2
Size: Medium
Tendency to sway: Low

Yellow Tang

Yellow Tang Points: 200
Speed: 3
Size: Large
Tendency to sway: Medium

Pacific Blue Tang

Pacific Blue Tang Points: 400
Speed: 2
Size: Large
Tendency to sway: Large

Mono

Mono Points: 400
Speed: 4
Size: Medium
Tendency to sway: Medium

Longfin Bannerfish

Longfin Bannerfish Points: 300
Speed: 2
Size: Medium
Tendency to sway: Large

Swordtail

Swordtail Points: 400
Speed: 3
Size: Medium
Tendency to sway: Low

Clownfish

Clownfish Points: 500
Speed: 4
Size: Medium
Tendency to sway: Medium

Life Bottle

Life Bottle TThis adds one third of your life.

Death Bottle

Death Bottle This subtracts one third of your life.

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.