A few months ago, I came across a very promising ressource for 3D flash : Alternativa Platform. Of course, I had already heard of a few others like Away3D or Flare3D, but I have the feeling Alternativa has greater performance. Anyway, the overwhelming features are numerous, I’d only point out it makes use of GPU acceleration for advanced gaming, supports multiplayer, has a physics engine, etc… and it’s open-source too, so you can go look under the hood if you feel like it. You only need to watch the showcase demos to realize what amazing possibilities are offered to 3D flash by the platform.
The technology – currently released in version 8 – is developped by a russian company, and although it’s fully documented, it’s sometimes not that easy to understand, their English is incredibly worse than mine ! Nonetheless, I decided to dive into it and discover what it was capable of. There’s a tutorial called Alternativa 8 for dummies where they give an interesting example based on cubes which I thought would be a good starting point for my primary testing.
It’s basically a maze made of simple cubes where you wander in First Person view. The sample code is provided, so let’s see what it’s all about. Oh, and I also only just discovered Flash Develop, an open source code editor which is quite convenient as long as you don’t need to use a GUI.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
package { // Class imports import alternativa.engine3d.controllers.SimpleObjectController; import alternativa.engine3d.core.Camera3D; import alternativa.engine3d.core.Object3D; import alternativa.engine3d.core.Resource; import alternativa.engine3d.core.View; import alternativa.engine3d.materials.FillMaterial; import alternativa.engine3d.primitives.Box; import flash.display.Sprite; import flash.display.Stage3D; import flash.events.Event; public class Main extends Sprite { private var rootContainer:Object3D = new Object3D(); // the container that will contain all the objects in the scene private var camera:Camera3D; private var stage3D:Stage3D; private var box:Box; private var simpleController:SimpleObjectController; private const BOX_SIZE:int = 500; // cube size private const MAZE:Array = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // 2D definition of the maze [1, 0, 1, 0, 1, 1, 0, 0, 0, 1], [1, 0, 1, 0, 0, 0, 0, 0, 1, 1], [1, 0, 0, 0, 1, 0, 1, 0, 0, 1], [1, 1, 1, 0, 1, 1, 0, 1, 0, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1], [1, 0, 0, 1, 1, 0, 0, 0, 1, 1], [1, 0, 0, 0, 0, 0, 1, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]; public function Main(){ stage3D = stage.stage3Ds[0]; stage3D.addEventListener(Event.CONTEXT3D_CREATE, init); //init is hooked to this event, fired when 3D context created stage3D.requestContext3D(); // context3D is the stage property associated with the video memory } private function init(e:Event):void { camera = new Camera3D(0.1, 10000); // create camera with near boundary and far boundary camera.view = new View(stage.stageWidth, stage.stageHeight); // initial camera position and orientation camera.rotationX = -100 * Math.PI / 180; camera.rotationZ = -90 * Math.PI / 180; camera.x = 300 camera.y = 500; camera.z = 0; addChild(camera.view); rootContainer.addChild(camera); // add camera to the scene for (var i:int = 0; i < MAZE.length; i++){ //construction of the maze for (var j:int = 0; j < MAZE[i].length; j++){ if (MAZE[i][j] == 0) continue; var box:Box = new Box(BOX_SIZE, BOX_SIZE, BOX_SIZE); //create a cube box.setMaterialToAllSurfaces(new FillMaterial(0x999999)); //plane material applied to each surface box.x = BOX_SIZE * i; // cube position box.y = BOX_SIZE * j; rootContainer.addChild(box); // add cube to scene } } // create a controller where the controlled object is the camera, 400 is the speed simpleController = new SimpleObjectController(stage, camera, 400); // loads resources to video memory for use by the GPU for each (var resource:Resource in rootContainer.getResources(true)){ resource.upload(stage3D.context3D); } //add an enter frame listener stage.addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(e:Event):void { // Run on every frame simpleController.update(); // User input updates camera.render(stage3D); // render the scene } } } |
And this is what we get (with a link to the demo)
You can play around with the demo, the feel is pretty good, of course it’s only very basic, but that calls for improvements.
I listed the aspects I’d like to change, add or improve – I’m open to all suggestions though.
Appearance :
Well, it lacks a floor for one, so I need to create one. Then I’d like to apply textures to the walls and floor, instead of having a plane color. I guess putting a sky in there would also be nice, but then I should add lighting for realism, and probably shadows too. I know all this is possible, we’ll see what I manage.
Control :
There are a list of things to improve here as well. Once I get a floor in the scene, I have to prevent the ability to go down through it, and also through the walls, as it’s the case in this demo. This probably implies collision detection. I’m not too keen on having to press the mouse button to look around, I’ll see if I can deal with that. I also want to disable the [E]
and [C]
keys that make you move up / down, and add control to [Q]
and [Z]
for french keyboards. Maybe I’d like running to be default, and walking made possible with [shift]
. And finally, some kind of jump or jetpack mode with [spacebar]
, just for the fun of it !