Archive for March, 2008

Monday, March 31st, 2008

The FFilmation AS3 Flash Isometric Engine has been released into the wild.  Jordi Ministral has been generous to watch his creation grow and evolve with the help of the open source community and the flash community is one of the best open source communities out there even though the core (adobe flash) is still closed. Open sourcing is one of the best ways to market test your skills really and this engine has much anyone can learn in making isometric engines for flash. You can see our first post on this great engine here.

Here’s a peek at the classes in the API:

http://www.ffilmation.org/docs/api/1.0/class-summary.html

All Classes

BumpMap
fAiContainer
fCamera
fCharacter
fCollideEvent
fElement
fEngine
fEngineMaterial
fEngineSceneRetriever
fEventIn
fEventOut
fFloor
fGlobalLight
fLight
fMaterial
fMoveEvent
fObject
fOmniLight
fPlane
fProcessEvent
fRenderableElement
fScene
fSceneLoader
fWalkoverEvent
fWall
line
mathUtils
movieClipUtils
polygonProjection
polygonUtils
Vector
vport

Get your game on!

Friday, March 28th, 2008

I have been one upped by mr. doob! I did a little nascar like RC pro am like prototype in march ’07 when the pv3d kit showed up on my screen and I was hooked like most suceptible flashers who have longed for 3d in flash! Only my version is like Nintendo64 and his is like xbox360 with updated effects and physics kits and some doob magic. All these are based off of, of course the original race car driver in Papervision and its creator Carlos Ulloa (Adobe should be paying this man).

To the feature! This is a sweet game by mr. doob, called burn and brag for Nascar.

Now I don’t’ particularly like Nascar all that much but who doesn’t like to peel out to some fiddlin’? I mainly do Nascar stuff because it is highly marketable and like the only answer most ad agencies have for getting the southern us markets it seems, that and c-o-u-n-t-r-y mu-si-c (must be said at a slower rate).

But I digress, this is a perfect mix of advertisment, game play, fun and experience. It is fast, simple, and playable. Exactly the simplicity and smoothness needed of gameplay and playback.  Great ad work but it also gives something fun to do and best of all it is built in AS3 flash with a plethora of libraries from the flash as3 community.

The game platform is emerging fantastically in the AS3 market. mrdoob used these kits to build this:

It would be cool to see a post on how he did the replays with tweener – I imagine just a series of points collected with car state (current position state) and then just play them back with a call back or time delay. You’d have to capture alot for smooth playback without laggy movements.  I am working on multiplayer games with this same issue for a current project.

Game on! The question is when will this be SOTD or SOTM at thefwa.com?

Thursday, March 27th, 2008

If there ever was a proof that more intense applications like word processors and image manipulation software are capable of being built and some aspects even better than their desktop counterparts with flash and flex then Scrapblog, Buzzword, Picnik and Photoshop Express are that (in fact Photoshop Express is a direct competitor with Picnik it seems…).  

Adobe launches Photoshop Express today to add to that set that are very usable, quality applications built with Flash9/Flex and most of all actionscript 3 (as3) and the new AVM2. These apps just weren’t possible with AS2 and with Flex they can be easily managed codebases (one major problem with old skool flash actionscript is it was throwaway many times because it was so scripter specific and full of optimizations just to barely perform – now these are actual code bases made by programmers and you see the results).  The great thing about buzzword, picnik and photoshop express are that they are easy to use. Flash/Flex make sense in their case and they tend to mimic and use very good usability patterns.There is no way an AJAX app (even though I build lots of those too) can come close to this integration of style, usability and expected results on all browsers.One important point of this article on news.com mentioning this:

The service will go live in beta test mode on Thursday. Mack said that the company intends to use the test period as a way garner feedback from customers.Adobe intends to offer more features to consumers who pay a yearly fee. Some planned features include a printing service, more storage, support for audio and other media, and the ability to read additional image file types (the service works with .JPGs now.)Adobe also plans to build an offline client using AIR (the Adobe Integrated Runtime) so that people can edit photos offline, executives said.

A couple things here.  First there is going to be an AIR version for the same experience on the web and the desktop for a major application.  Second, flash IS limited to certain file types JPG, SWF, PNG, GIF, and a few others for sound and video.  So why an online photoshop is great, it is still only web based photos, simple edits, etc.  Photographers and users above 72dpi in the 300 600 ++ ranges will still be using Photoshop.  Users with EPS,RAW, etc will still have to use Photoshop until Adobe figures a way to either proxy an image and handle the real source (be it another format) behind the scenes.  Or, improve the flash player to handle other raster and vector image types.A project a while back we had this issue where it was a approval system of media types but the types could be PDF or EPS in addition to web image formats or on occasion other formats and it became a challenge where the content was marked up with flash.  Eventually it was in a div overlay so we could load in the unsupported types behind and sync them with javascript, where flash was just a canvas or screen on top to put notes and markings.  But when it comes to editing that is different, you expect to edit. Also, working with the real source in image manipulation is extremely important so a proxy to the real image seems unlikely a good choice except for simple web uses.In any case, Photoshop Express is a great web based image tool but there are limitations that prevent it from taking any large swath of share from the normal old desktop Photoshop any time soon.

Tuesday, March 25th, 2008

I was able to download the demo and it is in the store and on Adobe’s site. The new AGEIA™ PhysX™  physics engine and some sort of updated 3D with hardware rendering is nice.

But, Director is like the Rodney Dangerfield of products at Adobe.  Everywhere you have to dig for it, it doesn’t even have updated marketing in most places, the shockwave player link is still from 2002 etc.  I wish that Adobe would support it more, open it up, allow better IDEs, integrate ES4 based Actionscript 3 or 4 into it and keep the 3d market that shockwave supports moving along.

Maybe they will give Director more love but if they don’t allow for some community input and work on the platform like Flex and Flash have thrived on, well they might just lose that piece of the market (3d gaming, hardware).

First impression is the fonts do look much better.  Unicode support is so far so good and I haven’t had a chance to dig into the AEGIS PhysX engine yet but that looks very very fun.

For instance here is a Physics Engine call that creates a rigid body terrain


//JavaScript Syntax
var objTerrain= member("PhysicsWorld").createTerrain("myterrain",terrainDesc,position,orientation,1,1,1);

Or some raycasting:


//JavaScript Syntax
var lstraycast = member("PhysicsWorld").rayCastAll (vector(10,0,0),vector(0,0,1));
for(i = 1; i < = lstraycast.count ; i++)
{
    raycstEntry = lstraycast[i];
    put("Name:" + raycstEntry[1].name);
    put"Contact Point:" & raycstEntry[2]);
    put("Contact Normal:" & raycstEntry[3]);
    put("Distance:" & raycstEntry[4]);
}

I use the Javascript source simply because it is much more usable to me. Unfortunately the docs are only partially converted to Javascript.  Lingo is pretty close to it though but it scares people off.

What Adobe needs to do is port into Flash the ability to use Shockwave3D (hardware rendering for 3d), AEGIS PhysX, would that not blow up big time or what?

Saturday, March 22nd, 2008

Den Ivanov scored another “why didn’t I think of that” flash demos with extruding pixels into 3d with papervision.  He has some great samples and demos on his site about it.  Den Ivanov is a long time flasher and recent scores with Brahma bus (one of the coolest first papervision commercial projects) and the terrain generator.

This uses ExtrudeImage which does exactly what the class says.

Saturday, March 22nd, 2008

Forrest Briggs throwing down with a real-time raytracer in AS3. Also a C++ OpenGL version sample on the page.

Real-time pixel manipulation in flash is getting faster, but is still probably going to have to be faked in AS3, maybe AS4 will provide us per pixel speeds that Andre Michelle has been harping on since flash 8.5. Native operations can be much faster in that area. AIF might look to change some of that but that is Flash 10.

Here is the code for the as3 raytracer. Read more at laserpirate.

package
{
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
import flash.utils.getTimer;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFormat;

public class RayTracer extends Sprite
{
 private var t:Number;
 private var dt:Number = .01;
 private var frameTimeTxt:TextField;

 public static const BUFFER_WIDTH:int = 160;
 public static const BUFFER_HEIGHT:int = 120;
 public static const BUFFER_SCALEDDOWN:int = 320 / BUFFER_WIDTH;

 public static const HALF_BUFFER_WIDTH:int = BUFFER_WIDTH / 2;
 public static const HALF_BUFFER_HEIGHT:int = BUFFER_HEIGHT / 2;

 private var outputBitmapData:BitmapData;
 private var outputBitmap:Bitmap;

 public var FOV:Number = 20;

 public var sphereCenterX:Array 	= [0,	0,		0, 		0];
 public var sphereCenterY:Array 	= [0, -.2,	.4, 		100.5];
 public var sphereCenterZ:Array 	= [4, 	4,		4, 		10];
 public var sphereRadius:Array 	= [.35, .35,	.25, 	100];
 public var sphereR:Array 		= [255,	0,		0,		20];
 public var sphereG:Array 		= [0, 	150,	0,		20];
 public var sphereB:Array 		= [0, 	0,		255,	20];
 public var sphereReflects:Array = [false, false, false, true];
 public var sphereReflectiveness:Array = [0,0,0,.3];
 public var sphere2dX:Array = new Array(sphereCenterX.length);
 public var sphere2dY:Array = new Array(sphereCenterX.length);
 public var sphere2dR:Array = new Array(sphereCenterX.length);

	public var numSpheres = sphereCenterX.length;

	var skyR:int =  20;
 var skyG:int =  20;
 var skyB:int =  20;
 var skyColor:int = (skyR< <16) + (skyG<<8) + skyB;
 var ambientIllumination:Number = .1;

	var canvas:BlankClip;

	var theta:Number = 0;
 var mouseIsDown:Boolean = false;
 var mouseDownTheta:Number = 0;
 var mouseDownX:Number = 0;

	public function RayTracer()
 {
 	outputBitmapData = new BitmapData(BUFFER_WIDTH, BUFFER_HEIGHT, false);
 	outputBitmap = new Bitmap(outputBitmapData);
 	addChild(outputBitmap);
 	//outputBitmap.smoothing = true;

		outputBitmap.width= 320;
 	outputBitmap.height = 240;

		canvas = new BlankClip;
 	addChild(canvas);
 	canvas.buttonMode = true;
 	canvas.useHandCursor = true;

		frameTimeTxt = new TextField();
 	frameTimeTxt.defaultTextFormat = new TextFormat("Arial");
 	frameTimeTxt.x = 8;
 	frameTimeTxt.y = 8;
 	frameTimeTxt.width = 640;
 	frameTimeTxt.textColor = 0xFFFFFF;
 	frameTimeTxt.selectable = false;
 	addChild(frameTimeTxt);

		t = 0;
 	addEventListener(Event.ENTER_FRAME, update, false, 0, true);

		canvas.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
 	canvas.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
 }

	public function mouseDownHandler(e:*):void
 {
 	mouseIsDown = true;
 	mouseDownX = stage.mouseX;
 	mouseDownTheta = theta;
 }

	public function mouseUpHandler(e:*):void
 {
 	mouseIsDown = false;
 }

	public function update(e:*)
 {
 	// start frame timer and update global time
 	var timer:Number = getTimer();
 	t += dt;

		// handle mouse rotation
 	if( mouseIsDown ) theta = mouseDownTheta - .0015 * (stage.mouseX - mouseDownX);
 	theta += dt;

		// do some funky animation
 	sphereCenterX[0] = .5*Math.sin(theta*5);
 	sphereCenterZ[0] =1 + .5*Math.cos(theta*5);

		sphereCenterX[1] = .5*Math.sin(theta*5 + 2 * Math.PI / 3);
 	sphereCenterZ[1] = 1 + .5*Math.cos(theta*5 + 2 * Math.PI / 3);

		sphereCenterX[2] = .5*Math.sin(theta*5 + 4 * Math.PI / 3);
 	sphereCenterZ[2] = 1 + .5*Math.cos(theta*5 + 4 * Math.PI / 3);

		// reused variables
 	var x:int;
 	var y:int;
 	var i:int;
 	var j:int;

		var r:int;
 	var g:int;
 	var b:int;

		var dx:Number;
 	var dy:Number;

		var rayDirX:Number;
 	var rayDirY:Number;
 	var rayDirZ:Number;
 	var rayDirMag:Number;

		var reflectRayDirX:Number;
 	var reflectRayDirY:Number;
 	var reflectRayDirZ:Number;

		var intersectionX:Number;
 	var intersectionY:Number;
 	var intersectionZ:Number;

		var reflectIntersectionX:Number;
 	var reflectIntersectionY:Number;
 	var reflectIntersectionZ:Number;

		var rayToSphereCenterX:Number;
 	var rayToSphereCenterY:Number;
 	var rayToSphereCenterZ:Number;

		var lengthRTSC2:Number;
 	var closestApproach:Number;
 	var halfCord2:Number;
 	var dist:Number;

		var normalX:Number;
 	var normalY:Number;
 	var normalZ:Number;
 	var normalMag:Number;

		var illumination:Number;
 	var reflectIllumination:Number;

		var reflectR:Number;
 	var reflectG:Number;
 	var reflectB:Number;

		// setup light dir
 	var lightDirX:Number = .3;
 	var lightDirY:Number = -1;
 	var lightDirZ:Number = -.5;
 	var lightDirMag:Number = 1/Math.sqrt(lightDirX*lightDirX +lightDirY*lightDirY +lightDirZ*lightDirZ);
 	lightDirX *= lightDirMag;
 	lightDirY *= lightDirMag;
 	lightDirZ *= lightDirMag;

		// vars used to in intersection tests
 	var closestIntersectionDist:Number;
 	var closestSphereIndex:int;
 	var reflectClosestSphereIndex:int;

		// compute screen space bounding circles
 	//canvas.graphics.clear();
 	//canvas.graphics.lineStyle(1, 0xFF0000, .25);
 	for(i = 0; i < numSpheres; ++i)
 	{
 		sphere2dX[i] = (BUFFER_WIDTH / 2 + FOV * sphereCenterX[i] / sphereCenterZ[i]);
 		sphere2dY[i] = (BUFFER_HEIGHT /2 + FOV * sphereCenterY[i] / sphereCenterZ[i]);
 		sphere2dR[i] = (3 * FOV * sphereRadius[i] / sphereCenterZ[i]);
 		//canvas.graphics.drawCircle(sphere2dX[i]*BUFFER_SCALEDDOWN, sphere2dY[i]*BUFFER_SCALEDDOWN, sphere2dR[i]*BUFFER_SCALEDDOWN);
 		sphere2dR[i] *= sphere2dR[i]; // store the squared value
 	}

		// write to each pixel
 	outputBitmapData.lock();
 	for(y = 0; y < BUFFER_HEIGHT; ++y)
 	{
 		for(x = 0; x < BUFFER_WIDTH; ++x)
 		{
 			// compute ray direction
 			rayDirX = x - HALF_BUFFER_WIDTH;
 			rayDirY = y - HALF_BUFFER_HEIGHT;
 			rayDirZ = FOV;

				rayDirMag = 1/Math.sqrt(rayDirX * rayDirX + rayDirY * rayDirY +rayDirZ * rayDirZ);
 			rayDirX *= rayDirMag;
 			rayDirY *= rayDirMag;
 			rayDirZ *= rayDirMag;

				/// trace the primary ray ///
 			closestIntersectionDist = Number.POSITIVE_INFINITY;
 			closestSphereIndex = -1
 			for(i = 0; i < numSpheres; ++i)
 			{
 				// check against screen space bounding circle
 				dx = x - sphere2dX[i];
 				dy = y - sphere2dY[i];
 				if( dx * dx + dy * dy > sphere2dR[i] ) continue;

					// begin actual ray tracing if its inside the bounding circle

					lengthRTSC2 = 		sphereCenterX[i] * sphereCenterX[i] +
 									sphereCenterY[i] * sphereCenterY[i] +
 									sphereCenterZ[i] * sphereCenterZ[i];

					closestApproach =	sphereCenterX[i] * rayDirX +
 									sphereCenterY[i] * rayDirY +
 									sphereCenterZ[i] * rayDirZ;

					if( closestApproach < 0 ) // intersection behind the origin
 					continue;

					halfCord2 = sphereRadius[i] * sphereRadius[i] - lengthRTSC2 + (closestApproach * closestApproach);
 				if( halfCord2 < 0 ) // ray misses the sphere
 					continue;

					// ray hits the sphere
 				dist = closestApproach - Math.sqrt(halfCord2);
 				if( dist < closestIntersectionDist )
 				{
 					closestIntersectionDist = dist;
 					closestSphereIndex=i;
 				}
 			}
 			/// end of trace primary ray ///

				// primary ray doesn't hit anything
 			if( closestSphereIndex == - 1)
 			{
 				outputBitmapData.setPixel(x, y, skyColor);
 			}
 			else // primary ray hits a sphere.. calculate shading, shadow and reflection
 			{
 				// location of ray-sphere intersection
 				intersectionX = rayDirX * closestIntersectionDist;
 				intersectionY = rayDirY * closestIntersectionDist;
 				intersectionZ = rayDirZ * closestIntersectionDist;

					// sphere normal at intersection point
 				normalX = intersectionX - sphereCenterX[closestSphereIndex];
 				normalY = intersectionY - sphereCenterY[closestSphereIndex];
 				normalZ = intersectionZ - sphereCenterZ[closestSphereIndex];
 				normalX /= sphereRadius[closestSphereIndex]; // could be multiply by precacluated 1/rad
 				normalY /= sphereRadius[closestSphereIndex];
 				normalZ /= sphereRadius[closestSphereIndex];

					// diffuse illumination coef
 				illumination = 	normalX * lightDirX +
 								normalY * lightDirY +
 								normalZ * lightDirZ;

					if( illumination < ambientIllumination )
 					illumination = ambientIllumination;

					/// trace a shadow ray ///
 				var isInShadow:Boolean = false;
 				for(j = 0; j < numSpheres; ++j)
 				{
 					if( j == closestSphereIndex ) continue;

						rayToSphereCenterX = sphereCenterX[j] - intersectionX;
 					rayToSphereCenterY = sphereCenterY[j] - intersectionY;
 					rayToSphereCenterZ = sphereCenterZ[j] - intersectionZ;

						lengthRTSC2 = 		rayToSphereCenterX * rayToSphereCenterX +
 										rayToSphereCenterY * rayToSphereCenterY +
 										rayToSphereCenterZ * rayToSphereCenterZ;

						closestApproach =	rayToSphereCenterX * lightDirX +
 										rayToSphereCenterY * lightDirY +
 										rayToSphereCenterZ * lightDirZ;
 					if( closestApproach < 0 ) // intersection behind the origin
 						continue;

						halfCord2 = sphereRadius[j] * sphereRadius[j] - lengthRTSC2 + (closestApproach * closestApproach);
 					if( halfCord2 < 0 ) // ray misses the sphere
 						continue;

						isInShadow = true;
 					break;

					}

					/// end of shadow ray ///

					if( isInShadow ) illumination *= .5;

					/// trace reflected ray ///
 				if( sphereReflects[closestSphereIndex] )
 				{
 					// calculate reflected ray direction
 					var reflectCoef:Number = 2 * (rayDirX * normalX + rayDirY * normalY + rayDirZ * normalZ);
 					reflectRayDirX = rayDirX - normalX * reflectCoef;
 					reflectRayDirY = rayDirY - normalY * reflectCoef;
 					reflectRayDirZ = rayDirZ - normalZ * reflectCoef;

						closestIntersectionDist = Number.POSITIVE_INFINITY;
 					reflectClosestSphereIndex = -1
 					for(j = 0; j < numSpheres; ++j)
 					{
 						if( j == closestSphereIndex ) continue;

							rayToSphereCenterX = sphereCenterX[j] - intersectionX;
 						rayToSphereCenterY = sphereCenterY[j] - intersectionY;
 						rayToSphereCenterZ = sphereCenterZ[j] - intersectionZ;

							lengthRTSC2 = 		rayToSphereCenterX * rayToSphereCenterX +
 											rayToSphereCenterY * rayToSphereCenterY +
 											rayToSphereCenterZ * rayToSphereCenterZ;

							closestApproach = 	rayToSphereCenterX * reflectRayDirX +
 											rayToSphereCenterY * reflectRayDirY +
 											rayToSphereCenterZ * reflectRayDirZ;

							if( closestApproach < 0 ) // intersection behind the origin
 							continue;

							halfCord2 = sphereRadius[j] * sphereRadius[j] - lengthRTSC2 + (closestApproach * closestApproach);
 						if( halfCord2 < 0 ) // ray misses the sphere
 							continue;

							// ray hits the sphere
 						dist = closestApproach - Math.sqrt(halfCord2);
 						if( dist < closestIntersectionDist )
 						{
 							closestIntersectionDist = dist;
 							reflectClosestSphereIndex=j;
 						}
 					} // end loop through spheres for reflect ray

						if( reflectClosestSphereIndex == - 1) // reflected ray misses
 					{
 						r = sphereR[closestSphereIndex] * illumination;
 						g = sphereG[closestSphereIndex] * illumination;
 						b = sphereB[closestSphereIndex] * illumination;

						}
 					else
 					{
 						//trace("ref hit");
 						// location of ray-sphere intersection
 						reflectIntersectionX = reflectRayDirX * closestIntersectionDist + intersectionX;
 						reflectIntersectionY = reflectRayDirY * closestIntersectionDist + intersectionY;
 						reflectIntersectionZ = reflectRayDirZ * closestIntersectionDist + intersectionZ;

							// sphere normal at intersection point
 						normalX = reflectIntersectionX - sphereCenterX[reflectClosestSphereIndex];
 						normalY = reflectIntersectionY - sphereCenterY[reflectClosestSphereIndex];
 						normalZ = reflectIntersectionZ - sphereCenterZ[reflectClosestSphereIndex];

							normalX /= sphereRadius[reflectClosestSphereIndex]; // could be multiply by precacluated 1/rad
 						normalY /= sphereRadius[reflectClosestSphereIndex];
 						normalZ /= sphereRadius[reflectClosestSphereIndex];

							// diffuse illumination coef
 						reflectIllumination = 	normalX * lightDirX +
 												normalY * lightDirY +
 												normalZ * lightDirZ;

							if( reflectIllumination < ambientIllumination )
 							reflectIllumination = ambientIllumination;

							r = sphereR[closestSphereIndex] * illumination + .5 * sphereR[reflectClosestSphereIndex] * reflectIllumination;
 						g = sphereG[closestSphereIndex] * illumination + .5 * sphereG[reflectClosestSphereIndex] * reflectIllumination;
 						b = sphereB[closestSphereIndex] * illumination + .5 * sphereB[reflectClosestSphereIndex] * reflectIllumination;
 						if( r > 255 ) r = 255;
 						if( g > 255 ) g = 255;
 						if( b > 255 ) b = 255;

						}  // end if reflected ray hits

					} /// end if reflects
 				else // primary ray doesn't reflect
 				{
 					r = sphereR[closestSphereIndex] * illumination;
 					g = sphereG[closestSphereIndex] * illumination;
 					b = sphereB[closestSphereIndex] * illumination;
 				}

					outputBitmapData.setPixel(x, y, (r<<16) + (g<<8) + b);

				} // end if primary ray hit
 		} // end x loop
 	} // end y loop
 	outputBitmapData.unlock();

		// compute FPS
 	var fps:Number = 1.0/((getTimer() - timer) / 1000.0);
 	frameTimeTxt.text = "Drag to rotate. FPS: " + int(fps);
 }

}
}
Friday, March 21st, 2008

I was messing with water effects and Perlin Noise (sandy3d) and some other stuff and collected some water effects and simulations that are fluid like for research, a snapshot of the state of fluid and water effects in 3d in flash.

Ralph Hauwert, of course one of the original pv3d team members, posted some great samples on water effects on 3d objects in Papervision 3D. Of course the papervision list spawned this discussion from another great post on water simulation in papervision and away3d by Exey Panteleev .

Also, some other water like effects from Fabrice Closier and the notorious mrdoob.

Ralph’s Water Effect Demos:

Hey look, the water ball is smiling at you.

Exey Panteleev’s Water Simulation:

Some other Water Like Fluid Effects:

Water is hard in flash. Fluid dynamics will probably have to be cheated but it is still looking pretty good. The amount of processor usage depends on how real you want it to look.

If you are looking to make some agua, with x, the y AND the z in Flash or Flex, these are a good place to start.

Thursday, March 20th, 2008

I have officially been sucked into the Python vortex. I recently have really been digging IronPython, Jython and good old plain Python but have not ventured here yet. Google (They employ Guido), Microsoft (IronPython) and Sun (Jython) are all becoming infected pythonistas as well. But this is just too cool, Python to AS3 code with flex-pypy. This project is very young but could be fun, source at Google Code.

Haxe has a similar premise where it can compile to Flash6-9 versions of actionscript 2-3 which makes for a system with better reach. Python code for this is lots of fun and very flexible. Python is becoming a baseplane language and one great language for transcending platform lock-in.

Check out this snippet pulled from here (click to see sample game)

#/usr/bin/env python
"""
This simple example has very little to do with the pygame
chimp example, except that it will act the same (more or less)
and it uses the same resources, only they got converted to
mp3s, pngs.
"""

#Import Modules
from pypy.translator.flex.modules.flex import *

class MyRect:
    def __init__(self,x,y,w,h):
        self.x, self.y,self.w,self.h = x,y,w,h

SCREEN_W = 468
SCREEN_H = 60

class Game:
    def __init__(self):pass

    def init(self,screen):
        self.screen = screen
        screen.layout = 'absolute'
        screen.setActualSize(SCREEN_W, SCREEN_H)

        screen.addEventListener('mouseMove',mousemotion)
        screen.addEventListener('enterFrame',do_loop)
        screen.addEventListener('click',chimp_whip)

        self.bg = load_sprite("py_background_png");
        self.screen.addChild(self.bg)

        self.chimp = load_sprite("py_chimp_png");
        self.screen.addChild(self.chimp)

        self.orig_y = self.chimp.y

        img2 = self.fist = load_sprite("py_fist_png")
        self.screen.addChild(img2)
        img2.move(400,img2.height/2)
        self.move = 1
        self.spin = 0
        self.hit = 0
        self.hit_move = 1

        self.sfx = {}
        self.sfx['whip'] = load_sound_resource("py_punch_mp3")
        self.sfx['nohit'] = load_sound_resource("py_whiff_mp3")

    def loop(self):
        img = self.chimp
        if self.spin:
            self.spin -= 1
            img.rotation = self.spin*24
        else:
            img.x += self.move * 8
            if img.x > SCREEN_W-img.width:
                self.move = -1
            if img.x < 0:
                self.move = 1

        if self.hit:
            self.hit -= 1
            self.fist.y += 6 * self.hit_move

            if self.hit  SCREEN_W - img_halfw:
        newx = SCREEN_W - img.width
    if newx  img.x and e.stageX < img.x+img.width:
        game.sfx['whip'].play()
        game.spin = 20
    else:
        game.sfx['nohit'].play()

def flash_main( x=1 ):
    game.init(castToWindow(x))
Sunday, March 16th, 2008

Rostislav added a sample for his excellent SWFAddress kit using the new YouTubeAPI and deep linking to parts of the video. Part of the YouTubeAPI is by Geoff Stearns (the creator of SWFObject who works at YouTube now) and allows much more script control and embedding of the youtube player (chromeless with just the video canvas).

The sample Rostislav at Asual has, shows how you can incorporate SWFAddress now that the youtube player can be embedded by script, and thus how it can have deep-linking to sections of the video from the url.

So, today I spent some time trying to integrate SWFAddress with the sample YouTube video and the result is now available online. There were some tricky parts and probably the code can be encapsulated better, but overall I’m satisfied with the result. Every pause action or significant jump in the playback produces a deep link which will definitely make sense for long videos or specific scenarios. If you want to automatically start the video from the second verve just try this deep link. For this case I decided that it will be better to disable the generation of browser history and the SWFAddress strict mode.

The sample is available in the SWFAddress repository and will become a part of the upcoming 2.1 release.

The cool part about all this is is makes it extremely easy to add commenting at moments in time throughout youtube videos, enables deep-linking, allows snapshots of not just the flash application but also the video that might be playing in that chapter. This is done on services like viddler and others but now you can do it for youtube videos and this will also possibly start a standard way to do this across media players so that a platform of video commenting emerges.

The integration of SWFAddress is simple, on the normal onSWFAddressChange you just pass in the value to the seekTo call:

function onSWFAddressChange(event) {
  time = seek = parseInt(event.value);
  ytplayer = document.getElementById('myytplayer');
  ytplayer.seekTo(time, true);
 }

Google video always had jump to time params like:http://video.google.com/videoplay?docid=-5830318882717959520#01m30s (this is a classic/hilarious Erlang video)

…but this is not very workable with the google video player, also you can always add this to other players but having this ability for youtube is a great leap in allowing a more integrated commenting, chapter and community like feel to video.

Since youtube is so big finally having some more control with the YouTubeAPI will allow much more great additions to the capabilities of using youtube video in many more ways and integration of more great javascript kits like SWFAddress.

The YouTube API is really quite useful. Here are some links of interest:

Tuesday, March 11th, 2008

Just got word of this great isometric engine similar to the Alternativa engine or zenbullets but with plans for open source. I checked out the demos and it looks well done and is pretty responsive. Once you get to heavy lighting it can draw a little slow (the cowboy becomes more John Wayne like with slow drawls) but this seems like a great base for an isometric AS3 engine.

The author, who is currently anonymous, describes it as:

The FFilmation Engine is an AS3 isometric programing engine, focused mainly on game development. The aim of the project is providing a robust development platform, where game designers can work on the game’s details and forget about the render engine. It is intended to be really usable from a “real production scenario” point of view.

Unfortunately there is no name associated with the project yet, I think it would be wise to let that be known. The author has some info on the level structure of files and 3 great demos.

Here are some features and plans for the engine:

  • Have a programming interface as small and easy as possible, no matter how complex the internal code is. From a software engineering point of view, the OO structure may not be as correct and clean as it could have been. It is not messy, but several decisions where made that improved performance and simplicity at the cost of breaking some “good OO programming” conventions.
  • Rendering performance is a major concern when designing all the algorythms. Some of them have been rewritten 4 o 5 times from scratch until one fastest enought was found. If it doesn’t perform well, it is not usable. We’ve all seen several impressive actionscript demos that look really cool and invite to be used in your next project. But then if the effect takes 90% of your CPU, you can’t build anything on top of that.
  • Graphic designers should be able to work on the application’s ( game or not ) environments without any programming skills, visually, and with almost immediate previews of what they are doing. Using the engine should be fun to some degree. If you have this terrific engine and adding a wall to your dungeon means you have to write 10 lines of OO gibberish, lazyness will eventually win you over. If art directors can draw and place the walls and lights an floors and enemies and see them appearing onscreen, you have more chances of reaching your deadline.
  • Flash has built-in drawing and animation tools. You should be able to take advantage of them !!

All this is important because in reality projects depend on limited resources. Resources are money and time, but also the enthusiasm of indie developers or single individuals doing stuff “for fun” in their bedrooms. Projects, specially the “for fun” ones, have more chances of completion if the production process is gratifying to some degree.

Here’s a list of highlited features:

  • One engine capable of handling several isometric scenes of different complexities.
  • Create scenes from human-readable XML definitions, allowing easy edition of the scene’s topology and contents
  • Graphic media can be split into several external resources and loaded when an scene needs them
  • Flat textures. Paint your grahics directly into flash. Walls, floors and celings are edited as 2D graphics and projected by the engine. Elements and animated characters can be animated via flash timeline, no need for complex programming.
  • Dynamic lighting, global lighting, real-time shadow projection. Multiple lights from multiple sources affecting the same objects.
  • Bump-mapped surfaces. Still somehow buggy and a serious performance killer, but already there.
  • An extendable material interface. MovieClip materials, autotiled materials, procedural materials.
  • Automatic zSorting of all surfaces and objects
  • Built-in collision detection. No need to program complex coordinate comparisions, simple listen to COLLISION events generated by the engine.
  • Basic AI API helpers such as “is character A visible from character B’s position ?”

I plan to make the engine open-source, but I’ll wait until I have a release “solid” and documented enough.

I am looking forward to more updates and to find out more about the author. We have some great engines underway in ’08 for AS3 and it looks to be a very fun year in that aspect.

Because it is an isometric engine is is not true 3d but sprite based animation. However with planes and objects other isometric 3d objects can be built such as walls, boxes, buildings, cubes, etc. I wonder if there are any toolkits being used or if this is all custom built?

Keep your eye on this space. It is very similar to the Alternative Engine.

Here are all the Demos:

And some docs on the architecture:

Check it out!