easyWorker

easyWorker is a library to easily implement Workers. The main goal of the library is to lift the burden of creating another project and/or an extra SWF to use Workers, everything is in-memory. As a result developer don’t have to deal anymore with MessageChannel and other low level classes, just use the high level classes Thread an Events.

When using the Thread class, a developer must provide his own class that will run in as a the new worker. Before the thread creation, a few events can be listened to monitor the worker, such as if it has finished processing its task. The library is able to automatically register typed object to pass them back and forth the Worker.

Sample

public class ComplexWorker implements Runnable {
     // Mandatory declaration if you want your Worker be able to communicate.
     // This CrossThreadDispatcher is injected at runtime.
    public var dispatcher:CrossThreadDispatcher;

    public function run(args:Array):void {
        const values:TermsVo = args[0] as TermsVo;
        dispatcher.dispatchResult(add(values));
    }

    private function add(obj:TermsVo):Number {
        return obj.v1 + obj.v2;
    }
}

var _thread:IThread;

function startApp():void {
  _thread = new Thread(ComplexWorker, "nameOfMyThread");

  _thread.addEventListener(ThreadProgressEvent.PROGRESS, thread_progressHandler);
  _thread.addEventListener(ThreadResultEvent.RESULT, thread_resultHandler);
  _thread.addEventListener(ThreadFaultEvent.FAULT, thread_faultHandler);

  _thread.start(new TermsVo(1, 2));
}
Apache 2.0
6 Comments

as3delaunay

as3delaunay is a library to calculate Delaunay triangulation and Voronoi diagrams. Using this library, a developer can easily create, for instance, a Voronoi diagram based on a set of points. In addition to the Voronoi diagram and the Delaunay triangulation, the library also provides the convex hull, minimum and maximum spanning trees, and several other related geometric entities.

The library is based on Steven Fortune’s C implementation of his sweepline algorithm.

Sample

var voronoi:Voronoi;
var p0:Point, p1:Point, p2:Point;
var points:Vector;
var plotBounds:Rectangle;

points = new Vector([p0,p1,p2]);
plotBounds = new Rectangle(-20, -20, 40, 40);
voronoi = new Voronoi(points, null, plotBounds);
MIT
7 Comments

aseprite

Aseprite is a multi platform animated sprite editor and pixel art tool. Available for Windows, Mac OS X and Linux, the editor and its retro visual appeal provide artists and developers with a huge list of features. Sprites are composed by layers and frames (as separated concepts), which can be colored using RGBA, Indexed (palettes up to 256 colors), and Grayscale. It’s possible to lad/save sequence of PNG files and GIF animations (also FLC, FLI, JPG, BMP, PCX, TGA).

The editor has an option to export/import animations to/from Sprite Sheets, as well tiled drawing mode, useful to draw patterns and textures. There is the mini-editor with real-time animation preview, multiple editors support, pixel art specific tools like filled Contour and Polygon, and Onion skinning.

Aseprite

Commercial GPL2
Comments Off on aseprite

New plugin system in Flixel Community

The first implementation of the new plugin system has just landed in the dev branch of Flixel Community. Since it represents a big improvement and a lot of opportunities for future developers, I thought it would be a good idea to explain how the new system works.

The old plugin system was created to enhance Flixel’s features without the need of deeply changing the engine core code. An example is the FlxTimer plugin, created to help with timers and delayed function calls. The plugin API was very limited, forcing developers to tinker with Flixel code to achieve a more complex functionality. A plugin could use all data available in Flixel, but there was no easy way to know what was going on, e.g. be informed that the current game state was about to change.

That’s where the new plugin architecture comes in. The idea was simple: Flixel will dispatch messages related to important events, which can be anything from a state switch to a frame update. The approach we have chosen to implement this was signals. It’s easier to handle than events and it is lighter on the performance too. Here’s an example:

class Test extends FlxState {
  override public function create():void {
    // Subscribe to the preUpdate signal.
    FlxG.signals.preUpdate.add(myCallback);
  }

  public function myCallback():void {
    FlxG.log("Flixel is about to update the game state.");
  }
}

Developers can subscribe to signals using the FlxG.signals entry. In the example above, a class subscribes to the preUpdate signal, which will be dispatched by Flixel before every game update. The signals approach plays an important part in the new plugin system, because they abstract the engine code. A plugin developer doesn’t need to change any Flixel code anymore to be notified about something.

There are a few signals implemented already, but more will eventually be created as the need becomes more clear. Under the hood, it’s extremely easy to create and dispatch more signals. All we have to do is add an entry to FlxG.signals and, at the right place in Flixel code, dispatch the signal:

public function someFlixelMethod():void {
    // ...
    // Somewhere in the Flixel code, dispatch the signal
    FlxG.signals.preUpdate.dispatch();
    // ...
}

Flixel shipped with two built-in plugins, FlxTimer and DebugPathDisplay, which were based on the old system (with a few hacks in the Flixel core). Those plugins were already ported to the new architecture, which means they can be added or removed during runtime now :). While porting those two plugins, I decided to do the same with FlxReplay. As illustrated by the GIF below, this feature allows players to record a game session for later viewing:

flixel_replay

The code related to FlxReplay was deeply integrated in the Flixel core, but after some days of hard work, it was completely decoupled and moved to a plugin. Yay!

Some of the tasks on our TODO-list include the use of the new plugin system to implement more features that would not be part of a vanilla Flixel, but now they can be activated on demand by developers. That’s a huge gain for modularity and will help us keep things simple when adding more complex features.

Stay tuned for upcoming  features in the next release of Flixel Community!

development flixel flixel community gamedev
9 Comments

Spicelib Reflect

Spicelib Reflect is a reflection library to reflect on classes, methods and properties. The lib was created to improve the workflow required to parse the XML output from Flash’s describeType funcionality. The lib builds on top of the output generated by describeType and offers a convenient central cache so that XML parsing occurs only once for each class. There is a central repository to register Converter instances for any number of target types.

It’s also possible to use methods to reflectively set properties and invoke methods of instances while using the registered converters to automatically convert method parameters and property values if their type does not match the required type. A developer also has the option to register custom classes to represent metadata tags to offer a type-safe way to reflect on metadata tags and its attributes.

Sample

// Reflecting the flash.geo.Point class
var ci:ClassInfo = ClassInfo.forClass(Point);
var p:Property = ci.getProperty("x");
trace("type:     " + p.type.name); // Number
trace("readable: " + p.readable); // true
trace("writable: " + p.writable); // true

var point:Point = new Point(7, 5);
p.setValue(point, 12);
trace(point.x); // output: 12

var m:Method = ci.getMethod("add");
var params:Array = m.parameters;
trace("param count: " + params.length);
var param:Parameter = params[0] as Parameter;
trace("param type: " + param.type.name);
trace("param required: " + param.required);
trace("return type: " + m.returnType.name);

var result:Point = m.invoke(point, [new Point(3, 3)]);
trace(result.x); // output: 10
Apache 2.0
2 Comments

Worker from Class

Worker from Class is a small library to use create Workers from Class definitions. By the default, the Flash Worker’s API receives the content of a SWF file to create a new thread. The whole SWF file is seen as the code to be executed, which prevents a developer from choosing a specific class to run in the newly created thread. Some Worker’s management code must be added to the SWF to execute a specific class or method.

This lib abstracts all that process and allows a developer to create a new Worker based on a specific class. The lib handles the worker instantiation and ensures that the specified class will run in the thread instead of the whole SWF. The content of the SWF must still be provided, but this time the lib will inspect it look up the desired class. The SWF inspection is powered by as3swf.

Sample

package workers {
  import flash.display.Sprite;
  import flash.system.Worker;

  public class MyWorker extends Sprite {
    public function MyWorker() {
      super();
      trace("Hello from the Worker!");
      trace("isPrimordial: " + Worker.current.isPrimordial)
    }
  }
}

package {
  import flash.display.Sprite;
  import flash.system.Worker;

  import workers.MyWorker;

  public class WorkerFromClass extends Sprite {
    public function WorkerFromClass() {
      var worker:Worker = WorkerFactory.getWorkerFromClass(MyWorker, loaderInfo.bytes);
      worker.start();
    }
  }
}
Comments Off on Worker from Class

RectanglePacking

RectanglePacking is a utility class to pack smaller rectangles within larger container rectangle efficiently. Built is efficiency in mind, the algorithm can pack 500 rectangles in 1-2ms on a decent computer. The implementation uses the concept of “free rectangles” within the main rectangle. The packed rectangles are always placed in the top left corner of some free rectangle that they completely fit into.

Initially there is only one “free rectangle” that is the main rectangle itself. After packing the first rectangle, the original free rectangle is removed and zero to two new free ones are added. If the packed rectangle is as big as the container there are no more free rectangles. If the packed rectangle is as wide or as tall as the container there is one free rectangle either below or on the right side of it and if the packed rectangle is smaller there is one free rectangle below it and one on it’s right side. The library is especially useful when generating big textures containing many sub textures, which can be used to create a texture atlas, for instance.

Sample

var mScalingBox:ScalingBox = new ScalingBox(BOX_MARGIN, Y_MARGIN, WIDTH - (BOX_MARGIN*2), HEIGHT - (Y_MARGIN + (BOX_MARGIN*2)));
var mPacker:RectanglePacker = new RectanglePacker(mScalingBox.newBoxWidth, mScalingBox.newBoxHeight, padding);

var mRectangles:Vector. = new Vector.();
mRectangles.push(new Rectangle(0, 0, 20, 30));
mRectangles.push(new Rectangle(0, 0, 80, 90));

mPacker.insertRectangle(mRectangles[0].width, mRectangles[0].height, 0);
mPacker.insertRectangle(mRectangles[1].width, mRectangles[1].height, 1);

mPacker.packRectangles();
Comments Off on RectanglePacking

AStream

AStream is a XML to Object (and vice versa) mapping library. It was started as an attempt to implement an AS3 backend for Java XStream services. The library can handle primitive values, complex typed objects (with cycle- and corss-references), collections (arrays, vectors and all based on mx.collections.IList), implicit collections, classes based on IExternalizable and even enums (classes based on as3.lang.Enum in library).

The library is compatible with XStream.

Sample

import com.example.domain.User;
import com.example.domain.UserRole;

import flash.display.Sprite;

import ru.kokorin.astream.AStream;

public class Main extends Sprite {
    public function Main() {
        const aStream:AStream = new AStream();
        aStream.processMetadata(User);
        //or aStream.autodetectMetadata(true);

        const user:User = new User();
        user.id = 1;
        user.name = "Ivanov Ivan";
        user.role = UserRole.ADMINISTRATOR;

        const xml:XML = aStream.toXML(user);
        /* xml.toXMLString()
              <User>
                <id>1</id>
                <name>Ivanov Ivan</name>
                <role>ADMINISTRATOR</role>
              </User>            
          */

        const restoredUser:User = aStream.fromXML(xml) as User;
        /* restoredUser.toString()
        User{_name=Ivanov Ivan,id=1,role=ADMINISTRATOR} */
    }
}
Apache 2.0
11 Comments

In App Billing and Purchases

In-App Billing and Purchases is a native extension to purchase items from stores. Supported on more than one platform, the extension provides access to the Apple “InApp Purchases” and access to the Google Play “InApp Billing”. It’s possible to get a list of products, which will initialize the list of items available, retrieving information about the product such as: price, title, description etc.

The extension also allows a developer to restore purchases that a user may have previously made, dispatching the proper purchase events for the products. A purchase can be made by creating a new Purchase object and passing it to the extension. The only required information is the product ID, which must be one of the ID’s successfully retrieved through a call to get a list of products.

Sample

InAppBilling.init( DEV_KEY );
InAppBilling.service.setServiceType( InAppBillingServiceTypes.APPLE_INAPP_PURCHASE );
InAppBilling.service.addEventListener( InAppBillingEvent.SETUP_SUCCESS, setup_successHandler, false, 0, true );
InAppBilling.service.addEventListener( InAppBillingEvent.SETUP_FAILURE, setup_failureHandler, false, 0, true );
InAppBilling.service.setup( YOUR_SERVICE_ENCRYPTION_KEY );

InAppBilling.service.addEventListener( InAppBillingEvent.INVALID_PRODUCT, product_invalidHandler, false, 0, true );
InAppBilling.service.addEventListener( InAppBillingEvent.PRODUCTS_LOADED, products_loadedHandler, false, 0, true );
InAppBilling.service.addEventListener( InAppBillingEvent.PRODUCTS_FAILED, products_failedHandler, false, 0, true );
	 
InAppBilling.service.getProducts( [ "com.distriqt.test.exampleProduct" ] );

private function product_invalidHandler( event:InAppBillingEvent ) :void {
    trace( "invalid product:"+event.errorCode+":"+event.message );
}

private function products_loadedHandler( event:InAppBillingEvent ) :void {
    for each (var product:Product in event.data) {
        trace( "received:"+product.title+" price="+product.priceString );
    }

    // Retrieve any previously purchased products
    InAppBilling.service.restorePurchases();
}    
Commercial
Comments Off on In App Billing and Purchases

Camera Roll Extended

Camera Roll Extended is a native extension that provides a dialog where the user can select multiple assets from the device. Additionally it’s possible to use this extension to load the selected images from the device and use the loaded BitmapData objects the your application. It extends the functionality of the AIR built-in CameraRoll.

The API also provides a way to customize the appearance of the extension by changing the overlay for a selected image. A developer can also load the thumbnail or full resolution versions of images or auto load the images after user selection.

Sample

CameraRollExtended.init( DEV_KEY );
CameraRollExtended.service.addEventListener( CameraRollExtendedEvent.LOADED, cameraRoll_loadedHandler, false, 0, true );
     
var options:CameraRollExtendedBrowseOptions = new CameraRollExtendedBrowseOptions();
options.maximumCount = 2;
options.type = Asset.IMAGE;
options.autoLoadBitmapData = true;
options.autoLoadType = AssetRepresentation.THUMBNAIL;
     
CameraRollExtended.service.browseForImage( options );
     
private function cameraRoll_loadedHandler( event:CameraRollExtendedEvent ):void {
    // The selected images have been loaded
    for each (var asset:Asset in event.assets) {
        if (asset.bitmapData != null) {
            addChild( new Bitmap( asset.bitmapData ));
        }
   }
}
Commercial
Comments Off on Camera Roll Extended

Making a decent game: Madly Angry Cat

When I joined OneGameAMonth back in 2013 I had a few goals in mind: sharp my gamedev skills and learn how to constraint scope. For five months I worked and released five games, which is an awesome accomplishment for me. While I was working on those games, I had several ideas to make them better. Following the 1GAM spirit, I just skipped those ideas and focused on finishing a playable prototype. That worked, but it left a taste of incompleteness in my mouth.

After seeing the hard work of great indie gamedevs and their projects, I thought it would be a good idea to improve one of my games. All I have to do is pick one of my 1GAM entries and invest a significant amount of time and effort to turn that playable demo into a full and well-polished game. And that’s what I’m about to do.

Looking at the games I made, there is one in particular that I really like:

screenshot_0

Madly Andry Cat (MAC) was my first platformer game. I’m huge fan of that genre and, as expected, I had a lot of fun developing that game. Checking the stats at Kongregate, the game was played 960 times and had a 3.11/5 stars rating. It might be an extremely insignificant number for most developers, but not for me! MAC had a single level, was unbalanced and had just a fraction of what I have planned for it. Despite of all that, it still got a good rate and even a walk-through (!). That is AWESOME!

That’s why I have decided to spend part of my time working on MAC. I’m going to make it my very first published full game, with everything it deserves: decent gameplay/art, SFX, music, marketing, tech blog, etc. I will do it all just because I want a cool game to play. A game with everything I always wanted but I was not able to make by then.

Gameplay And Inspirations

I will use four of my favorite games as inspirations for MAC’s gameplay: Contra III (SNES), Megaman X (SNES), Metal Slug (arcade/PC) and Oddworld Abe’s Odyssey (PC).

Contra-III-4

MAC will have a fast paced gameplay, with moments of slow action and (soft) thinking. I will use as inspiration the shoot’em up mechanics from Contra III, the complex levels and weapons from Megaman X, the action and vehicle interaction from Metal Slug and the puzzles and multi-platform view from Abe’s Odyssey.

MAC will combine weapons with kung-fu, so the main character will be able to shoot everything as well as jump into the walls and kick/punch the bad guys. It will be enhanced by a robot “pet” that will aid the shooting and moving. I’m planning at least 12 different weapons, including a chainsaw, and several complex levels with boss and sub boss.

Plot

The game story is not finished yet, but it’s a bit crazy as is. At a certain year, the planet is stormed by zombies. Our hero (a cat) is the last cat on Earth and it is pissed off because the zombies ruined his comfortable life. At some point in the game, Earth is invaded by mech-aliens, which increases the number of enemy types (now the cat must fight the zombies and the space invaders).

Through all the game the player will face flesh-made zombies, mech-aliens and mech-made zombies. They will have different sizes, from little creatures to fill-the-whole-screen juggernauts. There will be plenty of things to shoot at and bring down.

Art

Everything will be 16-bit pixel art. I have no budged to spend on the game now, so all the art will be from OpenGameArt with enhancements by myself. I will try my best to create the assets I have in mind. Below is a visual reference I will follow:

cool-pixel-art-01_via_metinseven-com

Art by swedish pixel artist Junkboy – http://www.junkboy.se

Since I am a programmer with just a minimum of art background, I will probably spend countless hours tweaking assets to make them fit the visual appeal I’m targeting. That will be a fun challenge and an opportunity to learn more about pixel art.

Platform

The plan is to release the game as a OUYA exclusive. The reason is simple: I love the little Android console and I dreamed since I was a little kid about playing a game of my creation in the TV using a gamepad. Now I can make that come true.

ouya

If you liked the game, stay tuned for development updates with videos, screenshots and posts. Just to keep things in line, I’m planning to release the game somewhere by the end of this year. Wish me luck!

1gam gamedev OUYA
6 Comments

Scanner

Scanner is a native extension to create an interface using the camera to scan for codes such as QR Codes, bar codes and other such encoded information. It supports many popular symbologies (types of bar codes) including EAN-13/UPC-A, UPC-E, EAN-8, Code 128, Code 39, Interleaved 2 of 5 and QR Code. However the particular support will be determined by the underlying algorithm in use.

The extension uses the built in default camera for scanning. It works across iOS and Android with the same code.

Sample

Scanner.init( DEV_KEY );

if (Scanner.isSupported) {
    Scanner.service.addEventListener( ScannerEvent.CODE_FOUND, scanner_codeFoundHandler, false, 0, true );

    var options:ScannerOptions = new ScannerOptions();
    options.symbologies = [ Symbology.QRCODE ];
    options.singleResult = true;

    Scanner.service.startScan( options );
}

private function scanner_codeFoundHandler( event:ScannerEvent ):void {
    trace( "code found: " + event.data );
}
2 Comments

libtess2

libtess2 is a library for tessellation. It is the GLU libtess refactored and compiled to ActionScript 3 via Adobe CrossBridge. The usual Flash drawing API is based on vector graphics, which means that complex polygons can be rendered easily. All that is required is to inform the Flash player how the shape is and, under the hood, math curves and functions are used to achieve the desired result.

When working with the GPU, it’s not possible to easily draw complex polygons using curves and math functions, all information must be converted to triangles first. Since the GPU only understands triangles, in order to render a complex polygon (e.g. a a square with a role in the middle) a developer must put together a set of triangles to represent that. That process is know as tessellation. libtess2 is a library for tessellation. It is able to tessellate a complex polygon, returning an array of vertex data used to create the polygon.

Sample

var pathOuter:Vector. = Vector.([0, 0,   200, 0,  200, 200, 0, 200]);
var pathInner:Vector. = Vector.([50, 50, 150, 50, 150, 150, 50, 150]);

var t:Tesselator = new Tesselator();
t.newTess(1024 * 1024);
t.addContour(pathOuter, pathOuter.length / 2, 2);
t.addContour(pathInner, pathInner.length / 2, 2);
t.tesselate(Tesselator.WINDING_ODD, Tesselator.ELEMENT_TYPE_POLYGONS, 3, 2);
var vertices:Vector. = t.getVertices();
var vertexCount:int = t.getVertexCount();
var elements:Vector. = t.getElements();
var elementCount:int = t.getElementCount();
t.deleteTess();
MIT
7 Comments

LocalCacheLoader

LocalCacheLoader is a library to cache content (such as swf ,images , data file etc…) to the local file system. It is fully compatible with Loader, URLLoader and NetStream, being a very light weight adjustment to the browser cache functionality. When the application tries to fetch an asset or any other file, the library first checks locally for the file.

The consequence of using the lib for caching is that the communication with the server can be drastically reduced. The lib API is very similar to the native Flash loading classes as LoaderURLLoader and NetStream. The only difference is that a developer must instantiate the desired loader using the lib’s factory class. After this step, the loader will behave exactly like a native one.

Sample

// Setup cache Directory.
// Can be cached in the directory that you specify here .
LocalCacheSettings.WORKING_DIRECTORY = File.applicationDirectory;

// Please set the following: If AIR for Android, the AIR for iOS.
// LocalCacheSettings.WORKING_DIRECTORY = File.applicationStorageDirectory;

// Init Factory Class.
// Loader like normal will be used if you do not initialize the factory class .
NetClassFactory.initialize (LocalCacheLoader, LocalCacheURLLoader, LocalCacheNetStream);

/ Create Class.
// If true the second argument here , regardless of there without a cache that is stored in the local
// I will take the file from the Web always on .
_loader = NetClassFactory.createLoader (null, false);
 // I use normally after .
 _loader.contentLoaderInfo.addEventListener (Event.COMPLETE, _onComplete);
_loader.load (new URLRequest ("https://www.google.co.jp/images/srpr/logo11w.png"));
MIT
6 Comments

Application

Application is a native extension to access some additional application options that aren’t availble in the default AIR SDK. Using this extension a developer can make an application auto-start on boot, for instance. Among the available options are the ability to use additional display modes, change the iOS status bar styles (i.e. UIStatusBarStyle) for iOS7, control the System Navigation UI (in Android).

The extension also has an API to read the device unique Id, which is provided by several platforms.

Sample

var deviceID:String = Application.service.device.uniqueId( Device.VENDOR );
Application.init( DEV_KEY );
Application.service.setAutoStart(true);

if (!Application.service.isAutoStartEnabled()) {
    Application.service.setAutoStart(true);
}

Application.service.addEventListener( ApplicationEvent.UI_NAVIGATION_CHANGED, application_uiNavigationChangedHandler, false, 0, true );
Application.service.setDisplayMode( ApplicationDisplayModes.UI_NAVIGATION_HIDE );
     
private function application_uiNavigationChangedHandler( event:ApplicationEvent ):void {
    trace( event.type + "::" + event.option );
}
Commercial
6 Comments