Vert.x and Juju

I've been playing with Juju and Vert.x and I got a simple DEVOPS juju charm to deploy a Vert.x app with the minimal effort. Here is the required script:

juju deploy --repository juju-charms local:vertx-app

juju deploy redis-master

juju deploy haproxy

juju add-relation redis-master:db myapp

juju add-relation myapp haproxy

juju add-unit -n 10 myapp
juju expose haproxy

Use the status command to find the public IP address and enjoy! The app at the moment is hard coded to be a Hello World but work is in progress to make it configurable.

vert.x is awsome! Specially with BSON!

Vert.x is a polyglot event-driven application framework that runs on the Java Virtual Machine.

Similar environments written in other programming languages include Node.js for JavaScript that I've been working for the last 1 and a half year.

Vert.x exposes the API currently in Java, JavaScript, Groovy, Ruby and Python.

Scala and Clojure support is on the roadmap.

The application framework includes these features:

  • Polyglot. Application components can be written in Java, JavaScript, Groovy, Ruby or Python.
  • Simple concurrency model. All code is single threaded, freeing from the hassle of multi-threaded programming.
  • Simple, asynchronous programming model for writing truly scalable non-blocking applications.
  • Distributed event bus that spans the client and server side. The event bus even penetrates into in-browser JavaScript allowing to create effortless so-called real-time web applications.
  • Module system and public module repository, to re-use and share components.

I do like the freedom of being asynchronous and synchronous when needed, I like the real distributed programming model (not like the advertisement from Node.JS which in reallity is a process fork() with modules that require extra coding). With vert.x you just specify the number of instances and you're done!

I disliked the fact that all internal messages were JSON. The event bus is a wonderful component but JSON is too generic. It only allows String, Boolean, Double, Null, Lists and Hashes. Therefore I started a new vert.x module that uses BSON. I picked BSON because it maps easily to JSON and can be a simple replacement.

It turns out you will get a server 33% faster!!! if you use my module!!!

So get it now!!!

Android Clonabalt

It took a couple of days to make a basic clone of the popular game. I did not look to the original code, in fact i did not reuse any of it, and even wrote my own engine and sprites. The all game is just 50kb with resources for popular screen sizes, QVGA, HVGA and WVGA. The APK can be picked up from my dropbox.

This was a learning experience so it will not be published on any market. I might open source the minimal engine (basically 2 classes) but at the moment it is not a good idea since i haven't document anything.


SFX Audio on Android

Once upon the time all game audio was synthesized. We were amazed with the chips that would come out from the ZX Spectrum or the commodore 64 but nowadays we can still make cool explosion sounds for small devices such as the android mobile phones.

So i implemented a simple SFX util class based on an old project sfxr to generate sounds for Android games...

Read more



Learning Games for Radically Affordable Computers

Quick fixes for annoyances on my Ubuntu 11.04

Unity slow with ATI drivers?

sudo apt-get install compizconfig-settings-manager

Then Disable VSYNC on OpenGL tab.

Eclipse acts wierd with new scrollbars?

sudo nano /usr/share/applications/eclipse.desktop

change the Exec with:

sh -c "LIBOVERLAY_SCROLLBAR=0 eclipse"

Need several instances of one app?

middle click on the launcher

WebGL does not work on chromium because your ATI card is blacklisted?

sudo nano /usr/share/applications/chromium-browser.desktop

change Exec with:

Exec=/usr/bin/chromium-browser --ignore-gpu-blacklist %U

MinPSP 11.2 HotFix (only Win32)

If you are on windows and faced a issue with missing DLLs, you can grab then here: You need to unpack the 2 DLLs on C:\pspsdk\libexec\gcc\psp\4.3.5 Change C:\pspsdk to whatever you choose to install the SDK to. By default it should be Ok. A proper fix with a new build has been added. This fixes both broken GCC due to missing DLL and as well PSPSH.exe Get it here: pspsdk-setup-0.11.2r2.exe

MinPSP 11.2

This is the second build of 2011, in this build there are only a few changes, i changed the build of oslib to build with its internal libs (do not rely on the SDK ones), DEB files for Debian/Ubuntu have been reduced from 150Mb to 32Mb (Changed from the standard compression to LZMA). On linux there is no mpfr/gmp dependency it caused problems with different versions of Ubuntu.

From the community i added a couple of patches, one that adds a pack to the SceModule struct and sync with the gentoo scripts for build fixes and better support on other environments.

Enjoy and happy coding :) get it here!


ActionScript to Java

One of these days I wanted to convert some AS2/3 to Java. It was obvious that it was simple since ActionScript and Java share lots of language constructs, however it is a tedious task so i created a simple helper application:

package com.jetdrone.as2j; import; import; import; import; import; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class AS2J {   private static final Map AS2JTYPES = new HashMap();   public static void main(String[] args) throws Exception {     // e.g.: "~/Flixel2/as/AdamAtomic-flixel-348b55f"     File asSourceDir = new File(args[0]);     String skip = "docs";     // e.g.: "~/src"     File outSourceDir = new File(args[1]);     AS2JTYPES.put("uint", "int");     AS2JTYPES.put("Boolean", "boolean");     AS2JTYPES.put("Number", "float");     AS2JTYPES.put("Array", "java.util.List");      processFile(asSourceDir, asSourceDir.getAbsolutePath(), outSourceDir, skip);   }   private static String getType(String type) {     String t = AS2JTYPES.get(type.trim());     if(t != null) {       return t;     }     return type;   }   private static void processFile(File src, String prefix, File target, String skip)       throws Exception {     for(File f : src.listFiles()) {       if(!f.getName().equals(skip)) {         if(f.isDirectory()) {           processFile(f, prefix, target, skip);         } else {           if(f.getName().endsWith(".as")) {             String fname = f.getAbsolutePath();             String sourceFileName = fname.substring(prefix.length(), fname.length() - 3) + ".java";             convertFile(f, new File(target, sourceFileName));           }         }       }     }   }   private static void convertFile(File src, File dest) throws Exception {     String l;     BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(src)));     PrintWriter out = new PrintWriter(dest);     int i=1;     while((l = in.readLine()) != null) {       try {         l = processPackage(l);         l = processConst(l);         l = processVariable(l);         l = processMethod(l);         l = processConstructor(l);         l = processGetter(l);         l = processSetter(l);         l = processCast(l);       } catch(RuntimeException e) {         System.err.println("ERR (" + i + "): [" + src.getAbsolutePath() + "]");         System.err.println(" --> " + l);       }       out.println(l);       i++;     }     in.close();     out.close();   }   private static final Pattern PACKAGE = Pattern.compile("^\\s*package\\s+(.+)");   private static String processPackage(String line) {     Matcher matcher = PACKAGE.matcher(line);     if (matcher.find()) {       return line.substring(0, matcher.start()) + "package " + +           ";" + line.substring(matcher.end());     }     return line;   }   // public var exists:Boolean;     private static final Pattern VARIABLE = Pattern.compile("var\\s+(\\w+?)\\s*:\\s*(.+?);");   private static String processVariable(String line) {     Matcher matcher = VARIABLE.matcher(line);     if (matcher.find()) {       if('=') != -1) {         String type =,'='));         String defaultValue ='='));         return line.substring(0, matcher.start()) + getType(type) + " " + +             " " + defaultValue + ";" + line.substring(matcher.end());         } else {         return line.substring(0, matcher.start()) + getType( + " " +    + ";" + line.substring(matcher.end());       }     }     return line;   }   // static public const A_LIST:uint = 0;   private static final Pattern CONST = Pattern.compile("const\\s+(\\w+?)\\s*:\\s*(\\w+?)\\s*=\\s*(.+);");   private static String processConst(String line) {     Matcher matcher = CONST.matcher(line);     if (matcher.find()) {     return line.substring(0, matcher.start()) + "final " + getType( +         " " + + " = " + + ";" + line.substring(matcher.end());     }     return line;   }   // public function destroy():void   private static final Pattern METHOD = Pattern.compile("function\\s+(\\w+?)\\s*\\((.*?)\\)\\s*:(\\w+)");   private static String processMethod(String line) {     Matcher matcher = METHOD.matcher(line);     if (matcher.find()) {       return line.substring(0, matcher.start()) + getType( + " " +  + "(" + processArgs( + ")" + line.substring(matcher.end());     }     return line;   }   // public function destroy()   private static final Pattern CONSTRUCTOR = Pattern.compile("function\\s+(\\w+?)\\s*\\((.*?)\\)");   private static String processConstructor(String line) {     Matcher matcher = CONSTRUCTOR.matcher(line);     if (matcher.find()) {       return line.substring(0, matcher.start()) + + "(" +           processArgs( + ")" + line.substring(matcher.end());     }     return line;   }   private static final String processArgs(String line) {     StringBuffer sb = new StringBuffer();     for(String p : line.split(",")) {       sb.append(processArg(p));       sb.append(", ");     }     if(sb.length() > 0) {       sb.setLength(sb.length() - 2);     }     return sb.toString();   }   // Fixed:Boolean   private static final Pattern PARAM = Pattern.compile("\\s*(\\w+?)\\s*:\\s*(.+)");   private static final String processArg(String line) {     Matcher matcher = PARAM.matcher(line);     if (matcher.find()) {       if('=') != -1) {         // java has no default values         String defaultValue ='=') + 1);         return getType(,'='))) +             " " + + " /*" + defaultValue + "*/";       }       return getType( + " " +;     }     return line;   }   // public get right():Number   private static final Pattern GETTER = Pattern.compile(       "function\\s+get\\s+(\\w+?)\\s*\\(.*\\)\\s*:\\s*(\\w+)");   private static String processGetter(String line) {     Matcher matcher = GETTER.matcher(line);     if (matcher.find()) {       String methodName =;       return line.substring(0, matcher.start()) + getType( +           " get" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1) +           "()" + line.substring(matcher.end());     }     return line;   }   // public get right():Number   private static final Pattern SETTER = Pattern.compile(       "function\\s+set\\s+(\\w+?)\\s*\\((.*)\\)\\s*:\\s*(\\w+)");   private static String processSetter(String line) {     Matcher matcher = SETTER.matcher(line);     if (matcher.find()) {       String methodName =;       return line.substring(0, matcher.start()) + getType( +           " set" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1) +           "(" + processArgs( + ")" + line.substring(matcher.end());     }     return line;   }     // var members:Array = (Object as FlxGroup).members;   private static final Pattern CAST = Pattern.compile("\\s*(\\S+?)\\s+as\\s+(\\w+)");   private static String processCast(String line) {     Matcher matcher = CAST.matcher(line);     if (matcher.find()) {       if('=') != -1) {         String prefix =,'=') + 1);         String value ='=') + 1);         return line.substring(0, matcher.start()) + prefix + " (" +             getType( + ")" + value + line.substring(matcher.end());       } else {         if( == '(') {           return line.substring(0, matcher.start()) + " ((" + getType( +               ") " + + line.substring(matcher.end());         } else {           return line.substring(0, matcher.start()) + " (" + getType( +               ") " + + line.substring(matcher.end());         }       }     }     return line;   } }

Ubuntu 11.04

Just installed it on my laptop and am enjoying unity, still need to get used to it but it looks like a nice alternative to the old gnome 2 window manager.


Updates on minpsp project

Development has slowed down but it is not stalled, for the next release 11.2 you can expect better oslib_mod packages and a diet on the deb files, tests have shown that from more than 150Mb the new deb packages are about 50Mb...


MinPSP Eclipse Plugin @ Google Code

I've been using the MinPSP Eclipse plugin for a while and several people have downloaded it. I see that people are interested in the plugin and I get also requests for new features, such as project templates and better GDB support with the latest Eclipse. Since I don't have much time to work on this myself, I've open sourced the source code of the plugin.

You can get the source code here: minpsp-eclipse-plugin.

If you want to participate and make this plugin better just request it on the project site and I will work out a way for you to help.


New MinPSP plugin 1.0.0

A total refactoring of the plugin is complete, this time the plugin can discover compiler flags and default includes, in order to get it working properly, make sure your minpsp installation is on the path. On windows the installer does this automatically but for other platforms you need to do it yourself.

Once you do this and create a MinPSP lib project/or Makefile project, you will see that default includes get automatically indexed and it can compile out of the box lib projects.

Also a nice addition is that MinPSP debugger gets listed automatically on the debuggers panel.

I will plan to write a new tutorial with the new plugin soon :)

As usual get the plugin from the update site:


Today is KDE 4.6 release day

KDE is delighted to announce its latest set of releases, providing major updates to the KDE Plasma workspaces, KDE Applications and KDE Platform. These releases, versioned 4.6, provide many new features in each of KDE's three product lines.

Ken Thompson, Dennis Ritchie win Japan Prize

The two Bell Labs computer scientists - named today as winners of the 2011 Japan Prize for information and communications - just wanted to build a better operating system.

MinPSP Eclipse Plugin 0.0.1

In order to make your game development environment even more friendly with Eclipse, I am pleased to announce the initial release of the MinPSP Eclipse Plugin. This plugin will allow you to create:

  • Executable Projects
  • Static Library Projects
  • Makefile Projects

It is still very primitive and depends on having the Eclipse C/C++ Development Tools installed. To get started install the plugin by going to its update site:

You should be seeing something like this:

Eclipse Plugin Update Site

Once the install process completes and Eclipse is restarted you can start creating your projects:

Create new C Project


MinPSPW 0.11 is out for Windows Linux and Mac

New release is out, not so many features this time:

  • openTRI engine devpak
  • reverted binutils to 2.16 since 2.18 generates bad assembly for Daedalus
  • supports Mac as a development platform thanks to autilio
  • Fixed pspsh on win32 when run inside eclipse
  • added PRXTool 

Thanks for the bug reports and enjoy.


binutils 2.18 are broken :(

There is a subtle bug on the binutils 2.18 it is possible to reproduce if you build for example Daedalus PSP emulator, with the current SDK it fails to run, but with the old 0.9.5 or downgraded binutils the generated binary works... This is a very obscure bug that i will try to isolate but if any of the users of MinPSPW can help it would be welcome :)