Bluetooth

Bluetooth is a native extension to communicate using the Bluetooth interface on the device. It provides access to the Bluetooth interface, being able to power it on and off. It has the ability to scan for available devices and make the device discoverable by listening for connections.

It’s also possible to initiate a connection to another Bluetooth device. The extension allows an application to transmit any sort and amount of data as a ByteArray.

Sample

public function cancelScan():Boolean;
public function close(uuid:String, secure:Boolean = true):Boolean;
public function closeAll():Boolean;
public function connect(device:BluetoothDevice, uuid:String, secure:Boolean = true):Boolean;
public function disable():Boolean;
public function disconnect(device:BluetoothDevice, uuid:String):Boolean;
public function enable():Boolean;
public function enableWithUI():Boolean;
public function getPairedDevices():Vector;
public function getScanMode():String;
public function getState():String;
public function init(developerKey:String):void;
public function isDiscoverable():Boolean;
public function isEnabled():Boolean;
public function listen(uuid:String, secure:Boolean = true):Boolean;
public function readBytes(uuid:String):ByteArray;
public function setDeviceDiscoverable(discoverable:Boolean = true, seconds:int = 60):Boolean;
public function showSettings():Boolean;
public function startScan():Boolean;
public function writeBytes(uuid:String, data:ByteArray):Boolean;
Commercial
1 Comment

MicroPather

MicroPather is an AS3 port of Lee Thomason’s C++ A* solver.  The library focuses on being a path finding engine for video games but it is a generic A* solver. The main goals the library tries to meet are: an easy integration into games and other software, an easy to use and simple interface and performance (it has to be fast enough).

The library works by solving the path of a given object, which must implement the IGraph interface. That interface tells MicroPather how the map is organized, such as the cost of an edge. After it solves the path, the library returns a vector of points, each one representing a node of the route.

Sample

/*
Copyright (c) 2000-2005 Lee Thomason (www.grinninglizard.com)

Grinning Lizard Utilities.

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.
*/

package demo {

import micropather.IGraph;
import micropather.MicroPather;

public class Dungeon extends Sprite implements IGraph {

    private const MAPX:int = 30;
    private const MAPY:int = 10;
    private const gMap:String =
        "     |      |                |" +
        "     |      |----+    |      +" +
        "---+ +---DD-+      +--+--+    " +
        "   |                     +-- +" +
        "        +----+  +---+         " +
        "---+ +  D    D            |   " +
        "   | |  +----+    +----+  +--+" +
        "   D |            |    |      " +
        "   | +-------+  +-+    |--+   " +
        "---+                   |     +";

    private var children :Vector.;
    private var pather :MicroPather;

    public var playerX :int = 0;
    public var playerY :int = 0;

    public function init (e :Event) :void {
        pather = new MicroPather( this );
    }

    public function Index( x:int, y:int ):int {
        return y*MAPX + x;
    }

    public function Encode( x:int, y:int ):int {
        return y*MAPX+x;
    }

    public function Decode( s:Object ):Point {
        var state :int = int(s);
        var y:int = state / MAPX;
        var x:int = state - y*MAPX;
        return new Point( x, y );
    }

    public function onMouseMoveEvent(event:MouseEvent):void {
        var dx:Number = stage.stageWidth/MAPX;
        var dy:Number = stage.stageHeight/MAPY;
        var x:int = event.stageX / dx;
        var y:int = event.stageY / dy;
        var index:int = y*MAPX+x;

        var ct:ColorTransform = new ColorTransform();
        //ct.blueOffset = 100;
        //ct.redOffset = 100;
        ct.greenOffset = 100;
        if ( selected )
            selected.transform.colorTransform = new ColorTransform();
        children[index].transform.colorTransform = ct;
        selected = children[index];
    }

    public function onMouseClickEvent(event:MouseEvent):void {
        var x:int = // destination X;
        var y:int = // destination Y;
        var solution :Vector.<Object> = new Vector.<Object>();

        pather.solve( Encode( playerX, playerY ), Encode( x, y ), solution );

        for( var i:int=1; i= 0 && nx < MAPX && ny >= 0 && ny < MAPY ) {
            var index:int = ny*MAPX+nx;
            var c:String = gMap.charAt( index );

            if ( c == ' ' )
                return 1;
            else if ( c == 'D' )
                return 2;
        }
        return 0;
    }

    public function leastCostEstimate( stateStart:Object, stateEnd:Object ):Number {
        var d0:Point = Decode( stateStart );
        var d1:Point = Decode( stateEnd );
        var dx:int = d0.x - d1.x;
        var dy:int = d0.y - d1.y;

        return Math.sqrt( dx*dx + dy*dy );
    }

    public function adjacentCost( node:Object, states:Vector., costs:Vector. ):void {
        var dx:Array = [ 1, 1, 0, -1, -1, -1, 0, 1 ];
        var dy:Array = [ 0, 1, 1, 1, 0, -1, -1, -1 ];
        var cost:Array = [ 1.0, 1.41, 1.0, 1.41, 1.0, 1.41, 1.0, 1.41 ];

        var state:Point = Decode( node );

        for( var i:int=0; i<8; ++i ) {
            var nx:int = state.x + dx[i];
            var ny:int = state.y + dy[i];

            var pass:int = Passable( nx, ny );
            if ( pass > 0 ) {
                if ( pass == 1 || doorsOpen ) {
                    // Normal floor
                    states.push( Encode( nx, ny ) );
                    costs.push( cost[i] );
                }
            }
        }
    }
}

							
		
			
2 Comments

TorAS

TorAS is an ActionScript implementation of the Tor control and communication (SOCKS5) protocols. The library comes bundled with the binary Tor client which can be launched by an AIR application as an invisible background process — no extra installation or setup required. Once connected, TorAS gives developers unprecedented control and insight over their Tor network connection, as well as providing simplified access to the secure, anonymous communication channels for which Tor is famous.

The library has a number of default settings and pre-configurations intended to start the services automatically. While this will probably be sufficient for most developers, at least initially. It’s possible to gain additional low-level control by issuing direct commands to the Tor control and communication sockets.

Sample

import import flash.net.URLRequest;
import import flash.net.URLVariables;
import org.torproject.SOCKS5Tunnel;
import org.torproject.events.SOCKS5TunnelEvent;

var request:URLRequest=new URLRequest("http://www.myserver.com/");
var variables=new URLVariables();

variables.userName="Patrick";
variables.password="pass123";
request.data=variables;

var tunnel:SOCK5Tunnel = new SOCKS5Tunnel();
tunnel.addEventListener(SOCKS5TunnelEvent.ONHTTPRESPONSE, onSOCKSTunnelResponse);
tunnel.loadHTTP(request);       

function onSOCKSTunnelResponse(eventObj:SOCKS5TunnelEvent):void {
   trace ("Got response: ");
   trace (eventObj.httpResponse.body);
}
MIT
2 Comments

SMS

SMS is a native extension to use and manipulate SMS in Android devices. It has a huge set of features, including the ability to send SMS to another number,  get SMS information as id, address ( phoneNumber), body ( smsText ), type and date, as well as ways of updating SMS messages.

Using this extension, it’s possible to make SMS conversations, get an SMS information by unique ID, delete a SMS by unique ID, delete a conversation and its content by giving its unique number. Finally it can send & receive SMS information using some properties.

Sample

// initialize the extension
var _ex:SMS = new SMS();

// Call this method to get sms information 
_ex.addEventListener(SMSEvent.ALL_SMS, allSms); // When the sms information is ready we get them
_ex.allSms(); 

private function allSms(e:SMSEvent):void {
    var  _smsArray:Array = e.param;
}

// Call this method to make conversation 
var _conversationArray:Array = _ex.conversation(8);

// if you need only one SMS information you can use this method
var obj:Object = _ex.getDataById(1914);

// Call this method to send sms
var send:Boolean = _ex.sendSms("09999999999", "++++Hi SMS test", "15");

// Call this method to update sms information
 _ex.updateSms();
Commercial
Comments Off on SMS

Loading Dialog

Loading Dialog is a native extension to create and control loading dialogs on Android. Using the extension is possible to create the dialog and customize it to fit the application needs, such as decide if it is cancelable by the device back button or not.  It’s also possible to optionally create a BitmapData and send to the extension to show on the dialog.

The extension also has methods to create classic or progressive dialogs, as well as the ability to set the title, the message and the position of the dialog.

Sample

var _ex:Loading = new Loading();

// optionally set a listener to see when the dialog is closed!
_ex.addEventListener(LoadingEvent.DIALOG_CANCELED, onDialogClosed);

// check doc files to see how you can set the position of the dialog and even set a custom BitmapData!
_ex.showLoading("title", "loading message..."); 

// close the dialog when you don't need it with the following method
 _ex.hideLoading();

function onDialogClosed(e:LoadingEvent):void {
    trace("dialog closed");
}

// Progressive

// check doc files to see how you can set the position of the dialog and even set a custom BitmapData!
// in this example we have set 100 as the max value and 10 as the current value
_ex.showProgressiveLoading("title", "loading message...", 100, 10); 

// if you want to change the value, add value to the current value.
// This value will be added to the previuse value the new value will be 10 + 10 = 20
 _ex.updateProgressiveLoading(10);
Commercial
Comments Off on Loading Dialog

RateApp

RateApp is a native extension to help users rate an application. The extension prompts the user to rate the application after a period of time or after a specific number of launches. It is possible to set the value for how many days the extension has to wait until it is able to show the rating dialog box.

It’s also possible to set the value for how many launches until the rating dialog is displayed. The extension allows developers to adjust the rating parameters and texts, which results in a more engaging experience for the user.

Sample

import com.doitflash.air.extensions.rateApp.Rate;

var _ex:Rate = new Rate();

// NOTE: if Google Play was not installed on the user device, you
// can't set the Rating dialog box, to rate an app device needs to
// have access to Google Play... so just return
if (!_ex.isGooglePlayInstalled) return; 

// NOTE: if user has already rated then there's no need to continue
// and set Rate dialog box parameters anymore... he has already
// rated your app!
if (_ex.isAppRated) return; 

// ok, user has started your app and has not rated your app yet,
// set the needed parameters if this is the first time user has
// launched the app, then set the install date
if (_ex.numLaunch == 0) _ex.setInstallDate(); 
// add one time to the app launches number
_ex.raiseLaunchCount(); 

// after how many days you want to fire the dialog box?
_ex.daysToFireDialogBox = 3; 

// after how many launches you want to fire the dialog box?
_ex.launchesToFireDialogBox = 20;

// ok, this if statment won't happen until the date that the
// Rating dialog box should be fired and if the rating time has
// arrived, this if statement will happen again and again on
// app launches as far as user clicks "Ask Later" or doesn't
// rate your app...
if (!_ex.isAppRated && _ex.isRatingTime && _ex.askForRating) {
    _ex.setDialogBox("Rate Us!", "Did you enjoy our app? We really appreciate if you rate us", "Rate", "Ask Later", "Never Ask");
    _ex.showDialogBox();
}
Commercial
1 Comment

PackageManager

PackageManager is a native extension to access and manage apps on the device. It provides access to all the installed apps, along with the ability to install, uninstall and get any app icon. The extension can also launch a specific application programmatically.

The API has a rich set of features, including methods to get all the system apps, get all the user apps, get any app icons as BitmapData,  get apps names. It also has a set of different events, useful to check what is happening during the execution of a method.

Sample

var _ex:PackageManager = new PackageManager();

_ex.addEventListener(PackageManagerEvent.ERROR_APP_ICON, onExTrigger);
_ex.addEventListener(PackageManagerEvent.ERROR_APP_INFO, onExTrigger);
_ex.addEventListener(PackageManagerEvent.ERROR_APP_INSTALLING, onExTrigger);
_ex.addEventListener(PackageManagerEvent.ERROR_APP_RUN, onExTrigger);
_ex.addEventListener(PackageManagerEvent.ERROR_APP_UNINSTALLING, onExTrigger);
_ex.addEventListener(PackageManagerEvent.STATUS, onExTrigger);
_ex.addEventListener(PackageManagerEvent.SUCCESS_APP_RUN, onExTrigger);

// returns an Array which contains all of the installed system apps package names on your device
var systemAppsArr:Array = _ex.getSystemApps(); 
// returns an Array which contains all of the installed user apps package names on your device
var userAppsArr:Array = _ex.getUserApps(); 

// put a specific installed app package name into the function to get its icon BitmapData
var icBmd:BitmapData = _ex.getAppIcon("air.air.com.doitflash.exPackageManager"); 
var ic:Bitmap = new Bitmap(icBmd);
this.addChild(ic);

// put a specific installed app package name into the function to get its name
var appName:String = _ex.getAppName("air.air.com.doitflash.exPackageManager")); 

// call to install a specific app
_ex.installApp("air.com.ilikedroid.tunneler");
// call to uninstall a specific app
_ex.uninstallApp("air.air.com.doitflash.exPackageManager"); 
// call to run a specific app
_ex.runApp("air.air.com.doitflash.exPackageManager"); 

private function onExTrigger(e:PackageManagerEvent):void {
    trace("Extension triggers the following >> ", e.param);
    trace("Event type >> ", e.type);
}
Commercial
1 Comment

File Browser

File Browser is a native extension that allows applications to browse the SDcard folder on Android devices. It lets the user pick one or more files using a dialog window listing all files inside the SDcard folder. After the user touches the screen to pick a files, some events are fired so the application can check what is happening.

The extension can be customized to allow single or multi-selection of files. If the user touches a file that is not selected, a “selected” event is fired. If the file was already selected, a “canceled” event is fired. It’s possible to exclude hidden files (or not) in the listing dialog. The application receives the path of the file when it is selected.

The listing dialog also has preview icons (for popular files) and allows search of files and folders.

Sample

import com.doitflash.air.extensions.fileBrowse.FileBrowser;
import com.doitflash.air.extensions.fileBrowse.BrowseEvent;

var _ex:FileBrowser = new FileBrowser();
_ex.addEventListener(BrowseEvent.FILE_SELECT, onFileSelected);
_ex.addEventListener(BrowseEvent.SELECT_CANCELED, onBrowseCanceled);
_ex.showHiddenFiles = false;
_ex.labels = ["SELECT", "CANCEL"];
_ex.mode = FileBrowser.MULTIPLE;

// path to the root of your sdcard
_ex.open(File.documentsDirectory.resolvePath(""));

function onBrowseCanceled(e:BrowseEvent):void {
    trace("Browsing canceled")
}

function onFileSelected(e:BrowseEvent):void {
    for (var i:int = 0; i < e.param.length; i++) {
        trace(e.param[i])
    }
}
Commercial
4 Comments

Share

Share is a native extension that allows application to share data using whatever sharing apps are available on the user’s device. It’s possible to use general sharing methods such as shareMessage() or shareFile() that automatically searches for the available sharing apps installed on user’s device.  The result is displayed to the user in a dialog box.

If the application requires a more specific sharing method, there are plenty of pre-defined methods available to be invoked, allowing the application to share data via email, Facebook, Twitter, Google+, YouTube, Browser, SMS and MMS.

Sample

_ex = new Share();

_ex.addEventListener(ShareEvent.RETURNED_TO_APP, onReturn);
_ex.addEventListener(ShareEvent.ERROR, onError); 

var userAccountArr:Array = _ex.emailAccounts; 
var sharingAppsArr:Array = _ex.supportedSharingApps; 

trace(_ex.isSimcardAvailable); 
trace(_ex.isNetworkAvailable);

trace(_ex.checkFileExist("exShareBtn_assets/myappsnippet.jpg"));

_ex.shareMessage("Dialog Title", "Message Title", "Message body");
_ex.shareFile("Dialog Title", ["exShareBtn_assets/party.mp4", "exShareBtn_assets/myappsnippet.jpg"]);

// ... and more and specific ways to share files or message:
// shareViaGmail, shareViaFacebook, shareViaTwitter,
// shareViaGooglePlus, shareViaYoutube, shareViaBrowser,
// shareViaMMS, shareViaSMS
Commercial
6 Comments

DConsole

DConsole is a box of utilities for interacting with Flash application at run time, primarily taking the form of an output textfield and an input textfield. The output field doubles as a trace window, and is the source of feedback. The input field is how the interaction is made. The developer types in commands, built-in or custom, which take place and show some effect.

It works by sitting on top of the application, crawling objects, their properties and children, and allowing changes in their variable values, call methods and so forth. It also allows the use of plugins, that can go from simple collections of utility commands, to custom level editors or whatever else needed.

Sample

addChild(DConsole.view);

function getUserByName(name:String):UserData{
    ...
    return foundUser;
}
DConsole.createCommand("getUser",getUserByName);

// These commands can then be invoked from the commandline
// to execute their functionality and print their returned results.
>> getUser John User
<< [object UserData]
Comments Off on DConsole

Oni

Oni is a fast and scalable game engine built for top quality games that run across a variety of platforms. Games made with the engine can be played on such as: iPads, iPhones, Android tablets/phones, OUYA, native Mac/Linux/Windows and the web. Oni is built from the ground up to support console/desktop quality 2D games.

Combining standard game engine practices and techniques from lower level game engines, hardware acceleration powered by Starling, shaders, physics by Nape the engine aims to push the boundaries of Flash/AIR gaming. Among its features are Smart textures, 2D lighting system, weather system, post processing effects and automatic support for lower-end devices.

Sample

package  
{
	import oni.Oni;
	import oni.utils.Backend;
	import oni.utils.Platform;
	import flash.desktop.NativeApplication;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.geom.Rectangle;
	import starling.core.Starling;
	import starling.utils.RectangleUtil;
	import starling.utils.ScaleMode;

	/**
	 * Main startup class, you should extend this and set that class to your document if you don't know what you're doing.
	 * @author Sam Hellawell
	 */
	public class Main extends Sprite
	{
		/**
		 * The starling instance
		 */
		private var _starling:Starling;

		/**
		 * Initialiser
		 */
		public function Main() 
		{
			//Setup the stage
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;

			//Setup starling
			Starling.multitouchEnabled = true;
			Starling.handleLostContext = Platform.isAndroid();

			//Get the stage dimensions
			var stageWidth:int = stage.stageWidth;
			var stageHeight:int = stage.stageHeight;

			//Check if mobile and set screen dimensions
			if (Platform.isMobile()) {
				stageWidth = stage.fullScreenWidth;
				stageHeight = stage.fullScreenHeight;
			}

			//Check if we're an iPad, if so, set minimum stage dimensions
			if (stageWidth == 1024 || stageWidth == 2048) {
				Platform.STAGE_WIDTH = 1024;
				Platform.STAGE_HEIGHT = 768;
			}

			//Set viewport
			var viewport:Rectangle = RectangleUtil.fit(new Rectangle(0, 0, Platform.STAGE_WIDTH, Platform.STAGE_HEIGHT), new Rectangle(0, 0, stageWidth, stageHeight), ScaleMode.SHOW_ALL);

			//Create instance
			_starling = new Starling(Oni, stage, viewport);
			_starling.antiAliasing = 1;
			_starling.simulateMultitouch = false;
			_starling.showStats = Platform.debugEnabled;
			_starling.enableErrorChecking = Platform.debugEnabled;
			_starling.stage.stageWidth  = Platform.STAGE_WIDTH;
			_starling.stage.stageHeight = Platform.STAGE_HEIGHT;

			//test
			_starling.showStats = true;

			//Start!
			_starling.start();

			//Listen for application activate
			NativeApplication.nativeApplication.addEventListener(
			Event.ACTIVATE, function (e:*):void { _starling.start(); });

			//Listen for application deactivate
			NativeApplication.nativeApplication.addEventListener(
			Event.DEACTIVATE, function (e:*):void { _starling.stop(true); });
		}
	}	
}
MIT
12 Comments

vec2

vec2 is 2D math vector class. It supports many operations such as dot and cross product, rotation, tests for proximity, find orthogonal vectors, clamping, interpolation and more. The API calls can be chained which allows the creation of complex operation with a single line of code.

Besides the usual vector operations the class also has some useful ones for game development e.g. perpendicular rotation to the left/right. The class is a slightly reworked version of the original work made by playchilla.

Sample

var v1:Vec2 = new Vec2;
trace(v1.isZero());

// add sub mul div
v1.addSelf(new Vec2(1, 2)).subSelf(new Vec2(3, 4)).mulSelf(new Vec2(2, -3)).divSelf(new Vec2(2, 3));
v1 = new Vec2().addXY(1, 2).subXY(3, 4).mulXY(2, -3).divXY(2, 3);

// length and angle setters
v1.setXY(1, 1);
v1.length = 4;
v1.angle = Math.PI / 2;

// scale
v1.setXY(1, 2).scaleSelf(3);
v1.setXY(1, 2).scale(3)

// normalize
v1.setXY(10, 0).normalizeSelf();
v1.setXY(0, 10).normalize(5);
Comments Off on vec2

Game Dissection #001: Numbers Toys

Editor’s note: this is a guest post by game developer Roberto Peña. It is part of a series called Game Dissection, which aims to inspire and enlight game developers by showing how a game was made.

Game Dissection #001 - Numbers Toys

Numbers Toys is a jigsaw puzzles game mainly oriented for little kids (2-5 years old), with several different types of puzzles and with an increasing difficulty to invite playing children of all ages as well as mums and dads.

I decided to use the numbers (from number 1 to number 9) as an educational context, showing them as cartoon characters and putting them at the center of the jigsaw puzzles.

Development team: Roberto Peña (ImaGame)

Numbers Toys on Google Play

Numbers Toys on App Store

Development objective

The main objective from a development standpoint was to include in the app different variations of a conventional jigsaw puzzle, taking advantage of Object Oriented programming (OOP) techniques and the implementation of OO Design patterns. Abstraction, inheritance, polymorphic features between others, have been used to make three different kinds of puzzles in a first app version. The app would be ready to be extended with new types of puzzles for upcoming versions in a easy and costless way.

Numbers Toys version 1 contains 3 different kind of jigsaw puzzles, applied to each number (1 from 9), having 27 distinct puzzles. Difficulty level increases as you build the puzzles and complete levels, adding an additional variation factor to all the puzzles.

The 3 different types of puzzle games have internally lot of code in common. From an external point of view they are different kind of game. The 3 types of puzzles are explained below.


Puzzle Type 1

The goal in Puzzle Type 1 is to discover the silhouette of the Number which is hidden under colored squares:

numbers_toys_puzzle_type_1

The gameplay mechanics consist of removing colored squares when tapping on them, but only when the right color is selected:

  • The square will be removed only if its color is the same as the selected color indicator.
  • Each color indicator is active for a limited period of time
  • Color Indicators get active in a non sequential order
  • If you tap on an colored square different than the active indicator, removed squares will reappear. The number of squares that will reappear depends on the difficulty level.
  • The number of colors is different in each Number puzzle.
  • Duration of the selected colors varies depending on the difficulty level

As a result all the colored squares have been removed and the hidden silhouette of the numbers has become visible. Then Puzzle Type 2 is unlocked to continue playing.


Puzzle Type 2

The goal in Puzzle Type-2 is to put together the colored pieces that form the Number character, filling the silhouette of the number discovered in Puzzle Type 1.

numbers_toys_puzzle_type_2

The gameplay mechanics consist of drag-dropping each piece in the correct place matching the silhouette of the number:

  • Pieces initially appear on both sides of the number, in different starting positions.
  • Number of pieces depends on the difficulty level
  • Precision required to drop the piece in the correct place depends on the difficulty level
  • Pieces dropped in wrong puzzle positions automatically go back to their starting position

As a result all the pieces put together correctly aligned on the silhouette form the colored number. Eyes and mouth will appear on it, giving to the number its own personality. Then Puzzle Type 3 is unlocked to continue playing.


Puzzle Type 3

The Goal in Puzzle Type 3 is to put the shapes into the matching areas that have been dynamically created on top of the board, covering the number character image.

numbers_toys_puzzle_type_3

The gameplay mechanics consist of drag-dropping each shape (piece) in the correct place within the corresponding area.

  • Areas to be matched can correspond to only one shape, or to a group of several connected shapes (till 9 pieces).
  • Shapes and positions are different in each puzzle game
  • Basic shapes (star, cross, heart, hexagon,…) can be drag into the matching area in a easy way, but group of connected pieces are difficult to solve.
  • The number of shapes depends on the difficulty level.
  • Shapes can be drag an drop in any position. If the are dropped within the correct area and in the right position, the will merge with the board image.

As a result all the shapes connected together and located in its matching areas let the complete number image be visible.

Development Details

Game Engine

The game uses my own engine. It is basically a framework or set of related classes that forms the base of a game. The framework consist of the minimum required set of classes that were needed to build Number Toys. It has been evolving as the same pace as the game has been built.

Any required functionality that was required in the game has been abstracted and a generic class has been incorporated in the framework, thinking in using it in future games. Son many new features can be added to the framework, as well as the existing ones can be extended.

The key is that all of them can be directly reused for upcoming games. The main groups of classes are the following:

numbers_toys_diagram_1


Rendering

The app is designed to behave the same way when it runs on a device with a different screen size, aspect ratio, or pixel density. The rendering engine is not a blitting engine, instead it leverages the Flash display list. The key is all the object display list is contained in a unique sprite that behaves as the screen canvas.

The baseline size of this screen canvas is 480×320 pixels. It is scaled to fit the device resolution. It forces that all the display list objects are automatically scaled. Horizontal or vertical margins (depending on screen aspect ratio) are automatically filled by the engine, and the game use it as an active part of the app.

The developer is responsible for ensuring the main game activity is going to happen in the 480×320 subscreen resolution.

numbers_toys_diagram_3

numbers_toys_diagram_4


Game Sprites And Animations

Due to the rendering system there is only one unique graphics set (same graphics resources for all sizes and densities) which is scaled in an proportional factor in both dimensions.

All the graphics used are bitmaps (no vector grahics). No movieclips are used, only sprites (flash.display.Sprite). All game sprites extend from ImaSprite (static graphics) or ImaSpriteAnim (frame based animation sprites). ImaSprites add a finite state machine behavior to the sprite.


Input

All input event listeners are concentrated in ImaState engine class. The ones that are going to be used are overriden in each game state subclass, which are in charge of detecting the imaSprite object that is affected by the input interaction (mouse, touch), sending the corresponding messages to it to manage the operation.


Sound

Default flash media sound methods. MP3 sfx assets are prepared in a in-memory dictionary.


Data And Assets

Default graphics and sounds assets are embedded in compile time in the executable. Same for other specific game resources. No system to dynamically load from local or remote files has been required.


Control And Elements Interaction

A simple game loop controls the game, updating only the active game state. Additionally calls the Timer manager to update its list of timers. No advance features to dynamically vary duration of cycles or vary time frequency.

Each game state has its update method to perform required execution logic. ImaState update state executes update method in all ImaSprites objects it contains (all UI objects and game sprites extend from ImaSprite, which can override, redefine or extend default update execution).

Interaction between game objects is accomplished using two different techniques:

  • FSM based: The finite state machine logic move from one state to another based in specific logic conditions. Each states has defined its own behaviour.
  • Signal based: Subscribing/dispatching message model used to send a message from an object when an specific event raises. Subscribed objects have it own answer logic defined.

The decision to use one or another interaction technique is based on different factors.


Configuration

Use of SharedObjects to save game progress, and configuration state. No remote save/load logic is implemented.

Technical information – Tools and Libraries


Third-party Libraries:

  • TweenLite v11 (Greensock.com)
  • Tweening engine. Standard version, using the following plugins: TintPlugin, AutoAlphaPlugin.
  • As3-Signals by Robert Penner
  • Messaging tool for communication and interaction between objects

Graphics

  • Gimp 2.8.6, Photoshop CS4
  • Graphics formats: jpg (background), png (sprites, panels, dialogs, buttons, character numbers, pieces).

All graphics done by me.


Sound

  • Free sound effects, in mp3 format.
dissection game dissection gamedev
5 Comments

New series: Game Dissection

Game Dissection SeriesRight after I became a (professional) game developer, I noticed some strange thoughts in my head while I was playing any game. Instead of simply enjoying the game, I keep on thinking how something was done. “Did they use a graph to control the movement of that monster?” or “How many states does this FSM have?” are some of the questions that pop up.

Sometimes I see a great game, full of cool features and breath-taking art, and I wonder that it could only be made by an army of developers. Later on while reading the credits I discover that a single person made all that! He used free assets/sfx, a lot of passion and dedication. It inspires me to see a great game made by a small team, or a single person, it’s like a reminder saying “See? You could do that too, it’s not impossible!”.

Thinking about that, the how things are made and that it is possible to make them, I’m kicking off a new series of posts called Game Dissection. This series aim to motivate and enlight game developers by showing how a game was made. I will try to reach as many developers as I can, asking for development info, such as game engine, IDE, techniques, mechanics and so on.

I hope this series will help game developers realize that a great game can be made under hard circumstances, such as when you don’t have an art team or have a very low (or non-existent) budget. If you know of a game made by an “approachable” developer, just let me know! It can be my next game dissection subject.

In order to illustrate the dissections, I will use the awesome art by Mads Peitersen (http://madspeitersen.com/). He gently allowed me to use his images in the series and I’m extremely thankful for that. Thanks, Mads!

Let the dissections begin! Stay tuned!

 

dissection game dissection gamedev
8 Comments

Can Open URL

ANE-Can-Open-URL is a native extension for iOS to detect whether an app is installed to handle a specific URL scheme. The extension has a single command that checks for a URL handler, so an application can accurately decide is the current device has the proper software to open a URL, such as a YouTube video.

Since the extension rely on the URL scheme, it’s easy to test several different services. In order to test if the device can open an iTunes URL, for instance, the URL scheme is itms-apps://, or Twitter (twitter://) or Facebook (fb://).

Sample

// Test iTunes
if( CanOpenUrl.canOpen("itms-apps://itunes.apple.com/app/stick-cricket/id406781620?ls=1&mt=8")) {
}

// Test Twitter
if( CanOpenUrl.canOpen("twitter://user?screen_name=sticksports")) {
}

// Test Facebook
if( CanOpenUrl.canOpen("fb://page/6340028662")) {
}
BSD
3 Comments