Blog
I write code, this blog is a dream.
2013.01.09Bases
The Proselytizer (temporary project name) is slowly shaping up. Here's what it looks like today.
Like you can see and imagine, there's still a HUGE load of work to do before the end of the month!
Now's the time to really plan things up and decide what I really want to ship in 20 days.
If I am happy with the result and people like the game I will improve it after the release (better graphics from me -or a real artist- and more game content).
Buy the way, the game is in flash, browser based, you can play with your gamepad if you use Google Chrome and you can also play it full-screen still from your browser, yes I know all this feels strange but my little finger tells me it's cool and many will follow really soon :)
2013.01.07The proselytizer
First post of the year, Happy new year!
For 2013 I made the good resolution of shipping lots of games.
To enforce this wish, I joined the One Game A Month experience. Developers all over the world will try to create and ship 12 games, one shipping per month.
My January game will be a Shoot'Em Up, my first real SHMUP, hooray! … Well OK, I made "Happy Pti Tank" for KadoKado.com (gameplay video) a few years ago, but it hardly classifies as a Shoot'Em Up in my mind :)
The more I am working on this project and the more it feels like I can do something original. I may have to create a second shooter later…
Because I like stories I had to found something for the game's background: You will incarnate a priest full of muscles and guns. The priest was sent on mission to a new distant world. The task of your order is to… oh well you will find out soon anyway.
I hope the game will be as good as I would like it to be but I only start and there's a lot to do before the end of the month… wish me Godspeed!
I wish you a year of fun!
2012.12.20Gamepad for flash
I think my next game will be developed using the Haxe/Flash target and the Haxe/Flash Gaming SDK.
But I badly wanted my next game to work with a gamepad and Flash doesn't allow this on the web.
The WC3 works on a new Gamepad API for HTML5, already available in Google Chrome and soon on Firefox.
Thanks to the great haxe.remoting.Connection feature, what is available to Javascript can also be made available to Flash.
If you have Google Chrome and a Gamepad, you can try this, the code is there.
Pew pew pew.
2012.12.17Flash Haxe Gaming SDK, their tools, our tools
So Adobe released a few weeks ago its Gaming SDK for flash.
The package includes Starling, Away3D and Feathers, three well know quality open source ActionScript3 libraries.
You can easily find some externs for most of them on http://lib.haxe.org, which is great!
However, during the development of my last game (which used Starling and Haxe) I found out that using haxelibs wasn't enough.
A lot of good stuff is happening in the AS3 side, Starling is improving day after day on Github, users create really useful extensions for it.
Time is precious and we don't want to write externs for everything or rewrite everything in haxe do we?
Thanks to the great haxe/flash support, we can easily use all the good stuff in a matter of seconds, we can hack AS3 code and use the result from Haxe too.
In this post I will try to teach beginners how to fish AS3 :)
- how to compile a bunch of .as files into a .swf using the Flex SDK.
- how to use those .swf files in haxe (with no extra work)
- how to patch things when haxe is not happy with the .swf
We'll end up with the entire Adobe Gaming SDK, and more, for Haxe. But the journey is more important than the destination.
NOTE: If you are not interested in the process and just want the SDK, I created a bunch of github repositories to host the results. See the test repository to learn how to play with it https://github.com/labe-me/haxe-gaming-sdk-test
NOTE: I do not intend to write any extern for these libraries (I am too lazy for that), hence I won't submit them to haxelib. Feel free to use my work in any way you want to create nice haxelib packages. As far as I am concerned I really enjoy the haxelib git support :)
Start.
We are going to compile .as
files, you'll need to install the Flex SDK.
Let's learn how it works with Starling.
(1) get the library sources:
$ git clone https://github.com/PrimaryFeather/Starling-Framework
(2) We have to find the root of the library. Search .as
files, take a look at the package they declare (for instance package starling.core
) and go up until you get the root. For Starling the root is the Starling-Framework/starling/src
directory.
(3) Compile all the .as files to produce a .swc file.
We can do this with the compc command line tool (from the Flex SDK).
compc \ -swf-version 17 \ -source-path Starling-Framework/starling/src \ -include-sources Starling-Framework/starling/src \ -output Starling.swc
Easy, isn't it? Two times the same parameter telling the root of the sources we are trying to build, one output.
The -swf-version is recommended but chances are the swc will work without it.
(4) Extract the .swf file which is hidden in the .SWC
$ unzip Starling.swc $ mv library.swf Starling.swf $ rm catalog.xml
Ok now let's use this SWF, we'll encounter a useful error for the next lesson...
// File StarlingTest.hx import starling.text.TextField; import starling.core.Starling;class StarlingTest extends starling.display.Sprite { public function new(){ super(); var textField = new TextField(400, 300, "Starling!"); addChild(textField); }
public static function main(){ var s = new Starling(StarlingTest, flash.Lib.current.stage); s.start(); } }
Compile (notice the -swf-lib Starling.swf):
haxe \ -swf-lib Starling.swf \ -swf-version 11 \ -main StarlingTest \ -swf-header 640:480:60:aaaaaa \ -swf test.swf
Error:
Starling.swc@starling.core.RenderSupport:1: character 0 : Same field name can't be use for both static and instance : clear Starling.swc@starling.core.Starling:1: character 0 : Same field name can't be use for both static and instance : context Starling.swc@starling.core.Starling:1: character 0 : Same field name can't be use for both static and instance : juggler Starling.swc@starling.core.Starling:1: character 0 : Same field name can't be use for both static and instance : contentScaleFactor
What Haxe is telling us is that it does not accept a class looking like:
class T { static var context : String; var context : String: public function clear(){} public static function clear(){} }
You cannot have both a static and a non static member or function with the same name.
When you encounter this kind of error, you have to create a patch file like this:
//Starling.patch -starling.core.RenderSupport.clear -starling.core.Starling.context -starling.core.Starling.juggler -starling.core.Starling.contentScaleFactor
And use like this:
haxe \ -swf-lib Starling.swf \ --macro "patchTypes('Starling.patch')" \ -swf-version 11 \ -main StarlingTest \ -swf-header 640:480:60:aaaaaa \ -swf test.swf
This tell haxe to ignore these static fields. We won't be able to use them from our Haxe code but they are available from the Starling instance anyway.
And voila for Starling.
Now let's add Feathers to our tool-belt, we will learn a new thing along the way.
$ git clone https://github.com/joshtynjala/feathers
The source root is easy, it's the source
directory.
Compiling the SWC will give us a lot of errors and warnings.
$ compc \ -swf-version 17 \ -source-path feathers/source \ -include-sources feathers/source \ -output Feathers.swcWarning: Definition starling.display.DisplayObject could not be found. import starling.display.DisplayObject; ...
Don't panic! Feathers just needs Starling to compile.
The useful compc option is --external-library-path+=Starling.swc
$ compc \ -swf-version 17 \ -source-path feathers/source \ -include-sources feathers/source \ --external-library-path+=Starling.swc \ -output Feathers.swc
Extract the library.swf
$ unzip Feathers.swc $ mv library.swf Feathers.swf $ rm catalog.xml
And voila for feathers.
Well nearly.
To use feathers we need a skin. We could create our own… but they already created some nice skins they talk about in their tutorials… is it possible to use them?
Let's try.
$ git clone https://github.com/joshtynjala/feathers-examples
A quick look at the content of this repository shows that it contains a few themes. After reading the Feathers' introduction, I am interested in the MetalWorksMobileTheme. The corresponding folder contains a source sub-folder which contains the good old feathers/themes/MetalWorksMobileTheme.as file. Can you guess what we are going to do? Yes:
$ compc \ -swf-version 17 \ -source-path feathers-examples/MetalWorksMobileTheme/source \ -include-sources feathers-examples/MetalWorksMobileTheme/source \ --external-library-path+=Starling.swc \ --external-library-path+=Feathers.swc \ -output Feathers-MetalWorksMobileTheme.swc
Note that we specified two external library dependencies: Starling.swc and Feathers.swc.
Extract the library.swf (this step won't be required in future version of haxe, haxe svn already supports .swc as -swf-lib parameters):
$ unzip Feathers-MetalWorksMobileTheme.swc $ mv library.swf Feathers-MetalWorksMobileTheme.swf $ rm catalog.xml
Let's try feathers now:
// FeathersTest.hx import starling.core.Starling; import feathers.themes.MetalWorksMobileTheme;class FeathersTest extends starling.display.Sprite { public function new(){ super(); var theme = new MetalWorksMobileTheme(this, false); var button = new feathers.controls.Button(); button.label = "Good old button"; button.addEventListener( starling.events.Event.TRIGGERED, function(e){ trace("POP"); } ); addChild(button); }
public static function main(){ var s = new Starling(FeathersTest, flash.Lib.current.stage); s.start(); } }
And the more complicated compile command:
$ haxe \ -swf-lib Starling.swf \ --macro "patchTypes('Starling.patch')" \ -swf-version 11 \ -swf-lib Feathers.swf \ -swf-lib Feathers-MetalWorksMobileTheme.swf \ -main FeathersTest \ -swf-header 640:480:60:aaaaaa \ -swf test.swf
It is a good idea to learn how haxelib works to create packages and simplify those compilation parameters… later.
Let's see, what do we miss to par the Adobe Gaming SDK? Oh yes Away3D of course.
$ git clone https://github.com/away3d/away3d-core-fp11
away3d-core-fp11/src/ seems to be the root of the package, let's rock:
$ compc \ -swf-version 17 \ -source-path away3d-core-fp11/src \ -include-sources away3d-core-fp11/src \ -output Away3d.swc
This one will produce some warnings, you are free to fix them and submit your patch to the Away3D team to improve the project, but don't worry it will work :)
Extract the library.swf
$ unzip Away3d.swc $ mv library.swf Away3d.swf $ rm catalog.xml
And test:
// Away3DTest.hx import flash.display.BitmapData; import away3d.materials.TextureMaterial; import away3d.textures.BitmapTexture;class Away3DTest { static var view : away3d.containers.View3D;
public static function main(){ view = new away3d.containers.View3D(); view.camera.x = 300; view.camera.z = -600; view.camera.y = -600; view.camera.lookAt(new flash.geom.Vector3D(0,0,0)); flash.Lib.current.addChild(view); var cubeBmd = new BitmapData(128, 128, false, 0x0); cubeBmd.perlinNoise(70, 207, 5, 123, true, true, 70, true); var cubeTexture = new BitmapTexture(cubeBmd); var cubeMaterial = new TextureMaterial(cubeTexture); cubeMaterial.gloss = 20; cubeMaterial.ambientColor = 0x808080; cubeMaterial.ambient = 1; var geom = new away3d.primitives.CubeGeometry(300, 300, 300); var cube = new away3d.entities.Mesh(geom, cubeMaterial); cube.x = 0; cube.y = 150; view.scene.addChild(cube); flash.Lib.current.addEventListener( flash.events.Event.ENTER_FRAME, onEnterFrame ); }
static function onEnterFrame(e){ view.render(); } }
And the compilation command line:
$ haxe \ -main Away3DTest \ -swf-lib Away3d.swf \ -swf-header 640:480:60:aaaaaa \ -swf-version 11 \ -swf test.swf
This is it for the Adobe Gaming SDK… but we want more, we want the almighty Flash Haxe Gaming SDK :)
So let's add this great starling extension I'd like to use in my future games:
$ git clone https://github.com/PrimaryFeather/Starling-Extension-Particle-System
Compile:
$ compc \ -swf-version 17 \ -source-path Starling-Extension-Particle-System/src \ -include-sources Starling-Extension-Particle-System/src \ -output Starling-Extension-Particle-System.swc \ --external-library-path+=Starling.swc
Extract the swf (we could easily create a small script to automate all this and more):
$ unzip Starling-Extension-Particle-System.swc $ mv library.swf Starling-Extension-Particle-System.swf $ rm catalog.xml
Again you will need a patch to use this swf (static methods conflicting with instance methods, like usual, nothing difficult really, just read haxe output):
//Starling-Extension-Particle-System.patch -starling.extensions.ColorArgb.fromArgb -starling.extensions.ColorArgb.fromRgb
Test it (you will need these two files created with ParticleDesigner: pdesign.pex, pdesign.png
//ParticlesTest.hx import starling.core.Starling; import starling.textures.Texture; import starling.extensions.PDParticleSystem;@:bitmap("pdesign.png") class Particle extends flash.display.BitmapData {} @:file("pdesign.pex") class Config extends flash.utils.ByteArray {}
class ParticlesTest extends starling.display.Sprite { public function new(){ super(); var config = new flash.xml.XML(new Config().toString()); var texture = Texture.fromBitmapData(new Particle(0,0)); var system = new PDParticleSystem(config, texture); system.emitterX = flash.Lib.current.stage.stageWidth / 2; system.emitterY = flash.Lib.current.stage.stageHeight / 2; addChild(system); Starling.juggler.add(system); system.start(); }
public static function main(){ var s = new Starling(ParticlesTest, flash.Lib.current.stage); s.start(); } }
Which we compile with the following command line:
$ haxe \ -swf-lib Starling.swc \ --macro "patchTypes('Starling.patch')" \ -swf-version 11 \ -swf-lib Starling-Extension-Particle-System.swc \ --macro "patchTypes('Starling-Extension-Particle-System.patch')" \ -main ParticlesTest \ -swf-header 640:480:60:000000 \ -swf test.swf
Shabang.
Now let's organize and simplify this mess.
I created some git repositories on github:
- https://github.com/labe-me/haxe-starling
- https://github.com/labe-me/haxe-feathers
- https://github.com/labe-me/haxe-starling-particle-system
- https://github.com/labe-me/haxe-away3d
- https://github.com/labe-me/haxe-gaming-sdk-test (an ugly test with all together)
Thanks to the new haxelib's git support I can install them with these commands:
haxelib git away3d https://github.com/labe-me/haxe-away3d haxelib haxelib git starling https://github.com/labe-me/haxe-starling haxelib haxelib git feathers https://github.com/labe-me/haxe-feathers haxelib haxelib git starling-particle-system https://github.com/labe-me/haxe-starling-particle-system haxelib
Here's how I created these repositories:
I created the haxe-starling repository on github, then:
# clone git clone git@github.com:labe-me/haxe-starling.git cd haxe-starling # link the real AS3 Starling-Framework repository to my repository git submodule add https://github.com/PrimaryFeather/Starling-Framework starling # create a separate haxelib folder mkdir haxelib
I created a Makefile to automate the Starling.swf creation. It basically does what we did above. (https://github.com/labe-me/haxe-starling/blob/master/Makefile)
I put the Starling.patch file we created inside the haxelib folder. (https://github.com/labe-me/haxe-starling/blob/master/haxelib/Starling.patch)
I created an extraParams.hxml
file. When the library will be used via -lib starling
, haxe will use the content of this file to add some parameters to the compiler. We tell haxe to include our Starling.swf and to patch it with the provided patch. This way we won't have to bother about it anymore. Stage3D also requires swf-version 11. (https://github.com/labe-me/haxe-starling/blob/master/haxelib/extraParams.hxml).
I also created an include.nmml file inside haxelib. This file is automatically used by NME to do the same as the extraParams.hxml file. (https://github.com/labe-me/haxe-starling/blob/master/haxelib/include.nmml).
I created a small test and told haxelib to use my local version of the library:
$ haxe dev starling `pwd`/haxelib
The process was the same with the other repositories.
During this experiment, I found two bugs which you may encounter if you try (I used haxe svn version):
- Haxe has problems parsing the swf generated by compc if you add the -debug flag to your compilation. The bug is reported and I am pretty sure Nicolas will want to correct it.
- I experienced problems with the extraParams.hxml feature, I had to specify
-swf-lib MyLibrary.swf
by hand when two extraParams.hxml where active, say Starling and Feathers (https://github.com/labe-me/haxe-feathers/blob/master/test/Makefile). I bet this bug will be corrected in no time too :)
That's it.
I hope this really big post will be useful to the Haxe community and will help fill the gap between Haxe and AS3.
Lastly, a few thoughts which may help the community save some energy:
I think that writing externs is unrewarding monkey work. I did it for three.js and a few other libs and I mostly hated it. I think that in the case of openly typed platforms like Flash and maybe Java and C# we shouldn't have to do it. The compiler should be able to -jar-lib or -cs-lib just like it can -swf-lib.
Moreover, taking an existing successful project and porting it to Haxe is only interesting if you intend to make it cross-platform. If you only target the original platform, chances are the original project will improve and be fixed faster than your one man port.
No offense intended of course, these are just personal advises coming from experience and time lost :)
If you find any mistake or have any question, please comment, I will be happy to help!
And Happy end of the world.