Pages

Showing posts with label OpenFL. Show all posts
Showing posts with label OpenFL. Show all posts

Sunday, July 21, 2013

OpenFL gestures using roxlib gesture library

When I work with NME before , I used a gesture library called roxlib  for gesture handling. This roxlib library is greats! it's not dependent on native features so I can use it on flash also (for the sake rapid prototyping of course). now that this library is updated to support OpenFL (thanks rockswang!) I can happily tell everyone how awesome this library is. This library is great for basic mobile touch screen gestures, it supports :
  • pinch
  • pan
  • swipe 
  • long press
  • tap 
  • rotation
All the gesture that is common usage in the mobile environment nowadays.

The only problem with this library is the lack of documentation and how cluttered it's code with so many unnecessary code (the "how to use" piece of code could be separated from the library itself I guess). But after a while I figured out how this library works. So I'll write a little tutorial for those who need to use gestures on their games :)

Gesture with Roxlib

First we must download the roxlib library from the github page and extract it somewhere. 


Then copy the roxlib library into your project, this is necessary because it's not a haxelib project so we need to import it manually into the project. 

copy library to project


There's not only gesture package inside the library, but we can remove the others without any problem (once again thanks roxswang for making it independent from another package).

only gesture package left


now for the coding part, all we need to do is create a RoxGestureAgent for the gesture event handler, and some sprite used for the target of gesture , the register the gesture event handler to the target sprite using RoxGestureEvent.


var image:Sprite = new Sprite();
image.addChild(new Bitmap(Assets.getBitmapData("img/rock.png")));
image.x = 300;
image.y = 200;
image.scaleX = 2;
image.scaleY = 2;

var roxAgent = new RoxGestureAgent(image, RoxGestureAgent.GESTURE);

image.addEventListener(RoxGestureEvent.GESTURE_SWIPE, onSwipe);
image.addEventListener(RoxGestureEvent.GESTURE_PAN, onPan);
image.addEventListener(RoxGestureEvent.GESTURE_PINCH, onPinch);
image.addEventListener(RoxGestureEvent.GESTURE_ROTATION, onRotation);
image.addEventListener(RoxGestureEvent.GESTURE_TAP, onTap);
image.addEventListener(RoxGestureEvent.GESTURE_LONG_PRESS, onLongPress);


then for each callBack method, as it receive RoxGestureEvent as parameter, the 2 necessary properties to remember from it are the target and extra properties. The target properties contain the target sprite used as gesture target, and extra properties contain different thing for different actions :

  • extra on Pinch contain scale factor (float)
  • extra on Rotation contain rotation angle (float)
  • extra on Pan/Swipe contain pan/swipe speed (Point)
One thing to note about Pan and Swipe difference is that Pan action called continously when you move your finger across the screen, and swipe is only called when you removed your hand from the screen. 

The below codes is the callback I use for this tutorial, you can create your own version. I'll not really explain too much about each callback but here's a brief explanation about each callback method 

When tap gesture called the target will be scaled up:


 private function onTap(e:RoxGestureEvent):Void
 {
  var sp:DisplayObject = cast(e.target, DisplayObject);
  var scX = sp.scaleX; //current scaleX factor
  var scY = sp.scaleY; //current scaleY factor 
  Actuate.tween(sp, 0.5, { scaleX: scX + 0.1, scaleY:scY + 0.1 } ).ease(Bounce.easeOut);
 }

When long press gesture called the target will be scaled down:


 private function onLongPress(e:RoxGestureEvent):Void
 {
  
  var sp:DisplayObject = cast(e.target, DisplayObject);
  var scX = sp.scaleX; //current scaleX factor
  var scY = sp.scaleY; //current scaleY factor 
  Actuate.tween(sp, 0.5, { scaleX: scX - 0.3, scaleY:scY - 0.3 } ).ease(Bounce.easeOut);
  
 }

When pinch called the target will be resized:


private function onPinch(e:RoxGestureEvent):Void
{
 var sp = cast(e.target, DisplayObject);
 var scale: Float = e.extra;
        var spt = sp.parent.localToGlobal(new Point(sp.x, sp.y));
        var dx = spt.x - e.stageX, dy = spt.y - e.stageY;
        var angle = Math.atan2(dy, dx);
        var nowlen = new Point(dx, dy).length;
        var newlen = nowlen * scale;
        var newpos = Point.polar(newlen, angle);
        newpos.offset(e.stageX, e.stageY);
        newpos = sp.parent.globalToLocal(newpos);
        sp.scaleX *= scale;
        sp.scaleY *= scale;
        sp.x = newpos.x;
        sp.y = newpos.y;
}

When pan called the object will move following the mouse/finger movement:


private function onPan(e:RoxGestureEvent):Void
{
 var sp = cast(e.target, DisplayObject);
 var pt = cast(e.extra,Point);
        sp.x += pt.x;
        sp.y += pt.y;
}

When swipe called the target will move using the swipe speed


private function onSwipe(e:RoxGestureEvent):Void
{
 var sp= cast(e.target, DisplayObject);
 var pt = cast(e.extra, Point);
        Actuate.tween(sp,  0.5, { x:sp.x + pt.x, y:sp.y + pt.y });
}

And here's the result of the example:
Note : I have only tested this on flash, android, and windows and works without problem . If anyone can try it on iOS or blackberry and tell me the result I would be grateful!
Note : When I tested this on html5 ,swipe and pan didn't work. maybe anyone can figure out why? 

That's all. 

I hope you can make use of this awesome library. as for this is the best library I found for simple mobile gestures. again, all thanks for rockswang for this awesome gesture library :D

Cheers!

Monday, July 1, 2013

From NME to OpenFL with FlashDevelop

Right now OpenFL already up on the haxelib  so I could say that it's safe to use it now. For some , the migration process wouldn't be as smooth as one expect. Some problem like different build file type (NME use .nmml while OpenFL use .xml) and the support of OpenFL on FlashDevelop would cause a problem.

I've sucessfully migrated my NME project into OpenFL, it's not a big deal but maybe it can help they who don't know how to migrate :) 


First here's how to install OpenFL and FlashDevelop :
  1. Install haxe 3 from and the official site
  2. open the newly installed haxelib and install these libs: openfl, openfl-compatibility, openfl-tools,openfl-native,openfl-html5
  3. after those libs installed, run this command : haxelib run openfl setup 
  4. run additional setup command to setup each platform : openfl setup android, openfl setup blackberry, etc . If you already run nme setup [platform] previously , the setting would be saved in OpenFL
  5. The current release build of FlashDevelop doesn't support OpenFL project, so you need to install the dev build version of FlashDevelop. you can download it here
  6. if you select New Project in FlashDevelop you can see the OpenFL project can be created there.

Migrating NME Project to OpenFL Project

Using the new FlashDevelop we can migrate NME Project to OpenFL, but it need some configuration changes in .nmml file to do so.
  • change .nmml file extension in your NME project into .xml 
  • change <haxelib="nme"/> into <haxelib="openfl"/>
  • add <haxelib="openfl-compatibility"/> so OpenFL will recognize all the old nme package
  • looks like <haxelib="actuate"/> is necessary in OpenFL so don't forget to add that (Edit: turns out It's not really necessary if you don't use actuate)
  • I'm not sure if this one necessary or not but you can delete all <ndll/> tags without problem (except your own ndll of course)
  • This one too , delete the old <haxeflag/> tag and change with this one <haxeflag name="-dce std" if="haxe3" />
  • Last, we need to tell FlashDevelop to use the .xml file as the build file. Right click Project -> Properties . On the output file, change the application.nmml extension to application.xml
  • Try to run the project. It should be no problem now.


Other notes
  • check the haxe 3 migration  for some feature changes like Maps and properties
  • haxe 3 use different haxelib repo than haxe 2. so make sure that your lib that you use is  exist in lib.haxe.org 
  • some library like spritesheet changes it's package name so you need to be careful about that.
for the end note, OpenFL is a great framework with so many potential. so don't hestitate to use it and keep creating awesome things . Cheers! :)

Sunday, April 28, 2013

Animated Sprite using Bitmap Spritesheet with Haxe NME/OpenFL Spritesheet Library

NME comes with great spritesheet lib which can be installed with haxelib install spritesheet command on commandline. Unfortunately it lacks documentation and how to example tutorial. The only spritesheet tutorial available is the singmajesty's tutorial which also doesn't give a clue about how to work with bitmap spritesheet. So I tried to figured it out myself. And turns out it's not that hard, so I'll tell you how in a fast and effective way.

The first thing needed to create animated sprite of course is the spritesheet itself. I will use the spritesheet I took from opengameart as example.



also don't forget to add  spritesheet lib to nmml with haxelib tag


<haxelib name="spritesheet" />


to load the bitmap and parse it as animation frames we can use BitmapImporter class inside com.ecleticdesignstudio.spritesheet.importers package. this class is really simple because it's only contain one static function called create(). as the input parameter it ask for the BitmapData , column count, row count, frame width, frame height, and some additional parameter which I'm not sure what it is so I'll leave it like that for now. The create() methods gives output a Spritesheet class, we need to create a variable to hold this output.


var spritesheet:Spritesheet = BitmapImporter.create(Assets.getBitmapData("img/kit_from_firefox.png"), 3, 9, 56, 80);


we can (and must) assign BehaviourData this Spritesheet object. BehaviourData required to define how the spritesheet should be used, which frame should be played at what speed(fps) and should it be looped or not.
for this example I create 9 behaviour for the spritesheet and assigns it to each row of frames, and I give different parameter for each behaviour. What's important for this BehaviourData input parameter is the name and frame number.


spritesheet.addBehavior(new BehaviorData("stand", [0, 1, 2], true));
spritesheet.addBehavior(new BehaviorData("down", [3, 4, 5], false,15));
spritesheet.addBehavior(new BehaviorData("jump", [6, 7, 8], false,15));
spritesheet.addBehavior(new BehaviorData("hit", [9, 10, 11], false,15));
spritesheet.addBehavior(new BehaviorData("punch", [12, 13, 14], false,5));
spritesheet.addBehavior(new BehaviorData("kick", [15, 16, 17], false,15));
spritesheet.addBehavior(new BehaviorData("flypunch", [18, 19, 20], false,10));
spritesheet.addBehavior(new BehaviorData("flykick", [21, 22, 23], false,10));
spritesheet.addBehavior(new BehaviorData("dizzy", [24, 25, 26], true));


The spritesheet itself is ready, but we can't use it directly. spritesheet library has their own sprite class for animation called AnimatedSprite. We can use this AnimatedSprite to animate the spritesheet created before. to use it simply input the spritesheet into the constructor parameter.


var animated:AnimatedSprite = new AnimatedSprite(spritesheet, true)


AnimatedSprite need to update itself for animation, so we must call it's update() method on each update cycle


 public function onEnterFrame(e:Event):Void
 {
  var delta = Lib.getTimer()- lastTime;
  animated.update(delta);
  lastTime = Lib.getTimer();
 }


To play animation we can call behaviour names from spritesheet using showBehaviour() method or showBehaviours() if we want to call a list of behaviour consecutively. We can also queue behaviour using queueBehaviour(), the method will queue behaviour and animate it after the current animation finished. Remember that a looping behaviour will loop forever and so it should not be used inside the behaviour queue (if we use showBehaviours() or queueBehaviour())


animated.showBehavior("stand");
animated.showBehaviors(["down","jump","hit","punch"]);


So that's what I know about how to use spritesheet library . I hope it could help as the a simple tutorial of how to use Haxe NME spritesheet library because spritesheet is a fundamental thing in game. and spritesheet lib is a neat library for a playing animation. :)

Here is the result: https://dl.dropboxusercontent.com/u/27073998/BitmapSpritesheet.swf
you could find the example source here .

Cheers! :)

Update : Dealing with Haxe 3 Change

if you switch to haxe 3 you may deal with error saying that package not found. that's happen because spritesheet library on haxe 3 use different package name. The solution is to change the package name

From


1
2
3
4
import com.eclecticdesignstudio.spritesheet.AnimatedSprite;
import com.eclecticdesignstudio.spritesheet.data.BehaviorData;
import com.eclecticdesignstudio.spritesheet.importers.BitmapImporter;
import com.eclecticdesignstudio.spritesheet.Spritesheet;


to


1
2
3
4
import spritesheet.AnimatedSprite;
import spritesheet.data.BehaviorData;
import spritesheet.importers.BitmapImporter;
import spritesheet.Spritesheet;


there you go. now it will run without any problems . Good luck! :)