├── .gitignore
├── LICENSE
├── Nesbox.as3proj
├── README.md
├── bin
├── Nesbox.swf
├── gb.swf
├── gba.swf
├── nes.swf
├── sega.swf
└── snes.swf
├── lib
├── as3corelib.swc
├── as3crypto.swc
└── fzip.swc
└── src
├── Analytics.as
├── EmulatorState.as
├── Focus.as
├── GameData.as
├── GamepadButton.as
├── ICoreModule.as
├── IGameDataHandler.as
├── IGamepadModule.as
├── JSProxy.as
├── Locale.as
├── Nesbox.as
├── Text.as
├── Tools.as
├── Variables.as
├── assets
├── en.json
├── facebook.png
├── favorite.png
├── fullscreen.png
├── gamepad.png
├── github.png
├── google.png
├── load.png
├── mute.png
├── save.png
├── setup.png
├── twitter.png
├── upload.png
└── vkontakte.png
├── core
├── CorePlayerBase.as
├── CorePlayerContest.as
├── CorePlayerNetwork.as
├── CorePlayerOwnServer.as
├── CorePlayerSingle.as
├── CorePlayerWalk.as
├── ICoreHandler.as
├── ICorePlayer.as
└── ICorePlayerHandler.as
├── mode
├── Base.as
├── Contest.as
├── Network.as
├── Own.as
├── OwnServer.as
├── Single.as
└── Walk.as
├── model
├── Gamepad.as
├── ServerSettings.as
└── Settings.as
├── network
├── INetworkSessionHandler.as
├── IOwnServerSessionHandler.as
├── NetworkSession.as
└── OwnServerSession.as
├── server
├── Api.as
└── IApiHandler.as
└── ui
├── ActionAsset.as
├── Actions.as
├── ActionsMode.as
├── Button.as
├── FullscreenMessage.as
├── IActionsHandler.as
├── IBaseSetup.as
├── IOwnServerSetupHandler.as
├── ISetupHandler.as
├── ISignHandler.as
├── Keyboard.as
├── Message.as
├── OwnServerSetup.as
├── Setup.as
├── SetupBuilder.as
├── SetupTutorial.as
└── TextInput.as
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build and Release Folders
2 | bin-debug/
3 |
4 | # Other files and folders
5 | .settings/
6 |
7 | # Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
8 | # should NOT be excluded as they contain compiler settings and other important
9 | # information for Eclipse / Flash Builder.
10 | obj/
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Vadim Grigoruk
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Nesbox.as3proj:
--------------------------------------------------------------------------------
1 |
2 |
' + 187 | Locale.instance.loading_emulator + 188 | ' ' + int(event.bytesLoaded * 100 / event.bytesTotal) + '%
'); 189 | }); 190 | 191 | moduleLoader.load(request); 192 | } 193 | 194 | private function loadRom():void 195 | { 196 | rom = rom || url.split('/').pop(); 197 | 198 | var romLoader:URLLoader = new URLLoader(); 199 | romLoader.dataFormat = URLLoaderDataFormat.BINARY; 200 | 201 | romLoader.addEventListener(Event.COMPLETE, function():void 202 | { 203 | if (rom.indexOf(ZipExt) != -1) 204 | { 205 | var zip:FZip = new FZip(); 206 | 207 | zip.addEventListener(Event.COMPLETE, function():void 208 | { 209 | var romFile:FZipFile = zip.getFileAt(0); 210 | 211 | data = romFile.content; 212 | }); 213 | 214 | zip.loadBytes(romLoader.data); 215 | } 216 | else 217 | { 218 | data = romLoader.data; 219 | } 220 | 221 | handler.onLoadRom(); 222 | }); 223 | 224 | romLoader.addEventListener(ProgressEvent.PROGRESS, function(event:ProgressEvent):void 225 | { 226 | handler.onInfoShow('
' + 227 | Locale.instance.loading_game + 228 | ' ' + int(event.bytesLoaded * 100 / event.bytesTotal) + '%
'); 229 | }); 230 | 231 | romLoader.load(new URLRequest(url)); 232 | } 233 | } 234 | } -------------------------------------------------------------------------------- /src/GamepadButton.as: -------------------------------------------------------------------------------- 1 | package 2 | { 3 | import flash.display.Bitmap; 4 | 5 | public class GamepadButton 6 | { 7 | public var bitmap:Bitmap; 8 | public var name:String; 9 | public var x:int; 10 | public var y:int; 11 | 12 | public function GamepadButton() 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/ICoreModule.as: -------------------------------------------------------------------------------- 1 | package 2 | { 3 | import flash.display.BitmapData; 4 | import flash.utils.ByteArray; 5 | 6 | public interface ICoreModule extends IGamepadModule 7 | { 8 | function init(ntsc:Boolean, rom:ByteArray, region:String):void; 9 | function tick(input:uint, data:BitmapData):void; 10 | function sound(data:ByteArray):void; 11 | function save():ByteArray; 12 | function load(data:ByteArray):void; 13 | 14 | function set muted(value:Boolean):void; 15 | function get muted():Boolean; 16 | 17 | function getWidth():int; 18 | function getHeight():int; 19 | } 20 | } -------------------------------------------------------------------------------- /src/IGameDataHandler.as: -------------------------------------------------------------------------------- 1 | package 2 | { 3 | public interface IGameDataHandler 4 | { 5 | function onInfoShow(value:String):void; 6 | function onLoadRom():void; 7 | function onLoadLocale():void; 8 | } 9 | } -------------------------------------------------------------------------------- /src/IGamepadModule.as: -------------------------------------------------------------------------------- 1 | package 2 | { 3 | import flash.display.Bitmap; 4 | 5 | public interface IGamepadModule 6 | { 7 | function getGamepadKeysNames():Array; 8 | function getGamepadImage():Bitmap; 9 | function getGamepadButton(name:String):GamepadButton; 10 | function getGamepadDefaultKeys():Array; 11 | function getSettingsUid():String; 12 | } 13 | } -------------------------------------------------------------------------------- /src/JSProxy.as: -------------------------------------------------------------------------------- 1 | package 2 | { 3 | import flash.external.ExternalInterface; 4 | 5 | public class JSProxy 6 | { 7 | public static function windowOpen(url:String, title:String, width:int = 800, height:int = 400):void 8 | { 9 | if(ExternalInterface.available) 10 | { 11 | ExternalInterface.call('function(){window.open("' + url + 12 | '", "' + title + '", "width=' + width + ',height=' + 300 + '");}'); 13 | } 14 | } 15 | 16 | public static function showSignInModal():void 17 | { 18 | if(ExternalInterface.available) 19 | { 20 | ExternalInterface.call('function(){$("#signin").modal("show");}'); 21 | } 22 | } 23 | 24 | public static function showSignUpModal():void 25 | { 26 | if(ExternalInterface.available) 27 | { 28 | ExternalInterface.call('function(){$("#signup").modal("show");}'); 29 | } 30 | } 31 | 32 | public static function onNetworkInit(peer:String = null):void 33 | { 34 | if(ExternalInterface.available) 35 | { 36 | ExternalInterface.call(peer && peer.length == 64 37 | ? 'function(){Client.onNetworkInit("'+peer+'");}' 38 | : 'function(){Client.onNetworkInit();}'); 39 | } 40 | } 41 | 42 | public static function addCallback(name:String, callback:Function):void 43 | { 44 | if(ExternalInterface.available) 45 | { 46 | ExternalInterface.addCallback(name, callback); 47 | } 48 | } 49 | 50 | public static function showDefaultKeyboard():void 51 | { 52 | if(ExternalInterface.available) 53 | { 54 | ExternalInterface.call('function(){Client.showDefaultKeyboard();}'); 55 | } 56 | } 57 | 58 | public static function resizeOwnEmulator(width:int, height:int):void 59 | { 60 | if(ExternalInterface.available) 61 | { 62 | ExternalInterface.call('function(){resizeOwnEmulator("'+width+'px", "'+height+'px");}'); 63 | } 64 | } 65 | 66 | public static function initSigningCallback(callback:Function):void 67 | { 68 | if(ExternalInterface.available) 69 | { 70 | ExternalInterface.addCallback('onUserSigned', function(signed:Boolean):void 71 | { 72 | callback(signed); 73 | }); 74 | } 75 | } 76 | 77 | public static function log(value:String):void 78 | { 79 | trace(value); 80 | 81 | if(ExternalInterface.available) 82 | { 83 | ExternalInterface.call('function(){console.log("'+value+'");}'); 84 | } 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /src/Locale.as: -------------------------------------------------------------------------------- 1 | package 2 | { 3 | public class Locale 4 | { 5 | private static var instanceValue:Locale; 6 | 7 | public function Locale() 8 | { 9 | 10 | } 11 | 12 | public static function get instance():Locale 13 | { 14 | if(!instanceValue) 15 | { 16 | instanceValue = new Locale; 17 | instanceValue.init(); 18 | } 19 | 20 | return instanceValue; 21 | } 22 | 23 | private function init():void 24 | { 25 | 26 | } 27 | 28 | public var click_here_to_play_the_game:String; 29 | public var error_occured:String; 30 | public var close:String; 31 | public var cancel:String; 32 | public var click_allow_button:String; 33 | public var now_connect_gamepad:String; 34 | public var configure:String; 35 | public var or:String; 36 | public var press:String; 37 | public var button:String; 38 | public var connecting_please_wait:String; 39 | public var if_you_want_to_use_gamepad:String; 40 | public var user_name:String; 41 | public var email:String; 42 | public var password:String; 43 | public var forgot_password:String; 44 | public var sign_in:String; 45 | public var sign_up:String; 46 | public var to_save_load_game_you_need:String; 47 | public var keyboard_setup:String; 48 | public var select_joystick_button:String; 49 | public var load_defaults:String; 50 | public var save:String; 51 | public var select_mode:String; 52 | public var one_player:String; 53 | public var two_players_via_internet:String; 54 | public var game_walkthrough:String; 55 | public var your_own_server:String; 56 | public var supported_rom_formats:String; 57 | public var click_here_to_load_your_own_rom:String; 58 | public var loading_module:String; 59 | public var loading_game:String; 60 | public var loading_emulator:String; 61 | public var uploading_walkthrough:String; 62 | public var please_wait:String; 63 | public var you_already_have_saved_walkthrough:String; 64 | public var yes:String; 65 | public var no:String; 66 | public var you_need_to_be_signed_in_to_upload_walk:String; 67 | public var waiting_for_connection:String; 68 | public var if_you_cannot_connect:String; 69 | public var connecting_to_server:String; 70 | public var new_send_copied_url:String; 71 | public var also_you_can_find_partner:String; 72 | public var public_chat:String; 73 | public var remote_url:String; 74 | public var click_here_to_copy_url_to_clipboard:String; 75 | public var then_send_it_to_friend:String; 76 | public var connected_to_server:String; 77 | public var connection_error:String; 78 | public var testing_connection:String; 79 | public var ping_is:String; 80 | public var the_game_will_be_uncomfortable:String; 81 | public var saving_game:String; 82 | public var you_have_saved_state:String; 83 | public var do_you_want_to_load_state:String; 84 | public var you_need_to_be_signed_in_to_save:String; 85 | public var loading_walkthrough:String; 86 | 87 | public var gamepad_app_info:String; 88 | public var gamepad_app_downloaded:String; 89 | public var click_here_to_save_it:String; 90 | 91 | public var hint_pause:String; 92 | public var hint_setup:String; 93 | public var hint_mute:String; 94 | public var hint_load:String; 95 | public var hint_save:String; 96 | public var hint_fullscreen:String; 97 | public var hint_share:String; 98 | public var hint_upload:String; 99 | public var hint_gamepad:String; 100 | public var hint_favorite:String; 101 | public var server_setup:String; 102 | public var server_port:String; 103 | public var server_frameskip:String; 104 | public var connect:String; 105 | public var server_connection_error:String; 106 | public var make_sure_entered_correct_ip:String; 107 | public var try_again:String; 108 | public var you_are_connected:String; 109 | public var and_send_to_friend:String; 110 | public var remote_url_is:String; 111 | public var connection_has_closed:String; 112 | 113 | public var please_read:String; 114 | public var how_start_own_server:String; 115 | 116 | public function sprintf(buffer:String, ...args):String 117 | { 118 | for(var index:int = 0; index < args.length; index++) 119 | buffer = buffer.split('%'+(index+1)+'%').join(args[index]); 120 | 121 | return buffer; 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/Nesbox.as: -------------------------------------------------------------------------------- 1 | package 2 | { 3 | import flash.display.DisplayObject; 4 | import flash.display.Sprite; 5 | import flash.display.StageAlign; 6 | import flash.display.StageScaleMode; 7 | import flash.events.ContextMenuEvent; 8 | import flash.events.Event; 9 | import flash.net.FileFilter; 10 | import flash.net.FileReference; 11 | import flash.net.navigateToURL; 12 | import flash.net.URLRequest; 13 | import flash.ui.ContextMenu; 14 | import flash.ui.ContextMenuItem; 15 | 16 | import mode.Contest; 17 | import mode.Network; 18 | import mode.Own; 19 | import mode.OwnServer; 20 | import mode.Single; 21 | import mode.Walk; 22 | 23 | import ui.Message; 24 | 25 | [SWF(width='640', height='480', backgroundColor='0x000000')] 26 | 27 | public class Nesbox extends Sprite implements IGameDataHandler 28 | { 29 | private var gameData:GameData; 30 | private var info:Message; 31 | private var message:Message; 32 | private var emulator:DisplayObject; 33 | private var locale:Locale; 34 | 35 | public function Nesbox() 36 | { 37 | if(stage) 38 | { 39 | init(); 40 | } 41 | else 42 | { 43 | addEventListener(Event.ADDED_TO_STAGE, function():void 44 | { 45 | init(); 46 | }); 47 | } 48 | } 49 | 50 | public function setSize(width:int, height:int):void 51 | { 52 | Variables.Width = width; 53 | Variables.Height = height; 54 | } 55 | 56 | public function onInfoShow(value:String):void 57 | { 58 | info.show(value); 59 | } 60 | 61 | private function createContextMenu():void 62 | { 63 | var customMenu:ContextMenu = new ContextMenu(); 64 | customMenu.hideBuiltInItems(); 65 | 66 | var emulatorItem:ContextMenuItem = new ContextMenuItem(locale.hint_share); 67 | emulatorItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, function():void 68 | { 69 | Tools.gotoNesboxPage(); 70 | }); 71 | 72 | customMenu.customItems.push(emulatorItem); 73 | 74 | contextMenu = customMenu; 75 | 76 | } 77 | 78 | private function init():void 79 | { 80 | setSize(stage.stageWidth / 2, stage.stageHeight / 2); 81 | 82 | scaleX = scaleY = 2; 83 | 84 | Focus.init(stage); 85 | 86 | stage.scaleMode = StageScaleMode.NO_SCALE; 87 | stage.align = StageAlign.TOP_LEFT; 88 | 89 | locale = Locale.instance; 90 | gameData = new GameData(this, stage.loaderInfo.loaderURL); 91 | 92 | gameData.loadParams(stage.loaderInfo.parameters); 93 | 94 | addChild(info = new Message); 95 | 96 | gameData.loadLocale(); 97 | } 98 | 99 | public function onLoadLocale():void 100 | { 101 | createContextMenu(); 102 | 103 | if (gameData.action == GameData.Own 104 | && gameData.url == null) 105 | { 106 | initOwnRomMode(); 107 | } 108 | else 109 | gameData.init(); 110 | } 111 | 112 | public function onLoadRom():void 113 | { 114 | removeChild(info); 115 | 116 | if(gameData.action) 117 | { 118 | switch(gameData.action) 119 | { 120 | case GameData.One: 121 | startSingleMode(); 122 | break; 123 | case GameData.Arena: 124 | startNetworkMode(); 125 | break; 126 | case GameData.Save: 127 | startSingleMode(); 128 | break; 129 | case GameData.Walk: 130 | gameData.value ? startWalkMode() : startContestMode(); 131 | break; 132 | case GameData.Own: 133 | startOwnRomMode(); 134 | break; 135 | case GameData.Room: 136 | startOwnServerMode(); 137 | break; 138 | default: 139 | selectMode(); 140 | } 141 | } 142 | else 143 | { 144 | selectMode(); 145 | } 146 | } 147 | 148 | private function selectMode():void 149 | { 150 | message = new Message(); 151 | addChild(message); 152 | 153 | var callbacks:Object = 154 | { 155 | single:startSingleMode, 156 | network:startNetworkMode, 157 | contest:startContestMode, 158 | own:startOwnServerMode 159 | }; 160 | 161 | message.show('
' + locale.select_mode.toUpperCase() + ':
' +
162 | '
1 - '+locale.one_player+'' +
163 | '
2 - '+locale.game_walkthrough+''+
164 | '
3 - '+locale.two_players_via_internet+'' +
165 | '
4 - '+locale.your_own_server+' (beta)' +
166 | '
'+locale.supported_rom_formats+':
NES (*.nes), SNES (*.smc), SEGA (*.gen),
GAMEBOY/COLOR/ADVANCE (*.gb, *.gbc, *.gba)
' +
210 | ''+
211 | locale.click_here_to_load_your_own_rom +
212 | '...
' + 202 | locale.click_here_to_play_the_game + //value('Click here to play the game') + 203 | '...
'); 204 | } 205 | 206 | protected function initActivateEngine():void 207 | { 208 | activeMessage = new Message; 209 | addChild(activeMessage); 210 | 211 | gamepadMessage = new Message; 212 | addChild(gamepadMessage); 213 | 214 | fullscreenMessage = new FullscreenMessage; 215 | addChild(fullscreenMessage); 216 | 217 | stage.addEventListener(Event.ACTIVATE, function():void 218 | { 219 | if(fullscreenMessage.visible)return; 220 | resume(); 221 | }); 222 | 223 | stage.addEventListener(Event.DEACTIVATE, function():void 224 | { 225 | if(fullscreenMessage.visible)return; 226 | pause(); 227 | }); 228 | } 229 | 230 | public function onApiError(info:String):void 231 | { 232 | if(!activeMessage) return; 233 | 234 | var callbacks:Object = 235 | { 236 | close:function():void 237 | { 238 | activeMessage.hide(); 239 | } 240 | }; 241 | 242 | activeMessage.show(''+locale.error_occured
243 | + '
'
244 | + locale.close
245 | + '
'
321 | + locale.click_allow_button
322 | + '
'
323 | + ''+locale.cancel.toUpperCase()+'
'+locale.gamepad_app_info+'
' +
411 | 'Download Adobe AIR
' +
412 | 'Download Nesbox Companion
' +
413 | ''+locale.close.toLocaleUpperCase()+'
'+locale.uploading_walkthrough+'...
'); 113 | 114 | api.uploadWalk(gameData.rom, nes.getWalk()); 115 | } 116 | 117 | private function initUploadShortcut():void 118 | { 119 | stage.addEventListener(KeyboardEvent.KEY_DOWN, function(event:KeyboardEvent):void 120 | { 121 | switch(event.keyCode) 122 | { 123 | case UploadHotkeyCode: 124 | onActionsUpload(); 125 | break; 126 | } 127 | }); 128 | } 129 | 130 | private function onSignIn():void 131 | { 132 | nes.pause(); 133 | JSProxy.showSignInModal(); 134 | } 135 | 136 | private function onSignUp():void 137 | { 138 | nes.pause(); 139 | JSProxy.showSignUpModal(); 140 | } 141 | 142 | public function onSetupSave(joystick:Gamepad):void 143 | { 144 | settings.keyboard = joystick; 145 | nes.updateKeyCodes(joystick.codes); 146 | nes.play(); 147 | setup.visible = false; 148 | } 149 | 150 | public function onSetupCancel():void 151 | { 152 | nes.play(); 153 | setup.visible = false; 154 | } 155 | 156 | protected override function start():void 157 | { 158 | nes.updateKeyCodes(settings.keyboard.codes); 159 | 160 | initUploadShortcut(); 161 | nes.initContestEmulation(gameData.ntsc, gameData.data, gameData.region); 162 | Focus.activated ? nes.play() : pause(); 163 | } 164 | 165 | public override function onActionsMute():void 166 | { 167 | nes.muted = !nes.muted; 168 | settings.muted = nes.muted; 169 | actions.muted = nes.muted; 170 | } 171 | 172 | public override function onActionsSetup():void 173 | { 174 | nes.pause(); 175 | setup.show(settings.keyboard); 176 | } 177 | 178 | public override function onActionsUpload():void 179 | { 180 | state = EmulatorState.Uploadig; 181 | uploadWalk(); 182 | } 183 | 184 | public function onSigninCancel():void 185 | { 186 | message.hide(); 187 | nes.play(); 188 | } 189 | 190 | public override function onApiError(info:String):void 191 | { 192 | var callbacks:Object = 193 | { 194 | cancelsign:onSigninCancel 195 | }; 196 | 197 | message.show('' + locale.error_occured +
198 | '
' + locale.close.toUpperCase() +
199 | '
'+locale.you_need_to_be_signed_in_to_upload_walk+'
' +
212 | ''+locale.sign_in.toUpperCase()+' ' +
213 | locale.or +
214 | ' '+locale.sign_up.toUpperCase()+'
' +
215 | ''+locale.cancel.toUpperCase()+'
'+locale.waiting_for_connection +'...
' +
115 | locale.sprintf(locale.if_you_cannot_connect, 'http://cc.rtmfp.net')+'
'+locale.connecting_to_server+'...
'); 122 | session.connect(); 123 | } 124 | } 125 | 126 | 127 | public override function onActionsMute():void 128 | { 129 | nes.muted = !nes.muted; 130 | settings.muted = nes.muted; 131 | actions.muted = nes.muted; 132 | } 133 | 134 | public override function onActionsSetup():void 135 | { 136 | nes.pause(); 137 | setup.show(settings.keyboard); 138 | } 139 | 140 | public override function onActionsUpload():void {} 141 | 142 | public function onSetupSave(joystick:Gamepad):void 143 | { 144 | settings.keyboard = joystick; 145 | nes.updateKeyCodes(joystick.codes); 146 | nes.play(); 147 | setup.visible = false; 148 | } 149 | 150 | public function onSetupCancel():void 151 | { 152 | nes.play(); 153 | setup.visible = false; 154 | } 155 | 156 | protected override function start():void 157 | { 158 | nes.updateKeyCodes(settings.keyboard.codes); 159 | nes.play(); 160 | 161 | checkArena(); 162 | } 163 | 164 | public function sendInput(input:uint):void 165 | { 166 | session.sendInput(input); 167 | } 168 | 169 | public function sendDummy():void 170 | { 171 | session.sendDummy(); 172 | } 173 | 174 | public function onNetworkPeer(value:String):void 175 | { 176 | if(!gameData.value || gameData.value.length != 64) 177 | { 178 | gameData.value = value; 179 | 180 | var arenaUrl:String = 181 | [ 182 | gameData.domain, 183 | (gameData.locale == 'en' ? '' : '/' + gameData.locale), 184 | '/game/', gameData.system, 185 | '/', gameData.game, 186 | '/rom/', gameData.rom, 187 | '#arena=', gameData.value 188 | ].join(''); 189 | 190 | Tools.shortLink(arenaUrl, function(shortUrl:String):void 191 | { 192 | if(shortUrl) 193 | { 194 | var callbacks:Object = 195 | { 196 | clipboard:function():void 197 | { 198 | System.setClipboard(shortUrl); 199 | 200 | message.show(''+locale.new_send_copied_url+'
' +
201 | locale.waiting_for_connection+'...
' +
202 | locale.sprintf(locale.also_you_can_find_partner, '
'+locale.public_chat+'')+'
' +
203 | locale.sprintf(locale.if_you_cannot_connect, 'cc.rtmfp.net')+'
'+locale.connected_to_server+'...
' +
208 | locale.remote_url+': ' + shortUrl + '
' +
209 | '' +
210 | locale.click_here_to_copy_url_to_clipboard+',
' +
211 | locale.then_send_it_to_friend+'...
'+locale.connection_error+'
'); 216 | } 217 | }); 218 | } 219 | } 220 | 221 | public function onNetworkInput(input:uint):void 222 | { 223 | nes.recvInputValue(input); 224 | } 225 | 226 | public function onNetworkTest():void 227 | { 228 | message.show(''+locale.testing_connection+'...
'); 229 | 230 | session.test(); 231 | } 232 | 233 | public function onNetworkStart(isFirstPeer:Boolean, ping:uint):void 234 | { 235 | var callbacks:Object = 236 | { 237 | ok:function():void 238 | { 239 | message.hide(); 240 | nes.play(); 241 | 242 | if(!Focus.activated) 243 | { 244 | pause(); 245 | } 246 | 247 | nes.updateKeyCodes(settings.keyboard.codes); 248 | nes.initNetworkEmulation(gameData.ntsc, isFirstPeer, gameData.data, gameData.region); 249 | } 250 | }; 251 | 252 | if(ping < 100) 253 | callbacks.ok(); 254 | else 255 | message.show(''+locale.sprintf(locale.ping_is, ping) +'
' +
256 | locale.the_game_will_be_uncomfortable + '
' +
257 | 'OK
' + locale.loading_game + '...
'); 120 | 121 | var onComplete:Function = function():void 122 | { 123 | this.state = EmulatorState.Playing; 124 | nes.load(lastState); 125 | message.hide(); 126 | nes.play(); 127 | } 128 | 129 | if(lastState 130 | && lastState.length) 131 | { 132 | onComplete(); 133 | } 134 | else 135 | { 136 | var ref:FileReference = new FileReference(); 137 | ref.addEventListener(Event.CANCEL, function():void 138 | { 139 | this.state = EmulatorState.Playing; 140 | message.hide(); 141 | nes.play(); 142 | }); 143 | ref.addEventListener(Event.COMPLETE, function():void 144 | { 145 | lastState = ref.data; 146 | onComplete(); 147 | }); 148 | ref.addEventListener(Event.SELECT, function():void 149 | { 150 | ref.load(); 151 | }); 152 | ref.browse([new FileFilter('Saved files', '*.save')]); 153 | } 154 | } 155 | 156 | private function saveState():void 157 | { 158 | var data:ByteArray = nes.save(); 159 | 160 | if(data && data.bytesAvailable) 161 | { 162 | nes.pause(); 163 | message.show('' + locale.saving_game + '...
'); 164 | 165 | var onComplete:Function = function():void 166 | { 167 | this.state = EmulatorState.Playing; 168 | message.hide(); 169 | nes.play(); 170 | } 171 | 172 | var ref:FileReference = new FileReference(); 173 | ref.addEventListener(Event.CANCEL, function():void 174 | { 175 | onComplete(); 176 | }); 177 | ref.addEventListener(Event.COMPLETE, function():void 178 | { 179 | lastState = data; 180 | onComplete(); 181 | }); 182 | ref.save(data, gameData.rom + '.save'); 183 | } 184 | } 185 | 186 | private function initSaveLoadShortcuts():void 187 | { 188 | stage.addEventListener(KeyboardEvent.KEY_DOWN, function(event:KeyboardEvent):void 189 | { 190 | switch(event.keyCode) 191 | { 192 | case SaveHotkeyCode: 193 | onActionsLoad(); 194 | break; 195 | case LoadHotkeyCode: 196 | onActionsSave(); 197 | break; 198 | } 199 | }); 200 | } 201 | 202 | public function onSetupSave(joystick:Gamepad):void 203 | { 204 | settings.keyboard = joystick; 205 | nes.updateKeyCodes(joystick.codes); 206 | nes.play(); 207 | setup.visible = false; 208 | } 209 | 210 | public function onSetupCancel():void 211 | { 212 | nes.play(); 213 | setup.visible = false; 214 | } 215 | 216 | protected override function start():void 217 | { 218 | nes.updateKeyCodes(settings.keyboard.codes); 219 | 220 | initSaveLoadShortcuts(); 221 | nes.initSingleEmulation(gameData.ntsc, gameData.data, gameData.region); 222 | 223 | Focus.activated ? resume() : pause(); 224 | } 225 | 226 | public override function onActionsMute():void 227 | { 228 | nes.muted = !nes.muted; 229 | settings.muted = nes.muted; 230 | actions.muted = nes.muted; 231 | } 232 | 233 | public override function onActionsLoad():void 234 | { 235 | loadState(); 236 | } 237 | 238 | public override function onActionsSave():void 239 | { 240 | state = EmulatorState.Saving; 241 | saveState(); 242 | } 243 | 244 | public override function onActionsSetup():void 245 | { 246 | nes.pause(); 247 | setup.show(settings.keyboard); 248 | } 249 | 250 | protected override function onScreenShot():void 251 | { 252 | api.screen(gameData.rom, nes.screen); 253 | } 254 | 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /src/mode/OwnServer.as: -------------------------------------------------------------------------------- 1 | package mode 2 | { 3 | import com.hurlant.util.Base64; 4 | 5 | import core.CorePlayerOwnServer; 6 | import core.ICorePlayerHandler; 7 | 8 | import flash.system.System; 9 | 10 | import model.Gamepad; 11 | import model.ServerSettings; 12 | 13 | import network.IOwnServerSessionHandler; 14 | import network.OwnServerSession; 15 | 16 | import ui.Actions; 17 | import ui.ActionsMode; 18 | import ui.IBaseSetup; 19 | import ui.IOwnServerSetupHandler; 20 | import ui.ISetupHandler; 21 | import ui.Message; 22 | import ui.OwnServerSetup; 23 | import ui.Setup; 24 | import ui.SetupBuilder; 25 | 26 | public class OwnServer extends Base 27 | implements 28 | ICorePlayerHandler, 29 | IOwnServerSessionHandler, 30 | ISetupHandler, 31 | IOwnServerSetupHandler 32 | { 33 | private var nes:CorePlayerOwnServer; 34 | private var actions:Actions; 35 | private var setup:IBaseSetup; 36 | private var message:Message; 37 | private var session:OwnServerSession; 38 | private var ownServerSetup:OwnServerSetup; 39 | private var isFirstPeer:Boolean; 40 | 41 | public function OwnServer(gameData:GameData) 42 | { 43 | super(gameData); 44 | 45 | nes = new CorePlayerOwnServer(gameData.core, this); 46 | actions = new Actions(this, ActionsMode.Network); 47 | setup = SetupBuilder.Make(this, gameData); 48 | message = new Message(); 49 | session = new OwnServerSession(this); 50 | ownServerSetup = new OwnServerSetup(this); 51 | 52 | actions.muted = nes.muted = settings.muted; 53 | actions.visible = false; 54 | actions.enableFullscreen = Tools.isInteractiveFullscreenSupported(); 55 | } 56 | 57 | protected override function init():void 58 | { 59 | addChild(nes); 60 | addChild(actions); 61 | addChild(setup.sprite); 62 | addChild(message); 63 | addChild(ownServerSetup); 64 | 65 | super.init(); 66 | } 67 | 68 | protected override function startActionsShow():void 69 | { 70 | super.showActions(actions); 71 | } 72 | 73 | protected override function stopActionsShow():void 74 | { 75 | super.hideActions(actions); 76 | } 77 | 78 | protected override function resume():void 79 | { 80 | super.resume(); 81 | 82 | if(!setup.visible 83 | && !message.visible) 84 | { 85 | nes.play(); 86 | } 87 | } 88 | 89 | protected override function pauseEmulation():void 90 | { 91 | nes.pause(); 92 | } 93 | 94 | protected override function resumeEmulation():void 95 | { 96 | nes.play(); 97 | } 98 | 99 | protected override function enableFullscreen(enable:Boolean):void 100 | { 101 | actions.enableFullscreen = enable; 102 | } 103 | 104 | private function checkRoom():void 105 | { 106 | if(gameData.value && gameData.value.length > 0) 107 | { 108 | var data:Object = JSON.parse(Base64.decode(gameData.value)); 109 | 110 | if(data && data.ip && data.port) 111 | { 112 | if(data.room) 113 | { 114 | isFirstPeer = false; 115 | 116 | message.show(''+locale.waiting_for_connection +'...
'); 117 | 118 | session.connect(data.ip, data.port, data.room); 119 | } 120 | else 121 | { 122 | isFirstPeer = true; 123 | var serverSettings:ServerSettings = new ServerSettings(data.ip, data.port, 0); 124 | ownServerSetup.show(serverSettings); 125 | } 126 | } 127 | else 128 | { 129 | onOwnServerError(); 130 | } 131 | } 132 | else 133 | { 134 | isFirstPeer = true; 135 | 136 | ownServerSetup.show(settings.server); 137 | } 138 | } 139 | 140 | public override function onActionsMute():void 141 | { 142 | nes.muted = !nes.muted; 143 | settings.muted = nes.muted; 144 | actions.muted = nes.muted; 145 | } 146 | 147 | public override function onActionsSetup():void 148 | { 149 | nes.pause(); 150 | setup.show(settings.keyboard); 151 | } 152 | 153 | public override function onActionsUpload():void {} 154 | 155 | public function onSetupSave(joystick:Gamepad):void 156 | { 157 | settings.keyboard = joystick; 158 | nes.updateKeyCodes(joystick.codes); 159 | nes.play(); 160 | setup.visible = false; 161 | } 162 | 163 | public function onSetupCancel():void 164 | { 165 | nes.play(); 166 | setup.visible = false; 167 | } 168 | 169 | protected override function start():void 170 | { 171 | nes.updateKeyCodes(settings.keyboard.codes); 172 | nes.play(); 173 | 174 | checkRoom(); 175 | } 176 | 177 | public function sendInput(input:uint):void 178 | { 179 | session.sendInput(input); 180 | } 181 | 182 | public function sendDummy():void {} 183 | 184 | public function onOwnServerConnected(ip:String, port:int, room:String, frameskip:int):void 185 | { 186 | if(isFirstPeer) 187 | { 188 | var value:String = Base64.encode(JSON.stringify( 189 | { 190 | ip:ip, 191 | port:port, 192 | room:room 193 | })); 194 | 195 | var roomUrl:String = 196 | [ 197 | gameData.domain, 198 | (gameData.locale == 'en' ? '' : '/' + gameData.locale), 199 | '/game/', gameData.system, 200 | '/', gameData.game, 201 | '/rom/', gameData.rom, 202 | '#room=', value 203 | ].join(''); 204 | 205 | Tools.shortLink(roomUrl, function(shortUrl:String):void 206 | { 207 | if(shortUrl) 208 | { 209 | var callbacks:Object = 210 | { 211 | clipboard:function():void 212 | { 213 | System.setClipboard(shortUrl); 214 | 215 | message.show(''+locale.new_send_copied_url+'
' +
216 | locale.waiting_for_connection+'...
'+locale.you_are_connected+'.
' +
223 | locale.remote_url_is+': '+shortUrl+'.
' +
224 | ''+locale.click_here_to_copy_url_to_clipboard+'
' +
225 | locale.and_send_to_friend+'.
'+locale.connection_error+'
'); 230 | } 231 | }); 232 | } 233 | else 234 | { 235 | startPlaying(frameskip); 236 | } 237 | } 238 | 239 | private function startPlaying(frameskip:int):void 240 | { 241 | nes.play(); 242 | nes.updateKeyCodes(settings.keyboard.codes); 243 | nes.initNetworkEmulation(gameData.ntsc, gameData.data, gameData.region, frameskip); 244 | } 245 | 246 | public function onOwnServerDisconnected():void 247 | { 248 | nes.pause(); 249 | message.show(''+locale.connection_has_closed+'!
'); 250 | } 251 | 252 | public function onOwnServerError():void 253 | { 254 | var callbacks:Object = 255 | { 256 | again:function():void 257 | { 258 | ownServerSetup.show(settings.server); 259 | } 260 | }; 261 | 262 | message.show(''+locale.server_connection_error+',
' +
263 | locale.make_sure_entered_correct_ip+'.' +
264 | '
' +
265 | ''+locale.try_again.toUpperCase()+'
'+locale.waiting_for_connection +'...
'); 278 | 279 | settings.server = serverSettings; 280 | 281 | session.connect(serverSettings.ip 282 | , serverSettings.port 283 | , null 284 | , serverSettings.frameskip); 285 | } 286 | 287 | public function onOwnServerInput(input:uint):void 288 | { 289 | if(message.visible) 290 | message.hide(); 291 | 292 | nes.recvInputValue(input); 293 | } 294 | } 295 | } -------------------------------------------------------------------------------- /src/mode/Single.as: -------------------------------------------------------------------------------- 1 | package mode 2 | { 3 | import com.adobe.images.PNGEncoder; 4 | 5 | import core.CorePlayerSingle; 6 | 7 | import flash.display.BitmapData; 8 | import flash.events.KeyboardEvent; 9 | import flash.geom.Matrix; 10 | import flash.geom.Point; 11 | import flash.geom.Rectangle; 12 | import flash.utils.ByteArray; 13 | 14 | import model.Gamepad; 15 | 16 | import ui.Actions; 17 | import ui.ActionsMode; 18 | import ui.IBaseSetup; 19 | import ui.ISetupHandler; 20 | import ui.Message; 21 | import ui.Setup; 22 | import ui.SetupBuilder; 23 | 24 | public class Single extends Base 25 | implements 26 | ISetupHandler 27 | { 28 | private var nes:CorePlayerSingle; 29 | private var setup:IBaseSetup; 30 | private var message:Message; 31 | private var actions:Actions; 32 | private var state:EmulatorState; 33 | 34 | private var lastState:ByteArray; 35 | 36 | public function Single(gameData:GameData) 37 | { 38 | super(gameData); 39 | 40 | nes = new CorePlayerSingle(gameData.core, this); 41 | actions = new Actions(this, ActionsMode.Single); 42 | setup = SetupBuilder.Make(this, gameData); 43 | message = new Message(); 44 | 45 | actions.muted = nes.muted = settings.muted; 46 | actions.visible = false; 47 | actions.loadActive = false; 48 | actions.enableFullscreen = Tools.isInteractiveFullscreenSupported(); 49 | actions.favoriteActive = false; 50 | } 51 | 52 | protected override function init():void 53 | { 54 | addChild(nes); 55 | addChild(actions); 56 | addChild(setup.sprite); 57 | addChild(message); 58 | 59 | state = EmulatorState.Playing; 60 | 61 | super.init(); 62 | } 63 | 64 | protected override function startActionsShow():void 65 | { 66 | super.showActions(actions); 67 | } 68 | 69 | protected override function stopActionsShow():void 70 | { 71 | super.hideActions(actions); 72 | } 73 | 74 | protected override function resume():void 75 | { 76 | super.resume(); 77 | 78 | if(!setup.sprite.visible 79 | && !message.visible) 80 | { 81 | nes.play(); 82 | } 83 | } 84 | 85 | protected override function pause():void 86 | { 87 | if(!setup.sprite.visible 88 | && !message.visible) 89 | { 90 | super.pause(); 91 | nes.pause(); 92 | } 93 | } 94 | 95 | protected override function pauseEmulation():void 96 | { 97 | nes.pause(); 98 | } 99 | 100 | protected override function resumeEmulation():void 101 | { 102 | nes.play(); 103 | } 104 | 105 | // protected override function updateGamepadCodes(codes:Array):void 106 | // { 107 | // nes.updateGamepadCodes(codes); 108 | // } 109 | 110 | protected override function enableFullscreen(enable:Boolean):void 111 | { 112 | actions.enableFullscreen = enable; 113 | } 114 | 115 | // protected override function enableGamepad(enable:Boolean):void 116 | // { 117 | // actions.enableGamepad = enable; 118 | // } 119 | 120 | private function loadState(saveId:String = null):void 121 | { 122 | nes.pause(); 123 | 124 | message.show('' + locale.loading_game + '...
'); 125 | 126 | if(lastState 127 | && lastState.length) 128 | { 129 | onApiLoaded(lastState); 130 | } 131 | else 132 | { 133 | api.loadState(gameData.rom, saveId); 134 | } 135 | } 136 | 137 | private function saveState():void 138 | { 139 | nes.pause(); 140 | 141 | message.show(''+locale.please_wait+'...
'); 142 | 143 | var data:ByteArray = nes.save(); 144 | 145 | if(data && data.bytesAvailable) 146 | { 147 | nes.pause(); 148 | message.show('' + locale.saving_game + '...
'); 149 | 150 | api.save(gameData.rom, data, nes.screen); 151 | } 152 | } 153 | 154 | private function initSaveLoadShortcuts():void 155 | { 156 | stage.addEventListener(KeyboardEvent.KEY_DOWN, function(event:KeyboardEvent):void 157 | { 158 | switch(event.keyCode) 159 | { 160 | case SaveHotkeyCode: 161 | onActionsLoad(); 162 | break; 163 | case LoadHotkeyCode: 164 | onActionsSave(); 165 | // case 114: 166 | // onScreenShot(); 167 | // break; 168 | } 169 | }); 170 | } 171 | 172 | private function onSignIn():void 173 | { 174 | message.hide(); 175 | nes.pause(); 176 | JSProxy.showSignInModal(); 177 | } 178 | 179 | private function onSignUp():void 180 | { 181 | message.hide(); 182 | nes.pause(); 183 | JSProxy.showSignUpModal(); 184 | } 185 | 186 | public function onSetupSave(joystick:Gamepad):void 187 | { 188 | settings.keyboard = joystick; 189 | nes.updateKeyCodes(joystick.codes); 190 | nes.play(); 191 | setup.sprite.visible = false; 192 | } 193 | 194 | public function onSetupCancel():void 195 | { 196 | nes.play(); 197 | setup.sprite.visible = false; 198 | } 199 | 200 | protected override function start():void 201 | { 202 | nes.updateKeyCodes(settings.keyboard.codes); 203 | 204 | initSaveLoadShortcuts(); 205 | nes.initSingleEmulation(gameData.ntsc, gameData.data, gameData.region); 206 | 207 | if(gameData.value && gameData.value.length) 208 | { 209 | if(!Focus.activated) 210 | { 211 | pause(); 212 | } 213 | 214 | state = EmulatorState.Loading; 215 | message.show('' + locale.loading_game + '
'); 216 | 217 | api.loadState(gameData.rom, gameData.value); 218 | } 219 | else 220 | { 221 | api.check(gameData.rom); 222 | } 223 | 224 | api.isFavorited(gameData.rom); 225 | } 226 | 227 | public override function onActionsFavorite():void 228 | { 229 | // api.favorite(gameData.rom, !actions.favorited); 230 | } 231 | 232 | public override function onActionsMute():void 233 | { 234 | nes.muted = !nes.muted; 235 | settings.muted = nes.muted; 236 | actions.muted = nes.muted; 237 | } 238 | 239 | public override function onActionsLoad():void 240 | { 241 | if(actions.loadActive) 242 | { 243 | var handlers:Object = 244 | { 245 | yes:function():void 246 | { 247 | message.hide(); 248 | state = EmulatorState.Loading; 249 | loadState(); 250 | }, 251 | no:function():void 252 | { 253 | message.hide(); 254 | nes.play(); 255 | } 256 | }; 257 | 258 | nes.pause(); 259 | message.show(''+locale.do_you_want_to_load_state+'
'+
260 | '' +
261 | locale.yes.toUpperCase() + ' ' +
262 | locale.or + ' ' +
263 | locale.no.toUpperCase() + '
' + locale.error_occured +
294 | '
' + locale.close.toUpperCase() +
295 | '
' +
341 | locale.you_need_to_be_signed_in_to_save + '
' +
342 | '' + locale.sign_in.toUpperCase()+' ' +
343 | locale.or + ' ' +
344 | locale.sign_up.toUpperCase() + '
' +
345 | ''+locale.cancel.toUpperCase()+'
'+locale.do_you_want_to_load_state + '
' +
394 | '' +
395 | locale.yes.toUpperCase() + ' ' +
396 | locale.or + ' ' +
397 | locale.no.toUpperCase() + '
'+locale.loading_walkthrough+'...
'); 45 | 46 | api.loadWalk(gameData.rom, gameData.value); 47 | } 48 | 49 | protected override function startActionsShow():void 50 | { 51 | super.showActions(actions); 52 | } 53 | 54 | protected override function stopActionsShow():void 55 | { 56 | super.hideActions(actions); 57 | } 58 | 59 | protected override function resume():void 60 | { 61 | super.resume(); 62 | 63 | if(!message.visible) 64 | { 65 | nes.play(); 66 | } 67 | } 68 | 69 | protected override function pause():void 70 | { 71 | if(!message.visible) 72 | { 73 | super.pause(); 74 | nes.pause(); 75 | } 76 | } 77 | 78 | public override function onActionsMute():void 79 | { 80 | nes.muted = !nes.muted; 81 | settings.muted = nes.muted; 82 | actions.muted = nes.muted; 83 | } 84 | 85 | public override function onApiError(info:String):void 86 | { 87 | var callbacks:Object = 88 | { 89 | close:function():void 90 | { 91 | nes.play(); 92 | } 93 | }; 94 | 95 | message.show('Error occurred,
please, try again later...' +
96 | '
CLOSE
' + 128 | [ 129 | hours < 10 ? '0' + hours.toString() : hours 130 | , minutes < 10 ? '0' + minutes.toString() : minutes 131 | , seconds < 10 ? '0' + seconds.toString() : seconds 132 | ].join(':') + '
'; 133 | 134 | frames--; 135 | 136 | if(frames == 0) 137 | { 138 | stage.removeEventListener(Event.ENTER_FRAME, onUpdateTime); 139 | } 140 | } 141 | 142 | protected override function onScreenShot():void 143 | { 144 | api.screen(gameData.rom, nes.screen); 145 | } 146 | } 147 | } -------------------------------------------------------------------------------- /src/model/Gamepad.as: -------------------------------------------------------------------------------- 1 | package model 2 | { 3 | public class Gamepad 4 | { 5 | public var codes:Array; 6 | 7 | private var size:int; 8 | 9 | public function Gamepad(size:int) 10 | { 11 | this.size = size; 12 | codes = new Array(size); 13 | } 14 | 15 | public function get empty():Boolean 16 | { 17 | for(var index:int = 0; index < size; index++) 18 | if(!codes[index]) 19 | return true; 20 | 21 | return false; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/model/ServerSettings.as: -------------------------------------------------------------------------------- 1 | package model 2 | { 3 | public class ServerSettings 4 | { 5 | public var ip:String; 6 | public var port:int; 7 | public var frameskip:int; 8 | 9 | public function ServerSettings(ip:String, port:int, frameskip:int) 10 | { 11 | this.ip = ip; 12 | this.port = port; 13 | this.frameskip = frameskip; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/model/Settings.as: -------------------------------------------------------------------------------- 1 | package model 2 | { 3 | import flash.net.SharedObject; 4 | 5 | public class Settings 6 | { 7 | private var settings:Object = 8 | { 9 | muted:false, 10 | keyboard:null, 11 | server:new ServerSettings('127.0.0.1', 8080, 3) 12 | }; 13 | 14 | private var sharedSettings:SharedObject; 15 | 16 | public function Settings(uid:String) 17 | { 18 | sharedSettings = SharedObject.getLocal(uid); 19 | 20 | var valid:Boolean = false; 21 | 22 | if(sharedSettings.data.settings) 23 | { 24 | valid = true; 25 | 26 | for(var key:String in settings) 27 | { 28 | if(!sharedSettings.data.settings.hasOwnProperty(key)) 29 | { 30 | valid = false; 31 | break; 32 | } 33 | } 34 | } 35 | 36 | if(valid) 37 | { 38 | for(var validKey:String in settings) 39 | { 40 | settings[validKey] = sharedSettings.data.settings[validKey]; 41 | } 42 | sharedSettings.data.settings = settings; 43 | } 44 | else 45 | { 46 | sharedSettings.data.settings = settings; 47 | sharedSettings.flush(); 48 | } 49 | } 50 | 51 | public function get muted():Boolean 52 | { 53 | return settings.muted; 54 | } 55 | 56 | public function set muted(value:Boolean):void 57 | { 58 | settings.muted = value; 59 | sharedSettings.flush(); 60 | } 61 | 62 | public function get keyboard():Gamepad 63 | { 64 | if(settings.keyboard && settings.keyboard as Array) 65 | { 66 | var gamepad:Gamepad = new Gamepad(settings.keyboard.length); 67 | gamepad.codes = settings.keyboard; 68 | return gamepad; 69 | } 70 | 71 | return null; 72 | } 73 | 74 | public function set keyboard(value:Gamepad):void 75 | { 76 | if(value) 77 | { 78 | settings.keyboard = value.codes; 79 | sharedSettings.flush(); 80 | } 81 | } 82 | 83 | public function get server():ServerSettings 84 | { 85 | var serverSettings:ServerSettings = new ServerSettings(settings.server.ip, settings.server.port, settings.server.frameskip); 86 | 87 | return serverSettings; 88 | } 89 | 90 | public function set server(value:ServerSettings):void 91 | { 92 | settings.server = value; 93 | sharedSettings.flush(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/network/INetworkSessionHandler.as: -------------------------------------------------------------------------------- 1 | package network 2 | { 3 | public interface INetworkSessionHandler 4 | { 5 | function onNetworkPeer(value:String):void; 6 | function onNetworkInput(value:uint):void; 7 | function onNetworkTest():void; 8 | function onNetworkStart(isFirstPeer:Boolean, ping:uint):void; 9 | } 10 | } -------------------------------------------------------------------------------- /src/network/IOwnServerSessionHandler.as: -------------------------------------------------------------------------------- 1 | package network 2 | { 3 | public interface IOwnServerSessionHandler 4 | { 5 | function onOwnServerConnected(ip:String, port:int, room:String, frameskip:int):void; 6 | function onOwnServerDisconnected():void; 7 | function onOwnServerError():void; 8 | function onOwnServerInput(input:uint):void; 9 | } 10 | } -------------------------------------------------------------------------------- /src/network/NetworkSession.as: -------------------------------------------------------------------------------- 1 | package network 2 | { 3 | import flash.events.NetStatusEvent; 4 | import flash.net.NetConnection; 5 | import flash.net.NetStream; 6 | import flash.utils.getTimer; 7 | 8 | public class NetworkSession 9 | { 10 | private static const ServerAddress:String = 'rtmfp://p2p.rtmfp.net'; 11 | private static const DeveloperKey:String = '48faff0c77b9daf283b09c73-c7547fd7f58f'; 12 | private static const PublisherType:String = 'snesbox'; 13 | private static const TestIterations:uint = 100; 14 | 15 | private var nc:NetConnection; 16 | 17 | private var myPeerId:String; 18 | private var farPeerId:String; 19 | 20 | private var sendStream:NetStream; 21 | private var recvStream:NetStream; 22 | 23 | private var sendStreamStarted:Boolean; 24 | private var recvStreamStarted:Boolean; 25 | private var isFirstPeer:Boolean; 26 | 27 | public var handler:INetworkSessionHandler; 28 | 29 | public function NetworkSession(handler:INetworkSessionHandler) 30 | { 31 | this.handler = handler; 32 | 33 | nc = new NetConnection(); 34 | 35 | var client:Object = {}; 36 | client.onRelay = function(id:String):void 37 | { 38 | if (!farPeerId || !farPeerId.length) 39 | { 40 | farPeerId = id; 41 | initStreams(); 42 | } 43 | }; 44 | 45 | nc.client = client; 46 | 47 | nc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus) 48 | } 49 | 50 | public function connect(farPeerId:String = ''):void 51 | { 52 | this.farPeerId = farPeerId; 53 | 54 | nc.connect(ServerAddress, DeveloperKey); 55 | } 56 | 57 | private function onNetStatus(event:NetStatusEvent):void 58 | { 59 | switch(event.info.code) 60 | { 61 | case 'NetConnection.Connect.Success': 62 | { 63 | if (!myPeerId) 64 | { 65 | myPeerId = nc.nearID; 66 | 67 | handler.onNetworkPeer(myPeerId); 68 | 69 | var isSecondPeer:Boolean = farPeerId && farPeerId.length == 64; 70 | 71 | isFirstPeer = !isSecondPeer; 72 | 73 | if (isSecondPeer) 74 | { 75 | nc.call('relay', null, farPeerId); 76 | initStreams(); 77 | } 78 | } 79 | } 80 | break; 81 | 82 | case 'NetStream.Connect.Success': 83 | break; 84 | case 'NetStream.Connect.Closed': 85 | break; 86 | } 87 | } 88 | 89 | private function initStreams():void 90 | { 91 | sendStream = new NetStream(nc, NetStream.DIRECT_CONNECTIONS); 92 | sendStream.addEventListener(NetStatusEvent.NET_STATUS, sendStreamStatusHandler); 93 | sendStream.publish(PublisherType); 94 | 95 | recvStream = new NetStream(nc, farPeerId); 96 | recvStream.addEventListener(NetStatusEvent.NET_STATUS, recvStreamStatusHandler); 97 | recvStream.play(PublisherType); 98 | 99 | var recvClient:Object = { }; 100 | var testIndex:uint = TestIterations; 101 | var totalPing:uint = 0; 102 | 103 | recvClient.i = function(value:uint):void 104 | { 105 | var input:uint = value & 0xffffff; 106 | 107 | handler.onNetworkInput(input); 108 | }; 109 | 110 | recvClient.d = function(value:uint):void {}; 111 | 112 | recvClient.ping = function(time:uint):void 113 | { 114 | sendStream.send('pong', time); 115 | } 116 | 117 | recvClient.pong = function(time:uint):void 118 | { 119 | var delta:uint = getTimer() - time; 120 | testIndex--; 121 | totalPing += delta; 122 | 123 | if(testIndex) 124 | { 125 | test(); 126 | } 127 | else 128 | { 129 | var ping:uint = totalPing / TestIterations; 130 | handler.onNetworkStart(isFirstPeer, ping); 131 | } 132 | } 133 | 134 | recvStream.client = recvClient; 135 | } 136 | 137 | private function sendStreamStatusHandler(event:NetStatusEvent):void 138 | { 139 | switch(event.info.code) 140 | { 141 | case 'NetStream.Play.Start': 142 | sendStreamStarted = true; 143 | break; 144 | } 145 | 146 | checkStart(); 147 | } 148 | 149 | private function recvStreamStatusHandler(event:NetStatusEvent):void 150 | { 151 | switch(event.info.code) 152 | { 153 | case 'NetStream.Play.Start': 154 | recvStreamStarted = true; 155 | break; 156 | } 157 | 158 | checkStart(); 159 | } 160 | 161 | private function checkStart():void 162 | { 163 | if (sendStreamStarted 164 | && recvStreamStarted) 165 | { 166 | sendStream.removeEventListener(NetStatusEvent.NET_STATUS, sendStreamStatusHandler); 167 | recvStream.removeEventListener(NetStatusEvent.NET_STATUS, recvStreamStatusHandler); 168 | 169 | handler.onNetworkTest(); 170 | } 171 | } 172 | 173 | public function sendInput(input:uint):void 174 | { 175 | sendStream.send('i', input); 176 | } 177 | 178 | public function sendDummy():void 179 | { 180 | sendStream.send('d', 555); 181 | } 182 | 183 | public function test():void 184 | { 185 | sendStream.send('ping', getTimer()); 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/network/OwnServerSession.as: -------------------------------------------------------------------------------- 1 | package network 2 | { 3 | import flash.events.ErrorEvent; 4 | import flash.events.Event; 5 | import flash.events.IOErrorEvent; 6 | import flash.events.ProgressEvent; 7 | import flash.events.SecurityErrorEvent; 8 | import flash.net.Socket; 9 | 10 | public class OwnServerSession 11 | { 12 | private var socket:Socket; 13 | private var ip:String; 14 | private var port:int; 15 | private var room:String; 16 | private var frameskip:int; 17 | 18 | private var connected:Boolean; 19 | 20 | public var handler:IOwnServerSessionHandler; 21 | 22 | public function OwnServerSession(handler:IOwnServerSessionHandler) 23 | { 24 | this.handler = handler; 25 | 26 | connected = false; 27 | 28 | socket = new Socket(); 29 | 30 | socket.addEventListener(Event.CONNECT, onConnect); 31 | socket.addEventListener(Event.CLOSE, onDisconnect); 32 | socket.addEventListener(IOErrorEvent.IO_ERROR, onError); 33 | socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError); 34 | 35 | socket.addEventListener(ProgressEvent.SOCKET_DATA, onData); 36 | } 37 | 38 | public function connect(ip:String, port:int, room:String, frameskip:int = 0):void 39 | { 40 | this.ip = ip; 41 | this.port = port; 42 | this.frameskip = frameskip; 43 | this.room = room; 44 | 45 | socket.connect(ip, port); 46 | } 47 | 48 | private function onConnect(event:Event):void 49 | { 50 | sendMessage( 51 | { 52 | type:'handshake', 53 | room:room, 54 | frameskip:frameskip 55 | }); 56 | } 57 | 58 | private function onData(event:ProgressEvent):void 59 | { 60 | if(connected) 61 | { 62 | var input:uint = socket.readUnsignedInt() & 0xffffff; 63 | handler.onOwnServerInput(input); 64 | } 65 | else 66 | { 67 | var data:String = socket.readUTFBytes(socket.bytesAvailable); 68 | var response:Object = JSON.parse(data); 69 | 70 | switch(response.type) 71 | { 72 | case 'handshake': 73 | { 74 | var room:String = response.room; 75 | 76 | frameskip = response.frameskip; 77 | 78 | if(room) 79 | { 80 | connected = true; 81 | handler.onOwnServerConnected(ip, port, room, frameskip); 82 | } 83 | 84 | break; 85 | } 86 | } 87 | } 88 | } 89 | 90 | private function onDisconnect(event:Event):void 91 | { 92 | handler.onOwnServerDisconnected(); 93 | } 94 | 95 | private function onError(event:ErrorEvent):void 96 | { 97 | handler.onOwnServerError(); 98 | } 99 | 100 | private function sendMessage(data:Object):void 101 | { 102 | socket.writeUTFBytes(JSON.stringify(data)); 103 | socket.flush(); 104 | } 105 | 106 | public function sendInput(input:uint):void 107 | { 108 | if(connected) 109 | { 110 | socket.writeUnsignedInt(input); 111 | socket.flush(); 112 | } 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/server/Api.as: -------------------------------------------------------------------------------- 1 | package server 2 | { 3 | import flash.utils.ByteArray; 4 | 5 | public class Api 6 | { 7 | public function Api(handler:IApiHandler, domain:String) {} 8 | public function isFavorited(rom:String):void {} 9 | public function favorite(rom:String, value:Boolean):void {} 10 | public function check(rom:String):void {} 11 | public function loadState(rom:String, user:String):void {} 12 | public function loadWalk(rom:String, user:String):void {} 13 | public function save(rom:String, state:ByteArray, screen:ByteArray):void {} 14 | public function uploadWalk(rom:String, walk:ByteArray):void {} 15 | public function screen(rom:String, screen:ByteArray):void {} 16 | } 17 | } -------------------------------------------------------------------------------- /src/server/IApiHandler.as: -------------------------------------------------------------------------------- 1 | package server 2 | { 3 | import flash.utils.ByteArray; 4 | 5 | public interface IApiHandler 6 | { 7 | function onApiError(info:String):void; 8 | function onApiSaved(state:ByteArray):void; 9 | function onApiLoaded(state:ByteArray):void; 10 | function onApiNeedSign():void; 11 | function onApiUserSigned(signed:Boolean):void; 12 | function onApiState(userLogined:Boolean, state:ByteArray):void; 13 | function onApiUploaded():void; 14 | function onApiFavorited(value:Boolean):void; 15 | } 16 | } -------------------------------------------------------------------------------- /src/ui/ActionAsset.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | internal final class ActionAsset 4 | { 5 | [Embed(source='/assets/setup.png')] 6 | public static const SetupButton:Class; 7 | 8 | [Embed(source='/assets/mute.png')] 9 | public static const MuteButton:Class; 10 | 11 | [Embed(source='/assets/load.png')] 12 | public static const LoadButton:Class; 13 | 14 | [Embed(source='/assets/save.png')] 15 | public static const SaveButton:Class; 16 | 17 | [Embed(source='/assets/fullscreen.png')] 18 | public static const FullscreenButton:Class; 19 | 20 | [Embed(source='/assets/upload.png')] 21 | public static const UploadButton:Class; 22 | 23 | [Embed(source='/assets/gamepad.png')] 24 | public static const GamepadButton:Class; 25 | 26 | [Embed(source='/assets/favorite.png')] 27 | public static const FavoriteButton:Class; 28 | 29 | [Embed(source='/assets/facebook.png')] 30 | public static const FacebookButton:Class; 31 | 32 | [Embed(source='/assets/google.png')] 33 | public static const GoogleButton:Class; 34 | 35 | [Embed(source='/assets/twitter.png')] 36 | public static const TwitterButton:Class; 37 | 38 | [Embed(source='/assets/vkontakte.png')] 39 | public static const VkontakteButton:Class; 40 | 41 | [Embed(source='/assets/github.png')] 42 | public static const GithubButton:Class; 43 | 44 | } 45 | } -------------------------------------------------------------------------------- /src/ui/Actions.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | import flash.display.Sprite; 4 | 5 | public class Actions extends Sprite 6 | { 7 | private static const UpColor:uint = 0x000000; 8 | private static const OverColor:uint = 0xffffff; 9 | private static const ToggleColor:uint = 0x9b9b9b; 10 | private static const OffColor:uint = 0x777777; 11 | private static const BackColor:uint = 0x666666; 12 | 13 | private var handler:IActionsHandler; 14 | 15 | private const singleModeButtonsMap:Array = 16 | [ 17 | {name:'setup', icon:ActionAsset.SetupButton, click:setup}, 18 | {name:'mute', icon:ActionAsset.MuteButton, click:mute}, 19 | {name:'save', icon:ActionAsset.SaveButton, click:save}, 20 | {name:'load', icon:ActionAsset.LoadButton, click:load}, 21 | {name:'gamepad', icon:ActionAsset.GamepadButton, click:gamepad}, 22 | {name:'fullscreen', icon:ActionAsset.FullscreenButton, click:fullscreenInteractive} 23 | ]; 24 | 25 | private const ownModeButtonsMap:Array = 26 | [ 27 | {name:'setup', icon:ActionAsset.SetupButton, click:setup}, 28 | {name:'mute', icon:ActionAsset.MuteButton, click:mute}, 29 | {name:'save', icon:ActionAsset.SaveButton, click:save}, 30 | {name:'load', icon:ActionAsset.LoadButton, click:load}, 31 | {name:'gamepad', icon:ActionAsset.GamepadButton, click:gamepad}, 32 | {name:'fullscreen', icon:ActionAsset.FullscreenButton, click:fullscreenInteractive}, 33 | ]; 34 | 35 | private const networkModeButtonsMap:Array = 36 | [ 37 | {name:'setup', icon:ActionAsset.SetupButton, click:setup}, 38 | {name:'mute', icon:ActionAsset.MuteButton, click:mute}, 39 | {name:'gamepad', icon:ActionAsset.GamepadButton, click:gamepad}, 40 | {name:'fullscreen', icon:ActionAsset.FullscreenButton, click:fullscreenInteractive}, 41 | ]; 42 | 43 | private const walkModeButtonsMap:Array = 44 | [ 45 | {name:'mute', icon:ActionAsset.MuteButton, click:mute}, 46 | {name:'fullscreen', icon:ActionAsset.FullscreenButton, click:fullscreen}, 47 | ]; 48 | 49 | private const contestModeButtonsMap:Array = 50 | [ 51 | {name:'setup', icon:ActionAsset.SetupButton, click:setup}, 52 | {name:'mute', icon:ActionAsset.MuteButton, click:mute}, 53 | {name:'upload', icon:ActionAsset.UploadButton, click:upload}, 54 | {name:'gamepad', icon:ActionAsset.GamepadButton, click:gamepad}, 55 | {name:'fullscreen', icon:ActionAsset.FullscreenButton, click:fullscreenInteractive}, 56 | ]; 57 | 58 | private const socialSingleModeButtonsMap:Array = 59 | [ 60 | {name:'setup', icon:ActionAsset.SetupButton, click:setup}, 61 | {name:'mute', icon:ActionAsset.MuteButton, click:mute}, 62 | {name:'save', icon:ActionAsset.SaveButton, click:save}, 63 | {name:'load', icon:ActionAsset.LoadButton, click:load}, 64 | {name:'fullscreen', icon:ActionAsset.FullscreenButton, click:fullscreenInteractive}, 65 | ]; 66 | 67 | private const socialNetworkModeButtonsMap:Array = 68 | [ 69 | {name:'setup', icon:ActionAsset.SetupButton, click:setup}, 70 | {name:'mute', icon:ActionAsset.MuteButton, click:mute}, 71 | {name:'fullscreen', icon:ActionAsset.FullscreenButton, click:fullscreenInteractive}, 72 | ]; 73 | 74 | private const socialButtonsMap:Array = 75 | [ 76 | {name:'github', icon:ActionAsset.GithubButton, click:github}, 77 | ]; 78 | 79 | private var buttons:Array = []; 80 | private var loadActiveValue:Boolean = false; 81 | private var saveActiveValue:Boolean = false; 82 | private var favoriteValue:Boolean = false; 83 | private var favoriteActiveValue:Boolean = false; 84 | private var infoText:Text; 85 | 86 | public static const Height:uint = 16; 87 | 88 | public function Actions(handler:IActionsHandler, mode:ActionsMode) 89 | { 90 | this.handler = handler; 91 | 92 | graphics.beginFill(BackColor); 93 | graphics.drawRect(0, 0, Variables.Width, Height); 94 | graphics.endFill(); 95 | 96 | switch(mode) 97 | { 98 | case ActionsMode.Single: 99 | fillButtons(singleModeButtonsMap); 100 | break; 101 | case ActionsMode.Network: 102 | fillButtons(networkModeButtonsMap); 103 | break; 104 | case ActionsMode.Walk: 105 | fillButtons(walkModeButtonsMap); 106 | break; 107 | case ActionsMode.Contest: 108 | fillButtons(contestModeButtonsMap); 109 | break; 110 | case ActionsMode.SocialSingle: 111 | fillButtons(socialSingleModeButtonsMap); 112 | return; 113 | case ActionsMode.SocialNetwork: 114 | fillButtons(socialNetworkModeButtonsMap); 115 | return; 116 | case ActionsMode.Custom: 117 | fillButtons(ownModeButtonsMap); 118 | break; 119 | } 120 | 121 | fillSocialButtons(); 122 | } 123 | 124 | public function set info(value:String):void 125 | { 126 | if(!infoText) 127 | { 128 | infoText = new Text; 129 | addChild(infoText); 130 | } 131 | 132 | infoText.htmlText = value; 133 | infoText.x = (Variables.Width - infoText.width)/2; 134 | infoText.y = - 1; 135 | } 136 | 137 | private function fillSocialButtons():void 138 | { 139 | var offset:int = Variables.Width - socialButtonsMap.length*Height; 140 | for each(var item:Object in socialButtonsMap) 141 | { 142 | var button:Button = new Button(item.name, item.icon, item.click, 'share'); 143 | addChild(button).x = offset; 144 | offset += Height; 145 | 146 | buttons.push(button); 147 | } 148 | } 149 | 150 | private function fillButtons(map:Array):void 151 | { 152 | var offset:int = 0; 153 | for each(var item:Object in map) 154 | { 155 | var button:Button = new Button(item.name, item.icon, item.click, item.name); 156 | addChild(button).x = offset; 157 | offset += Height; 158 | 159 | buttons.push(button); 160 | } 161 | } 162 | 163 | private function mute():void 164 | { 165 | Analytics.trackActionMuteEvent(); 166 | handler.onActionsMute(); 167 | } 168 | 169 | private function fullscreen():void 170 | { 171 | Analytics.trackActionFullscreenEvent(); 172 | handler.onActionsFullscreen(); 173 | } 174 | 175 | private function fullscreenInteractive():void 176 | { 177 | Analytics.trackActionFullscreenEvent(); 178 | handler.onActionsFullscreenInteractive(); 179 | } 180 | 181 | public function set muted(value:Boolean):void 182 | { 183 | getButton('mute').upColor = value ? ToggleColor : UpColor; 184 | } 185 | 186 | private function load():void 187 | { 188 | Analytics.trackActionLoadEvent(); 189 | handler.onActionsLoad(); 190 | } 191 | 192 | private function save():void 193 | { 194 | Analytics.trackActionSaveEvent(); 195 | handler.onActionsSave(); 196 | } 197 | 198 | private function enableButton(name:String, value:Boolean):void 199 | { 200 | var button:Button = getButton(name); 201 | 202 | if(button) 203 | { 204 | button.enabled = value; 205 | button.upColor = value ? UpColor : OffColor; 206 | } 207 | } 208 | 209 | public function set enableFullscreen(value:Boolean):void 210 | { 211 | enableButton('fullscreen', value); 212 | } 213 | 214 | // public function set enableGamepad(value:Boolean):void 215 | // { 216 | // enableButton('gamepad', value); 217 | // } 218 | 219 | public function set loadActive(value:Boolean):void 220 | { 221 | enableButton('load', value); 222 | loadActiveValue = value; 223 | } 224 | 225 | public function get loadActive():Boolean 226 | { 227 | return loadActiveValue; 228 | } 229 | 230 | public function set saveActive(value:Boolean):void 231 | { 232 | enableButton('save', value); 233 | saveActiveValue = value; 234 | } 235 | 236 | public function get saveActive():Boolean 237 | { 238 | return saveActiveValue; 239 | } 240 | 241 | private function setup():void 242 | { 243 | Analytics.trackActionSetupEvent(); 244 | handler.onActionsSetup(); 245 | } 246 | 247 | private function getButton(name:String):Button 248 | { 249 | for each(var button:Button in buttons) 250 | { 251 | if(button.name == name) 252 | { 253 | return button; 254 | } 255 | } 256 | 257 | return null; 258 | } 259 | 260 | private function upload():void 261 | { 262 | Analytics.trackActionUploadEvent(); 263 | handler.onActionsUpload(); 264 | } 265 | 266 | private function facebook():void 267 | { 268 | Analytics.trackShareFacebookEvent(); 269 | handler.onActionsShareFacebook(); 270 | } 271 | 272 | private function google():void 273 | { 274 | Analytics.trackShareGoogleEvent(); 275 | handler.onActionsShareGoogle(); 276 | } 277 | 278 | private function twitter():void 279 | { 280 | Analytics.trackShareTwitterEvent(); 281 | handler.onActionsShareTwitter(); 282 | } 283 | 284 | private function vkontakte():void 285 | { 286 | Analytics.trackShareVkontakteEvent(); 287 | handler.onActionsShareVkontakte(); 288 | } 289 | 290 | private function github():void 291 | { 292 | handler.onActionsShareGithub(); 293 | } 294 | 295 | private function gamepad():void 296 | { 297 | Analytics.trackActionGamepadEvent(); 298 | handler.onActionsGamepad(); 299 | } 300 | 301 | private function favorite():void 302 | { 303 | Analytics.trackActionFavoriteEvent(); 304 | handler.onActionsFavorite(); 305 | } 306 | 307 | // public function get favorited():Boolean 308 | // { 309 | // return favoriteValue; 310 | // } 311 | // 312 | // public function set favorited(value:Boolean):void 313 | // { 314 | // getButton('favorite').upColor = value ? ToggleColor : UpColor; 315 | // favoriteValue = value; 316 | // } 317 | 318 | public function set favoriteActive(value:Boolean):void 319 | { 320 | enableButton('favorite', value); 321 | favoriteActiveValue = value; 322 | } 323 | 324 | public function get favoriteActive():Boolean 325 | { 326 | return favoriteActiveValue; 327 | } 328 | } 329 | } 330 | -------------------------------------------------------------------------------- /src/ui/ActionsMode.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | public final class ActionsMode 4 | { 5 | public static const Single:ActionsMode = new ActionsMode; 6 | public static const Custom:ActionsMode = new ActionsMode; 7 | public static const Network:ActionsMode = new ActionsMode; 8 | public static const Walk:ActionsMode = new ActionsMode; 9 | public static const Contest:ActionsMode = new ActionsMode; 10 | public static const SocialSingle:ActionsMode = new ActionsMode; 11 | public static const SocialNetwork:ActionsMode = new ActionsMode; 12 | } 13 | } -------------------------------------------------------------------------------- /src/ui/Button.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | import flash.display.Bitmap; 4 | import flash.display.SimpleButton; 5 | import flash.display.Sprite; 6 | import flash.events.Event; 7 | import flash.events.MouseEvent; 8 | import flash.geom.ColorTransform; 9 | import flash.geom.Point; 10 | import flash.geom.Rectangle; 11 | import flash.utils.clearTimeout; 12 | import flash.utils.setTimeout; 13 | 14 | internal final class Button extends SimpleButton 15 | { 16 | private var index:int; 17 | private var upIcon:Bitmap; 18 | private var hintTimerId:uint; 19 | private var hintName:String; 20 | 21 | private static var hint:Text; 22 | 23 | public function Button(name:String, icon:Object, handler:Object, hintName:String, isAlpha:Boolean = false) 24 | { 25 | this.name = name; 26 | this.hintName = hintName; 27 | 28 | tabEnabled = false; 29 | 30 | var up:Sprite = new Sprite; 31 | var over:Sprite = new Sprite; 32 | 33 | upIcon = new icon; 34 | var overIcon:Bitmap = new icon; 35 | 36 | if(isAlpha) 37 | { 38 | overIcon.alpha = .8; 39 | } 40 | else 41 | { 42 | setStateColor(overIcon, 0xffffff); 43 | } 44 | 45 | up.addChild(upIcon); 46 | over.addChild(overIcon); 47 | 48 | super(up, over, up, up); 49 | 50 | addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void 51 | { 52 | hideHint(); 53 | 54 | if(handler != null && enabled) 55 | { 56 | handler(); 57 | } 58 | }); 59 | 60 | addEventListener(MouseEvent.MOUSE_OVER, function(event:MouseEvent):void 61 | { 62 | if(!hintTimerId) 63 | { 64 | hintTimerId = setTimeout(function():void 65 | { 66 | showHint(); 67 | hintTimerId = 0; 68 | }, 300); 69 | } 70 | }); 71 | 72 | addEventListener(MouseEvent.MOUSE_OUT, function(event:MouseEvent):void 73 | { 74 | hideHint(); 75 | }); 76 | 77 | addEventListener(Event.ADDED_TO_STAGE, function(event:Event):void 78 | { 79 | if(!hint) 80 | { 81 | hint = new Text('#000000'); 82 | hint.visible = false; 83 | hint.background = true; 84 | hint.backgroundColor = 0xffffff; 85 | 86 | parent.addChild(hint); 87 | } 88 | }); 89 | } 90 | 91 | private function showHint():void 92 | { 93 | hint.visible = true; 94 | 95 | hint.htmlText = '' + Locale.instance['hint_' + hintName] + '
'; 96 | 97 | const HINT_GAP:int = 2; 98 | hint.x = int(x - (hint.width-16)/2); 99 | hint.y = -(hint.height + HINT_GAP); 100 | 101 | if(hint.x <= 0) 102 | { 103 | hint.x = HINT_GAP; 104 | } 105 | 106 | if(hint.x + hint.width > stage.stageWidth/2) 107 | { 108 | hint.x = stage.stageWidth/2 - hint.width - HINT_GAP; 109 | } 110 | 111 | } 112 | 113 | private function hideHint():void 114 | { 115 | hint.visible = false; 116 | hint.htmlText = ''; 117 | 118 | if(hintTimerId) 119 | { 120 | clearTimeout(hintTimerId); 121 | hintTimerId = 0; 122 | } 123 | } 124 | 125 | private static function setStateColor(stateIcon:Bitmap, color:uint):void 126 | { 127 | var transform:ColorTransform = new ColorTransform; 128 | 129 | transform.color = color; 130 | stateIcon.bitmapData.colorTransform(new Rectangle(0, 0, stateIcon.width, stateIcon.height), transform); 131 | } 132 | 133 | public function set upColor(value:uint):void 134 | { 135 | setStateColor(upIcon, value); 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /src/ui/FullscreenMessage.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | import flash.events.Event; 4 | 5 | public class FullscreenMessage extends Message 6 | { 7 | public function FullscreenMessage() 8 | { 9 | super(); 10 | scale = 2; 11 | } 12 | 13 | protected override function onAddedToStage(event:Event):void 14 | { 15 | x = y = 0; 16 | alpha = .95; 17 | 18 | graphics.beginFill(0x666666); 19 | graphics.drawRect(0, 0, stage.fullScreenWidth, stage.fullScreenHeight); 20 | graphics.endFill(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/ui/IActionsHandler.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | public interface IActionsHandler 4 | { 5 | function onActionsMute():void; 6 | function onActionsFullscreen():void; 7 | function onActionsFullscreenInteractive():void; 8 | function onActionsLoad():void; 9 | function onActionsSave():void; 10 | function onActionsSetup():void; 11 | function onActionsUpload():void; 12 | function onActionsGamepad():void; 13 | function onActionsFavorite():void; 14 | 15 | function onActionsShareFacebook():void; 16 | function onActionsShareGoogle():void; 17 | function onActionsShareTwitter():void; 18 | function onActionsShareVkontakte():void; 19 | function onActionsShareGithub():void; 20 | } 21 | } -------------------------------------------------------------------------------- /src/ui/IBaseSetup.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | import flash.display.DisplayObject; 4 | 5 | import model.Gamepad; 6 | 7 | public interface IBaseSetup 8 | { 9 | function show(gamepad:Gamepad):void; 10 | function get sprite():DisplayObject; 11 | function get visible():Boolean; 12 | function set visible(value:Boolean):void; 13 | } 14 | } -------------------------------------------------------------------------------- /src/ui/IOwnServerSetupHandler.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | import model.ServerSettings; 4 | 5 | public interface IOwnServerSetupHandler 6 | { 7 | function onOwnServerSetupConnect(serverSettings:ServerSettings):void; 8 | } 9 | } -------------------------------------------------------------------------------- /src/ui/ISetupHandler.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | import model.Gamepad; 4 | 5 | public interface ISetupHandler 6 | { 7 | function onSetupSave(joystick:Gamepad):void; 8 | function onSetupCancel():void; 9 | } 10 | } -------------------------------------------------------------------------------- /src/ui/ISignHandler.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | public interface ISignHandler 4 | { 5 | function onSignin(login:String, password:String):void; 6 | function onSignup(login:String, email:String, password:String):void; 7 | function onSigninCancel():void; 8 | } 9 | } -------------------------------------------------------------------------------- /src/ui/Keyboard.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | internal final class Keyboard 4 | { 5 | public static const Keys:Object = 6 | { 7 | '110' : 'numpad decimal' 8 | , '108' : 'numpad enter' 9 | , '111' : 'numpad divide' 10 | , '38' : 'up' 11 | , '117' : 'f6' 12 | , '191' : 'slash' 13 | , '107' : 'numpad add' 14 | , '105' : 'numpad 9' 15 | , '221' : 'rightbracket' 16 | , '116' : 'f5' 17 | , '21' : 'numpad' 18 | , '55' : 'number 7' 19 | , '97' : 'numpad 1' 20 | , '189' : 'minus' 21 | , '118' : 'f7' 22 | , '119' : 'f8' 23 | , '57' : 'number 9' 24 | , '120' : 'f9' 25 | , '9' : 'tab' 26 | , '35' : 'end' 27 | , '219' : 'leftbracket' 28 | , '36' : 'home' 29 | , '45' : 'insert' 30 | , '65' : 'a' 31 | , '70' : 'f' 32 | , '115' : 'f4' 33 | , '112' : 'f1' 34 | , '186' : 'semicolon' 35 | , '67' : 'c' 36 | , '102' : 'numpad 6' 37 | , '68' : 'd' 38 | , '66' : 'b' 39 | , '104' : 'numpad 8' 40 | , '69' : 'e' 41 | , '54' : 'number 6' 42 | , '75' : 'k' 43 | , '56' : 'number 8' 44 | , '190' : 'period' 45 | , '72' : 'h' 46 | , '222' : 'quote' 47 | , '73' : 'i' 48 | , '49' : 'number 1' 49 | , '101' : 'numpad 5' 50 | , '48' : 'number 0' 51 | , '79' : 'o' 52 | , '17' : 'control' 53 | , '33' : 'page up' 54 | , '76' : 'l' 55 | , '71' : 'g' 56 | , '74' : 'j' 57 | , '81' : 'q' 58 | , '77' : 'm' 59 | , '16' : 'shift' 60 | , '78' : 'n' 61 | , '125' : 'f14' 62 | , '83' : 's' 63 | , '126' : 'f15' 64 | , '84' : 't' 65 | , '80' : 'p' 66 | , '85' : 'u' 67 | , '114' : 'f3' 68 | , '86' : 'v' 69 | , '82' : 'r' 70 | , '27' : 'escape' 71 | , '53' : 'number 5' 72 | , '87' : 'w' 73 | , '52' : 'number 4' 74 | , '124' : 'f13' 75 | , '88' : 'x' 76 | , '32' : 'space' 77 | , '89' : 'y' 78 | , '113' : 'f2' 79 | , '121' : 'f10' 80 | , '90' : 'z' 81 | , '122' : 'f11' 82 | , '187' : 'equal' 83 | , '103' : 'numpad 7' 84 | , '13' : 'enter' 85 | , '123' : 'f12' 86 | , '39' : 'right' 87 | , '100' : 'numpad 4' 88 | , '37' : 'left' 89 | , '15' : 'command' 90 | , '8' : 'backspace' 91 | , '188' : 'comma' 92 | , '46' : 'delete' 93 | , '51' : 'number 3' 94 | , '106' : 'numpad multiply' 95 | , '220' : 'backslash' 96 | , '99' : 'numpad 3' 97 | , '20' : 'caps lock' 98 | , '96' : 'numpad 0' 99 | , '109' : 'numpad subtract' 100 | , '34' : 'page down' 101 | , '50' : 'number 2' 102 | , '40' : 'down' 103 | , '192' : 'backquote' 104 | , '18' : 'alternate' 105 | , '98' : 'numpad 2' 106 | }; 107 | } 108 | } -------------------------------------------------------------------------------- /src/ui/Message.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | import flash.display.Sprite; 4 | import flash.events.Event; 5 | import flash.events.TextEvent; 6 | import flash.text.StyleSheet; 7 | import flash.text.TextFieldAutoSize; 8 | import flash.text.TextFormat; 9 | import flash.text.TextFormatAlign; 10 | 11 | public class Message extends Sprite 12 | { 13 | protected var scale:int = 1; 14 | 15 | public function Message() 16 | { 17 | visible = false; 18 | 19 | addEventListener(Event.ADDED_TO_STAGE, onAddedToStage); 20 | } 21 | 22 | protected function onAddedToStage(event:Event):void 23 | { 24 | x = y = 0; 25 | alpha = .95; 26 | 27 | graphics.beginFill(0x666666); 28 | graphics.drawRect(0, 0, Variables.Width, Variables.Height); 29 | graphics.endFill(); 30 | } 31 | 32 | public function show(value:String, handler:Object = null):void 33 | { 34 | visible = value.length > 0; 35 | 36 | this.removeChildren(); 37 | 38 | const LINE_HEIGHT:int = 10; 39 | var parts:Array = value.split('').join(''); 56 | part = part.split('
').join(''); 57 | 58 | var field:Text = new Text; 59 | field.multiline = true; 60 | field.autoSize = TextFieldAutoSize.NONE; 61 | field.wordWrap = true; 62 | 63 | var style:Object = field.styleSheet.getStyle('p'); 64 | style.textAlign = 'center'; 65 | field.styleSheet.setStyle('p', style); 66 | 67 | field.addEventListener(TextEvent.LINK, onInfoLink); 68 | field.htmlText = ['', part, '
'].join(''); 69 | 70 | field.width = int((width-32)/scale); 71 | field.x = 16/scale; 72 | field.y = int(vertPos); 73 | 74 | vertPos += LINE_HEIGHT; 75 | 76 | addChild(field); 77 | } 78 | } 79 | 80 | public function hide():void 81 | { 82 | show(''); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /src/ui/OwnServerSetup.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | import flash.display.Sprite; 4 | import flash.events.TextEvent; 5 | 6 | import model.ServerSettings; 7 | 8 | public class OwnServerSetup extends Sprite 9 | { 10 | private var title:Text; 11 | 12 | private var howToLabel:Text; 13 | 14 | private var ipLabel:Text; 15 | private var ipInput:TextInput; 16 | 17 | private var portLabel:Text; 18 | private var portInput:TextInput; 19 | 20 | private var frameskipLabel:Text; 21 | private var frameskipInput:TextInput; 22 | 23 | private var buttons:Text; 24 | 25 | private var handler:IOwnServerSetupHandler; 26 | 27 | private var locale:Locale; 28 | 29 | public function OwnServerSetup(handler:IOwnServerSetupHandler) 30 | { 31 | super(); 32 | 33 | locale = Locale.instance; 34 | 35 | this.handler = handler; 36 | 37 | visible = false; 38 | 39 | title = new Text; 40 | title.htmlText = ''+locale.server_setup.toUpperCase()+'
'; 41 | addChild(title); 42 | 43 | howToLabel = new Text(); 44 | howToLabel.htmlText = '' 45 | + locale.please_read 46 | + ': '+locale.how_start_own_server+'?
'; 47 | addChild(howToLabel); 48 | 49 | ipLabel = new Text; 50 | ipLabel.htmlText = 'IP:
'; 51 | addChild(ipLabel); 52 | 53 | portLabel = new Text; 54 | portLabel.htmlText = ''+locale.server_port+':
'; 55 | addChild(portLabel); 56 | 57 | ipInput = new TextInput(); 58 | addChild(ipInput); 59 | 60 | portInput = new TextInput(); 61 | addChild(portInput); 62 | 63 | frameskipLabel = new Text; 64 | frameskipLabel.htmlText = ''+locale.server_frameskip+':
'; 65 | addChild(frameskipLabel); 66 | 67 | frameskipInput = new TextInput(); 68 | addChild(frameskipInput); 69 | 70 | buttons = new Text(); 71 | buttons.htmlText = '' + 72 | ''+locale.connect.toLocaleUpperCase()+'
'; 73 | buttons.addEventListener(TextEvent.LINK, onLink); 74 | addChild(buttons); 75 | } 76 | 77 | public function show(serverSettings:ServerSettings):void 78 | { 79 | ipInput.text = serverSettings.ip; 80 | portInput.text = serverSettings.port.toString(); 81 | frameskipInput.text = serverSettings.frameskip.toString(); 82 | 83 | update(); 84 | 85 | visible = true; 86 | } 87 | 88 | private function update():void 89 | { 90 | graphics.clear(); 91 | graphics.beginFill(0x666666); 92 | graphics.drawRect(0, 0, Variables.Width, Variables.Height); 93 | graphics.endFill(); 94 | 95 | const Gap:int = 10; 96 | 97 | title.x = (Variables.Width - title.width) / 2; 98 | title.y = Gap; 99 | 100 | howToLabel.x = Gap; 101 | howToLabel.y = title.y + title.height + Gap; 102 | 103 | ipLabel.x = Gap; 104 | ipLabel.y = howToLabel.y + howToLabel.height + Gap; 105 | 106 | ipInput.x = ipLabel.x + ipLabel.width; 107 | ipInput.y = ipLabel.y; 108 | ipInput.width = 80; 109 | ipInput.height = ipLabel.height; 110 | 111 | portLabel.x = ipLabel.x; 112 | portLabel.y = ipInput.y + ipInput.height + Gap; 113 | 114 | portInput.x = portLabel.x + portLabel.width; 115 | portInput.y = portLabel.y; 116 | portInput.width = 40; 117 | portInput.height = portLabel.height; 118 | 119 | frameskipLabel.x = portLabel.x; 120 | frameskipLabel.y = portInput.y + portInput.height + Gap; 121 | 122 | frameskipInput.x = frameskipLabel.x + frameskipLabel.width; 123 | frameskipInput.y = frameskipLabel.y; 124 | frameskipInput.width = 40; 125 | frameskipInput.height = frameskipLabel.height; 126 | 127 | buttons.x = (Variables.Width - buttons.width) / 2; 128 | buttons.y = portInput.y + portInput.height + Gap*5; 129 | } 130 | 131 | private function onLink(event:TextEvent):void 132 | { 133 | switch(event.text) 134 | { 135 | case 'connect': 136 | connect(); 137 | break; 138 | } 139 | } 140 | 141 | private function connect():void 142 | { 143 | handler.onOwnServerSetupConnect(new ServerSettings(ipInput.text, int(portInput.text), int(frameskipInput.text))); 144 | } 145 | } 146 | } -------------------------------------------------------------------------------- /src/ui/Setup.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | import flash.display.DisplayObject; 4 | import flash.display.Sprite; 5 | import flash.events.KeyboardEvent; 6 | import flash.events.MouseEvent; 7 | import flash.events.TextEvent; 8 | 9 | import model.Gamepad; 10 | 11 | internal class Setup extends Sprite implements IBaseSetup 12 | { 13 | private var joystickSprite:Sprite; 14 | private var title:Text; 15 | private var info:Text; 16 | private var leftKeys:Sprite; 17 | private var middleKeys:Sprite; 18 | private var rightKeys:Sprite; 19 | private var buttons:Text; 20 | private var defaults:Text; 21 | private var joystickData:Gamepad; 22 | private var assigning:String; 23 | private var gamepadModule:IGamepadModule; 24 | private var keyNames:Array; 25 | private var locale:Locale; 26 | 27 | private var handler:ISetupHandler; 28 | 29 | public function Setup(handler:ISetupHandler, gamepadModule:IGamepadModule) 30 | { 31 | super(); 32 | 33 | locale = Locale.instance; 34 | 35 | this.handler = handler; 36 | this.gamepadModule = gamepadModule; 37 | 38 | keyNames = gamepadModule.getGamepadKeysNames(); 39 | 40 | visible = false; 41 | 42 | initJoystick(); 43 | 44 | title = new Text; 45 | title.htmlText = '' + locale.keyboard_setup.toUpperCase() + '
'; 46 | addChild(title); 47 | 48 | info = new Text; 49 | info.htmlText = '' + locale.select_joystick_button + '...
'; 50 | addChild(info); 51 | 52 | leftKeys = new Sprite; 53 | addChild(leftKeys); 54 | 55 | middleKeys = new Sprite; 56 | addChild(middleKeys); 57 | 58 | rightKeys = new Sprite; 59 | addChild(rightKeys); 60 | 61 | defaults = new Text; 62 | defaults.htmlText = ''; 63 | addChild(defaults); 64 | defaults.addEventListener(TextEvent.LINK, onLink); 65 | 66 | buttons = new Text; 67 | buttons.htmlText = '' + 68 | locale.save.toUpperCase() + 69 | ' ' + locale.or + ' ' + 70 | locale.cancel.toUpperCase() + '
'; 71 | addChild(buttons); 72 | buttons.addEventListener(TextEvent.LINK, onLink); 73 | } 74 | 75 | public function get sprite():DisplayObject 76 | { 77 | return this; 78 | } 79 | 80 | public function show(joystick:Gamepad):void 81 | { 82 | visible = true; 83 | buttons.htmlText = '' + 84 | locale.save.toUpperCase() + 85 | ' ' + locale.or + ' ' + 86 | locale.cancel.toUpperCase() + '
'; 87 | 88 | joystickData = new Gamepad(0); 89 | joystickData.codes = joystick.codes.slice(); 90 | 91 | update(); 92 | } 93 | 94 | private function initJoystick():void 95 | { 96 | joystickSprite = new Sprite; 97 | joystickSprite.addChild(gamepadModule.getGamepadImage()); 98 | addChild(joystickSprite); 99 | 100 | var keyNames:Array = gamepadModule.getGamepadKeysNames(); 101 | 102 | for each(var name:String in keyNames) 103 | { 104 | var gamepadButton:GamepadButton = gamepadModule.getGamepadButton(name); 105 | var button:Sprite = new Sprite; 106 | 107 | button.addChild(gamepadButton.bitmap); 108 | joystickSprite.addChild(button); 109 | 110 | button.x = gamepadButton.x; 111 | button.y = gamepadButton.y; 112 | button.buttonMode = true; 113 | button.name = gamepadButton.name; 114 | 115 | button.addEventListener(MouseEvent.MOUSE_OVER, function(event:MouseEvent):void 116 | { 117 | Sprite(event.target).alpha = .6; 118 | }); 119 | 120 | button.addEventListener(MouseEvent.MOUSE_OUT, function(event:MouseEvent):void 121 | { 122 | Sprite(event.target).alpha = 1; 123 | }); 124 | 125 | button.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void 126 | { 127 | assignKey(Sprite(event.target).name); 128 | }); 129 | } 130 | } 131 | 132 | private function assignKey(name:String):void 133 | { 134 | assigning = name; 135 | 136 | joystickData.codes[keyNames.indexOf(assigning)] = 0; 137 | 138 | updateKeys(); 139 | 140 | stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); 141 | } 142 | 143 | private function onKeyDown(event:KeyboardEvent):void 144 | { 145 | var key:uint = event.keyCode; 146 | 147 | joystickData.codes[keyNames.indexOf(assigning)] = key; 148 | 149 | assigning = ''; 150 | 151 | updateKeys(); 152 | 153 | stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); 154 | } 155 | 156 | private function update():void 157 | { 158 | graphics.clear(); 159 | graphics.beginFill(0x666666); 160 | graphics.drawRect(0, 0, Variables.Width, Variables.Height); 161 | graphics.endFill(); 162 | 163 | title.x = (Variables.Width - title.width) / 2; 164 | title.y = 4; 165 | 166 | info.x = (Variables.Width - info.width) / 2; 167 | info.y = title.y + title.height; 168 | 169 | joystickSprite.x = (Variables.Width - joystickSprite.width) / 2; 170 | joystickSprite.y = info.y + info.height; 171 | 172 | defaults.x = (Variables.Width - defaults.width) / 2; 173 | defaults.y = joystickSprite.y + joystickSprite.height; 174 | 175 | updateKeys(); 176 | 177 | leftKeys.x = 10; 178 | middleKeys.x = int(Variables.Width / 3) + leftKeys.x; 179 | rightKeys.x = int(Variables.Width / 3) + middleKeys.x; 180 | 181 | leftKeys.y = middleKeys.y = rightKeys.y = defaults.y + defaults.height; 182 | 183 | buttons.x = (Variables.Width - buttons.width) / 2; 184 | buttons.y = leftKeys.y + leftKeys.height - 4; 185 | 186 | } 187 | 188 | private function getKeyText(value:int):String 189 | { 190 | if(joystickData && joystickData.codes) 191 | { 192 | var text:String = Keyboard.Keys[joystickData.codes[value]]; 193 | 194 | if(text && text.length) 195 | { 196 | return text.toUpperCase(); 197 | } 198 | 199 | } 200 | 201 | return '...'; 202 | } 203 | 204 | private function updateKeys():void 205 | { 206 | var fill:Function = function(parent:Sprite, data:Array):void 207 | { 208 | var vertPos:int = 0; 209 | 210 | for each(var item:String in data) 211 | { 212 | var text:Text = new Text(assigning == item ? '#ffffff' : '#cccccc'); 213 | 214 | text.styleSheet.setStyle('.' + item, 215 | { 216 | color: assigning == item ? '#ffffff' : '#cccccc' 217 | }); 218 | 219 | text.htmlText += '' + item + ' - ' 221 | + getKeyText(keyNames.indexOf(item)) + '
'; 222 | 223 | text.y = vertPos; 224 | vertPos += 12; 225 | 226 | parent.addChild(text); 227 | } 228 | }; 229 | 230 | leftKeys.removeChildren(); 231 | middleKeys.removeChildren(); 232 | rightKeys.removeChildren(); 233 | 234 | if(keyNames.length >= 4) 235 | { 236 | fill(leftKeys, keyNames.slice(0, 4)); 237 | } 238 | 239 | if(keyNames.length >= 8) 240 | { 241 | fill(middleKeys, keyNames.slice(4, 8)); 242 | } 243 | 244 | if(keyNames.length >= 12) 245 | { 246 | fill(rightKeys, keyNames.slice(8, 12)); 247 | } 248 | 249 | buttons.visible = !joystickData.empty; 250 | } 251 | 252 | private function onLink(event:TextEvent):void 253 | { 254 | switch(event.text) 255 | { 256 | case 'save': 257 | save(); 258 | break; 259 | case 'cancel': 260 | cancel(); 261 | break; 262 | // case 'done': 263 | // done(); 264 | // break; 265 | case 'defaults': 266 | loadDefaults(); 267 | break; 268 | } 269 | } 270 | 271 | private function save():void 272 | { 273 | handler.onSetupSave(joystickData); 274 | } 275 | 276 | private function cancel():void 277 | { 278 | handler.onSetupCancel(); 279 | } 280 | 281 | // private function done():void 282 | // { 283 | // handler.onSetupDone(joystickData); 284 | // } 285 | 286 | private function loadDefaults():void 287 | { 288 | joystickData.codes = gamepadModule.getGamepadDefaultKeys(); 289 | 290 | updateKeys(); 291 | } 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /src/ui/SetupBuilder.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | public class SetupBuilder 4 | { 5 | public static function Make(handler:ISetupHandler, gameData:GameData):IBaseSetup 6 | { 7 | var isTutorial:Boolean = gameData.system == 'gb' || gameData.system == 'gba'; 8 | 9 | return isTutorial 10 | ? new SetupTutorial(handler, gameData.core) 11 | : new Setup(handler, gameData.core); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/ui/SetupTutorial.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | import flash.display.DisplayObject; 4 | import flash.display.Sprite; 5 | import flash.events.KeyboardEvent; 6 | import flash.events.TextEvent; 7 | import flash.text.StyleSheet; 8 | import model.Gamepad; 9 | 10 | 11 | public class SetupTutorial extends Sprite implements IBaseSetup 12 | { 13 | private var locale:Locale; 14 | private var gamepadModule:IGamepadModule; 15 | private var joystickData:Gamepad; 16 | private var keyNames:Array; 17 | 18 | private var title:Text; 19 | private var keysText:Text; 20 | private var message:Message; 21 | private var assigning:String; 22 | private var defaults:Text; 23 | private var buttons:Text; 24 | 25 | private var handler:ISetupHandler; 26 | 27 | public function SetupTutorial(handler:ISetupHandler, gamepadModule:IGamepadModule) 28 | { 29 | super(); 30 | 31 | locale = Locale.instance; 32 | 33 | this.handler = handler; 34 | this.gamepadModule = gamepadModule; 35 | 36 | keyNames = gamepadModule.getGamepadKeysNames(); 37 | 38 | visible = false; 39 | 40 | { 41 | title = new Text; 42 | title.htmlText = '' + locale.keyboard_setup.toUpperCase() + '
'; 43 | addChild(title); 44 | } 45 | 46 | { 47 | keysText = new Text(); 48 | keysText.multiline = true; 49 | 50 | var style:StyleSheet = keysText.styleSheet; 51 | 52 | style.setStyle('a', {textDecoration : 'none'}); 53 | style.setStyle('a:hover', {textDecoration : 'underline'}); 54 | 55 | keysText.styleSheet = style; 56 | addChild(keysText); 57 | 58 | keysText.addEventListener(TextEvent.LINK, assignButton); 59 | } 60 | 61 | { 62 | defaults = new Text; 63 | defaults.htmlText = '' + 64 | locale.load_defaults + '
'; 65 | addChild(defaults); 66 | defaults.addEventListener(TextEvent.LINK, onLink); 67 | } 68 | 69 | { 70 | buttons = new Text; 71 | buttons.htmlText = '' + 72 | locale.save.toUpperCase() + 73 | ' ' + locale.or + ' ' + 74 | locale.cancel.toUpperCase() + '
'; 75 | addChild(buttons); 76 | buttons.addEventListener(TextEvent.LINK, onLink); 77 | } 78 | 79 | message = new Message(); 80 | addChild(message); 81 | 82 | } 83 | 84 | private function onLink(event:TextEvent):void 85 | { 86 | switch(event.text) 87 | { 88 | case 'save': 89 | save(); 90 | break; 91 | case 'cancel': 92 | cancel(); 93 | break; 94 | case 'defaults': 95 | loadDefaults(); 96 | break; 97 | } 98 | } 99 | 100 | private function save():void 101 | { 102 | handler.onSetupSave(joystickData); 103 | } 104 | 105 | private function cancel():void 106 | { 107 | handler.onSetupCancel(); 108 | } 109 | 110 | private function loadDefaults():void 111 | { 112 | joystickData.codes = gamepadModule.getGamepadDefaultKeys(); 113 | 114 | updateKeys(); 115 | } 116 | 117 | private function onKey(event:KeyboardEvent):void 118 | { 119 | var key:uint = event.keyCode; 120 | 121 | joystickData.codes[keyNames.indexOf(assigning)] = key; 122 | assigning = ''; 123 | updateKeys(); 124 | 125 | stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKey); 126 | message.hide(); 127 | } 128 | 129 | private function assignButton(event:TextEvent):void 130 | { 131 | assigning = event.text; 132 | 133 | stage.addEventListener(KeyboardEvent.KEY_DOWN, onKey); 134 | 135 | var callbacks:Object = 136 | { 137 | cancel:function():void 138 | { 139 | stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKey); 140 | message.hide(); 141 | } 142 | }; 143 | 144 | message.show('Please, press button on your keyboard to assign...
' +
145 | 'CANCEL
' + htmlText + '
'; 196 | } 197 | 198 | private function getKeyText(value:int):String 199 | { 200 | if(joystickData && joystickData.codes) 201 | { 202 | var text:String = Keyboard.Keys[joystickData.codes[value]]; 203 | 204 | if(text && text.length) 205 | { 206 | return text.toUpperCase(); 207 | } 208 | } 209 | 210 | return '...'; 211 | } 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/ui/TextInput.as: -------------------------------------------------------------------------------- 1 | package ui 2 | { 3 | import flash.text.TextField; 4 | import flash.text.TextFieldType; 5 | import flash.text.TextFormat; 6 | 7 | internal class TextInput extends TextField 8 | { 9 | private var format:TextFormat; 10 | 11 | public function TextInput(defaultText:String = '') 12 | { 13 | background = true; 14 | backgroundColor = 0x888888; 15 | type = TextFieldType.INPUT; 16 | tabEnabled = true; 17 | 18 | format = new TextFormat; 19 | 20 | format.font = 'verdana'; 21 | format.color = 0xffffff; 22 | format.size = 8; 23 | 24 | text = defaultText; 25 | } 26 | 27 | public override function set text(value:String):void 28 | { 29 | super.text = value; 30 | 31 | setTextFormat(format); 32 | } 33 | } 34 | } --------------------------------------------------------------------------------