Inverse Kinematics: Part 2 of 2
September 19th, 2010
Now on to the algorithm that requires a little mathematical understanding, the Jacobian matrix method. This method approximates the IK problem as a linear problem, which it almost is if you only change the angles of the joints by small amounts.
Mathematics of the Method
Starting with the vector of angles,
We have the forward kinematic function f, i.e the function that return the position of the endpoint, x, given the angles of the joints.
Our goal is to find
this can be done be firstly introducing the Jacobian matrix as well as differentiating w.r.t. time resulting in this,
Since,
Replacing the δ operators with Δ operators to approximate the differentiation,
Sets us up for an iterative solution.
Outline of the Algorithm
Our goal is to find
this can be done be firstly introducing the Jacobian matrix as well as differentiating w.r.t. time resulting in this,
Since,
Replacing the δ operators with Δ operators to approximate the differentiation,
Sets us up for an iterative solution.
Outline of the Algorithm
- Calculate Δx = Goal – f(q) if the size to Δx is small enough exit loop
- Compute J-1. J may not be square in which case use the pseudo inverse (JTJ)-1JT
- Compute Δθ = J-1Δx
- θ = θ + Δθ
- Repeat
Casting vs Not Casting in Strict Mode and not in Strict Mode
September 18th, 2010
Preamble
Actionscript is, for the most part, a dynamically typed language, which means that the types (i.e. String, int, GameObject) of variables are checked at run-time rather than at compile-time like they are in C and Java. This is supposedly beneficial to the programmer since such a language is more flexible. All sorts of crap like this is valid:
var i = new GameObject(); i = "1";As you can see it’s possible to change the type of a reference to something entirely different. This can generate type errors at run-time since later you may try to call i.update(). Although this example is very obvious real world examples can be more nuanced and thus more complicated to find and fix. Casting and using ‘Strict Mode’ is a technique to essentially make Actionscript a little bit like a statically typed language. The performance boost comes from firstly doing as much as possible at compile-time (thus less at run-time) and secondly helping the process of type checking by casting. Read more: Code, Results and Conclusion
New Flash Game! Orbital
September 14th, 2010
I recently released Orbital! And submitted it to ‘Made for Mobile’ contest over at Mochimedia.
Description
Use gravity and well timed rocket thrusts to slingshot your ship around the planets, collecting stars and destroying debris while saving fuel and minimising time taken.
Controls
Initially the ship is stationary holding down the left mouse button or your finger builds up your boost. Releasing fires your ship off with the power indicated in the top left corner. After the initial boost stage use the left mouse button or finger to active the rocket thrusts, these propel your ship in the direction of the cursor. Collide with stars to collect them. Debris can be destroyed with either the missile or the mine. Select which weapon with the button in the bottom left corner or press SPACE. Rockets fly straight and the mines are affected by gravity.
Read more: Play the game
Description
Use gravity and well timed rocket thrusts to slingshot your ship around the planets, collecting stars and destroying debris while saving fuel and minimising time taken.
Controls
Initially the ship is stationary holding down the left mouse button or your finger builds up your boost. Releasing fires your ship off with the power indicated in the top left corner. After the initial boost stage use the left mouse button or finger to active the rocket thrusts, these propel your ship in the direction of the cursor. Collide with stars to collect them. Debris can be destroyed with either the missile or the mine. Select which weapon with the button in the bottom left corner or press SPACE. Rockets fly straight and the mines are affected by gravity.
Read more: Play the game
Inverse Kinematics: Part 1 of 2
September 13th, 2010
Inverse Kinematics: Part 1 of 2
Inverse kinematics (IK) is the process of calculating the angles of joints required to reach from a start point to an end point. It has many uses, for example in robotics, 3D animation and computer games.
There are a number of algorithms to solve the IK problem; the three that I will describe are an analytic solution, a Cyclic-Coordinate Descent (CCD) solution and a Jacobian matrix iterative solution.
Analytic Solution
This method uses trigonometry to compute an exact solution to the IK problem. Often there are several solutions but the analytic solution may only give one (depending on the implementation) which could require unnecessary movement compared to another possible solution. Also given more than two joints this method is likely to involve impractical maths, but is perfect if your problem consists of two joints in 2D or an additional swivel point in 3D.
Given a situation like this:
θ1, θ2 can be calculated thusly:
Since acos(θ) is not real when θ is outside the range -1 to 1 which occurs when the goal (x,y) is out of reach of the arm you may want to make the arm form a straight line in the direction of (x,y).
Read more: Analytic Example, CDD Solution and CCD Example
θ1, θ2 can be calculated thusly:
Since acos(θ) is not real when θ is outside the range -1 to 1 which occurs when the goal (x,y) is out of reach of the arm you may want to make the arm form a straight line in the direction of (x,y).
Read more: Analytic Example, CDD Solution and CCD Example
ActionScript 3: Socket Programming
January 27th, 2010
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
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.
Flash / ActionScript 3 Performance: Traditional Main Loop vs Multiple Event Listeners
January 11th, 2010
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:
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.
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 |
Flash / ActionScript 3 Performance: Object Recycling
January 6th, 2010
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