The majority of the art assets for the game are contained within the Flash .FLA files, including the levels, the entities, and UI, and the majority of the game’s animations. Starforce Battlement primarily uses Bitmap art because the models for the units and towers were done in 3D for convenience.
A subset of the game’s art, primarily icons used in the UI, is external to the FLA files. These external images are loaded at runtime via ActionScript.
Starforce Battlement consists of three distinct FLA files:
The logic for Starforce Battlement’s gameplay and UI is written entirely in ActionScript 3. This makes gameplay code highly portable, since there is no device specific implementation inherent to Starforce other than the iOS Game Center integration.
Entry Point
The entry point for the game is the StarforceTD.as class, which is tied to StarforceTD.swf using the Flash Document Class property. More information on Document Classes can be found online at Adobe’s Flash documentation.
Game States
The game is broken up into three ‘GameStates’, each representative of a different state that the game may be in. Only one GameState is active at a time and the active GameState is owned and managed by the StarforceTD class. The three game states are as follows:
The constructor for StarforceTD initializes the subsystems (data, sound, multi-touch) and loads the main menu which is defined by StarforceMenu.swf and MainMenuView.as.
Main Menu Implementation
The main menu is primarily implemented in the com.scaleform.std.menu package (see below for more information on packages). The main menu is built on an event-driven architecture where events are passed between the various main menu views using ActionScript 3’s native event system. As the user makes selections, events are dispatched and processed to open and close windows, read data, and/or transition to entirely new states (e.g. launching a mission).
When a mission is launched, a GameEvent is dispatched from the main menu. The StarforceTD.as class listens for this event and transitions to the level immediately by loading the LoadingGameState, unloading the MenuGameState, and loading the LevelGameState. The LevelGameState loads the selected level and begins the game as soon as the level as completed loading.
Note that a LoadingGameState is actually unnecessary from a technical point of view because the level content that will be drawn is already loaded in memory within StarforceTD.swf. However, the LoadingGameState transition is used here to hide the initialization of the Level and the HUD from the user and make for a smoother transition into gameplay.
Gameplay Implementation
Level.as is at the core of the game’s implementation. This class serves as the base class for all of the game’s levels. The Level.as class initializes and manages almost all of the elements that make-up the game including the level, the HUD, enemies, towers, and user abilities. Level is the base class for all of the levels. Each level has its own subclass which defines the enemies and may override other behaviors and variables to make the level more unique (e.g. default amount of gold, time between waves, enemy types, number of waves, etc…).
The Level is responsible for the creation, destruction, and management of all entities. Generally, the entities in the game are the towers and the enemies. All entities are ticked by the level, which causes them to update (i.e. move across the map, search for enemies, attack, etc…).
Flash Professional makes it easy to bind an ActionScript class to Symbol, which is comprised of graphics, animations, and ActionScript. These symbols can then be referenced and instantiated at runtime via ActionScript. This is the method Starforce Battlement uses for instantiation of almost all graphical content in the game and menu system. More information on binding Symbols to ActionScript and creating instances at runtime can be found in Adobe’s Flash documentation.
For example, the TowerMech Symbol can be found in the Flash Library for StarforceTD.fla. In the properties for the TowerMech symbol, note that the symbol is bound to the com.scaleform.std.entities.TowerMech ActionScript class. Whenever this class is instantiated via ActionScript, an instance of this graphic Symbol will be created and can then be manipulated via code.
The Level.as class manages the game using an event-driven framework. The class listens for events that will be dispatched from entities, the user interface, or any one of the other system frameworks (sound, data, achievements) and updates the game and HUD accordingly. For example, when a Tower attacks a unit, rather than directly modifying the health of the unit it is attacking, the Tower dispatches an AttackEvent. The Level, listening for AttackEvents globally, receives the AttackEvent, processes the attacker and defender, calculates the amount of damage that the defender should receive, and applies that damage to the defender.
Most interoperability between game entities passes through the Level as a means of abstracting the various classes from one another and including data outside the scope of the entities in calculations (e.g. the player’s technology tree, which may affect the amount of damage the defender takes in some cases). This design pattern also makes many game-wide changes easier to because it removes redundant code and keeps entity classes independent of one another.
Game Data
The majority of the data for the game, including statistics for all of the towers, missions, abilities, and enemies, is defined in the com.scaleform.std.data package. This data is accessed throughout the implementation using the GameData static class. This allows the GameData class to make modifications to the data before returning it to the requesting class in the case that an external variable is currently affecting it (for example, a player’s technology tree may change the standard attack damage of a tower).
Ideally, the default data for the game would not be stored within ActionScript but rather some external data definition format like XML or JSON and then loaded at runtime. Unfortunately, XML was unsupported in Scaleform 4.0 and therefore the quickest workaround was to store the data within class definitions. This may be updated in a future release to reflect best-practices.
Input Handling
Input for the game is scripted using ActionScript event listeners. This allows input logic to function cross-platform as the Scaleform Player will abstract the mouse/touch input across platforms and pass it to ActionScript appropriately.
The game listens for either mouse or touch input depending on whether the native Scaleform application currently supports touch input. Assuming FxPlayer has been setup correctly, the application will discern whether touch is supported at runtime based on whether a MultitouchInputState is installed on the MovieView and whether the proper operating system functions related to touch are available.
All interactive elements in Starforce have logic for both TouchEvents and MouseEvents, although only one set of listeners is actively used based on the application settings. The types for TouchEvents and MouseEvents are different, although many TouchEvent types have very similar MouseEvent types and vice versa. For example, a TouchEvent.TOUCH_TAP can be used like a MouseEvent.MOUSE_CLICK and a TouchEvent.PRESS can be used like a MouseEvent.MOUSE_DOWN.
To use a single function declaration as a listener for both TouchEvents and MouseEvents, the parameter of the function must be of type Event. If further information is required from the event, like the target or the coordinates of the input event, the event must be cast to the proper. One standard method for discerning the type at runtime is the “is” operator, shown below:
protected function onSetRallyClick( e:Event ):void { var point:Point; if (e is MouseEvent) { var me:MouseEvent = e as MouseEvent; point = new Point( me.stageX, me.stageY ); } else { var te:TouchEvent = e as TouchEvent; point = new Point( te.stageX, te.stageY ); } }
The ActionScript code for the game is divided into ActionScript ‘packages’ based on the functionality and/or purpose of the classes it contains.
All of the following packages are prefixed by “com.scaleform.std”:
Save/Load Framework
The save and load framework, defined in com.scaleform.std.system.SaveSystem.as, is a sample implementation for writing to and reading data from disk. Although the code used to store the player’s progress is simplistic, it is provided as a basis for a more complex implementation.
The ActionScript interface for this functionality leverages the SharedObject class. SharedObject is a standard ActionScript 3 class that allows developers to store and retrieve data from an ActionScript Object on disk. Scaleform’s implementation of the SharedObject class supports primitive types and Arrays.
Each SharedObject is defined by a unique string identifier used for reading and writing at runtime. In the code below, the SharedObject’s unique string identifier is “sb_player_data”.
// Local reference to the galaxy progress. Populated from the PlayerData. public static var galaxyProgress:Array = null; // Constant String for the property of the SharedObject we'll modify. protected static const GALAXY_PROGRESS_SO_PROP:String = "galaxyProgress"; // Reference to the SharedObject once we retrieve it. protected static var _playerDataSO:SharedObject = null; public static function load( pd:PlayerData ):void { _playerDataSO = SharedObject.getLocal("sb_player_data"); galaxyProgress = _playerDataSO.data[ GALAXY_PROGRESS_SO_PROP ]; pd.setGalaxyProgress( galaxyProgress ); } public static function save( pd:PlayerData ):void { // Write PlayerData into SharedObject. _playerDataSO = SharedObject.getLocal("sb_player_data"); galaxyProgress = pd.getGalaxyProgress(); _playerDataSO.data[ GALAXY_PROGRESS_SO_PROP ] = galaxyProgress; _playerDataSO.flush(); }
Note that developers are not limited to a single SharedObject instance. Multiple SharedObjects can be stored on disk as long as each uses a unique name. This is a convenient way to segment data into categories.
More detailed information on the SharedObject class can be found online here: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/SharedObject.html
Sound Framework
The sound framework, defined in com.scaleform.std.system.SoundSystem, is a sample implementation for handling sound effect and music playback within your game. The framework loads and plays external sounds, .mp3s in this case, from disk based on SoundEvents dispatched from the game. SoundEvents can be dispatched from any class with a reference to the stage.
dispatchEvent( new SoundEvent( SoundEvent.PLAY_SOUND, true, true, "infantry_attack.mp3", 1, false ) );
The sound framework uses two sound channels, one for the background and one for the foreground. SoundEvents designate which channel the target sound should play on. All sound effects for the game are played on the foreground channel while background music is played in the background channel. This allows each to be muted or toggled independently using a SoundEvent.
dispatchEvent( new SoundEvent( SoundEvent.MUTE_SOUNDFX, true, true );