Singleplayer game in AS3
From GatchaWiki
Getting started
What you need to create Actionscript 3.0 games for Gatcha:
- Actionscript 3.0 knowledge.
- Adobe Flash CS3 or CS4.
- The Gatcha swc library which can be downloaded here.
This article covers:
- Setting up your project for Gatcha game development in Actionscript 3.0.
- All API calls to-from the wrapper.
- Basic game security against hackers.
How it works
Gatcha games for Actionscript 3.0 are loaded inside a flash player 10 wrapper that manages the calls to the Gatcha API for you. Communication with this wrapper works through the Flash Event system. Events are dispatched inside the game.swf which bubble up to the wrapper.swf. Listeners can also be added to listen for callbacks or events that are dispatched by the wrapper.swf. All these events are bundled inside an Actionscript class called GameEvent.as. The swc library containing this class can be downloaded Media:here.
Downloads
Including the class library inside Flash CS3
You cannot link an swc to a project in Flash CS3, but there is a component bundle available which you can install and has the same result.
File:AddGatchaComponentCS3Folder.jpg
Extract the contents of the zip to C:\Program Files (x86)\Adobe\Adobe Flash CS3\<installation language>\Configuration\Components on Windows (64bit) or /Applications/Adobe Flash CS3/Configuration/Components on Mac OS X. A folder Gatcha will be created at that location. This folder contains the GatchaAS3Library.swc file. After a restart of the Flash IDE, you will find a Gatcha folder in your components view with the required components. All you need to do, is add these to your FLA library to start using them.
File:AddGatchaComponentCS3.jpg
Including the swc library inside Flash CS4
Through the Advanced settings for Actionscript 3, you can add the SWC library as a Class Library. This can be done in the following menu: Edit -> Preferences -> Actionscript -> Actionscript 3.0 Settings. Under "library path", add the location of the "GatchaAS3Library.swc" which is found in the Gatcha folder. These classes will now be available for all your projects. You may also wish to add this package to a single project, which can be done through the project's publish settings. Note: in the screenshot below that the link to the swc is relative because the swc is inside the project's bin folder.
Available classes
Upon installation, the following classes are available:
com.gatcha.api.GameEvent (Event)
This is the Event class that will be used to dispatch and receive Events from/to the wrapper swf.
com.gatcha.api.Translations (Singleton)
This class can be used to easely access copy translations for your game (if available)
com.gatcha.memory.SafeMemory (Singleton)
This Class must be used to store all your sensitive data (scores,lives,levels,bonus values,configurations...). This is a countermeasure against memory hacking.
Sending events to the game API through Flash Events
A GameEvent is basically the same as a normal Event, but it contains an extra "data" property. This property will hold valuable information passed to the wrapper or to the game depending on the type of GameEvent you are dispatching. All GameEvent types are defined inside the GameEvent class as public constants. When defining a new GameEvent, always use the GameEvent constants to define the type of the new Event.
SINGLEPLAYER_START_GAME
This event starts a singleplayer game session and must be dispatched before starting the gameplay. If this command is not executed, scores cannot be saved. This event will most likely be dispatched after a click on a "Start game" button inside the game's main menu screen.
dispatchEvent(new GameEvent(GameEvent.SINGLEPLAYER_START_GAME));
SINGLEPLAYER_UPDATE_HIGHSCORE
This event updates the score of a player for this particular game and this particular game session. A score of 0 is ignored and will not be sent by the wrapper swf. You will get a fail event back stating that scores of 0 are invalid. You can pass an integer as a score to save, or if you are using our supplied SafeMemory Class, you can pass the String which contains the location of the score. Remember to dispatch the update score event before the end game event!
dispatchEvent(new GameEvent(GameEvent.SINGLEPLAYER_UPDATE_HIGHSCORE, scoreToSend));
SINGLEPLAYER_END_GAME
This event will end the current game session. All dispatched events after this will return errors. A new startGame event must be dispatched to start playing again. This event will most likely be dispatched when the game is over. You can also create a "play again" button that will dispatch the startGame event again to start another game.
dispatchEvent(new GameEvent(GameEvent.SINGLEPLAYER_END_GAME));
WRAPPER_LOG_THIS
This will cause the String that is send with this event to be appended to the log for this particular game session.Everytime a player plays a game, a log is generated, this is a anti-cheating measure. Logs can then later be viewed and show information about how the player played that particular game. It is important to only send vital information about the gameplay in a short format to be logged.
dispatchEvent(new GameEvent(GameEvent.WRAPPER_LOG_THIS, "stringDataToAppend"));
WRAPPER_PAUSE
This will make the wrapper.swf overlay a Pause screen, which has buttons for unpausing. This screen overlays the entire game, so there is no need to create a pause screen for your game since it will not be visible. Make sure to pause your game logic when you receive the WRAPPER_PAUSED GameEvent.
dispatchEvent(new GameEvent(GameEvent.WRAPPER_PAUSE));
ACHIEVEMENT_REACHED
This tells the wrapper an achievement has been unlocked for this game. A popup overlay will be displayed showing the an icon and specified information about the unlocked achievement. Achievement events should always be dispatched even if that user has already unlocked that achievement. The wrapper check who has achieved what.
dispatchEvent(new GameEvent(GameEvent.ACHIEVEMENT_REACHED, achievementData));
The GameEvent takes a data object parameters with following properties:
- achievement:String Required key identifier of the achievement. This should be a unique name in your game.
- title:String Required textual represantion of the achievement. This should be a short identifier for the achievement that was reached. eg. "Coin Collector"
- description:String Required textual representation of the achievement. This explains what the player did to reach this achievement. eg. "Collected 100 gold coins."
- category: Optional textual identifier of the category the achievement is in. Can be used for filtering when fetching achievements. eg. Campaign achievements, Time-trial achievements, Survivor achievements, etc...
- icon: Optional URL to an icon serving as a visual representation of the achievement. When no icon is provided, the default Gatcha icon will be shown. Icons are automatically scaled to 50x50px and masked with a 5px rounded rectangle.
- data: Optional JSON encoded array of key-value pairs specific to this user's achievement. Will be assigned to the achievement template to determine textual representation of the achievement.
GET_ACHIEVEMENTS
This asks the wrapper for an Array of achievement objects that were unlocked for this game by the player.
dispatchEvent(new GameEvent(GameEvent.GET_ACHIEVEMENTS, achievementData));
PUT_PERSISTENT_STORAGE
Saves data in the persistent storage.
dispatchEvent(new GameEvent(GameEvent.PUT_PERSISTENT_STORAGE, storageData));
The GameEvent takes a String as parameter:
- key:String Unique id to store the given data and will be used to retrieve or delete the data. This may only contain alphanumeric (A-Za-z0-9) characters, underscore(_), dot(.) or dash(-).
- value:String The value that will be stored. You can use Base64 to encode non-string data as a String.
GET_PERSISTENT_STORAGE
Fetches data for a certain key from the persistent storage.
dispatchEvent(new GameEvent(GameEvent.GET_PERSISTENT_STORAGE, key));
The GameEvent takes a String as parameter:
- key:String This should be one of the keys that was specified in a GET_PERSISTENT_STORAGE api call.
DELETE_PERSISTENT_STORAGE
Removes previously stored data from the persistent storage for a certain key.
dispatchEvent(new GameEvent(GameEvent.DELETE_PERSISTENT_STORAGE, key));
The GameEvent takes a String as parameter:
- key:String This should be one of the keys that was specified in a DELETE_PERSISTENT_STORAGE api call.
Callbacks from the wrapper
Callbacks for SINGLEPLAYER_START_GAME
SINGLEPLAYER_START_GAME_RESULT
This GameEvent is fired if the API confimed the game has been started and is valid.
addEventListener(GameEvent.SINGLEPLAYER_START_GAME_RESULT, startGameResultHandler);
SINGLEPLAYER_START_GAME_FAIL
This GameEvent is fired if the API returns an error when trying to start a game, check the data property of the Event to find out what exactly went wrong.
addEventListener(GameEvent.SINGLEPLAYER_START_GAME_FAIL, startGameFailHandler);
Callbacks for SINGLEPLAYER_END_GAME
SINGLEPLAYER_END_GAME_RESULT
This GameEvent is fired if the API confimed the game has ended.
addEventListener(GameEvent.SINGLEPLAYER_END_GAME_RESULT, endGameResultHandler);
SINGLEPLAYER_END_GAME_FAIL
This GameEvent is fired if the API returns an error when trying to end a game, check the data property of the Event to find out what exactly went wrong.
addEventListener(GameEvent.SINGLEPLAYER_END_GAME_FAIL, endGameFailHandler);
Callbacks for SINGLEPLAYER_UPDATE_HIGHSCORE
SINGLEPLAYER_UPDATE_HIGHSCORE_RESULT
This GameEvent is fired if the API confimed the score was saved.
addEventListener(GameEvent.SINGLEPLAYER_UPDATE_HIGHSCORE_RESULT, updateHighscoreResultHandler);
SINGLEPLAYER_UPDATE_HIGHSCORE_FAIL
This GameEvent is fired if the API returns an error when saving of a score failed, check the data property of the Event to find out what exactly went wrong.
addEventListener( GameEvent.SINGLEPLAYER_UPDATE_HIGHSCORE_FAIL, updateHighscoreFailHandler);
Callbacks for WRAPPER_PAUSE
WRAPPER_PAUSED
This GameEvent is fired if the wrapper is showing the pause screen. Remember to pause your game logic!
addEventListener(GameEvent.WRAPPER_PAUSED, gamePausedHandler);
WRAPPER_UNPAUSED
This GameEvent is fired if the wrapper hides the pause screen and wants the game to continue.
addEventListener(GameEvent.WRAPPER_UNPAUSED, gameUnpausedHandler);
Callbacks for ACHIEVEMENT_REACHED
ACHIEVEMENT_REACHED_RESULT
This GameEvent is fired when a new achievement has been reached and registered with the api for the player.
addEventListener(GameEvent.ACHIEVEMENT_REACHED_RESULT, achievementReachedResultHandler);
ACHIEVEMENT_REACHED_FAIL
This GameEvent is fired when a new achievement failed to register with the gatcha api.
addEventListener(GameEvent.ACHIEVEMENT_REACHED_FAIL, achievementReachedFailHandler);
Callbacks for GET_ACHIEVEMENTS
GET_ACHIEVEMENTS_RESULT
This GameEvent is fired when the list of achievements was loaded.
GET_ACHIEVEMENTS_RESULT addEventListener(GameEvent.GET_ACHIEVEMENTS_RESULT, getAchievementResultHandler);
GET_ACHIEVEMENTS_FAIL
This GameEvent is fired when the list of achievements could not be loaded.
addEventListener(GameEvent.GET_ACHIEVEMENTS_FAIL, getAchievementFailHandler);
Callbacks for PUT_PERSISTENT_STORAGE
PUT_PERSISTENT_STORAGE_RESULT
This GameEvent is fired when the data was successfully saved.
addEventListener(GameEvent.PUT_PERSISTENT_STORAGE_RESULT, putPersistentStorageResultHandler);
PUT_PERSISTENT_STORAGE_FAIL
This GameEvent is fired when the data could not be saved.
addEventListener(GameEvent.PUT_PERSISTENT_STORAGE_FAIL, putPersistentStorageFailHandler);
Callbacks for GET_PERSISTENT_STORAGE
GET_PERSISTENT_STORAGE_RESULT
This GameEvent is fired when the data was successfully retrieved.
addEventListener(GameEvent.GET_PERSISTENT_STORAGE_RESULT, getPersistentStorageResultHandler);
GET_PERSISTENT_STORAGE_FAIL
This GameEvent is fired when the data could not be retrieved.
addEventListener(GameEvent.GET_PERSISTENT_STORAGE_FAIL, getPersistentStorageFailHandler);
Callbacks for DELETE_PERSISTENT_STORAGE
DELETE_PERSISTENT_STORAGE_RESULT
This GameEvent is fired when the data was successfully deleted.
addEventListener(GameEvent.DELETE_PERSISTENT_STORAGE_RESULT, deletePersistentStorageResultHandler);
DELETE_PERSISTENT_STORAGE_FAIL
This GameEvent is fired when the data could not be deleted.
addEventListener(GameEvent.DELETE_PERSISTENT_STORAGE_FAIL, deletePersistentStorageFailHandler);
Configuring translations for your game
Through the instance of the Translations singleton, you can access the translations of the messagebundle. Do note that these are only available when your game is loaded into the wrapper .Translations can be read out, but will be turn out "{Missing <translationskey>}" if not available.
A messagebundle is a xml file with following syntax (Messagebundle documentation):
<messagebundle> <msg name="labelScore">Points</msg> <msg name="labelLife">Lifes</msg> <msg name="labelStart">Start the game!</msg> </messagebundle>
Each name should be unique for that messagebundle whereas the value between the msg tags is the translations for that key.
Accessing the translations for your game
Use the Translations class in the GatchaAS3Library. Translations that cannot be loaded will always return a string "Missing <key>" with the key you specified.
Translations.instance.getString(key):String returns a translation for the specified key
txtScore.text = Translations.instance.getString(labelScore);
Translations.instance.exists(key):Boolean returns true or false if the translation exists. You can use this to set a default language if the translation could not be loaded
(Translations.instance.exists(labelScore) ? txtScore.text = Translations.instance.getString(labelScore) : txtScore.text = "Score";
Encrypting valuable game data against hackers
Cheating in Flash games can be very easy. We have erected several countermeasures to try and withhold some forms of hacking. One of the most common ways for players to cheat is memory hacking. To prevent this, the library provides a SafeMemory class which will encrypt all the given variables in the memory, to stop easy memory readouts. As a general rule: Never store sensitive data in class variables or constants!
Saving a numeric value
SafeMemory.instance.setValue("score", 100);
Reading a numeric value
SafeMemory.instance.getValue("score");
Operators on numeric values
Instead of reading out values, performing operations on it and saving the value again, there are some functions available that do that for you
SafeMemory.instance.incrementValue("score",1); SafeMemory.instance.decrementValue("score",1); SafeMemory.instance.multiplyValue("score",10); SafeMemory.instance.divideValue("score",2);
