Procedural Floating Islands

I’ve been roaming blogs and wikis about the fascinating topic of procedural generation of terrain, and tonight I finally decided to give it a go. After a couple hours, here’s where I’m at:

This movie requires Flash Player 9

Press any key to generate a new floating island. It’s fast enough that you can keep the key down and it’ll draw 30 islands per second. Fuck yeah bitmap data.

AS3 tricks

Here are some handy tricks I’ve found and come across while working in ActionScript.

1. with

Sometimes, we need to write some very repetitive code to set the properties of an object, like a TextField or a Sprite. Instead of this:

graphics.beginFill(0x00ccff);
graphics.drawCircle(0, 0, 12);
graphics.endFill();

 … you could write this:

with (graphics)
{
	beginFill(0x00ccff);
	drawRect(0, 0, 12);
	endFill();
}

While I’m not avoiding a bajillion lines of code in this particular example, it should be enough to illustrate my point and get you thinking about all the possibilities of such a keyword!

2. Event Listeners

Sure, you may not be able to pass arguments when an Event is triggered, but don’t forget that Events themselves have various properties, including a “type“. This can be useful to avoid writing a function for every event.

// event handlers
function handler(event:MouseEvent):void
{
	if(event.type == "mouseDown")
		trace("Down");
	else
		trace("Up");
}

movieClip.addEventListener(MouseEvent.MOUSE_DOWN, handler);
movieClip.addEventListener(MouseEvent.MOUSE_UP, handler);

Bonus trick: if you have a lot of EventListeners, you could put them all in an Array/Vector and remove them all easily when the time comes. Yay efficient garbage collection!

3. Setting properties

Ever wanted to set more than one property at once, instead of each of them individually? Lookie here:

// this function sets multiple properties of an Object
function setProps(item:*, props:Object):void
{
	for (each var s:String in props)
		item[key] = props[key];
}

// for instance, to set the properties of a Sprite:
var s:Sprite = new Sprite();
setProps(s, {x:100, y:50, scaleX:2, scaleY:2, rotation:45});

 

Happy coding :)

UTD Game Jam!

Hey internet! About two weeks ago, I participated in game jam at UTD, which went absolutely great. The theme was “eight”, so after spending a couple hours designing a game of gigantic scale, we settled on the more reasonable idea of “you crash-land on a planet and only have eight bullets to gtfo”. We used ChevyRay‘s FlashPunk and Matt Thorson‘s Ogmo Editor and crafted a SuperMeatBoy/IWBTG-esque game in thirty-six hours.

This thing is stressful as hell.

Having worked with Spencer in the past, the whole thing went even more smoothly than I thought it would – we didn’t encounter any major issues. The game is up on Kongregate, so you should have a look! And make sure to login, if you want your score saved :)

Play it here!

Happy Fourth :)

Haven’t posted in a while, job hunting and learning UnrealScript have taken up most of my time. However, a programmer is never too busy to make particle systems, and since some of my friends were out of the country and could not see the fireworks, i took the opportunity to make this.

This movie requires Flash Player 9

Click the movie to set focus on it, click outside to stop firing, or look at the full-screen version right here.

Happy Independence Day, American friends :)

Lightning Effect in AS3

Working on Flux, I was tasked with implementing the Electrolaser, which basically shoots a lightning arc at the target, and branches out to enemies around the target… fun stuff! I thought I would share with the interwebz the logic behind lightning generation (or the way I do it at least). But first, a demo of what it looks like!

This movie requires Flash Player 9

The example above features only 2 bolts so you can get a basic idea of the system. Click anywhere in the movie to start the generation. The bolts will strike the mouse!

The basic idea behind creating those lightning bolts is to start with a single line, or more accurately a segment. If you spent your geometry classes playing Snake on your graphing calculators (unlike me, of course), here’s a short reminder: a segment is a part of a line bounded by two points. It’s that simple. So first, you create the segment:

Create a segment

Then, the trick is to get the middle point of that segment and to offset it perpendicularly a short amount, like so:

Offset the middle point, creating 2 segments

And then, you guessed it: keep going until you get enough subdivisions to suit your needs.

Create ALL the segments!

Now on to the code side. First, i recommend creating a Segment class, which i outlined below:

public class Segment
{
	private var start_point:Point;
	private var end_point:Point;

	public function Segment(start:Point, end:Point)
	{
		start_point = start;
		end_point = end;
	}
	public function getStart():Point { return start_point; }
	public function getEnd():Point { return end_point; }
	public function getMiddle():Point
	{
		var middle:Point = new Point();
		middle.x = (start_point.x + end_point.x) / 2;
		middle.y = (start_point.y + end_point.y) / 2;
		return middle;
	}
}

Then , create a vector of Segments to store all your lightning bolts, and create the main bolt (in the example above, it goes from the top of the movie to the position of the mouse).

var bolts:Vector.<Segment> = new Vector.<Segment>();
bolts.push(new Segment(start_point, end_point));

Then, you create two segments out of the first one, while offsetting the middle a little:

bolts.push(new Segment(bolts[0].getStart(), bolts[0].getMiddle()));

// offset the end of the previous bolt
bolts[1].setEnd(offsetTangeant(getAngle(bolts[0].getStart(), bolts[0].getEnd()), bolts[1].getEnd(), (Math.random() - 0.5) * 10);

// create the second part of the bolt
bolts.push(new Segment(bolts[1].getEnd(), bolts[0].getEnd());

My offsetting function looks like this:

// offset a point orthogonally to the tangent
private function offsetTangeant(tan_angle:Number, point:Point, offset:Number):Point
{
	point.x += Math.cos(tan_angle + Math.PI / 2) * offset;
	point.y += Math.sin(tan_angle + Math.PI / 2) * offset;

	return point;
}
// get the angle between two points (radians)
private function getAngle(p1:Point, p2:Point):Number
{
	return Math.atan2(p2.y - p1.y, p2.x - p1.x);
}

And keep going until you have enough bolts! I find that 4-6 iterations is usually enough. After you have populated the “bolts” Vector, all you have to do is draw a line between all those segments, and voila.

Stay tuned for part 2, where we will see how to add branches to that main lightning bolt!

AS3 and PHP

Been spending most of my time on Flux 112 lately, and one of my duties is to track data in real time within Flash. After much trial-and-error, i’ve found that getting data from PHP is actually really easy, but there aren’t many great tutorials out there, so here is how i do it.

First use this function to send a query to the PHP script:

private function sendQuery():void
{
	var variables:URLVariables = new URLVariables();
		variables.username = "Bruce Willis";

	var request:URLRequest = new URLRequest("http://yoursite.com/the_script.php");
		request.method = URLRequestMethod.POST;
		request.data = variables;

	var loader:URLLoader = new URLLoader();
		loader.dataFormat = URLLoaderDataFormat.TEXT;
		loader.addEventListener(Event.COMPLETE, querySent);

	try
	{
		loader.load(request);
	}
	catch (error:Error)
	{
		trace("Upload failed.");
	}
}

URLVariables are what you send to the PHP script. I am sending a String here, but you can send Numbers, pictures, etc.

Next, we create the URLRequest, which we will send through a URLLoader. Set the URLRequestMethod to “POST” (i will explain why later) and give the request whatever data it should send (our previously created variables).

Then, create the URLLoader (you can send the request to the constructor, or leave it blank and load it like i did below). I like to set the DataFormat to “TEXT”, but this is not always necessary. Add an EventListener to that loader, so that you can execute a function when the request was completed. And finally, load the request! I use a “try / catch” statement in case there is an issue, and trace out whatever error message you want.

Then comes the function that is called when the loader is complete:

private function querySent(e:Event):void
{
	if (!e.target.data)
		trace("No data back");

	else
		trace("The most awesome actor is: " + e.target.data);
}

 This one is simple: when the loader is complete, it first checks to see if any data came back from the request (line 3). If so, it traces the data you sent (in this case, “Bruce Willis”).

Here is the PHP script, called “the_script.php” and saved on your website.

<?php
/**
* @author: Maxime Preaux
*/

// get the variable from AS3
$name = $_POST["username"];

if (!$name)
{
	echo("no data sent from Flash");
}
else
{
	echo($name);
}

?>

First, a PHP script starts with “<?php” and ends by closing that tag: “?>”.

Then, I declare the variable like so: “$name”. It’s that simple. Then, I assign the value of $_POST["username"] to that variable. In PHP, you can either use “GET” or “POST” to send data to a script. The “GET” method actually writes the data in the browser bar, whereas the “POST” method keeps it hidden. In our case, either method would work.

Make sure that ["username"] matches the variable sent from AS3 (see line 4. of the first AS3 script).

After that, we check to see if $name has a value. If it got the data from AS3 correctly, it should! Otherwise, it will send “no data sent from Flash” back to your program. But if all works correctly, it will send the value of username back to you using the “echo()” function.

And that’s it! You now know how to send and get data from AS3 and PHP!

If you have any questions or better ways to do this, please post in the comments below :)

AS3 Optimization

Optimization is a tricky-yet-important part of a project. You don’t want to sacrifice the clarity fo your code, but it’s essential to strike the correct balance between OOP and performance.

First, ask yourself: is your project fast enough? Do you really need to make it faster? Computers keep getting faster, and while books teach you that using a float instead of a double will make a world of difference, it is not really the case unless you go through countless iterations of a loop.

Final advice before we get to the juicy part: do not optimize until you are close to being done and everything works correctly, or it will be a pain to make changes later. That being said, here is what I know about AS3 optimization.

1. Use uints and numbers only when you have to! With the current version of the player, integers are almost twice as fast as unsigned ints. Numbers are just slightly slower than uints.

2. Stacked operators are slow!

if (a && b && c) // slower
// faster
if (a)
{
	if (b)
	{
		if (c)
		{
		}
	}
}

3. “for each” is really convenient… and hundred of times slower than “for”

// slow...
for each (var s:String in array)

// fast!
for (var i:int = 0; i < array.length; i++)

4. Declare variables before loops! For instance, if you use a “for” loop to go through a large array or vector, you should avoid accessing that array’s “length” property more than once, like below. Also, avoid declaring variables within a loop.

var max:int = array.length
var i:int;
for (i = 0; i < max; i++)
{
	// do stuff
}

5. Point.distance() is slower than computing the Euclidian distance between two points (see below). Also, using Math.pow() is slower that multiplying a number by itself.

d = Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));

The Future is Exciting

This coming semester looks really exciting. Graduation is looming ahead, and I have no job to keep my fridge populated, and thus no idea what will happen when my lease ends in May.

But trivial matters aside, this semester is indeed promising, as I have begun to work on a new game! I can’t release many details as of now, but know that it features “a system that procedurally generates and modifies the game level at runtime to better match players’ varying skill levels and playstyles.”

Sounds smart, eh? It is a really abstract system that may well turn HAL9000 on us!

Keep checking back for updates…