Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

17. April 2013

 

With any project, you've got to start at the very beginning and that is exactly what I am going to do with Haxe.  First we are going to create the seminal Hello World and explore the cross platform nature of Haxe.

 

I originally worked in FlashDevelop to author these examples.  I ran into a couple gotchas as I went.  First, I discovered that package names need to start with a lower case character, but FlashDevelop will allow you to make this mistake.  On top, packages are more like Java, than C# or C++ namespaces.  Behind the scenes, they are mirrored on the file system.  So a package mike.is.great becomes /mike/is/great on the file system.  So, when renaming my package, I had to change at the file system level too… lesson learned.  Second, the debugger is incredibly fragile in FlashDevelop, if it goes on the fritz, restart FlashDevelop.  Finally, for some bizarre reason, you can't set a watch on a non local variable.  So if you want to watch a global value, make a local reference.  All told though, working in FlashDevelop is pretty pleasant.

 

Alright, back to HelloWorld.  I'll start with a straight Haxe version that runs in the Neko VM:

package gfs;

import neko.Lib;

class Main
{
	
	static function main()
	{
		Lib.println("Hello world");
	}
	
}

Not the most exciting code, but Hello World rarely is. Now we run our application in the Neko VM:

1

 

Nothing too exciting, but that's Hello World.  Now let's look at the Flash version of Hello World:

 

 

package gfs;

import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.Lib;
import flash.text.TextField;

class Main
{
	
	static function main()
	{
		var stage = Lib.current.stage;
		
		// entry point
		var text = new TextField();
		text.text = "Hello world!";
		stage.addChild(text);
	}
	
}

 

And here it is running in Flash:

2

Once again, not the most exciting app, but it's Hello World.

 

That said, it's pretty annoying creating a version for each platform.  For this we will turn to NME.  NME provides a series of libraries that abstract out the different platform capabilities using a consistent set of libraries.  This HelloWorld is a little bit more advanced:

 

 

 

package gfs;

import nme.display.Sprite;
import nme.events.Event;
import nme.Lib;
import nme.text.TextField;
import nme.text.TextFieldAutoSize;
import nme.text.TextFormat;

class Main extends Sprite
{
	public function new()
	{
		super();
		var stage = Lib.current.stage;
		
		var textFormat = new TextFormat();
		textFormat.font = "Courier";
		textFormat.color = 0xff0000;
		textFormat.size = 42;
		
		var text = new TextField();
		text.text = "Hello World!";
		text.x = Lib.current.stage.stageWidth / 2 - 145;
		text.y = Lib.current.stage.stageHeight / 2 - 21;
		text.width = 290;
		
		text.setTextFormat(textFormat);
		Lib.current.stage.addChild(text);
	}
	
	public static function main()
	{
		// static entry point
		Lib.current.addChild(new Main());
	}
}

 

This code is pretty similar, once again, there is a main method.  You may find it a bit strange that Main inherits from Sprite… this is an ActionScript/Flash thing, the library NME models after.  Now the cool part is running it on various platforms, here are the results (in order) of running:

nme test ios -simulator

nme test Flash

nme test html5

 

iOS

3

 

Flash

Hello World Haxe FLash

 

HTML5

HaxeHTML5HelloWorld.png

 

One source, many platforms… have we reached nirvana?

 

Sadly no.  Here is the result of nme test mac:

Hello world haxe mac

 

Ugh, something obviously went wrong.  Coincidentally the same code runs on Windows, so this is a Mac specific problem.  The problem is, this code is implemented in C++, so then you have to jump in to the generated code.  So, what does this generated code look like?  Well, here's some now:

 

 

#include <hxcpp.h>

#ifndef INCLUDED_gfs_Main
#include <gfs/Main.h>
#endif
#ifndef INCLUDED_native_display_DisplayObject
#include <native/display/DisplayObject.h>
#endif
#ifndef INCLUDED_native_display_DisplayObjectContainer
#include <native/display/DisplayObjectContainer.h>
#endif
#ifndef INCLUDED_native_display_IBitmapDrawable
#include <native/display/IBitmapDrawable.h>
#endif
#ifndef INCLUDED_native_display_InteractiveObject
#include <native/display/InteractiveObject.h>
#endif
#ifndef INCLUDED_native_display_MovieClip
#include <native/display/MovieClip.h>
#endif
#ifndef INCLUDED_native_display_Sprite
#include <native/display/Sprite.h>
#endif
#ifndef INCLUDED_native_display_Stage
#include <native/display/Stage.h>
#endif
#ifndef INCLUDED_native_events_EventDispatcher
#include <native/events/EventDispatcher.h>
#endif
#ifndef INCLUDED_native_events_IEventDispatcher
#include <native/events/IEventDispatcher.h>
#endif
#ifndef INCLUDED_native_text_TextField
#include <native/text/TextField.h>
#endif
#ifndef INCLUDED_native_text_TextFormat
#include <native/text/TextFormat.h>
#endif
#ifndef INCLUDED_nme_Lib
#include <nme/Lib.h>
#endif
namespace gfs{

Void Main_obj::__construct()
{
HX_STACK_PUSH("Main::new","gfs/Main.hx",13);
{
	HX_STACK_LINE(14)
	super::__construct();
	HX_STACK_LINE(15)
	::native::display::Stage stage = ::nme::Lib_obj::get_current()->get_stage();
		HX_STACK_VAR(stage,"stage");
	HX_STACK_LINE(17)
	::native::text::TextFormat textFormat = ::native::text::TextFormat_obj::__new(null(),null(),
null(),null(),null(),null(),null(),null(),null(),null(),null(),null(),null());		
HX_STACK_VAR(textFormat,"textFormat");
	HX_STACK_LINE(18)
	textFormat->font = HX_CSTRING("Courier");
	HX_STACK_LINE(19)
	textFormat->color = (int)16711680;
	HX_STACK_LINE(20)
	textFormat->size = (int)42;
	HX_STACK_LINE(22)
	::native::text::TextField text = ::native::text::TextField_obj::__new();		
HX_STACK_VAR(text,"text");
	HX_STACK_LINE(23)
	text->set_text(HX_CSTRING("Hello World!"));
	HX_STACK_LINE(24)
	text->set_x(((Float(::nme::Lib_obj::get_current()->get_stage()
->get_stageWidth()) / Float((int)2)) - (int)150));
	HX_STACK_LINE(25)
	text->set_y(((Float(::nme::Lib_obj::get_current()->get_stage()
->get_stageHeight()) / Float((int)2)) - (int)21));
	HX_STACK_LINE(26)
	text->set_width((int)300);
	HX_STACK_LINE(28)
	text->setTextFormat(textFormat,null(),null());
	HX_STACK_LINE(29)
	::nme::Lib_obj::get_current()->get_stage()->addChild(text);
}
;
	return null();
}

Main_obj::~Main_obj() { }

Dynamic Main_obj::__CreateEmpty() { return  new Main_obj; }
hx::ObjectPtr< Main_obj > Main_obj::__new()
{  hx::ObjectPtr< Main_obj > result = new Main_obj();
	result->__construct();
	return result;}

Dynamic Main_obj::__Create(hx::DynamicArray inArgs)
{  hx::ObjectPtr< Main_obj > result = new Main_obj();
	result->__construct();
	return result;}

Void Main_obj::main( ){
{
		HX_STACK_PUSH("Main::main","gfs/Main.hx",33);
		HX_STACK_LINE(33)
		::nme::Lib_obj::get_current()->addChild(::gfs::Main_obj::__new());
	}
return null();
}


STATIC_HX_DEFINE_DYNAMIC_FUNC0(Main_obj,main,(void))


Main_obj::Main_obj()
{
}

void Main_obj::__Mark(HX_MARK_PARAMS)
{
	HX_MARK_BEGIN_CLASS(Main);
	super::__Mark(HX_MARK_ARG);
	HX_MARK_END_CLASS();
}

void Main_obj::__Visit(HX_VISIT_PARAMS)
{
	super::__Visit(HX_VISIT_ARG);
}

Dynamic Main_obj::__Field(const ::String &inName,bool inCallProp)
{
	switch(inName.length) {
	case 4:
		if (HX_FIELD_EQ(inName,"main") ) { return main_dyn(); }
	}
	return super::__Field(inName,inCallProp);
}

Dynamic Main_obj::__SetField(const ::String &inName,const Dynamic &inValue,bool inCallProp)
{
	return super::__SetField(inName,inValue,inCallProp);
}

void Main_obj::__GetFields(Array< ::String> &outFields)
{
	super::__GetFields(outFields);
};

static ::String sStaticFields[] = {
	HX_CSTRING("main"),
	String(null()) };

static ::String sMemberFields[] = {
	String(null()) };

static void sMarkStatics(HX_MARK_PARAMS) {
	HX_MARK_MEMBER_NAME(Main_obj::__mClass,"__mClass");
};

static void sVisitStatics(HX_VISIT_PARAMS) {
	HX_VISIT_MEMBER_NAME(Main_obj::__mClass,"__mClass");
};

Class Main_obj::__mClass;

void Main_obj::__register()
{
	Static(__mClass) = hx::RegisterClass(HX_CSTRING("gfs.Main"), hx::TCanCast< Main_obj> ,
sStaticFields,sMemberFields,
	&__CreateEmpty, &__Create,
	&super::__SGetClass(), 0, sMarkStatics, sVisitStatics);
}

void Main_obj::__boot()
{
}

} // end namespace gfs

 

You can read it, but barely. So when the cross platform part of NME breaks down, you are in for a world of hurt. That such a simple example breaks doesn't bode well for the future.

 

In the next post we look at graphics in Haxe and NME.

16. April 2013

 

While I was working on my PlayStation Mobile book I didn’t produce all that many PlayStation Mobile tutorials.  I guess it was a matter of PSM overload in a way, although you should expect to see a few more in the near future covering things that have been added since the book was released.  The good new is, there is another developer, Alex McGilvray, that has created some great PSM tutorials!  His series of tutorials are a bit lower leveled than the ones here on GameFromScratch and are a good compliment.

 

He has made the following tutorials:

Tutorial 1 -- Getting Started

Tutorial 2 Part 1 – Shader Programming

Tutorial 2 Part 2 – Vertices, Indices and Vertex Colors

Tutorial 2 Part 3 – Texture Coordinates

Tutorial 2 Part 4 – Vertex Buffers

Tutorial 2 Part 5 – The Render Loop

Tutorial 3 – Improving PSM Rendering Performance

 

Or you can just check out his blog.  Nice work Alex! 

Programming , ,

15. April 2013

So last week I decided to run a poll to see which gaming technology people would be most interested in and the results actually shocked me:

 

 

Haxe narrowly edged out LibGDX ( by two votes ), while my original plan of HTML5 came in a distant third.  The other category seemed to be mostly composed of people interested in MonoGame.

 

I have long been a fan of C# and XNA, so Monogame was an obvious option.  It was ( and is ) discounted for a couple reasons.  First is the inability to target the web.  It's a shame Microsoft put a bullet in Silverlight, as otherwise this limitation wouldn't exist.  Second, paying 300$ to deploy on iOS and another 300$ to deploy on Android is a bit steep.  LibGDX suffers this to a degree too, as you need Xamarin to target iOS.  Hopefully in time this changes.

 

Hello Haxe World

So over the last couple days I've taken a closer look at Haxe or more specifically Haxe + NME.  Haxe as a programming language is an interesting choice.  It has an ActionScript like syntax and compiles to it's own virtual machine like Java ( the VM is called Neko, so if you are wondering what Neko is…  well, now you know!)  If that was all Haxe did, we wouldn't be having this conversation.  More interestingly, it compiles to a number of other programming languages including HTML5 ( JavaScript ), ActionScript ( Flash ) and C++.  As a result, you can compile to C++ for Android and iOS and get native performance.  This makes Haxe quite often many times faster than ActionScript.

 

There is however a serious problem or flaw with Haxe.  Let's take a quick look at part of the Haxe API and you will see what I mean:

 

Haxe Api

 

Notice how there are a number of language specific apis, such as cpp, which I've expanded above.  So, what happens if you use the cpp Random api and want to target Flash? Short answer is, you can't.  If course you could right a great deal of code full of if X platform, do this, otherwise do that, but you will quickly find yourself writing the same application for each platform.  So, what do you do if you want to write for multiple platforms with a single code base?

 

Meet NME

This is where NME comes in.  NME builds on top of the Haxe programming language and provides a Flash like API over top.  Most importantly, it supports Windows, Mac, Linux, iOS, Android, BlackBerry, webOS, Flash and HTML5 using a single code base.  Let's take a quick look at part of the NME libraries to show you what I mean:

NME api

 

There are still platform/language specific libraries, like the neko.vm above.  There are also the nme.* libraries.  These provide a Flash like API for the majority of programming tasks needed to make a game.  Targeting your code towards these libraries, and minimizing the use of native libraries, and you can target a number of different platforms with a single code base.

 

There is another aspect to NME that makes life nice.  If you read my review of the Loom Game Engine you may recall I was a big fan of the command line interface.  NME has a very similar interface.  Once you've installed it, creating a new project from one of the samples is as simple typing nme create samplename then you can test it by running nme test platform.

 

Here is an example of creating the DisplayingABitmap sample and running it as an HTML5 project:

Creating an NME project

 

And your browser will open:

NME running as HTML5

 

What makes this most impressive is when you target C++, it fires off the build for you using the included tool chain.  Configuring each platform is as simple as nme setup platformname, valid platforms are currently windows, linux, android, blackberry and webos.  Unfortunately Xcode can't be installed automatically, so this process won't work for iOS or Mac, you need to setup Xcode yourself.  As you can see, setting up and running NME/Haxe is quite simple, and worked perfectly for me out of the box.  If you are curious what options you can provide for sample names, you can get them from the Github directory.  There are a fair number of samples to start with.

 

Now is when things take a bit of a turn for the worse…  getting an IDE up and running.  This part was a great deal less fun for me.  You can get basic syntax highlighting and autocompletion working on a number of different IDEs, here is the list of options.  This is when things got rather nasty.  I was working on MacOS so this presented a bit of a catch.  I tried getting IntelliJ to work.  Adding the plugin is trivial ,although for some reason you need to use the zip version, it's not in the plugin directory.  Configuring the debugger though… that's another story.  I spent a couple hours googling, and sadly only found information a year or two old.

 

Then I tried MonoDevelop, there is a plugin available and its supposed to be a great option on MacOS.  And….  MonoDevelop 3 is no longer available…  It's now Xamarin Studio 4 and the plugin doesn't work anymore.  Good luck getting a download for MonoDevelop 3!  There is also FDT, which I intend to check out, but it's built on top of Eclipse and I HATE Eclipse.  Eventually I got IntelliJ Flash debugging to work but it was a great deal less fun.

 

After this frustrating experience, I rebooted into Windows and things got a TON better.  FlashDevelop is easily the best option for developing with Haxe but sadly it's only available on Windows.  There was however a major catch… debugging simply did not work.  After some digging, it turns out you have to run the 32bit JDK or it doesn't work.  Seriously, in this day and age, still having Java VM problems like this is just insane.  Once I got that licked, I was up and running.

 

At this point I have a working development environment up and running I can get to coding.  If you are working on Windows, using FlashDevelop you can get up and running very easily, so long as you are running 32bit Java.  On MacOS though, expect a much rockier experience.  It would be great if FlashDevelop could be ported to Mac, but apparently it can't be… there have been a number of attempts.  They have however provided a configuration for working in Virtualized settings ( VMWare, Parallels, etc ).

 

Stay tuned for some code related posts soon.

14. April 2013

I just finished performing an upgrade on the software that runs this site. I ran into a couple small snags during the upgrade that resulted in the site being unavailable for about 15 minutes. If you we're trying to access the site earlier today and received errors... My bad, sorry.

 

 

The new software should be a little quicker, but it was mostly about server security and a few perks for me, like better blogging software support. I think the upgrade went smoothly enough, but there are a lot of moving pieces. If you encounter any errors, please let me know what and where so I can fix it!

 

 

Cheers and thanks for your patience.

 

News ,

12. April 2013
During GDC Havok announced Project Anarchy a collection of their gaming technologies including Physics, Animation and the Vision engine for mobile. Today a few more details where announced and its all great news!

What’s included?

We have a powerful toolset made up of Havok’s Vision Engine, Physics, AI and Animation Studio; components of which have been used to build games like Modern Combat 4, Halo 4, Skyrim, Orcs Must Die and Guild Wars 2 to name a few. Project Anarchy bundles these technologies together, allowing users to download a complete toolkit with exporters for max and maya and a full WYSIWYG editor.

The Havok Vision Engine is built on top of an extensible C++ plugin framework and Project Anarchy will include the source for the plugins we use to connect our other products to the Vision engine. This source will also be maintained online and will provide insight for users on how to extend functionality with their own offerings; mail [email protected] if you’d like to know more.

How free is “free?”

You can download and develop your game on the PC for free. Releasing that game for iOS or Android is completely free. We’ve tried to keep it simple. No crippleware, no restriction on how big you are, no hidden royalty payments on the back end. You can opt to purchase direct support from our engineers or additional source code.

What about other platforms?

Additional platforms are not free. If you want to expand and generate revenue from other platforms you can license those directly from us. Given the ability with Project Anarchy to quickly move to new platforms, the risk/reward here will be easily understood based on the game’s initial success. We’re hoping that with these options and the opportunities afforded by a large community sharing a common technology base, as well as the fact that more and more developers will grow up with our technology, we’ll all benefit from what Project Anarchy brings.

They also have a launch trailer showcasing Project Anarchy on mobile.


News

Month List

Popular Comments