KeyActionBinder

KeyActionBinder provides universal game input control for both keyboard and game controllers in Adobe AIR. It is independent of the game engine used or the hardware platform it is running in. While Adobe Flash already provides all the means for using keyboard and game input (via KeyboardEvent and GameInput), KeyActionBinder tries to abstract those classes behind a straightforward, higher-level interface. It is meant to be simple but powerful, while solving some of the most common pitfalls involved with player input in games.

In KeyActionBinder, it’s possible to evaluate your own arbitrary “actions” instead of specific keys or controls. On the game loop those actions can be check and processed. For actions that are not repeated, like a player jump, it’s possible to “consume” them via consumeAction(). This forces the player to activate the button again if they want to perform the action again.

Sample

binder = new KeyActionBinder(stage);

// keyboard binding
binder.addKeyboardActionBinding("move-left", Keyboard.LEFT);
binder.addKeyboardActionBinding("move-right", Keyboard.RIGHT);

/ gamepad binding
binder.addGamepadActionBinding("move-left", GamepadControls.WINDOWS_DPAD_LEFT);
binder.addGamepadActionBinding("move-right", GamepadControls.WINDOWS_DPAD_RIGHT);

// evaluating actions
if (binder.isActionActivated("move-left")) {
    // Move the player to the left...
    // Optional: consume action
    consumeAction("move-left");
} else if (binder.isActionActivated("move-right")) {
    // Move the player to the right...
}

// gamepad bindings (analog)
binder.addGamepadSensitiveActionBinding("run-speed", GamepadControls.WINDOWS_L2_SENSITIVE); // L2/LT
binder.addGamepadSensitiveActionBinding("axis-x", GamepadControls.WINDOWS_STICK_LEFT_X, NaN, -1, 1); // Any player, min value, max value
binder.addGamepadSensitiveActionBinding("axis-y", GamepadControls.WINDOWS_STICK_LEFT_Y, NaN, -1, 1);

// ... in the game loop
var runSpeed:Number = binder.getActionValue("run-speed"); // Value will be between 0 and 
var speedX:Number = binder.getActionValue("axis-x"); // Value will be between -1 and 1
var speedY:Number = binder.getActionValue("axis-y");
MIT
1 Comment

Burstly

ANE-Burstly is a native extension for Burstly SDK on iOS and Android. Using this extension it’s possible to programmatically show or hide banners, as well as interstitials. An interstitial can also be displayed, using a cache mechanism to reduce the waiting time for the player.

The extension also fires a set of events that are useful to monitor the status of an operation, such as when a show operation of an interstitials fails due to network connectivity.

Sample

// Initialize Burstly
Burstly.getInstance().init("MY_BURSTLY_APP_ID", "MY_BURSTLY_BANNER_ZONE_ID", "MY_BURSTLY_INTERSTITIAL_ZONE_ID");

// Show the banner
Burstly.getInstance().showBanner();

// Hide the banner
Burstly.getInstance().hideBanner();

// Check if an interstitial is pre-cached
Burstly.getInstance().isInterstitialPreCached();

// Cache the interstitial
Burstly.getInstance().cacheInterstitial();

// Show the interstitial
Burstly.getInstance().showInterstitial();
Apache 2.0
Comments Off on Burstly

In App Purchase

ANE-In-App-Purchase is a native extension for In-App Purchase integration on the iOS platform. The extension allows the application to check if in-app purchase payments are possible or have been disabled on the device, fetch product information, purchase a product, restore past non-consumable purchases and get all transactions in the transactions queue.

Transactions remain in the transaction queue until they are marked as finished. After handling a successful or failed purchase or restored transaction, the developer should remove it from the transaction queue by calling a method to finish the transaction.

Sample

if(InAppPurchase.isSupported && InAppPurchase.canMakePayments) {
  // Dispatches InAppPurchase.productInformationReceived and InAppPurchase.productInformationFailed
  InAppPurchase.fetchProductInformation(...productIds);
  // Dispatches InAppPurchase.transactionPurchased and InAppPurchase.transactionFailed 
  InAppPurchase.purchaseProduct("productId", quantity);
  InAppPurchase.finishTransaction(transactionId);
  // Dispatches InAppPurchase.transactionRestored with an IAPTransaction for each restored transaction.
  InAppPurchase.restorePurchases();
  // Get all transactions in the transactions queue, via array of IAPTransaction objects.
  var trans :Array = InAppPurchase.getCurrentTransactions();
}
BSD
1 Comment

Flurry Analytics

ANE-Flurry-Analytics is a native extension for Flurry analytics on the iOS and Android platforms. Flurry allows applications to measure audience reach, engagement, retention, conversions, revenue and more, all free of charge. The extension provides the application with the ability to track user actions during the usage session.

It’s possible to start and end a session, log a single event (or an event with parameters), a timed action or an error and much more. All the features of the Flurry api have been implemented.

Sample

public function game() :void {
  Flurry.startSession(flurryId);
  Flurry.logEvent("some event");
  Flurry.logEvent("another event", {
    size : Capabilities.screenResolutionX + " x " + Capabilities.screenResolutionY,
    dpi : Capabilities.screenDPI
  });
  Flurry.logError(errorId, errorName);
  Flurry.startTimedEvent("player did something");
  Flurry.endTimedEvent( "player did something");
  Flurry.endSession();
}
BSD
4 Comments

Social

Social-ANE is a native extension for sending messages to social networks on iOS. It uses the social functionality added in iOS6. The extension allows the application to send messages using Twitter, Facebook and sinaWeibo. It’s possible to individually test if a particular social network is supported.

A developer can programmatically set the message text, add URLs and images. At the end of the process, the developer can launch the iOS message view for the user to edit and send the message. The extension fires events after the message view was launched, allowing the application to monitor if the message was sent or not.

Sample

// Test if the extension is supported
if(Social.isSupported && Social.isAvailableForService(SocialService.twitter)) {
  var social : Social = new Social(SocialService.twitter);

  social.addEventListener( SocialEvent.CANCELLED, eventReceived);
  social.addEventListener( SocialEvent.COMPLETE, eventReceived);

  social.setMessage("A test message");
  social.addUrl("http://test.com/");
  var bmp :BitmapData = new BitmapData(200, 200);
  social.addImage(bmp);
  social.launch();
}

private function eventReceived( event : SocialEvent ) : void {
  trace( "\n " + event.type);
}
BSD
1 Comment

AS3WebSocket

AS3WebSocket is a WebSocket client implementation for the final WebSocket Draft RFC6455. The client only works with RFC6455 compliant servers, as a result it will not work with draft-75 or draft-76/-00 servers that are deployed on the internet.

Among its features is the wss:// TLS support with As3 Crypto library and the ability to send and receive fragmented messages. The library has two demos to test subprotocols from Andy Green’s libwebsockets test server, the dumb-increment-protocol and the lws-mirror-protocol.

Sample

var websocket:WebSocket = new WebSocket("wss://localhost:4321/foo?bing=baz", "*", "my-chat-protocol");
websocket.enableDeflateStream = true;
websocket.addEventListener(WebSocketEvent.CLOSED, handleWebSocketClosed);
websocket.addEventListener(WebSocketEvent.OPEN, handleWebSocketOpen);
websocket.addEventListener(WebSocketEvent.MESSAGE, handleWebSocketMessage);
websocket.addEventListener(WebSocketErrorEvent.CONNECTION_FAIL, handleConnectionFail);
websocket.connect();

function handleWebSocketOpen(event:WebSocketEvent):void {
  trace("Connected");
  websocket.sendUTF("Hello World!\n");

  var binaryData:ByteArray = new ByteArray();
  binaryData.writeUTF("Hello as Binary Message!");
  websocket.sendBytes(binaryData);
}

function handleWebSocketClosed(event:WebSocketEvent):void {
  trace("Disconnected");
}

private function handleConnectionFail(event:WebSocketErrorEvent):void {
  trace("Connection Failure: " + event.text);
}

function handleWebSocketMessage(event:WebSocketEvent):void {
  if (event.message.type === WebSocketMessage.TYPE_UTF8) {
    trace("Got message: " + event.message.utf8Data);
  }
  else if (event.message.type === WebSocketMessage.TYPE_BINARY) {
    trace("Got binary message of length " + event.message.binaryData.length);
  }
}
Apache 2.0
1 Comment

Flash-Animated-GIF-Library

Flash-Animated-GIF-Library is a fast and robust library for playing Animated GIFs. Its parser is quite strict, however, so if there is a GIF that works in the browser but not with this library it probably means the browser is being overly lenient with the corrupt image data.

The speed gains are achieved by specifically avoiding doing any pixel decoding at all and instead splitting and re-packaging each frame of the animation into its own freestanding gif file. The resulting single-frame GIF files are handled to Flash to decode the frame’s image data internally via the Loader class.

Sample

var player:GIFPlayer = new GIFPlayer();

gifContainer.addChild(player);
player.smoothing = false;

player.addEventListener(GIFPlayerEvent.COMPLETE, handleGifLoadComplete);
player.addEventListener(AsyncDecodeErrorEvent.ASYNC_DECODE_ERROR, handleAsyncDecodeErrorEvent);
player.addEventListener(GIFPlayerEvent.FRAME_RENDERED, handleFrameRendered);
player.loadBytes(file.data);

private function handleAsyncDecodeErrorEvent(event:AsyncDecodeErrorEvent):void {
	trace("GifPlayer: Async Decode Error Event: " + event.text);
}

private function handleGifLoadComplete(event:GIFPlayerEvent):void {
	trace("Gif load complete, adding to stage");
}

private function handleFrameRendered(event:GIFPlayerEvent):void {
	trace("Frame " + event.frameIndex + " rendred.");
}
Apache 2.0
3 Comments

RhinoAS3

RhinoAS3 is a port of Mozilla’s Rhino JavaScript interpreter. Rhino is an open-source implementation of JavaScript written entirely in Java and is typically embedded into Java applications to provide scripting to end users. This port allows developers to embed ActionScript3 code instead of Javascript.

The project has a working lexer, a parser, the AST (Abstract syntax tree) node classes and a debuging class to print the AST.

Mozilla Public 2.0
4 Comments

CrystalAtf

CrystalAtf is an optimized ATF and DDS converter based on the CrystalDXT library. It’s a command line tool that can be used to convert images from one type to another, quite useful for game development. The supported compression output formats are  DXT1, DXT5, RGB888 and RGBA8888, while the supported input formats are PSD (only in compatibility mode and with no transparency), PNG, BMP, JPG, JPE and JPEG.

The tool can also generate mipmaps and allows the processing of images in batch mode, combining different flags. It is extremely optimized, sometimes 24 times faster than known tools as png2atf.

Sample

// Converting wildcard (? - Any single character, * - 0 or more of any characters)
CrystalAtf.exe images / src /? Image *. *

// Specify the output file
CrystalAtf.exe somepicture.png -> atf/picture.atf

// Batch process
CrystalAtf.exe -dds-nomip picture1.jpeg-atf-rgb pictures / *. *-Mip-dxt1 pic999.psd
Free
Comments Off on CrystalAtf

VideoRoll

VideoRoll is a native extension for accessing saved videos. Using this extension it’s possible to display the video roll dialog and read information related to the video that has been selected by the user. The extension provides methods to read the video as a ByteArray stream, check its length, generate a thumbnail of any frame or the video itself (as BitmapData) and much more.

The extension can return a URL to a selected video location, set a custom label on the video roll screen, use the native iOS video trimmer, set a max length on a video and create multiple thumbnails from an array of times.

Sample

protected function showVideoRoll():void {
    var videoRoll:VideoRoll = VideoRoll.instance; // Acquire an instance
    videoRoll.addEventListener(VideoRollEvent.ON_VIDEO_SELECT, handleVideoSelect); // Dispatched on video select
    videoRoll.openVideoRoll(); // Open the video roll
}

private function handleVideoSelect(e:VideoRollEvent):void { // this will not return a thumbnail or video ByteArray
    e.videoUrl //Video URL
    e.videoLength //Video Length
    var f:File = new File(e.videoUrl); // The location is returned in the event
    var ba:ByteArray = new ByteArray(); // Create a ByteArray to load the video into
    var fs:FileStream = new FileStream();
    fs.open(f, FileMode.READ); 
    fs.readBytes(ba, 0, fs.bytesAvailable); // Read the video into the BA
    fs.close();
}
1 Comment

Some words about Flixel Community

During my working days at Decadium, I’ve used and coded several game engines. When I left the company and started playing as an indie game developer, I heard a lot about this Flash game engine called Flixel. It has to be good, so I gave it a shot.

Flixel was the very first open-source Flash game engine I used. I was amazed by its simplicity and power, not mentioning the huge community and the amount of documentation available. Adam ‘Atomic’ Saltsman built Flixel using several pieces of games he worked on; he did a hell of a job and I’m very grateful for that: thanks, Adam!

A few months ago I decided to invest more time to seriously learn Flixel, but I noticed it hasn’t received any updates within the last months. After a quick search I realized there was more people talking about that, so I got in touch with IQAndreas and moly and emailed Adam offering help to maintain Flixel.

Enters Flixel Community

Adam was extremely busy and, long story short, he kindly guided and motivated us to start a fork of Flixel. Adam himself encouraged us to grow a community version and maintain it to our heart’s content, even offering it as an alternative to Flixel. That was really cool!

Since that day, we started working on Flixel Community, a community driven version of Flixel. It’s been a lot of fun, we’ve crushed about 57 issues that were open on Flixel’s repo, received bug reports, contributions and attention from other Flixel users.

I must say it’s been an amazing experience! There are just a few issues currently open and we are heading to our very first community release.

Future plans

There are a lot of suggestions in the Flixel Community issue tracker. We plan to get on them as soon as we fix those last remaining bugs.

If you like Flixel as much as we do, please help us out! Even the smallest gesture can make the difference. You can help us test the current state of the development branch, report bugs, help us test pull requests or create your own changes to the engine and issue a pull request!

Stay tuned for more info on Flixel Community development!

Comments Off on Some words about Flixel Community

as3-msgpack

as3-msgpack is an implementation of MessagePack specification. MessagePack is an efficient binary serialization format, allowing applications to exchange data among multiple languages like JSON, but using a much faster and smaller representation. Small integers (like flags or error code), for instance, are encoded into a single byte.

Message pack specification was built to work mostly with primitive types. msgpack is similiar to JSON, but is based on binary data instead of text. The types available are: signed/unsigned integer, single/double precision floating point, nil (null), boolean, array, associative array (map) and raw buffer. These types are mapped to Actionscript3 as the following:

  • signed integer -> int
  • unsigned integer -> uint
  • single/double precision floating point -> Number
  • nil -> null
  • boolean -> Boolean
  • array -> Array
  • associative array -> Object
  • raw buffer -> String or ByteArray

Sample

// message pack object created
var msgpack:MsgPack = new MsgPack();

// encode an array
var bytes:ByteArray = msgpack.write([1, 2, 3, 4, 5]);

// rewind the buffer
bytes.position = 0;

// print the decoded object
trace(msgpack.read(bytes));
Apache 2.0
10 Comments

AIRControl

AIRControl is a native extension that allows the use of game controllers. The extension has the hability to read controller information such as the current value for any axis, POV hat switch, or a button status. It’s possible to listen to specific events, such as when a controller is attached or detached.

The extension has a list with all active controllers, each one indexed by an integer. Using the controller index number, a developer can read information from a specific controller. Every event fired by the extension (e.g. axis change) has the index of the source controller, so it’s possible to react accordingly.

Sample

/*
Copyright (C) 2012-2013 Alexander O'Mara alexomara.com

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.

2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.

3. This notice may not be removed or altered from any source
distribution.
*/

//Add the event listeners to detect controller attachment.
AIRControl.addEventListener(AIRControlEvent.CONTROLLER_ATTACH, controllerAttach);
AIRControl.addEventListener(AIRControlEvent.CONTROLLER_DETACH, controllerAttach);

private function controllerAttach(e:AIRControlEvent):void {
	//Fired on controller attach and detach.
	switch(e.type) {
		case AIRControlEvent.CONTROLLER_ATTACH:
			//Add event listeners for controller state changes.
			e.controller.addEventListener(AIRControlControllerEvent.AXIS_CHANGE, controllerEvent);
			e.controller.addEventListener(AIRControlControllerEvent.BUTTON_CHANGE, controllerEvent);
			e.controller.addEventListener(AIRControlControllerEvent.POV_CHANGE, controllerEvent);
			//Log the attach and a few key variables.
			trace("AIRControlEvent.CONTROLLER_ATTACH, controllerIndex=" + e.controllerIndex + ", controller.ID=" + e.controller.ID + ", controller.name=\"" + e.controller.name + "\"");
		break;
		case AIRControlEvent.CONTROLLER_DETACH:
			//Remove the event listeners.
			e.controller.removeEventListener(AIRControlControllerEvent.AXIS_CHANGE, controllerEvent);
			e.controller.removeEventListener(AIRControlControllerEvent.BUTTON_CHANGE, controllerEvent);
			e.controller.removeEventListener(AIRControlControllerEvent.POV_CHANGE, controllerEvent);
			//Log the detach and a few key variables.
			trace("AIRControlEvent.CONTROLLER_DETACH, controllerIndex=" + e.controllerIndex + ", controller.ID=" + e.controller.ID + ", controller.name=\"" + e.controller.name + "\"");
		break;
	}
}

private function controllerEvent(e:AIRControlControllerEvent):void {
	//Log information about what controller fired the event.
	switch(e.type) {
		case AIRControlControllerEvent.AXIS_CHANGE:
			trace("AIRControlControllerEvent.AXIS_CHANGE, controller.ID=" + e.controller.ID + ", controller.name=\"" + e.controller.name + "\", elementIndex=" + e.elementIndex + "\", element.position=" + e.element["position"]);
		break;
		case AIRControlControllerEvent.POV_CHANGE:
			trace("AIRControlControllerEvent.POV_CHANGE, controller.ID=" + e.controller.ID + ", controller.name=\"" + e.controller.name + "\", elementIndex=" + e.elementIndex + "\", element.X=" + e.element["X"] + ", element.Y=" + e.element["Y"]);
		break;
		case AIRControlControllerEvent.BUTTON_CHANGE:
			trace("AIRControlControllerEvent.BUTTON_CHANGE, controller.ID=" + e.controller.ID + ", controller.name=\"" + e.controller.name + "\", elementIndex=" + e.elementIndex + "\", element.down=" + e.element["down"]);
		break;
	}
}

private function enterFrame(e:Event):void {
	//Update the controller states.
	AIRControl.update();
	var text:String;
	var controller:AIRControlController;
	var i:uint;
	//Make sure the current controller index is not out of range.
	while(currentIndex && currentIndex > AIRControl.controllersTotal-1) {
		currentIndex--;
	}
	//Check if controllers are attached.
	if(AIRControl.controllersTotal) {
		//Get the controller at the specified index. NOTE: It is usually better to match controllers on attach/detach than requesting specific indexes.
		controller = AIRControl.controller(currentIndex);

		//Set the current controller header.
		currentControllerHeader.text = "Current Controller " + (currentIndex+1) + "/" + AIRControl.controllersTotal + ", index: " + currentIndex + "";

		//Get the details about the controller.
		text = "ID:\n\t" + controller.ID + 
			"\n\nname:\n\t" + controller.name + 
			"\n\nvendorID:\n\t" + controller.vendorID + 
			"\n\nproductID:\n\t" + controller.productID + 
			"\n\nAXIS_X:\n\t" + controller.AXIS_X + 
			"\n\nAXIS_Y:\n\t" + controller.AXIS_Y + 
			"\n\nAXIS_Z:\n\t" + controller.AXIS_Z + 
			"\n\nAXIS_R:\n\t" + controller.AXIS_R + 
			"\n\nAXIS_U:\n\t" + controller.AXIS_U + 
			"\n\nAXIS_V:\n\t" + controller.AXIS_V;

		//Loop over the axes.
		text += "\n\naxes (" + controller.axesTotal + "):";
		for(i = 0; i < controller.axesTotal; i++) {
			text += "\n\t" + controller.axis(i).position;
		}
		//Loop over the POV hat switches.
		text += "\n\npovs (" + controller.povsTotal + "):";
		for(i = 0; i < controller.povsTotal; i++) {
			text += "\n\tX: " + controller.pov(i).X + " \tY: " + controller.pov(i).Y;
		}
		//Loop over the buttons.
		text += "\n\nbuttons (" + controller.buttonsTotal + "):\n\t";
		for(i = 0; i < controller.buttonsTotal; i++) {
			text += controller.button(i).down ? "1" : "0";
		}
	}
}
zlib
1 Comment

MoPub

MoPub-ANE is a native extension to use the MoPub advertising platform on iOS and Android. The extension allows the developer to displaying banner adverts and interstitial adverts using a simple API. The banner loading process is asynchronous and can be monitored using events.

In order to display a banner, the application must load it first. When the loading is complete, an event is fired and the banner can be displayed. It’s possible to programatically close the ad at any time.

Sample

var banner : MoPubBanner = new MoPubBanner( yourAdUnitId, MoPubSize.banner );
banner.x = ( stage.fullScreenWidth - banner.width ) / 2;
banner.y = 0;
banner.addEventListener( MoPubEvent.LOADED, bannerReady );
banner.addEventListener( MoPubEvent.LOAD_FAILED, bannerFailed );
banner.load();

private function bannerReady( event : MoPubEvent ) : void {
    banner.show();
}
private function bannerFailed( event : MoPubEvent ) : void {
    banner = null;
}
BSD
1 Comment

SoundTouch

SoundTouch is a port of the SoundTouch sound processing library. The library allows real-time processing of audio in Flash 10. It includes filters that perform time compression/expansion and rate transposition. In tandem, these filters can perform pitch-shifting.

The original C++ library includes several features that have not yet been implemented in the port, including a FIR filter, which can be used to prevent aliasing during rate transposition.

Sample

var source:Sound = …;
var output:Sound = new Sound();

var soundTouch:SoundTouch = new SoundTouch();
soundTouch.pitchSemitones = -6;

var filter:SimpleFilter = new SimpleFilter(sound, soundTouch);
output.addEventListener(SampleDataEvent.SAMPLE_DATA, filter.handleSampleData);

output.play();
LGPL
2 Comments