From 0b24c03068d5951e49b8dfe040dc6fef94c2a9d4 Mon Sep 17 00:00:00 2001 From: shmyga Date: Mon, 13 Jul 2026 22:41:32 +0300 Subject: [PATCH] style: format code --- .editorconfig | 5 +- .env.default | 5 +- hxformat.json | 3 + scripts/format | 1 + scripts/lint | 1 + src/client/haxe/ru/m/Device.hx | 62 +- src/client/haxe/ru/m/animate/Animate.hx | 73 +- .../haxe/ru/m/animate/AnimateManager.hx | 44 +- src/client/haxe/ru/m/animate/OnceAnimate.hx | 31 +- src/client/haxe/ru/m/control/ControlBus.hx | 55 +- src/client/haxe/ru/m/control/DeviceAction.hx | 4 +- src/client/haxe/ru/m/control/DeviceType.hx | 8 +- src/client/haxe/ru/m/control/IControlBus.hx | 10 +- .../haxe/ru/m/control/IControlDevice.hx | 6 +- .../haxe/ru/m/control/JoystickDevice.hx | 89 ++- .../haxe/ru/m/control/KeyboardDevice.hx | 49 +- .../display/DisplayObjectContainerExtender.hx | 23 +- src/client/haxe/ru/m/skin/ButtonSVGSkin.hx | 75 +- src/client/haxe/ru/m/tankz/AppTheme.hx | 292 ++++--- src/client/haxe/ru/m/tankz/Client.hx | 82 +- src/client/haxe/ru/m/tankz/Const.hx | 24 +- src/client/haxe/ru/m/tankz/Init.hx | 94 +-- src/client/haxe/ru/m/tankz/LinuxIcon.hx | 31 +- src/client/haxe/ru/m/tankz/Preloader.hx | 210 +++-- .../ru/m/tankz/bundle/ClientLevelSource.hx | 37 +- .../haxe/ru/m/tankz/bundle/ConfigBundle.hx | 17 +- src/client/haxe/ru/m/tankz/control/Binding.hx | 4 +- .../haxe/ru/m/tankz/control/HumanControl.hx | 171 ++-- src/client/haxe/ru/m/tankz/game/GameInit.hx | 6 +- .../ru/m/tankz/local/LocalControlFactory.hx | 7 +- src/client/haxe/ru/m/tankz/local/LocalGame.hx | 49 +- .../haxe/ru/m/tankz/local/StageCaller.hx | 37 +- .../haxe/ru/m/tankz/network/NetworkControl.hx | 11 +- .../m/tankz/network/NetworkControlFactory.hx | 13 +- .../haxe/ru/m/tankz/network/NetworkGame.hx | 66 +- .../haxe/ru/m/tankz/network/NetworkManager.hx | 300 ++++--- .../haxe/ru/m/tankz/render/AnimateBundle.hx | 57 +- src/client/haxe/ru/m/tankz/render/IRender.hx | 8 +- src/client/haxe/ru/m/tankz/render/Render.hx | 510 ++++++------ .../haxe/ru/m/tankz/render/RenderUtil.hx | 33 +- .../m/tankz/render/item/BitmapRenderItem.hx | 38 +- .../ru/m/tankz/render/item/BonusRenderItem.hx | 44 +- .../ru/m/tankz/render/item/BrickRenderItem.hx | 171 ++-- .../m/tankz/render/item/BulletRenderItem.hx | 32 +- .../ru/m/tankz/render/item/EagleRenderItem.hx | 82 +- .../ru/m/tankz/render/item/IRenderItem.hx | 10 +- .../haxe/ru/m/tankz/render/item/RenderItem.hx | 73 +- .../ru/m/tankz/render/item/TankRenderItem.hx | 286 +++---- .../haxe/ru/m/tankz/sound/SoundManager.hx | 202 ++--- .../haxe/ru/m/tankz/storage/GameStorage.hx | 23 +- .../haxe/ru/m/tankz/storage/NetworkStorage.hx | 23 +- .../haxe/ru/m/tankz/storage/RecordStorage.hx | 55 +- .../ru/m/tankz/storage/SettingsStorage.hx | 163 ++-- src/client/haxe/ru/m/tankz/view/ClientView.hx | 51 +- src/client/haxe/ru/m/tankz/view/GameFrame.hx | 290 +++---- src/client/haxe/ru/m/tankz/view/LevelFrame.hx | 80 +- src/client/haxe/ru/m/tankz/view/MenuFrame.hx | 124 +-- .../haxe/ru/m/tankz/view/RecordFrame.hx | 25 +- .../haxe/ru/m/tankz/view/ResultFrame.hx | 76 +- .../haxe/ru/m/tankz/view/SettingsFrame.hx | 54 +- src/client/haxe/ru/m/tankz/view/StartFrame.hx | 197 +++-- src/client/haxe/ru/m/tankz/view/ViewUtil.hx | 76 +- .../m/tankz/view/common/NetworkStateView.hx | 91 ++- .../haxe/ru/m/tankz/view/common/PackView.hx | 39 +- .../haxe/ru/m/tankz/view/common/RecordView.hx | 56 +- .../haxe/ru/m/tankz/view/common/SlotView.hx | 57 +- .../haxe/ru/m/tankz/view/common/TankView.hx | 25 +- .../haxe/ru/m/tankz/view/game/PlayerView.hx | 71 +- .../haxe/ru/m/tankz/view/game/TeamView.hx | 47 +- .../m/tankz/view/gamepad/CircleActionArea.hx | 24 +- .../view/gamepad/DefaultActionAreaBuilder.hx | 55 +- .../ru/m/tankz/view/gamepad/GamepadSkin.hx | 49 +- .../ru/m/tankz/view/gamepad/GamepadView.hx | 203 +++-- .../ru/m/tankz/view/gamepad/IActionArea.hx | 6 +- .../tankz/view/gamepad/IActionAreaBuilder.hx | 2 +- .../tankz/view/gamepad/RectangleActionArea.hx | 24 +- .../m/tankz/view/gamepad/RhombusActionArea.hx | 40 +- .../view/gamepad/SmartActionAreaBuilder.hx | 63 +- .../haxe/ru/m/tankz/view/network/RoomFrame.hx | 55 +- .../ru/m/tankz/view/network/RoomItemView.hx | 49 +- .../ru/m/tankz/view/network/RoomListFrame.hx | 72 +- .../ru/m/tankz/view/network/SlotItemView.hx | 57 +- .../ru/m/tankz/view/popup/CreateGamePopup.hx | 99 ++- .../haxe/ru/m/tankz/view/popup/LoginPopup.hx | 48 +- .../haxe/ru/m/tankz/view/popup/PausePopup.hx | 8 +- .../haxe/ru/m/tankz/view/result/FragView.hx | 49 +- .../m/tankz/view/result/ResultPlayerView.hx | 61 +- .../ru/m/tankz/view/settings/ActionView.hx | 39 +- .../m/tankz/view/settings/SettingsEditor.hx | 202 +++-- src/client/haxe/ru/m/update/Updater.hx | 115 ++- src/client/haxe/ru/m/update/Version.hx | 72 +- src/common/haxe/ru/m/Base64.hx | 69 +- src/common/haxe/ru/m/Timer.hx | 79 +- src/common/haxe/ru/m/User.hx | 4 +- .../haxe/ru/m/connect/BaseConnection.hx | 72 +- src/common/haxe/ru/m/connect/IConnection.hx | 22 +- src/common/haxe/ru/m/connect/PacketQueue.hx | 99 ++- src/common/haxe/ru/m/connect/PacketUtil.hx | 21 +- .../haxe/ru/m/connect/WebSocketTools.hx | 34 +- .../ru/m/connect/desktop/DesktopConnection.hx | 111 ++- .../haxe/ru/m/connect/fake/FakeConnection.hx | 17 +- .../ru/m/connect/flash/FlashConnection.hx | 123 ++- .../haxe/ru/m/connect/js/JsConnection.hx | 143 ++-- .../haxe/ru/m/connect/neko/NekoConnection.hx | 79 +- .../ru/m/connect/neko/NekoWSConnection.hx | 309 ++++---- src/common/haxe/ru/m/geom/Circle.hx | 56 +- src/common/haxe/ru/m/geom/Direction.hx | 116 +-- src/common/haxe/ru/m/geom/GridPoint.hx | 43 +- src/common/haxe/ru/m/geom/Line.hx | 56 +- src/common/haxe/ru/m/geom/Point.hx | 37 +- src/common/haxe/ru/m/geom/Position.hx | 6 +- src/common/haxe/ru/m/geom/Rectangle.hx | 250 +++--- src/common/haxe/ru/m/tankz/Type.hx | 129 ++-- .../haxe/ru/m/tankz/bonus/ArmorEagleBonus.hx | 76 +- src/common/haxe/ru/m/tankz/bonus/BaseBonus.hx | 22 +- src/common/haxe/ru/m/tankz/bonus/BoatBonus.hx | 13 +- .../haxe/ru/m/tankz/bonus/BonusFactory.hx | 37 +- .../haxe/ru/m/tankz/bonus/DestroyTeamBonus.hx | 17 +- .../haxe/ru/m/tankz/bonus/FreezeTeamBonus.hx | 15 +- src/common/haxe/ru/m/tankz/bonus/IBonus.hx | 4 +- src/common/haxe/ru/m/tankz/bonus/LifeBonus.hx | 9 +- .../ru/m/tankz/bonus/ProtectEagleBonus.hx | 15 +- .../haxe/ru/m/tankz/bonus/ProtectTankBonus.hx | 13 +- .../haxe/ru/m/tankz/bonus/SuicideTankBonus.hx | 13 +- .../haxe/ru/m/tankz/bonus/UpgradeTankBonus.hx | 13 +- src/common/haxe/ru/m/tankz/bot/BotControl.hx | 72 +- src/common/haxe/ru/m/tankz/bot/BotHelper.hx | 58 +- .../haxe/ru/m/tankz/bot/HardBotControl.hx | 145 ++-- .../haxe/ru/m/tankz/bot/StupidBotControl.hx | 77 +- .../ru/m/tankz/bundle/CachedLevelBundle.hx | 61 +- .../haxe/ru/m/tankz/bundle/IConfigBundle.hx | 2 +- .../haxe/ru/m/tankz/bundle/ILevelBundle.hx | 12 +- src/common/haxe/ru/m/tankz/config/Config.hx | 381 +++++---- .../ru/m/tankz/control/BaseControlFactory.hx | 33 +- src/common/haxe/ru/m/tankz/control/Control.hx | 61 +- .../haxe/ru/m/tankz/control/Controller.hx | 33 +- .../ru/m/tankz/control/IControlFactory.hx | 2 +- .../ru/m/tankz/control/NoneControlFactory.hx | 9 +- .../haxe/ru/m/tankz/control/PlayerControl.hx | 8 +- src/common/haxe/ru/m/tankz/core/Bonus.hx | 11 +- src/common/haxe/ru/m/tankz/core/Bullet.hx | 30 +- src/common/haxe/ru/m/tankz/core/Eagle.hx | 33 +- src/common/haxe/ru/m/tankz/core/Entity.hx | 23 +- src/common/haxe/ru/m/tankz/core/EntityType.hx | 39 +- .../haxe/ru/m/tankz/core/MobileEntity.hx | 49 +- src/common/haxe/ru/m/tankz/core/Tank.hx | 103 +-- src/common/haxe/ru/m/tankz/core/Weapon.hx | 57 +- src/common/haxe/ru/m/tankz/engine/Engine.hx | 266 +++---- src/common/haxe/ru/m/tankz/engine/ICaller.hx | 4 +- src/common/haxe/ru/m/tankz/engine/IEngine.hx | 46 +- src/common/haxe/ru/m/tankz/engine/ITicker.hx | 14 +- src/common/haxe/ru/m/tankz/engine/Ticker.hx | 160 ++-- .../haxe/ru/m/tankz/engine/TimerCaller.hx | 33 +- .../haxe/ru/m/tankz/game/EntityBuilder.hx | 90 ++- src/common/haxe/ru/m/tankz/game/EventUtil.hx | 90 +-- src/common/haxe/ru/m/tankz/game/Game.hx | 225 +++--- src/common/haxe/ru/m/tankz/game/GameEvent.hx | 98 +-- src/common/haxe/ru/m/tankz/game/GameRunner.hx | 730 +++++++++--------- src/common/haxe/ru/m/tankz/game/GameState.hx | 230 +++--- src/common/haxe/ru/m/tankz/game/GameTracer.hx | 10 +- src/common/haxe/ru/m/tankz/game/GameUtil.hx | 171 ++-- src/common/haxe/ru/m/tankz/game/IGame.hx | 38 +- .../haxe/ru/m/tankz/game/PackProgress.hx | 80 +- src/common/haxe/ru/m/tankz/game/Player.hx | 36 +- src/common/haxe/ru/m/tankz/game/Spawner.hx | 120 +-- src/common/haxe/ru/m/tankz/game/Team.hx | 101 +-- .../haxe/ru/m/tankz/game/record/GamePlayer.hx | 73 +- .../haxe/ru/m/tankz/game/record/GameRecord.hx | 45 +- .../ru/m/tankz/game/record/GameRecorder.hx | 41 +- src/common/haxe/ru/m/tankz/map/Brick.hx | 122 ++- src/common/haxe/ru/m/tankz/map/Grid.hx | 119 +-- src/common/haxe/ru/m/tankz/map/LevelMap.hx | 131 ++-- src/common/haxe/ru/m/tankz/util/LevelUtil.hx | 159 ++-- src/common/haxe/ru/m/tankz/util/ZipUtil.hx | 51 +- src/common/haxe/ru/m/tankz2/config/Config.hx | 24 +- src/common/haxe/ru/m/tankz2/game/Game.hx | 8 +- src/common/haxe/ru/m/tankz2/game/Team.hx | 16 +- src/common/haxe/ru/m/tankz2/state/State.hx | 8 +- src/common/haxe/ru/m/yaml/SortingRenderer.hx | 103 ++- .../haxe/ru/m/tankz/editor/ColorView.hx | 43 +- src/editor/haxe/ru/m/tankz/editor/Editor.hx | 66 +- .../haxe/ru/m/tankz/editor/EditorStorage.hx | 22 +- src/editor/haxe/ru/m/tankz/editor/FileUtil.hx | 57 +- .../haxe/ru/m/tankz/editor/view/EditorView.hx | 3 +- .../haxe/ru/m/tankz/editor/view/PackFrame.hx | 223 +++--- .../ru/m/tankz/editor/view/PackListFrame.hx | 92 +-- .../haxe/ru/m/tankz/editor/view/PackView.hx | 63 +- .../haxe/ru/m/tankz/editor/view/TankFrame.hx | 32 +- .../ru/m/tankz/editor/view/map/BrickView.hx | 35 +- .../ru/m/tankz/editor/view/map/BrushView.hx | 77 +- .../ru/m/tankz/editor/view/map/MapEditView.hx | 245 +++--- .../m/tankz/editor/view/map/SpawnPointView.hx | 42 +- .../ru/m/tankz/editor/view/popup/PackPopup.hx | 29 +- .../ru/m/tankz/editor/view/tank/TankView.hx | 45 +- src/server/haxe/ru/m/tankz/server/Server.hx | 75 +- .../tankz/server/bundle/AssetConfigBundle.hx | 17 +- .../m/tankz/server/bundle/AssetLevelSource.hx | 37 +- .../tankz/server/bundle/ServerConfigBundle.hx | 15 +- .../tankz/server/bundle/ServerLevelSource.hx | 39 +- .../server/control/ServerControlFactory.hx | 7 +- .../ru/m/tankz/server/game/GameManager.hx | 190 +++-- .../ru/m/tankz/server/game/IGameManager.hx | 50 +- .../haxe/ru/m/tankz/server/game/ServerGame.hx | 154 ++-- .../ru/m/tankz/server/session/GameSession.hx | 267 +++---- .../ru/m/tankz/server/session/ISession.hx | 6 +- .../ru/m/tankz/server/session/ProtoSession.hx | 101 +-- tankz.code-workspace | 4 +- 207 files changed, 7639 insertions(+), 7816 deletions(-) diff --git a/.editorconfig b/.editorconfig index 8ab447a..6e87a00 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,5 +8,6 @@ indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true -[*.yaml] -indent_size = 2 +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/.env.default b/.env.default index 843e108..2457020 100644 --- a/.env.default +++ b/.env.default @@ -18,4 +18,7 @@ DOCKER_PROJECTS=( ) DOCKER_ARGS=( "PROJECT_NAME=$PROJECT" -) \ No newline at end of file +) + +NEKO_SDK="$SDK_PATH/neko/2.2.0" +HAXE_SDK="$SDK_PATH/haxe/4.2.5" \ No newline at end of file diff --git a/hxformat.json b/hxformat.json index 7bf0a43..d1dca53 100644 --- a/hxformat.json +++ b/hxformat.json @@ -1,5 +1,8 @@ { "indentation": { "character": " " + }, + "wrapping": { + "maxLineLength": 120 } } diff --git a/scripts/format b/scripts/format index f9b784b..a770fda 100755 --- a/scripts/format +++ b/scripts/format @@ -2,6 +2,7 @@ set -e cd "$(dirname $(dirname "$0"))" || exit +source .env source $NEKO_SDK/activate source $HAXE_SDK/activate haxelib install formatter diff --git a/scripts/lint b/scripts/lint index 3cc9a77..a4126ef 100755 --- a/scripts/lint +++ b/scripts/lint @@ -2,6 +2,7 @@ set -e cd "$(dirname $(dirname "$0"))" || exit +source .env source $NEKO_SDK/activate source $HAXE_SDK/activate haxelib install formatter diff --git a/src/client/haxe/ru/m/Device.hx b/src/client/haxe/ru/m/Device.hx index 99bf839..7a3f43a 100644 --- a/src/client/haxe/ru/m/Device.hx +++ b/src/client/haxe/ru/m/Device.hx @@ -1,44 +1,42 @@ package ru.m; @:enum abstract Platform(String) from String to String { - var ANDROID = "android"; - var LINUX = "linux"; - var WINDOWS = "windows"; + var ANDROID = "android"; + var LINUX = "linux"; + var WINDOWS = "windows"; } class Device { + public static var platform(get, null):Platform; - public static var platform(get, null):Platform; + private static function get_platform():Platform { + #if android + return ANDROID; + #elseif linux + return LINUX; + #elseif windows + return WINDOWS; + #else + return null; + #end + } - private static function get_platform():Platform { - #if android - return ANDROID; - #elseif linux - return LINUX; - #elseif windows - return WINDOWS; - #else - return null; - #end - } + private static var MOBILES(default, + never):Array = ["Android", "webOS", "iPhone", "iPad", "iPod", "BlackBerry", "Windows Phone",]; - private static var MOBILES(default, never):Array = [ - "Android", "webOS", "iPhone", "iPad", "iPod", "BlackBerry", "Windows Phone", - ]; - - public static function isMobile():Bool { - #if android + public static function isMobile():Bool { + #if android + return true; + #elseif js + var userAgent = js.Browser.navigator.userAgent; + for (mobile in MOBILES) { + if (userAgent.indexOf(mobile) > -1) { return true; - #elseif js - var userAgent = js.Browser.navigator.userAgent; - for (mobile in MOBILES) { - if (userAgent.indexOf(mobile) > -1) { - return true; - } - } - return false; - #else - return false; - #end + } } + return false; + #else + return false; + #end + } } diff --git a/src/client/haxe/ru/m/animate/Animate.hx b/src/client/haxe/ru/m/animate/Animate.hx index 57a7596..c3467e2 100644 --- a/src/client/haxe/ru/m/animate/Animate.hx +++ b/src/client/haxe/ru/m/animate/Animate.hx @@ -5,52 +5,51 @@ import flash.display.BitmapData; import flash.display.PixelSnapping; typedef Frame = { - var image:BitmapData; - var length:Int; + var image:BitmapData; + var length:Int; } class Animate extends Bitmap { + public var playing(default, default):Bool; + public var frames(default, set):Array; - public var playing(default, default):Bool; - public var frames(default, set):Array; + private var sequence:Array; + private var index:Int; - private var sequence:Array; - private var index:Int; + @:provide private static var manager:AnimateManager; - @:provide private static var manager:AnimateManager; + public function new(?frames:Array) { + super(null, PixelSnapping.AUTO, true); + this.frames = frames == null ? [] : frames; + manager.add(this); + } - public function new(?frames:Array) { - super(null, PixelSnapping.AUTO, true); - this.frames = frames == null ? [] : frames; - manager.add(this); + public function set_frames(value:Array):Array { + sequence = []; + index = 0; + if (value != null) { + frames = value; + for (frame in frames) { + sequence = sequence.concat([for (i in 0...frame.length) frame.image]); + } + bitmapData = sequence[0]; + } else { + bitmapData = null; } + return frames; + } - public function set_frames(value:Array):Array { - sequence = []; - index = 0; - if (value != null) { - frames = value; - for (frame in frames) { - sequence = sequence.concat([for (i in 0...frame.length) frame.image]); - } - bitmapData = sequence[0]; - } else { - bitmapData = null; - } - return frames; + public function update():Void { + if (++index >= sequence.length) { + index = 0; } + var nextBitmapData = sequence[index]; + x -= (nextBitmapData.width - bitmapData.width) / 2; + y -= (nextBitmapData.height - bitmapData.height) / 2; + bitmapData = nextBitmapData; + } - public function update():Void { - if (++index >= sequence.length) { - index = 0; - } - var nextBitmapData = sequence[index]; - x -= (nextBitmapData.width - bitmapData.width) / 2; - y -= (nextBitmapData.height - bitmapData.height) / 2; - bitmapData = nextBitmapData; - } - - public function dispose():Void { - manager.remove(this); - } + public function dispose():Void { + manager.remove(this); + } } diff --git a/src/client/haxe/ru/m/animate/AnimateManager.hx b/src/client/haxe/ru/m/animate/AnimateManager.hx index 9082a56..e4e6daf 100644 --- a/src/client/haxe/ru/m/animate/AnimateManager.hx +++ b/src/client/haxe/ru/m/animate/AnimateManager.hx @@ -1,34 +1,34 @@ package ru.m.animate; @:provide class AnimateManager { - public var playing(default, default):Bool; + public var playing(default, default):Bool; - private var timer:Timer; - private var animations:Array; + private var timer:Timer; + private var animations:Array; - public function new() { - animations = []; - timer = new Timer(30); - timer.run = update; - } + public function new() { + animations = []; + timer = new Timer(30); + timer.run = update; + } - public function update():Void { - if (playing) { - for (animation in animations) { - if (animation.playing) { - animation.update(); - } - } + public function update():Void { + if (playing) { + for (animation in animations) { + if (animation.playing) { + animation.update(); } + } } + } - public function add(animate:Animate):Void { - animations.push(animate); - } + public function add(animate:Animate):Void { + animations.push(animate); + } - public function remove(animate:Animate):Void { - if (animations.indexOf(animate) > -1) { - animations.remove(animate); - } + public function remove(animate:Animate):Void { + if (animations.indexOf(animate) > -1) { + animations.remove(animate); } + } } diff --git a/src/client/haxe/ru/m/animate/OnceAnimate.hx b/src/client/haxe/ru/m/animate/OnceAnimate.hx index 3e510cf..9366250 100644 --- a/src/client/haxe/ru/m/animate/OnceAnimate.hx +++ b/src/client/haxe/ru/m/animate/OnceAnimate.hx @@ -4,23 +4,22 @@ import promhx.Deferred; import promhx.Promise; class OnceAnimate extends Animate { + private var deferred:Deferred; - private var deferred:Deferred; + public function play():Promise { + deferred = new Deferred(); + playing = true; + return deferred.promise(); + } - public function play():Promise { - deferred = new Deferred(); - playing = true; - return deferred.promise(); - } - - override public function update():Void { - super.update(); - if (index == 0) { - playing = false; - if (deferred != null) { - deferred.resolve(this); - } - dispose(); - } + override public function update():Void { + super.update(); + if (index == 0) { + playing = false; + if (deferred != null) { + deferred.resolve(this); + } + dispose(); } + } } diff --git a/src/client/haxe/ru/m/control/ControlBus.hx b/src/client/haxe/ru/m/control/ControlBus.hx index 4a7886b..441bf16 100644 --- a/src/client/haxe/ru/m/control/ControlBus.hx +++ b/src/client/haxe/ru/m/control/ControlBus.hx @@ -4,40 +4,39 @@ import hw.signal.Signal; import ru.m.control.IControlBus; class ControlBus implements IControlBus { + private static inline var TAG = "control"; - private static inline var TAG = "control"; + public var devices(default, null):Array; - public var devices(default, null):Array; + public var signal(default, null):Signal3; + public var devicesSignal(default, null):Signal>; - public var signal(default, null):Signal3; - public var devicesSignal(default, null):Signal>; + private var connections:MapBool->Void>; - private var connections:MapBool->Void>; + public function new() { + devices = []; + signal = new Signal3(); + devicesSignal = new Signal(); + connections = new Map(); + } - public function new() { - devices = []; - signal = new Signal3(); - devicesSignal = new Signal(); - connections = new Map(); + public function connect(device:IControlDevice):Void { + var connector = function(action:DeviceAction, on:Bool):Void { + // L.d("TAG", '${device.type}, ${action}, ${on}'); + signal.emit(device.type, action, on); } + connections.set(device.type, connector); + device.signal.connect(connector); + devices.push(device); + devicesSignal.emit(devices); + } - public function connect(device:IControlDevice):Void { - var connector = function(action:DeviceAction, on:Bool):Void { - //L.d("TAG", '${device.type}, ${action}, ${on}'); - signal.emit(device.type, action, on); - } - connections.set(device.type, connector); - device.signal.connect(connector); - devices.push(device); - devicesSignal.emit(devices); - } - - public function disconnect(device:IControlDevice):Void { - if (connections.exists(device.type)) { - device.signal.disconnect(connections.get(device.type)); - connections.remove(device.type); - devices.remove(device); - devicesSignal.emit(devices); - } + public function disconnect(device:IControlDevice):Void { + if (connections.exists(device.type)) { + device.signal.disconnect(connections.get(device.type)); + connections.remove(device.type); + devices.remove(device); + devicesSignal.emit(devices); } + } } diff --git a/src/client/haxe/ru/m/control/DeviceAction.hx b/src/client/haxe/ru/m/control/DeviceAction.hx index b711555..0aed976 100644 --- a/src/client/haxe/ru/m/control/DeviceAction.hx +++ b/src/client/haxe/ru/m/control/DeviceAction.hx @@ -3,6 +3,6 @@ package ru.m.control; import ru.m.geom.Direction; enum DeviceAction { - DIRECTION(direction:Direction); - KEY(code:Int); + DIRECTION(direction:Direction); + KEY(code:Int); } diff --git a/src/client/haxe/ru/m/control/DeviceType.hx b/src/client/haxe/ru/m/control/DeviceType.hx index 0455309..1d4b83a 100644 --- a/src/client/haxe/ru/m/control/DeviceType.hx +++ b/src/client/haxe/ru/m/control/DeviceType.hx @@ -1,8 +1,8 @@ package ru.m.control; enum DeviceType { - NONE; - KEYBOARD; - SCREEN; - GAMEPAD(id:Int); + NONE; + KEYBOARD; + SCREEN; + GAMEPAD(id:Int); } diff --git a/src/client/haxe/ru/m/control/IControlBus.hx b/src/client/haxe/ru/m/control/IControlBus.hx index a9e337c..1da9d06 100644 --- a/src/client/haxe/ru/m/control/IControlBus.hx +++ b/src/client/haxe/ru/m/control/IControlBus.hx @@ -3,11 +3,11 @@ package ru.m.control; import hw.signal.Signal; interface IControlBus { - public var devices(default, null):Array; + public var devices(default, null):Array; - public var signal(default, null):Signal3; - public var devicesSignal(default, null):Signal>; + public var signal(default, null):Signal3; + public var devicesSignal(default, null):Signal>; - public function connect(device:IControlDevice):Void; - public function disconnect(device:IControlDevice):Void; + public function connect(device:IControlDevice):Void; + public function disconnect(device:IControlDevice):Void; } diff --git a/src/client/haxe/ru/m/control/IControlDevice.hx b/src/client/haxe/ru/m/control/IControlDevice.hx index 70b7121..4148e7b 100644 --- a/src/client/haxe/ru/m/control/IControlDevice.hx +++ b/src/client/haxe/ru/m/control/IControlDevice.hx @@ -3,8 +3,8 @@ package ru.m.control; import hw.signal.Signal; interface IControlDevice { - public var type(default, null):DeviceType; - public var signal(default, null):Signal2; + public var type(default, null):DeviceType; + public var signal(default, null):Signal2; - public function dispose():Void; + public function dispose():Void; } diff --git a/src/client/haxe/ru/m/control/JoystickDevice.hx b/src/client/haxe/ru/m/control/JoystickDevice.hx index 2a177b0..5346318 100644 --- a/src/client/haxe/ru/m/control/JoystickDevice.hx +++ b/src/client/haxe/ru/m/control/JoystickDevice.hx @@ -7,56 +7,55 @@ import ru.m.control.DeviceType; import ru.m.geom.Direction; class JoystickDevice implements IControlDevice { + public var type(default, null):DeviceType; + public var signal(default, null):Signal2; - public var type(default, null):DeviceType; - public var signal(default, null):Signal2; + private var joystick:Joystick; + private var axisState:Map; - private var joystick:Joystick; - private var axisState:Map; + public function new(joystick:Joystick) { + this.joystick = joystick; + type = GAMEPAD(joystick.id); + signal = new Signal2(); + axisState = new Map(); + joystick.onButtonDown.add(onButtonDown); + joystick.onButtonUp.add(onButtonUp); + joystick.onAxisMove.add(onAxisMove); + } - public function new(joystick:Joystick) { - this.joystick = joystick; - type = GAMEPAD(joystick.id); - signal = new Signal2(); - axisState = new Map(); - joystick.onButtonDown.add(onButtonDown); - joystick.onButtonUp.add(onButtonUp); - joystick.onAxisMove.add(onAxisMove); + private function onButtonDown(code:Int):Void { + signal.emit(KEY(code), true); + } + + private function onButtonUp(code:Int):Void { + signal.emit(KEY(code), false); + } + + private function onAxisMove(axis:Int, position:Float):Void { + var direction:Direction = switch [axis, position] { + case [0, 1]: Direction.RIGHT; + case [0, -1]: Direction.LEFT; + case [1, 1]: Direction.BOTTOM; + case [1, -1]: Direction.TOP; + case _: null; } - - private function onButtonDown(code:Int):Void { - signal.emit(KEY(code), true); + if (direction != null) { + axisState.set(axis, direction); + signal.emit(DIRECTION(direction), true); + } else if (position == 0) { + if (axisState.exists(axis)) { + signal.emit(DIRECTION(axisState.get(axis)), false); + axisState.remove(axis); + } } + } - private function onButtonUp(code:Int):Void { - signal.emit(KEY(code), false); - } - - private function onAxisMove(axis:Int, position:Float):Void { - var direction:Direction = switch [axis, position] { - case [0, 1]: Direction.RIGHT; - case [0, -1]: Direction.LEFT; - case [1, 1]: Direction.BOTTOM; - case [1, -1]: Direction.TOP; - case _: null; - } - if (direction != null) { - axisState.set(axis, direction); - signal.emit(DIRECTION(direction), true); - } else if (position == 0) { - if (axisState.exists(axis)) { - signal.emit(DIRECTION(axisState.get(axis)), false); - axisState.remove(axis); - } - } - } - - public function dispose():Void { - if (joystick != null) { - joystick.onButtonDown.remove(onButtonDown); - joystick.onButtonUp.remove(onButtonUp); - joystick.onAxisMove.remove(onAxisMove); - joystick = null; - } + public function dispose():Void { + if (joystick != null) { + joystick.onButtonDown.remove(onButtonDown); + joystick.onButtonUp.remove(onButtonUp); + joystick.onAxisMove.remove(onAxisMove); + joystick = null; } + } } diff --git a/src/client/haxe/ru/m/control/KeyboardDevice.hx b/src/client/haxe/ru/m/control/KeyboardDevice.hx index a968c87..9edb427 100644 --- a/src/client/haxe/ru/m/control/KeyboardDevice.hx +++ b/src/client/haxe/ru/m/control/KeyboardDevice.hx @@ -6,33 +6,32 @@ import hw.signal.Signal; import ru.m.control.DeviceAction; class KeyboardDevice implements IControlDevice { + public var type(default, null):DeviceType; + public var signal(default, null):Signal2; - public var type(default, null):DeviceType; - public var signal(default, null):Signal2; + private var stage:Stage; - private var stage:Stage; + public function new(stage:Stage) { + this.stage = stage; + type = DeviceType.KEYBOARD; + signal = new Signal2(); + stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); + stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); + } - public function new(stage:Stage) { - this.stage = stage; - type = DeviceType.KEYBOARD; - signal = new Signal2(); - stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); - stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); - } - - private function onKeyDown(event:KeyboardEvent):Void { - signal.emit(KEY(event.keyCode), true); - } - - private function onKeyUp(event:KeyboardEvent):Void { - signal.emit(KEY(event.keyCode), false); - } - - public function dispose():Void { - if (stage != null) { - stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); - stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp); - stage = null; - } + private function onKeyDown(event:KeyboardEvent):Void { + signal.emit(KEY(event.keyCode), true); + } + + private function onKeyUp(event:KeyboardEvent):Void { + signal.emit(KEY(event.keyCode), false); + } + + public function dispose():Void { + if (stage != null) { + stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); + stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp); + stage = null; } + } } diff --git a/src/client/haxe/ru/m/display/DisplayObjectContainerExtender.hx b/src/client/haxe/ru/m/display/DisplayObjectContainerExtender.hx index 4743713..0f2cae1 100644 --- a/src/client/haxe/ru/m/display/DisplayObjectContainerExtender.hx +++ b/src/client/haxe/ru/m/display/DisplayObjectContainerExtender.hx @@ -4,19 +4,18 @@ import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; class DisplayObjectContainerExtender { + public static function childrenIterator():Iterator { + throw "Not implemented"; + } - public static function childrenIterator():Iterator { - throw "Not implemented"; + public static function removeChildSafety(self:DisplayObjectContainer, child:DisplayObject):DisplayObject { + if (self.contains(child)) { + return self.removeChild(child); } + return null; + } - public static function removeChildSafety(self:DisplayObjectContainer, child:DisplayObject):DisplayObject { - if (self.contains(child)) { - return self.removeChild(child); - } - return null; - } - - public static function containsRecursivle(child:DisplayObject):Bool { - throw "Not implemented"; - } + public static function containsRecursivle(child:DisplayObject):Bool { + throw "Not implemented"; + } } diff --git a/src/client/haxe/ru/m/skin/ButtonSVGSkin.hx b/src/client/haxe/ru/m/skin/ButtonSVGSkin.hx index ee87121..313fe91 100644 --- a/src/client/haxe/ru/m/skin/ButtonSVGSkin.hx +++ b/src/client/haxe/ru/m/skin/ButtonSVGSkin.hx @@ -9,48 +9,47 @@ using StringTools; using hw.color.ColorUtil; @:style class ButtonSVGSkin implements ISkin { + @:style(null) private var svg:String; + @:style(0) private var color:Null; + @:style(false) private var solid:Null; - @:style(null) private var svg:String; - @:style(0) private var color:Null; - @:style(false) private var solid:Null; + private var svgs:Map; - private var svgs:Map; + public function new(?svg:String, ?color:Color, ?solid:Bool) { + this.svg = svg; + this.color = color; + this.solid = solid; + init(solid); + } - public function new(?svg:String, ?color:Color, ?solid:Bool) { - this.svg = svg; - this.color = color; - this.solid = solid; - init(solid); + private inline function buildSVG(color:Color):SVG { + return new SVG(svg.replace("currentColor", '#${color}')); + } + + private function init(solid:Bool):Void { + var color = color; + if (solid) { + color = color.multiply(1.5); } + svgs = new Map(); + svgs.set(UP, buildSVG(color)); + svgs.set(DOWN, buildSVG(color.diff(-24))); + svgs.set(OVER, buildSVG(color.diff(24))); + svgs.set(DISABLED, buildSVG(color.grey())); + } - private inline function buildSVG(color:Color):SVG { - return new SVG(svg.replace("currentColor", '#${color}')); - } - - private function init(solid:Bool):Void { - var color = color; - if (solid) { - color = color.multiply(1.5); - } - svgs = new Map(); - svgs.set(UP, buildSVG(color)); - svgs.set(DOWN, buildSVG(color.diff(-24))); - svgs.set(OVER, buildSVG(color.diff(24))); - svgs.set(DISABLED, buildSVG(color.grey())); - } - - public function draw(view:ButtonView):Void { - var svg = svgs.get(view.state); - var graphics = view.content.graphics; - graphics.beginFill(0, 0); - graphics.drawRect(0, 0, view.width, view.height); - graphics.beginFill(color); - if (!solid) { - graphics.lineStyle(2, color.multiply(1.5)); - } - // ToDo: padding - svg.render(graphics, 0, 0, Std.int(view.width * 0.8), Std.int(view.height * 0.8)); - graphics.lineStyle(); - graphics.endFill(); + public function draw(view:ButtonView):Void { + var svg = svgs.get(view.state); + var graphics = view.content.graphics; + graphics.beginFill(0, 0); + graphics.drawRect(0, 0, view.width, view.height); + graphics.beginFill(color); + if (!solid) { + graphics.lineStyle(2, color.multiply(1.5)); } + // ToDo: padding + svg.render(graphics, 0, 0, Std.int(view.width * 0.8), Std.int(view.height * 0.8)); + graphics.lineStyle(); + graphics.endFill(); + } } diff --git a/src/client/haxe/ru/m/tankz/AppTheme.hx b/src/client/haxe/ru/m/tankz/AppTheme.hx index b8c1d93..9c40759 100644 --- a/src/client/haxe/ru/m/tankz/AppTheme.hx +++ b/src/client/haxe/ru/m/tankz/AppTheme.hx @@ -15,186 +15,164 @@ import ru.m.skin.ButtonSVGSkin; using hw.color.ColorUtil; class AppTheme extends Theme { + public static var COLORS(default, never):ThemeColors = { + light: 0x95937D, + dark: 0x777564, + text: 0xE7E0BB, + active: 0xFFFF00, + } - public static var COLORS(default, never):ThemeColors = { - light: 0x95937D, - dark: 0x777564, - text: 0xE7E0BB, - active: 0xFFFF00, - } + public function new() { + super({embed: true}, COLORS, {base: "3h", big: "4h", veryBig: "4.5h"}); + } - public function new() { - super({embed: true}, COLORS, {base: "3h", big: "4h", veryBig: "4.5h"}); - } + override private function reload():Void { + super.reload(); + register(new Style("light", ["skin.background.color" => colors.light,])); - override private function reload():Void { - super.reload(); - register(new Style("light", [ - "skin.background.color" => colors.light, - ])); + register(new Style("dark", ["skin.background.color" => colors.dark,])); - register(new Style("dark", [ - "skin.background.color" => colors.dark, - ])); + register(new Style("font", ["_" => null,], ["text"])); - register(new Style("font", [ - "_" => null, - ], ["text"])); + register(new Style("text.header", [ + "font.size" => fontSize.big, + "font.align" => TextFormatAlign.CENTER, + "skin.background.color" => Color.fromInt(0x000000), + "skin.background.alpha" => 0.1, + "skin.border.color" => colors.light, + "geometry.padding" => Box.fromArray([50, 8]), + "geometry.margin" => Box.fromArray([0, 0, 30, 30]), + ], ["text"])); - register(new Style("text.header", [ - "font.size" => fontSize.big, - "font.align" => TextFormatAlign.CENTER, - "skin.background.color" => Color.fromInt(0x000000), - "skin.background.alpha" => 0.1, - "skin.border.color" => colors.light, - "geometry.padding" => Box.fromArray([50, 8]), - "geometry.margin" => Box.fromArray([0, 0, 30, 30]), - ], ["text"])); + register(new Style("button.menu", [ + "font.size" => fontSize.big, + "geometry.padding" => Box.fromFloat(0), + "geometry.width" => SizeValue.fromInt(250), + "geometry.height" => SizeValue.fromInt(50), + ], ["button"])); - register(new Style("button.menu", [ - "font.size" => fontSize.big, - "geometry.padding" => Box.fromFloat(0), - "geometry.width" => SizeValue.fromInt(250), - "geometry.height" => SizeValue.fromInt(50), - ], ["button"])); + register(new Style("button.small", [ + "font.size" => SizeValue.fromString("3h"), + "geometry.padding" => Box.fromArray([8, 2]), + "skin.round" => 5, + ], ["button"])); - register(new Style("button.small", [ - "font.size" => SizeValue.fromString("3h"), - "geometry.padding" => Box.fromArray([8, 2]), - "skin.round" => 5, - ], ["button"])); + register(new Style("text.box", [ + "skin.background.color" => Color.fromInt(0x000000), + "skin.background.alpha" => 0.1, + "skin.border.color" => colors.light, + "geometry.padding" => Box.fromArray([15, 8]), + ], ["text"])); - register(new Style("text.box", [ - "skin.background.color" => Color.fromInt(0x000000), - "skin.background.alpha" => 0.1, - "skin.border.color" => colors.light, - "geometry.padding" => Box.fromArray([15, 8]), - ], ["text"])); + register(new Style("text.box.active", [ + "skin.background.color" => Color.fromInt(0x55aa55), + "skin.background.alpha" => 1, + "skin.border.color" => Color.fromInt(0x88dd88), + ], ["text.box"])); - register(new Style("text.box.active", [ - "skin.background.color" => Color.fromInt(0x55aa55), - "skin.background.alpha" => 1, - "skin.border.color" => Color.fromInt(0x88dd88), - ], ["text.box"])); + register(new Style("button.level", [ + "font.size" => fontSize.big, + "geometry.width" => SizeValue.fromString("12h"), + "geometry.height" => SizeValue.fromString("12h"), + "geometry.padding" => Box.fromFloat(0), + ], ["button"])); - register(new Style("button.level", [ - "font.size" => fontSize.big, - "geometry.width" => SizeValue.fromString("12h"), - "geometry.height" => SizeValue.fromString("12h"), - "geometry.padding" => Box.fromFloat(0), - ], ["button"])); + register(new Style("container", [ + "geometry.width" => SizeValue.fromString("100%"), + "geometry.height" => SizeValue.fromString("100%"), + "layout.hAlign" => HAlign.CENTER, + "layout.vAlign" => VAlign.MIDDLE, + ], ["dark"])); - register(new Style("container", [ - "geometry.width" => SizeValue.fromString("100%"), - "geometry.height" => SizeValue.fromString("100%"), - "layout.hAlign" => HAlign.CENTER, - "layout.vAlign" => VAlign.MIDDLE, - ], ["dark"])); + register(new Style("panel", [ + "geometry.width" => SizeValue.fromString("100%"), + "geometry.padding" => Box.fromArray([20, 10]), + "layout.vAlign" => VAlign.MIDDLE, + ], ["light"])); - register(new Style("panel", [ - "geometry.width" => SizeValue.fromString("100%"), - "geometry.padding" => Box.fromArray([20, 10]), - "layout.vAlign" => VAlign.MIDDLE, - ], ["light"])); + register(new Style("panel_button", + ["font.size" => fontSize.big, "geometry.height" => SizeValue.fromString("100%"),], ["button"])); - register(new Style("panel_button", [ - "font.size" => fontSize.big, - "geometry.height" => SizeValue.fromString("100%"), - ], ["button"])); + register(new Style("window", ["geometry.padding" => Box.fromFloat(2),], ["dark", "border"])); - register(new Style("window", [ - "geometry.padding" => Box.fromFloat(2), - ], ["dark", "border"])); + register(new Style("line", [ + "geometry.width" => SizeValue.fromString("100%"), + "geometry.height" => SizeValue.fromInt(2), + ], ["border"])); - register(new Style("line", [ - "geometry.width" => SizeValue.fromString("100%"), - "geometry.height" => SizeValue.fromInt(2), - ], ["border"])); + register(new Style("window.close", [ + "skin" => function() return new ButtonSVGSkin(Assets.getText("resources/image/icon/window-close-solid.svg"), + colors.light), + "geometry.width" => SizeValue.fromString("8h"), + "geometry.height" => SizeValue.fromString("8h"), + ])); - register(new Style("window.close", [ - "skin" => function() return new ButtonSVGSkin(Assets.getText("resources/image/icon/window-close-solid.svg"), colors.light), - "geometry.width" => SizeValue.fromString("8h"), - "geometry.height" => SizeValue.fromString("8h"), - ])); + register(new Style("icon.tank", [ + "geometry.width" => SizeValue.fromString("6h"), + "geometry.height" => SizeValue.fromString("6h"), + "skin.fillType" => FillType.CONTAIN, + ])); - register(new Style("icon.tank", [ - "geometry.width" => SizeValue.fromString("6h"), - "geometry.height" => SizeValue.fromString("6h"), - "skin.fillType" => FillType.CONTAIN, - ])); + var green:Color = 0x00ff00; + var red:Color = 0xff0000; + register(new Style("result.winner", [ + "skin.border.color" => green, + "skin.border.alpha" => 0.5, + "skin.border.thickness" => 5, + "skin.round" => 10, + ], ["light"])); + register(new Style("result.loser", [ + "skin.border.color" => red, + "skin.border.alpha" => 0.5, + "skin.border.thickness" => 5, + "skin.round" => 10, + ], ["light"])); + register(new Style("player.winner", ["skin.background.alpha" => 0.2, "skin.background.color" => green,])); + register(new Style("player.loser", ["skin.background.alpha" => 0.2, "skin.background.color" => red,])); - var green:Color = 0x00ff00; - var red:Color = 0xff0000; - register(new Style("result.winner", [ - "skin.border.color" => green, - "skin.border.alpha" => 0.5, - "skin.border.thickness" => 5, - "skin.round" => 10, - ], ["light"])); - register(new Style("result.loser", [ - "skin.border.color" => red, - "skin.border.alpha" => 0.5, - "skin.border.thickness" => 5, - "skin.round" => 10, - ], ["light"])); - register(new Style("player.winner", [ - "skin.background.alpha" => 0.2, - "skin.background.color" => green, - ])); - register(new Style("player.loser", [ - "skin.background.alpha" => 0.2, - "skin.background.color" => red, - ])); + register(new Style("button.pack", [ + "geometry.width" => SizeValue.fromString("35h"), + "geometry.height" => SizeValue.fromString("20h"), + "geometry.padding" => Box.fromFloat(5), + "layout.hAlign" => HAlign.CENTER, + "layout.vAlign" => VAlign.MIDDLE, + "content.buttonMode" => true, + "content.mouseChildren" => false, + "skin.round" => 15, + ], ["border", "light"])); - register(new Style("button.pack", [ - "geometry.width" => SizeValue.fromString("35h"), - "geometry.height" => SizeValue.fromString("20h"), - "geometry.padding" => Box.fromFloat(5), - "layout.hAlign" => HAlign.CENTER, - "layout.vAlign" => VAlign.MIDDLE, - "content.buttonMode" => true, - "content.mouseChildren" => false, - "skin.round" => 15, - ], ["border", "light"])); + register(new Style("button.menu", ["geometry.padding" => Box.fromArray([20, 10]),])); - register(new Style("button.menu", [ - "geometry.padding" => Box.fromArray([20, 10]), - ])); + registerButton("settings", "cog-solid.svg"); + registerButton("close", "times-circle-solid.svg"); + registerButton("next", "arrow-alt-circle-right-solid.svg"); + registerButton("prev", "arrow-alt-circle-left-solid.svg"); + registerButton("start", "play-circle-solid.svg"); + registerButton("login", "sign-in-solid.svg"); + registerButton("logout", "sign-out-solid.svg"); + registerButton("bars", "bars-solid.svg"); - registerButton("settings", "cog-solid.svg"); - registerButton("close", "times-circle-solid.svg"); - registerButton("next", "arrow-alt-circle-right-solid.svg"); - registerButton("prev", "arrow-alt-circle-left-solid.svg"); - registerButton("start", "play-circle-solid.svg"); - registerButton("login", "sign-in-solid.svg"); - registerButton("logout", "sign-out-solid.svg"); - registerButton("bars", "bars-solid.svg"); + registerButton("keyboard", "keyboard-light.svg", true); + registerButton("backspace", "backspace-light.svg", true); + registerButton("tablet-android-alt", "tablet-android-alt-light.svg", true); - registerButton("keyboard", "keyboard-light.svg", true); - registerButton("backspace", "backspace-light.svg", true); - registerButton("tablet-android-alt", "tablet-android-alt-light.svg", true); + register(new Style("gamepad", ["skin.color" => colors.text, "skin.activeColor" => colors.active,])); - register(new Style("gamepad", [ - "skin.color" => colors.text, - "skin.activeColor" => colors.active, - ])); - - register(new Style("render", [ - "skin.background.color" => colors.dark, - ])); - } - - private function registerButton(name:String, resource:String, solid:Bool = false):Void { - register(new Style('button.$name', [ - "geometry.width" => SizeValue.fromString("10h"), - "geometry.height" => SizeValue.fromString("10h"), - "skin" => function() return new ButtonSVGSkin(Assets.getText('resources/image/icon/$resource'), colors.light, solid), - ])); - register(new Style('button.$name.small', [ - "geometry.width" => SizeValue.fromString("7h"), - "geometry.height" => SizeValue.fromString("7h"), - "skin" => function() return new ButtonSVGSkin(Assets.getText('resources/image/icon/$resource'), colors.light, solid), - ])); - } + register(new Style("render", ["skin.background.color" => colors.dark,])); + } + private function registerButton(name:String, resource:String, solid:Bool = false):Void { + register(new Style('button.$name', [ + "geometry.width" => SizeValue.fromString("10h"), + "geometry.height" => SizeValue.fromString("10h"), + "skin" => function() return new ButtonSVGSkin(Assets.getText('resources/image/icon/$resource'), colors.light, + solid), + ])); + register(new Style('button.$name.small', [ + "geometry.width" => SizeValue.fromString("7h"), + "geometry.height" => SizeValue.fromString("7h"), + "skin" => function() return new ButtonSVGSkin(Assets.getText('resources/image/icon/$resource'), colors.light, + solid), + ])); + } } diff --git a/src/client/haxe/ru/m/tankz/Client.hx b/src/client/haxe/ru/m/tankz/Client.hx index 6182fc5..a019a3d 100755 --- a/src/client/haxe/ru/m/tankz/Client.hx +++ b/src/client/haxe/ru/m/tankz/Client.hx @@ -12,49 +12,49 @@ import ru.m.tankz.storage.SettingsStorage; import ru.m.tankz.view.ClientView; class Client { - private static inline var TAG = "Tankz"; + private static inline var TAG = "Tankz"; - @:provide private static var settings:SettingsStorage; + @:provide private static var settings:SettingsStorage; - public static function main() { - L.push(new TraceLogger()); - #if flash - L.push(new hw.log.JSLogger()); - #end - #if debug - //L.push(new hw.log.SocketLogger()); - #end - // ToDo: fix @:provide macro - PopupManager; - LoaderManager; - GameStorage; - AnimateManager; - // - Const.init(); - Init.init(); - // TODO: - // Animate.bind(Lib.current.stage); - L.d(TAG, 'Debug: ${Const.DEBUG}'); - L.i(TAG, 'Version: ${Const.VERSION}'); - L.i(TAG, 'Build: ${Const.BUILD}'); - L.i(TAG, 'Mobile: ${Device.isMobile()}'); - #if linux - LinuxIcon.apply(); - #end - var view:ClientView = new ClientView(); - Root.bind(view); - view.launch(); + public static function main() { + L.push(new TraceLogger()); + #if flash + L.push(new hw.log.JSLogger()); + #end + #if debug + // L.push(new hw.log.SocketLogger()); + #end + // ToDo: fix @:provide macro + PopupManager; + LoaderManager; + GameStorage; + AnimateManager; + // + Const.init(); + Init.init(); + // TODO: + // Animate.bind(Lib.current.stage); + L.d(TAG, 'Debug: ${Const.DEBUG}'); + L.i(TAG, 'Version: ${Const.VERSION}'); + L.i(TAG, 'Build: ${Const.BUILD}'); + L.i(TAG, 'Mobile: ${Device.isMobile()}'); + #if linux + LinuxIcon.apply(); + #end + var view:ClientView = new ClientView(); + Root.bind(view); + view.launch(); - var fps = new openfl.display.FPS(0, 0, 0x00ff00); - fps.visible = settings.displayFPS; - Lib.current.addChild(fps); + var fps = new openfl.display.FPS(0, 0, 0x00ff00); + fps.visible = settings.displayFPS; + Lib.current.addChild(fps); - settings.signal.connect(function(setting) { - switch setting { - case DISPLAY_FPS(value): - fps.visible = value; - case _: - } - }); - } + settings.signal.connect(function(setting) { + switch setting { + case DISPLAY_FPS(value): + fps.visible = value; + case _: + } + }); + } } diff --git a/src/client/haxe/ru/m/tankz/Const.hx b/src/client/haxe/ru/m/tankz/Const.hx index 141bbd2..052f93a 100755 --- a/src/client/haxe/ru/m/tankz/Const.hx +++ b/src/client/haxe/ru/m/tankz/Const.hx @@ -4,17 +4,17 @@ import flash.Lib; import flash.system.Capabilities; class Const { - public static var FPS:Int; - public static var BUILD:String; - public static var VERSION:String; - public static var NAME:String; - public static var DEBUG:Bool; + public static var FPS:Int; + public static var BUILD:String; + public static var VERSION:String; + public static var NAME:String; + public static var DEBUG:Bool; - public static function init():Void { - FPS = Std.parseInt(Lib.current.stage.application.meta.get("fps")); - BUILD = CompilationOption.get("build"); - VERSION = Lib.current.stage.application.meta.get("version"); - NAME = Lib.current.stage.application.meta.get("name"); - DEBUG = Capabilities.isDebugger; - } + public static function init():Void { + FPS = Std.parseInt(Lib.current.stage.application.meta.get("fps")); + BUILD = CompilationOption.get("build"); + VERSION = Lib.current.stage.application.meta.get("version"); + NAME = Lib.current.stage.application.meta.get("name"); + DEBUG = Capabilities.isDebugger; + } } diff --git a/src/client/haxe/ru/m/tankz/Init.hx b/src/client/haxe/ru/m/tankz/Init.hx index 1c7d2ec..c2ddead 100644 --- a/src/client/haxe/ru/m/tankz/Init.hx +++ b/src/client/haxe/ru/m/tankz/Init.hx @@ -23,56 +23,56 @@ import ru.m.tankz.proto.pack.Response; import ru.m.update.Updater; class Init { + @:provide static var theme:ITheme; + @:provide static var levelBundle:ILevelBundle; + @:provide static var configBundle:IConfigBundle; + @:provide static var popupManager:PopupManager; + @:provide static var connection:IConnection; + @:provide static var bus:IControlBus; + @:provide static var updater:Updater; - @:provide static var theme:ITheme; - @:provide static var levelBundle:ILevelBundle; - @:provide static var configBundle:IConfigBundle; - @:provide static var popupManager:PopupManager; - @:provide static var connection:IConnection; - @:provide static var bus:IControlBus; - @:provide static var updater:Updater; + private static function buildConnection():IConnection { + var host:String = CompilationOption.get("host"); + var port:Int = CompilationOption.get("port"); + L.d("Init", 'connect to $host:$port'); + #if flash + return new ru.m.connect.flash.FlashConnection(host, port, Response); + #elseif html5 + return new ru.m.connect.js.JsConnection(host, + port + (ru.m.connect.js.JsConnection.isSecured() ? 1 : 0), Response); + #else + return new ru.m.connect.desktop.DesktopConnection(host, port, Response); + #end + } - private static function buildConnection():IConnection { - var host:String = CompilationOption.get("host"); - var port:Int = CompilationOption.get("port"); - L.d("Init", 'connect to $host:$port'); - #if flash - return new ru.m.connect.flash.FlashConnection(host, port, Response); - #elseif html5 - return new ru.m.connect.js.JsConnection(host, port + (ru.m.connect.js.JsConnection.isSecured() ? 1 : 0), Response); - #else - return new ru.m.connect.desktop.DesktopConnection(host, port, Response); - #end + public static function init():Void { + theme = new AppTheme(); + levelBundle = new CachedLevelBundle(new ClientLevelSource(), new SharedObjectStorage()); + levelBundle.load(); + configBundle = new ConfigBundle(); + + popupManager.showAnimateFactory = function(v) return new UnFadeAnimate(v, 100); + popupManager.closeAnimateFactory = function(v) return new FadeAnimate(v, 100); + + connection = buildConnection(); + + bus = new ControlBus(); + bus.connect(new KeyboardDevice(Lib.current.stage)); + + updater = new Updater(Const.VERSION, "https://shmyga.ru/repo/tankz/packages.json"); + + for (device in Gamepad.devices) { + trace('gamepad', device); } + Gamepad.onConnect.add(function(device) { + trace('connect gamepad', device); + }); - public static function init():Void { - theme = new AppTheme(); - levelBundle = new CachedLevelBundle(new ClientLevelSource(), new SharedObjectStorage()); - levelBundle.load(); - configBundle = new ConfigBundle(); - - popupManager.showAnimateFactory = function(v) return new UnFadeAnimate(v, 100); - popupManager.closeAnimateFactory = function(v) return new FadeAnimate(v, 100); - - connection = buildConnection(); - - bus = new ControlBus(); - bus.connect(new KeyboardDevice(Lib.current.stage)); - - updater = new Updater(Const.VERSION, "https://shmyga.ru/repo/tankz/packages.json"); - - for (device in Gamepad.devices) { - trace('gamepad', device); - } - Gamepad.onConnect.add(function(device) { - trace('connect gamepad', device); - }); - - for (device in Joystick.devices) { - bus.connect(new JoystickDevice(device)); - } - Joystick.onConnect.add(function(device) { - bus.connect(new JoystickDevice(device)); - }); + for (device in Joystick.devices) { + bus.connect(new JoystickDevice(device)); } + Joystick.onConnect.add(function(device) { + bus.connect(new JoystickDevice(device)); + }); + } } diff --git a/src/client/haxe/ru/m/tankz/LinuxIcon.hx b/src/client/haxe/ru/m/tankz/LinuxIcon.hx index 5abed7a..c405831 100644 --- a/src/client/haxe/ru/m/tankz/LinuxIcon.hx +++ b/src/client/haxe/ru/m/tankz/LinuxIcon.hx @@ -7,21 +7,20 @@ import flash.Lib; import openfl.Assets; class LinuxIcon { + private static function prepareIcon(bitmap:BitmapData):BitmapData { + var matrix:Array = []; + matrix = matrix.concat([0, 0, 1, 0, 0]); + matrix = matrix.concat([0, 1, 0, 0, 0]); + matrix = matrix.concat([1, 0, 0, 0, 0]); + matrix = matrix.concat([0, 0, 0, 1, 0]); + var cmf:ColorMatrixFilter = new ColorMatrixFilter(matrix); + var bitmap:BitmapData = bitmap.clone(); + bitmap.applyFilter(bitmap, bitmap.rect, new Point(0, 0), cmf); + return bitmap; + } - private static function prepareIcon(bitmap:BitmapData):BitmapData { - var matrix:Array = []; - matrix = matrix.concat([0, 0, 1, 0, 0]); - matrix = matrix.concat([0, 1, 0, 0, 0]); - matrix = matrix.concat([1, 0, 0, 0, 0]); - matrix = matrix.concat([0, 0, 0, 1, 0]); - var cmf:ColorMatrixFilter = new ColorMatrixFilter(matrix); - var bitmap:BitmapData = bitmap.clone(); - bitmap.applyFilter(bitmap, bitmap.rect, new Point(0, 0), cmf); - return bitmap; - } - - public static function apply() { - var icon = Assets.getBitmapData("resources/icon.png"); - Lib.current.stage.window.setIcon(prepareIcon(icon).image); - } + public static function apply() { + var icon = Assets.getBitmapData("resources/icon.png"); + Lib.current.stage.window.setIcon(prepareIcon(icon).image); + } } diff --git a/src/client/haxe/ru/m/tankz/Preloader.hx b/src/client/haxe/ru/m/tankz/Preloader.hx index 029ac8e..92bf62b 100644 --- a/src/client/haxe/ru/m/tankz/Preloader.hx +++ b/src/client/haxe/ru/m/tankz/Preloader.hx @@ -9,134 +9,132 @@ import hw.view.geometry.Size; import ru.m.tankz.AppTheme; class Progress extends Sprite { + public var color(default, set):Int = 0; + public var backColor(default, set):Int = 0; + public var progress(default, set):Float = 0; + public var size(default, set):Size = [0, 0]; + public var radius(get, null):Float; - public var color(default, set):Int = 0; - public var backColor(default, set):Int = 0; - public var progress(default, set):Float = 0; - public var size(default, set):Size = [0, 0]; - public var radius(get, null):Float; + private var maskShape:Shape; + private var toRedraw:Bool; - private var maskShape:Shape; - private var toRedraw:Bool; + public function new() { + super(); + maskShape = new Shape(); + addChild(maskShape); + mask = maskShape; + } - public function new() { - super(); - maskShape = new Shape(); - addChild(maskShape); - mask = maskShape; + private inline function get_radius():Float { + return Math.min(size.width, size.height) / 2; + } + + private function set_color(value:Int):Int { + if (color != value) { + color = value; + toRedraw = true; } + return color; + } - private inline function get_radius():Float { - return Math.min(size.width, size.height) / 2; + private function set_backColor(value:Int):Int { + if (backColor != value) { + backColor = value; + toRedraw = true; } + return color; + } - private function set_color(value:Int):Int { - if (color != value) { - color = value; - toRedraw = true; - } - return color; + private function set_progress(value:Float):Float { + if (progress != value) { + progress = value; + toRedraw = true; } + return progress; + } - private function set_backColor(value:Int):Int { - if (backColor != value) { - backColor = value; - toRedraw = true; - } - return color; + private function set_size(value:Size):Size { + if (size != value) { + size = value; + toRedraw = true; } + return size; + } - private function set_progress(value:Float):Float { - if (progress != value) { - progress = value; - toRedraw = true; - } - return progress; + public function update():Void { + if (toRedraw) { + redraw(); + redrawMask(); + toRedraw = false; } + } - private function set_size(value:Size):Size { - if (size != value) { - size = value; - toRedraw = true; - } - return size; - } + public function redraw():Void { + graphics.clear(); + graphics.beginFill(color); + graphics.drawCircle(radius, radius, radius); + graphics.beginFill(backColor); + graphics.drawCircle(radius, radius, radius / 2); + graphics.endFill(); + } - public function update():Void { - if (toRedraw) { - redraw(); - redrawMask(); - toRedraw = false; - } + public function redrawMask():Void { + maskShape.graphics.clear(); + maskShape.graphics.beginFill(0x00ff00); + maskShape.graphics.moveTo(radius, radius); + var sides = 6; + var rotation = (-(Math.PI) / 2); + var r = radius / Math.cos(1 / sides * Math.PI); + var lineToRadians = function(rads:Float):Void { + maskShape.graphics.lineTo(Math.cos(rads) * r + radius, Math.sin(rads) * r + radius); + }; + var sidesToDraw:Int = Math.floor(progress * sides); + for (i in 0...sidesToDraw + 1) { + lineToRadians((i / sides) * (Math.PI * 2) + rotation); } - - public function redraw():Void { - graphics.clear(); - graphics.beginFill(color); - graphics.drawCircle(radius, radius, radius); - graphics.beginFill(backColor); - graphics.drawCircle(radius, radius, radius / 2); - graphics.endFill(); - } - - public function redrawMask():Void { - maskShape.graphics.clear(); - maskShape.graphics.beginFill(0x00ff00); - maskShape.graphics.moveTo(radius, radius); - var sides = 6; - var rotation = (-(Math.PI) / 2); - var r = radius / Math.cos(1/sides * Math.PI); - var lineToRadians = function(rads:Float):Void { - maskShape.graphics.lineTo(Math.cos(rads) * r + radius, Math.sin(rads) * r + radius); - }; - var sidesToDraw:Int = Math.floor(progress * sides); - for (i in 0...sidesToDraw + 1) { - lineToRadians((i / sides) * (Math.PI * 2) + rotation); - } - if (progress * sides != sidesToDraw) { - lineToRadians(progress * (Math.PI * 2) + rotation); - } - maskShape.graphics.endFill(); + if (progress * sides != sidesToDraw) { + lineToRadians(progress * (Math.PI * 2) + rotation); } + maskShape.graphics.endFill(); + } } class Preloader extends Sprite { + private var progress:Progress; - private var progress:Progress; + public function new() { + super(); + Lib.current.stage.color = AppTheme.COLORS.light; + progress = new Progress(); + progress.color = AppTheme.COLORS.dark; + progress.backColor = AppTheme.COLORS.light; + progress.size = [200, 200]; + addChild(progress); + onResize(null); + Lib.current.stage.addEventListener(Event.RESIZE, onResize); + Lib.current.stage.addEventListener(Event.ENTER_FRAME, onEnterFrame); + Lib.current.stage.addEventListener(ProgressEvent.PROGRESS, onProgress); + addEventListener(Event.COMPLETE, onComplete); + } - public function new() { - super(); - Lib.current.stage.color = AppTheme.COLORS.light; - progress = new Progress(); - progress.color = AppTheme.COLORS.dark; - progress.backColor = AppTheme.COLORS.light; - progress.size = [200, 200]; - addChild(progress); - onResize(null); - Lib.current.stage.addEventListener(Event.RESIZE, onResize); - Lib.current.stage.addEventListener(Event.ENTER_FRAME, onEnterFrame); - Lib.current.stage.addEventListener(ProgressEvent.PROGRESS, onProgress); - addEventListener(Event.COMPLETE, onComplete); - } + private function onResize(event:Event):Void { + progress.x = (Lib.current.stage.stageWidth - progress.size.width) / 2; + progress.y = (Lib.current.stage.stageHeight - progress.size.height) / 2; + } - private function onResize(event:Event):Void { - progress.x = (Lib.current.stage.stageWidth - progress.size.width) / 2; - progress.y = (Lib.current.stage.stageHeight - progress.size.height) / 2; - } + private function onEnterFrame(event:Event):Void { + progress.update(); + } - private function onEnterFrame(event:Event):Void { - progress.update(); - } + private function onProgress(event:ProgressEvent):Void { + progress.progress = event.bytesLoaded / event.bytesTotal; + } - private function onProgress(event:ProgressEvent):Void { - progress.progress = event.bytesLoaded / event.bytesTotal; - } - - private function onComplete(event:Event):Void { - progress.update(); - Lib.current.stage.removeEventListener(Event.RESIZE, onResize); - Lib.current.stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame); - Lib.current.stage.removeEventListener(ProgressEvent.PROGRESS, onProgress); - removeEventListener(Event.COMPLETE, onComplete); - } + private function onComplete(event:Event):Void { + progress.update(); + Lib.current.stage.removeEventListener(Event.RESIZE, onResize); + Lib.current.stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame); + Lib.current.stage.removeEventListener(ProgressEvent.PROGRESS, onProgress); + removeEventListener(Event.COMPLETE, onComplete); + } } diff --git a/src/client/haxe/ru/m/tankz/bundle/ClientLevelSource.hx b/src/client/haxe/ru/m/tankz/bundle/ClientLevelSource.hx index 858e801..613eab4 100644 --- a/src/client/haxe/ru/m/tankz/bundle/ClientLevelSource.hx +++ b/src/client/haxe/ru/m/tankz/bundle/ClientLevelSource.hx @@ -8,26 +8,25 @@ import ru.m.tankz.Type; import ru.m.tankz.util.LevelUtil; class ClientLevelSource implements ILevelSource { + public function new() {} - public function new() {} + public function resolveMeta(id:PackId):LevelPackMeta { + var bytes = Assets.getBytes('level/${id}.zip'); + return LevelUtil.getMeta(bytes); + } - public function resolveMeta(id:PackId):LevelPackMeta { - var bytes = Assets.getBytes('level/${id}.zip'); - return LevelUtil.getMeta(bytes); - } - - public function resolve(id:PackId):LevelPack { - var bytes = Assets.getBytes('level/${id}.zip'); - return LevelUtil.unpack(bytes); - } - - public function list():Array { - var result = []; - for (path in Assets.list(AssetType.BINARY)) { - if (StringTools.startsWith(path, "level")) { - result.push(PackId.fromString(path.split("/").pop().split(".").shift())); - } - } - return result; + public function resolve(id:PackId):LevelPack { + var bytes = Assets.getBytes('level/${id}.zip'); + return LevelUtil.unpack(bytes); + } + + public function list():Array { + var result = []; + for (path in Assets.list(AssetType.BINARY)) { + if (StringTools.startsWith(path, "level")) { + result.push(PackId.fromString(path.split("/").pop().split(".").shift())); + } } + return result; + } } diff --git a/src/client/haxe/ru/m/tankz/bundle/ConfigBundle.hx b/src/client/haxe/ru/m/tankz/bundle/ConfigBundle.hx index e09c990..7ebe989 100644 --- a/src/client/haxe/ru/m/tankz/bundle/ConfigBundle.hx +++ b/src/client/haxe/ru/m/tankz/bundle/ConfigBundle.hx @@ -8,16 +8,15 @@ import yaml.Parser; import yaml.Yaml; class ConfigBundle implements IConfigBundle { + private var _cache:Map = new Map(); - private var _cache:Map = new Map(); + public function new() {} - public function new() {} - - public function get(type:GameType):Config { - if (!_cache.exists(type)) { - var source:ConfigSource = Yaml.parse(Assets.getText('config/${type}.yaml'), Parser.options().useObjects()); - _cache.set(type, Config.fromSource(type, source)); - } - return _cache.get(type); + public function get(type:GameType):Config { + if (!_cache.exists(type)) { + var source:ConfigSource = Yaml.parse(Assets.getText('config/${type}.yaml'), Parser.options().useObjects()); + _cache.set(type, Config.fromSource(type, source)); } + return _cache.get(type); + } } diff --git a/src/client/haxe/ru/m/tankz/control/Binding.hx b/src/client/haxe/ru/m/tankz/control/Binding.hx index ba210a8..bd1cf88 100644 --- a/src/client/haxe/ru/m/tankz/control/Binding.hx +++ b/src/client/haxe/ru/m/tankz/control/Binding.hx @@ -5,8 +5,8 @@ import ru.m.control.DeviceType; import ru.m.tankz.control.Control; typedef BindAction = { - var device:DeviceType; - var action:DeviceAction; + var device:DeviceType; + var action:DeviceAction; } typedef Binding = Map; diff --git a/src/client/haxe/ru/m/tankz/control/HumanControl.hx b/src/client/haxe/ru/m/tankz/control/HumanControl.hx index 0746fbe..f92c130 100644 --- a/src/client/haxe/ru/m/tankz/control/HumanControl.hx +++ b/src/client/haxe/ru/m/tankz/control/HumanControl.hx @@ -13,106 +13,105 @@ import ru.m.tankz.Type; using haxe.EnumTools.EnumValueTools; class HumanControl extends Control { + @:provide static var storage:SettingsStorage; + @:provide static var bus:IControlBus; - @:provide static var storage:SettingsStorage; - @:provide static var bus:IControlBus; + private var binding:Map>; - private var binding:Map>; + private var moveQueue:Array; + private var shotTimers:Map; - private var moveQueue:Array; - private var shotTimers:Map; - - public function new(playerId:PlayerId, controlIndex:Int) { - super(playerId); - var config = storage.getBinding(controlIndex); - binding = new Map(); - for (action in config.keys()) { - var bind = config.get(action); - if (!binding.exists(bind.device)) { - binding.set(bind.device, new Map()); - } - binding.get(bind.device).set(bind.action, action); - } - moveQueue = []; - shotTimers = new Map(); + public function new(playerId:PlayerId, controlIndex:Int) { + super(playerId); + var config = storage.getBinding(controlIndex); + binding = new Map(); + for (action in config.keys()) { + var bind = config.get(action); + if (!binding.exists(bind.device)) { + binding.set(bind.device, new Map()); + } + binding.get(bind.device).set(bind.action, action); } + moveQueue = []; + shotTimers = new Map(); + } - public function hasDevice(device:DeviceType):Bool { - for (d in binding.keys()) { - if (d.equals(device)) { - return true; - } - } - return false; + public function hasDevice(device:DeviceType):Bool { + for (d in binding.keys()) { + if (d.equals(device)) { + return true; + } } + return false; + } - private function onDeviceAction(device:DeviceType, action:DeviceAction, on:Bool):Void { - if (binding.exists(device) && binding[device].exists(action)) { - toggleAction(binding[device][action], on); - } + private function onDeviceAction(device:DeviceType, action:DeviceAction, on:Bool):Void { + if (binding.exists(device) && binding[device].exists(action)) { + toggleAction(binding[device][action], on); } + } - override public function start():Void { - super.start(); - bus.signal.connect(onDeviceAction); + override public function start():Void { + super.start(); + bus.signal.connect(onDeviceAction); + } + + override public function stop():Void { + super.stop(); + bus.signal.disconnect(onDeviceAction); + moveQueue = []; + for (timer in shotTimers) { + timer.stop(); } + shotTimers = new Map(); + } - override public function stop():Void { - super.stop(); - bus.signal.disconnect(onDeviceAction); - moveQueue = []; - for (timer in shotTimers) { - timer.stop(); - } - shotTimers = new Map(); - } - - public function toggleAction(action:TankAction, on:Bool):Void { - switch action { - case TankAction.MOVE(direction): - if (on) { - if (moveQueue.indexOf(direction) == -1) { - moveQueue.unshift(direction); - } - } else { - moveQueue.remove(direction); - } - updateMove(); - case TankAction.SHOT(weapon): - if (on) { - if (!shotTimers.exists(weapon)) { - // ToDo: weapon.config.delay - var timer = new Timer(350); - timer.run = shooter(weapon); - timer.run(); - shotTimers.set(weapon, timer); - } - } else { - if (shotTimers.exists(weapon)) { - shotTimers.get(weapon).stop(); - shotTimers.remove(weapon); - } - } - case TankAction.STOP: - } - } - - private function onFocusOut(event:FocusEvent):Void { - moveQueue = []; - updateMove(); - } - - private function updateMove():Void { - if (moveQueue.length == 0) { - action(STOP); + public function toggleAction(action:TankAction, on:Bool):Void { + switch action { + case TankAction.MOVE(direction): + if (on) { + if (moveQueue.indexOf(direction) == -1) { + moveQueue.unshift(direction); + } } else { - action(MOVE(moveQueue[0])); + moveQueue.remove(direction); } + updateMove(); + case TankAction.SHOT(weapon): + if (on) { + if (!shotTimers.exists(weapon)) { + // ToDo: weapon.config.delay + var timer = new Timer(350); + timer.run = shooter(weapon); + timer.run(); + shotTimers.set(weapon, timer); + } + } else { + if (shotTimers.exists(weapon)) { + shotTimers.get(weapon).stop(); + shotTimers.remove(weapon); + } + } + case TankAction.STOP: } + } - private function shooter(weapon:Int):Void -> Void { - return function():Void { - action(SHOT(weapon)); - } + private function onFocusOut(event:FocusEvent):Void { + moveQueue = []; + updateMove(); + } + + private function updateMove():Void { + if (moveQueue.length == 0) { + action(STOP); + } else { + action(MOVE(moveQueue[0])); } + } + + private function shooter(weapon:Int):Void->Void { + return function():Void { + action(SHOT(weapon)); + } + } } diff --git a/src/client/haxe/ru/m/tankz/game/GameInit.hx b/src/client/haxe/ru/m/tankz/game/GameInit.hx index 4cbe34b..cff19a1 100644 --- a/src/client/haxe/ru/m/tankz/game/GameInit.hx +++ b/src/client/haxe/ru/m/tankz/game/GameInit.hx @@ -5,7 +5,7 @@ import ru.m.tankz.game.record.GameRecord; import ru.m.tankz.network.NetworkManager; enum GameInit { - LOCAL(start:Start); - NETWORK(network:NetworkManager); - RECORD(record:GameRecord); + LOCAL(start:Start); + NETWORK(network:NetworkManager); + RECORD(record:GameRecord); } diff --git a/src/client/haxe/ru/m/tankz/local/LocalControlFactory.hx b/src/client/haxe/ru/m/tankz/local/LocalControlFactory.hx index e859632..5c0b1c2 100644 --- a/src/client/haxe/ru/m/tankz/local/LocalControlFactory.hx +++ b/src/client/haxe/ru/m/tankz/local/LocalControlFactory.hx @@ -6,8 +6,7 @@ import ru.m.tankz.control.HumanControl; import ru.m.tankz.Type; class LocalControlFactory extends BaseControlFactory { - - override private function buildHuman(id:PlayerId, index:Int):Control { - return new HumanControl(id, index); - } + override private function buildHuman(id:PlayerId, index:Int):Control { + return new HumanControl(id, index); + } } diff --git a/src/client/haxe/ru/m/tankz/local/LocalGame.hx b/src/client/haxe/ru/m/tankz/local/LocalGame.hx index c807ece..5ce741c 100644 --- a/src/client/haxe/ru/m/tankz/local/LocalGame.hx +++ b/src/client/haxe/ru/m/tankz/local/LocalGame.hx @@ -8,35 +8,34 @@ import ru.m.tankz.storage.GameStorage; import ru.m.tankz.Type; class LocalGame extends GameRunner { + @:provide static var gameStorage:GameStorage; - @:provide static var gameStorage:GameStorage; + public function new(start:Start) { + super(start); + controlFactory = new LocalControlFactory(); + } - public function new(start:Start) { - super(start); - controlFactory = new LocalControlFactory(); + override public function onGameEvent(event:GameEvent):Void { + super.onGameEvent(event); + switch event { + case COMPLETE(result): + updateProgress(result); + case _: } + } - override public function onGameEvent(event:GameEvent):Void { - super.onGameEvent(event); - switch event { - case COMPLETE(result): - updateProgress(result); - case _: - } + private function updateProgress(result:Result):Void { + var complete = false; + var humansTeams:Array = []; + for (control in controls) { + if (Std.is(control, HumanControl) && humansTeams.indexOf(control.playerId.team) == -1) { + humansTeams.push(control.playerId.team); + } } - - private function updateProgress(result:Result):Void { - var complete = false; - var humansTeams:Array = []; - for (control in controls) { - if (Std.is(control, HumanControl) && humansTeams.indexOf(control.playerId.team) == -1) { - humansTeams.push(control.playerId.team); - } - } - if (humansTeams.length == 1 && result.winner == humansTeams[0]) { - var progress = gameStorage.get(result.level.packId); - progress.completeLevel(result.level.id, result.state.presetId, {}); - gameStorage.set(progress); - } + if (humansTeams.length == 1 && result.winner == humansTeams[0]) { + var progress = gameStorage.get(result.level.packId); + progress.completeLevel(result.level.id, result.state.presetId, {}); + gameStorage.set(progress); } + } } diff --git a/src/client/haxe/ru/m/tankz/local/StageCaller.hx b/src/client/haxe/ru/m/tankz/local/StageCaller.hx index 7ee86a9..ca29b1d 100644 --- a/src/client/haxe/ru/m/tankz/local/StageCaller.hx +++ b/src/client/haxe/ru/m/tankz/local/StageCaller.hx @@ -5,27 +5,26 @@ import flash.events.Event; import ru.m.tankz.engine.ICaller; class StageCaller implements ICaller { + private var stage:Stage; + private var event:String; + private var calback:Void->Void; - private var stage:Stage; - private var event:String; - private var calback:Void -> Void; + public function new(stage:Stage, ?event:String) { + this.stage = stage; + this.event = event != null ? event : Event.ENTER_FRAME; + } - public function new(stage:Stage, ?event:String) { - this.stage = stage; - this.event = event != null ? event : Event.ENTER_FRAME; - } + private function onEvent(_):Void { + calback(); + } - private function onEvent(_):Void { - calback(); - } + public function start(calback:Void->Void):Void { + this.calback = calback; + stage.addEventListener(event, onEvent); + } - public function start(calback:Void -> Void):Void { - this.calback = calback; - stage.addEventListener(event, onEvent); - } - - public function stop():Void { - stage.removeEventListener(event, onEvent); - calback = null; - } + public function stop():Void { + stage.removeEventListener(event, onEvent); + calback = null; + } } diff --git a/src/client/haxe/ru/m/tankz/network/NetworkControl.hx b/src/client/haxe/ru/m/tankz/network/NetworkControl.hx index 70c98e3..46df115 100644 --- a/src/client/haxe/ru/m/tankz/network/NetworkControl.hx +++ b/src/client/haxe/ru/m/tankz/network/NetworkControl.hx @@ -5,12 +5,11 @@ import ru.m.tankz.network.NetworkManager; import ru.m.tankz.control.Control; class NetworkControl extends HumanControl { + @:provide private var network:NetworkManager; - @:provide private var network:NetworkManager; - - override public function action(action:TankAction):Void { - if (tankId > -1) { - network.action(tankId, action); - } + override public function action(action:TankAction):Void { + if (tankId > -1) { + network.action(tankId, action); } + } } diff --git a/src/client/haxe/ru/m/tankz/network/NetworkControlFactory.hx b/src/client/haxe/ru/m/tankz/network/NetworkControlFactory.hx index 12034fb..5c2a738 100644 --- a/src/client/haxe/ru/m/tankz/network/NetworkControlFactory.hx +++ b/src/client/haxe/ru/m/tankz/network/NetworkControlFactory.hx @@ -5,12 +5,11 @@ import ru.m.tankz.control.Control; import ru.m.tankz.Type; class NetworkControlFactory extends BaseControlFactory { + override private function buildHuman(id:PlayerId, index:Int):Control { + return new NetworkControl(id, index); + } - override private function buildHuman(id:PlayerId, index:Int):Control { - return new NetworkControl(id, index); - } - - override private function buildBot(id:PlayerId, type:String):Control { - return null; - } + override private function buildBot(id:PlayerId, type:String):Control { + return null; + } } diff --git a/src/client/haxe/ru/m/tankz/network/NetworkGame.hx b/src/client/haxe/ru/m/tankz/network/NetworkGame.hx index 3a3bbd9..cba17f1 100644 --- a/src/client/haxe/ru/m/tankz/network/NetworkGame.hx +++ b/src/client/haxe/ru/m/tankz/network/NetworkGame.hx @@ -10,45 +10,45 @@ import ru.m.tankz.proto.pack.GameEventResponse; import ru.m.tankz.proto.room.RoomSlotProto; class NetworkGame extends Game { + private var network:NetworkManager; - private var network:NetworkManager; + public function new(network:NetworkManager) { + super(network.room.game.type); + this.network = network; + this.controlFactory = new NetworkControlFactory(); + network.gameEventSignal.connect(onGameEventProto); + network.stateSignal.connect(onConnectionState); + } - public function new(network:NetworkManager) { - super(network.room.game.type); - this.network = network; - this.controlFactory = new NetworkControlFactory(); - network.gameEventSignal.connect(onGameEventProto); - network.stateSignal.connect(onConnectionState); - } + private function onGameEventProto(game:GameEventResponse):Void { + var time = game.event.time; + var eventStr = game.event.event; + var event:GameEvent = Unserializer.run(eventStr); + gameEventSignal.emit(event); + } - private function onGameEventProto(game:GameEventResponse):Void { - var time = game.event.time; - var eventStr = game.event.event; - var event:GameEvent = Unserializer.run(eventStr); - gameEventSignal.emit(event); - } - - private function onConnectionState(state:ConnectionState):Void { - switch state { - case ONLINE(user): - if (network.room != null) { - network.joinGame(network.room.game.id); - } - case _: + private function onConnectionState(state:ConnectionState):Void { + switch state { + case ONLINE(user): + if (network.room != null) { + network.joinGame(network.room.game.id); } + case _: } + } - override private function onStart(start:Start):Void { - var slot:RoomSlotProto = Lambda.find(network.room.slots, function(slot:RoomSlotProto) return slot.hasUser() && slot.user.uuid == network.user.uuid); - if (slot != null) { - start.state.controls.push({playerId: [slot.slot.team, slot.slot.index], controller: HUMAN(0)}); - } - super.onStart(start); + override private function onStart(start:Start):Void { + var slot:RoomSlotProto = Lambda.find(network.room.slots, + function(slot:RoomSlotProto) return slot.hasUser() && slot.user.uuid == network.user.uuid); + if (slot != null) { + start.state.controls.push({playerId: [slot.slot.team, slot.slot.index], controller: HUMAN(0)}); } + super.onStart(start); + } - override public function dispose():Void { - super.dispose(); - network.gameEventSignal.disconnect(onGameEventProto); - network.stateSignal.disconnect(onConnectionState); - } + override public function dispose():Void { + super.dispose(); + network.gameEventSignal.disconnect(onGameEventProto); + network.stateSignal.disconnect(onConnectionState); + } } diff --git a/src/client/haxe/ru/m/tankz/network/NetworkManager.hx b/src/client/haxe/ru/m/tankz/network/NetworkManager.hx index be7ef5e..2a146f8 100644 --- a/src/client/haxe/ru/m/tankz/network/NetworkManager.hx +++ b/src/client/haxe/ru/m/tankz/network/NetworkManager.hx @@ -28,172 +28,166 @@ import ru.m.tankz.storage.SettingsStorage; typedef ClientConnection = IConnection; enum ConnectionState { - OFFLINE; - CONNECT; - CONNECTED; - LOGIN; - ONLINE(user:User); - ERROR(error:Dynamic); + OFFLINE; + CONNECT; + CONNECTED; + LOGIN; + ONLINE(user:User); + ERROR(error:Dynamic); } @:provide class NetworkManager { + private static inline var TAG = "NetworkManager"; - private static inline var TAG = "NetworkManager"; + public var state(default, null):ConnectionState; + public var room(default, null):RoomProto; + public var user(default, null):UserProto; - public var state(default, null):ConnectionState; - public var room(default, null):RoomProto; - public var user(default, null):UserProto; + public var stateSignal:Signal; + public var listRoomSignal:Signal>; + public var roomSignal:Signal; + public var gameEventSignal:Signal; - public var stateSignal:Signal; - public var listRoomSignal:Signal>; - public var roomSignal:Signal; - public var gameEventSignal:Signal; + @:provide private var connection:ClientConnection; + @:provide private var storage:NetworkStorage; + @:provide private var settings:SettingsStorage; - @:provide private var connection:ClientConnection; - @:provide private var storage:NetworkStorage; - @:provide private var settings:SettingsStorage; + private var reconnectTimer:Timer; + private var reconnectDelay:Int; - private var reconnectTimer:Timer; - private var reconnectDelay:Int; + public function new() { + reconnectDelay = 500; + stateSignal = new Signal(); + listRoomSignal = new Signal(); + roomSignal = new Signal(); + gameEventSignal = new Signal(); + updateState(OFFLINE); + connection.handler.connect(onConnectionEvent); + connection.receiveHandler.connect(onResponse); + if (settings.enableNetwork) { + connect(); + } + settings.signal.connect(onSettingChange); + } - public function new() { + private function onSettingChange(setting:Setting):Void { + switch setting { + case ENABLE_NETWORK(value): + if (value) { + connect(); + } else { + disconnect(); + } + case _: + } + } + + private function updateState(value:ConnectionState):Void { + L.d(TAG, 'State: ${value}'); + state = value; + stateSignal.emit(value); + } + + public function login(name:String, uuid:String = null):Void { + updateState(LOGIN); + connection.send(new Request().setLogin(new LoginRequest().setUuid(uuid).setName(name))); + } + + public function logout():Void { + connection.send(new Request().setLogout(new LogoutRequest())); + } + + public function listGame(subscribe:Bool):Void { + connection.send(new Request().setRoomList(new RoomListRequest().setSubscribe(subscribe))); + } + + public function createGame(type:String, level:Int):Void { + connection.send(new Request().setRoom(new RoomRequest().setCreate(new CreateRequest().setType(type) + .setLevel(level)))); + } + + public function joinGame(gameId:Int, restore:Bool = false):Void { + connection.send(new Request().setRoom(new RoomRequest().setJoin(new JoinRequest().setGameId(gameId) + .setRestore(restore)))); + } + + public function selectSlot(slot:SlotProto):Void { + connection.send(new Request().setRoom(new RoomRequest().setSlot(new SlotRequest().setSlot(slot)))); + } + + public function leaveGame():Void { + connection.send(new Request().setRoom(new RoomRequest().setLeave(new LeaveRequest()))); + } + + public function startGame():Void { + connection.send(new Request().setRoom(new RoomRequest().setStart(new StartRequest()))); + } + + public function action(tankId:Int, action:TankAction):Void { + connection.send(new Request().setGameEvent(new GameEventRequest().setEvent(new GameEventProto().setTime(0) + .setEvent(Serializer.run(GameEvent.ACTION(tankId, action)))))); + } + + private function connect():Void { + if (reconnectTimer != null) { + reconnectTimer.stop(); + reconnectTimer = null; + } + reconnectTimer = null; + updateState(CONNECT); + connection.connect().catchError(function(error) {}); + } + + private function reconnect():Void { + reconnectDelay = Std.int(Math.min(reconnectDelay * 2, 10000)); + if (reconnectTimer == null) { + reconnectTimer = Timer.delay(connect, reconnectDelay); + } + } + + private function disconnect():Void { + connection.disconnect(); + } + + private function onConnectionEvent(event:ConnectionEvent):Void { + updateState(switch event { + case CONNECTED: CONNECTED; + case DISCONNECTED: OFFLINE; + case ERROR(error): ERROR(error); + }); + switch event { + case CONNECTED: reconnectDelay = 500; - stateSignal = new Signal(); - listRoomSignal = new Signal(); - roomSignal = new Signal(); - gameEventSignal = new Signal(); - updateState(OFFLINE); - connection.handler.connect(onConnectionEvent); - connection.receiveHandler.connect(onResponse); + var user = storage.user; + if (user != null) { + login(user.name, user.uuid); + } + case DISCONNECTED | ERROR(_): if (settings.enableNetwork) { - connect(); - } - settings.signal.connect(onSettingChange); - } - - private function onSettingChange(setting:Setting):Void { - switch setting { - case ENABLE_NETWORK(value): - if (value) { - connect(); - } else { - disconnect(); - } - case _: + reconnect(); } } + } - private function updateState(value:ConnectionState):Void { - L.d(TAG, 'State: ${value}'); - state = value; - stateSignal.emit(value); - } - - public function login(name:String, uuid:String = null):Void { - updateState(LOGIN); - connection.send(new Request().setLogin( - new LoginRequest() - .setUuid(uuid) - .setName(name) - )); - } - - public function logout():Void { - connection.send(new Request().setLogout(new LogoutRequest())); - } - - public function listGame(subscribe:Bool):Void { - connection.send(new Request().setRoomList(new RoomListRequest().setSubscribe(subscribe))); - } - - public function createGame(type:String, level:Int):Void { - connection.send(new Request().setRoom(new RoomRequest().setCreate(new CreateRequest().setType(type).setLevel(level)))); - } - - public function joinGame(gameId:Int, restore:Bool = false):Void { - connection.send(new Request().setRoom(new RoomRequest().setJoin(new JoinRequest().setGameId(gameId).setRestore(restore)))); - } - - public function selectSlot(slot:SlotProto):Void { - connection.send(new Request().setRoom(new RoomRequest().setSlot(new SlotRequest().setSlot(slot)))); - } - - public function leaveGame():Void { - connection.send(new Request().setRoom(new RoomRequest().setLeave(new LeaveRequest()))); - } - - public function startGame():Void { - connection.send(new Request().setRoom(new RoomRequest().setStart(new StartRequest()))); - } - - public function action(tankId:Int, action:TankAction):Void { - connection.send(new Request().setGameEvent(new GameEventRequest().setEvent( - new GameEventProto().setTime(0).setEvent( - Serializer.run(GameEvent.ACTION(tankId, action)) - ))) - ); - } - - private function connect():Void { - if (reconnectTimer != null) { - reconnectTimer.stop(); - reconnectTimer = null; - } - reconnectTimer = null; - updateState(CONNECT); - connection.connect().catchError(function(error) {}); - } - - private function reconnect():Void { - reconnectDelay = Std.int(Math.min(reconnectDelay * 2, 10000)); - if (reconnectTimer == null) { - reconnectTimer = Timer.delay(connect, reconnectDelay); - } - } - - private function disconnect():Void { - connection.disconnect(); - } - - private function onConnectionEvent(event:ConnectionEvent):Void { - updateState(switch event { - case CONNECTED: CONNECTED; - case DISCONNECTED: OFFLINE; - case ERROR(error): ERROR(error); - }); - switch event { - case CONNECTED: - reconnectDelay = 500; - var user = storage.user; - if (user != null) { - login(user.name, user.uuid); - } - case DISCONNECTED | ERROR(_): - if (settings.enableNetwork) { - reconnect(); - } - } - } - - private function onResponse(packet:Response):Void { - if (packet.hasLogin()) { - this.user = packet.login.user; - var user = { - uuid: this.user.uuid, - name: this.user.name, - }; - storage.user = user; - updateState(ONLINE(user)); - } else if (packet.hasLogout()) { - storage.user = null; - updateState(CONNECTED); - } else if (packet.hasRoomList()) { - listRoomSignal.emit(packet.roomList.rooms); - } else if (packet.hasRoom()) { - room = packet.room.room; - roomSignal.emit(room); - } else if (packet.hasGameEvent()) { - gameEventSignal.emit(packet.gameEvent); - } + private function onResponse(packet:Response):Void { + if (packet.hasLogin()) { + this.user = packet.login.user; + var user = { + uuid: this.user.uuid, + name: this.user.name, + }; + storage.user = user; + updateState(ONLINE(user)); + } else if (packet.hasLogout()) { + storage.user = null; + updateState(CONNECTED); + } else if (packet.hasRoomList()) { + listRoomSignal.emit(packet.roomList.rooms); + } else if (packet.hasRoom()) { + room = packet.room.room; + roomSignal.emit(room); + } else if (packet.hasGameEvent()) { + gameEventSignal.emit(packet.gameEvent); } + } } diff --git a/src/client/haxe/ru/m/tankz/render/AnimateBundle.hx b/src/client/haxe/ru/m/tankz/render/AnimateBundle.hx index 724b773..579f161 100644 --- a/src/client/haxe/ru/m/tankz/render/AnimateBundle.hx +++ b/src/client/haxe/ru/m/tankz/render/AnimateBundle.hx @@ -5,38 +5,35 @@ import ru.m.animate.Animate; import ru.m.animate.OnceAnimate; class AnimateBundle { + private static function buildAnimate(name:String, sequence:Array):OnceAnimate { + var template:String = 'resources/image/animate/${name}/%index%.png'; + var frames = [ + for (i in sequence) + ({ + image:Assets.getBitmapData(StringTools.replace(template, '%index%', Std.string(i))), length:1 + }) + ]; + return new OnceAnimate(frames); + } - private static function buildAnimate(name:String, sequence:Array):OnceAnimate { - var template:String = 'resources/image/animate/${name}/%index%.png'; - var frames = [for (i in sequence) ({ - image: Assets.getBitmapData(StringTools.replace(template, '%index%', Std.string(i))), - length: 1 - })]; - return new OnceAnimate(frames); - } + public static function tankSpawn():OnceAnimate { + return buildAnimate('appear', [0, 1, 2, 3, 3, 4, 5, 5, 6]); + } - public static function tankSpawn():OnceAnimate { - return buildAnimate('appear', [ - 0, 1, 2, 3, 3, 4, 5, 5, 6 - ]); - } + public static function tankBoom():OnceAnimate { + return buildAnimate('boom', [0, 1, 2, 3, 4, 4, 4, 1, 4, 4, 7, 7, 8, 9, 9]); + } - public static function tankBoom():OnceAnimate { - return buildAnimate('boom', [ - 0, 1, 2, 3, 4, 4, 4, 1, 4, 4, 7, 7, 8, 9, 9 - ]); - } + public static function bulletBoom():OnceAnimate { + return buildAnimate('boom-sm', [0, 1, 1, 0, 0, 1]); + } - public static function bulletBoom():OnceAnimate { - return buildAnimate('boom-sm', [ - 0, 1, 1, 0, 0, 1 - ]); - } - - public static function tankProtect():Animate { - return new Animate([for (i in 0...2) ({ - image: Assets.getBitmapData('resources/image/animate/protect/${i}.png'), - length: 5 - })]); - } + public static function tankProtect():Animate { + return new Animate([ + for (i in 0...2) + ({ + image:Assets.getBitmapData('resources/image/animate/protect/${i}.png'), length:5 + }) + ]); + } } diff --git a/src/client/haxe/ru/m/tankz/render/IRender.hx b/src/client/haxe/ru/m/tankz/render/IRender.hx index 42380be..0cd6bec 100644 --- a/src/client/haxe/ru/m/tankz/render/IRender.hx +++ b/src/client/haxe/ru/m/tankz/render/IRender.hx @@ -5,8 +5,8 @@ import ru.m.tankz.config.Config; import ru.m.tankz.game.IGame; interface IRender extends IView extends GameListener { - public var config(default, set):Config; - public var gridSize(default, set):GridSize; - public function draw():Void; - public function reset():Void; + public var config(default, set):Config; + public var gridSize(default, set):GridSize; + public function draw():Void; + public function reset():Void; } diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index 379cc15..1401c7d 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -23,281 +23,281 @@ import ru.m.tankz.render.item.EagleRenderItem; import ru.m.tankz.render.item.IRenderItem; import ru.m.tankz.render.item.TankRenderItem; import ru.m.tankz.Type; + using ru.m.display.DisplayObjectContainerExtender; class Render extends SpriteView implements IRender { + public var config(default, set):Config; + public var gridSize(default, set):GridSize; - public var config(default, set):Config; - public var gridSize(default, set):GridSize; + private var mapWidth(get, null):Float; + private var mapHeight(get, null):Float; - private var mapWidth(get, null):Float; - private var mapHeight(get, null):Float; + private var container:Sprite; + private var backgroundLayer:Sprite; + private var groundLayer:Sprite; + private var entryLayer:Sprite; + private var upLayer:Sprite; + private var upperLayer:Sprite; - private var container:Sprite; - private var backgroundLayer:Sprite; - private var groundLayer:Sprite; - private var entryLayer:Sprite; - private var upLayer:Sprite; - private var upperLayer:Sprite; + private var items:Map; + private var paused:Bool; - private var items:Map; - private var paused:Bool; + @:provide private static var animateManager:AnimateManager; - @:provide private static var animateManager:AnimateManager; + public function new() { + super(); + items = new Map(); + container = new Sprite(); + content.addChild(container); + backgroundLayer = new Sprite(); + groundLayer = new Sprite(); + entryLayer = new Sprite(); + upLayer = new Sprite(); + upperLayer = new Sprite(); + container.addChild(backgroundLayer); + container.addChild(groundLayer); + container.addChild(entryLayer); + container.addChild(upLayer); + container.addChild(upperLayer); + reset(); + } - public function new() { - super(); - items = new Map(); - container = new Sprite(); - content.addChild(container); - backgroundLayer = new Sprite(); - groundLayer = new Sprite(); - entryLayer = new Sprite(); - upLayer = new Sprite(); - upperLayer = new Sprite(); - container.addChild(backgroundLayer); - container.addChild(groundLayer); - container.addChild(entryLayer); - container.addChild(upLayer); - container.addChild(upperLayer); - reset(); + private function get_mapWidth():Float { + return config.map.cell.width * (gridSize != null ? gridSize.width : config.map.grid.width); + } + + private function get_mapHeight():Float { + return config.map.cell.height * (gridSize != null ? gridSize.height : config.map.grid.height); + } + + private function set_config(value:Config):Config { + config = value; + drawBackground(); + toRedraw(); + return config; + } + + private function set_gridSize(value:GridSize):GridSize { + gridSize = value; + drawBackground(); + toRedraw(); + return gridSize; + } + + private function drawBackground():Void { + var g:Graphics = backgroundLayer.graphics; + g.clear(); + g.beginFill(0x000000); + g.lineStyle(2, 0xcccccc); + g.drawRect(0, 0, mapWidth, mapHeight); + g.endFill(); + } + + override public function redraw():Void { + super.redraw(); + var scale = Math.min(width / mapWidth, height / mapHeight); + container.scaleX = container.scaleY = scale; + container.x = (width - (mapWidth * scale)) / 2; + container.y = (height - (mapHeight * scale)) / 2; + } + + public function draw():Void { + for (item in items) { + item.update(); } + } - private function get_mapWidth():Float { - return config.map.cell.width * (gridSize != null ? gridSize.width : config.map.grid.width); + private function onEnterFrame(event:Event):Void { + if (!paused) { + draw(); } + } - private function get_mapHeight():Float { - return config.map.cell.height * (gridSize != null ? gridSize.height : config.map.grid.height); + private function clearLayer(layer:DisplayObjectContainer) { + while (layer.numChildren > 0) { + layer.removeChildAt(0); } + } - private function set_config(value:Config):Config { - config = value; - drawBackground(); - toRedraw(); - return config; + public function reset():Void { + content.removeEventListener(Event.ENTER_FRAME, onEnterFrame); + for (item in items.iterator()) { + item.dispose(); } + items = new Map(); + clearLayer(entryLayer); + clearLayer(groundLayer); + clearLayer(upLayer); + clearLayer(upperLayer); + } - private function set_gridSize(value:GridSize):GridSize { - gridSize = value; - drawBackground(); - toRedraw(); - return gridSize; - } - - private function drawBackground():Void { - var g:Graphics = backgroundLayer.graphics; - g.clear(); - g.beginFill(0x000000); - g.lineStyle(2, 0xcccccc); - g.drawRect(0, 0, mapWidth, mapHeight); - g.endFill(); - } - - override public function redraw():Void { - super.redraw(); - var scale = Math.min(width / mapWidth, height / mapHeight); - container.scaleX = container.scaleY = scale; - container.x = (width - (mapWidth * scale)) / 2; - container.y = (height - (mapHeight * scale)) / 2; - } - - public function draw():Void { - for (item in items) { - item.update(); - } - } - - private function onEnterFrame(event:Event):Void { - if (!paused) { - draw(); - } - } - - private function clearLayer(layer:DisplayObjectContainer) { - while (layer.numChildren > 0) { - layer.removeChildAt(0); - } - } - - public function reset():Void { + public function onGameEvent(event:GameEvent):Void { + switch event { + case START(start): + animateManager.playing = true; + gridSize = start.level.size; + content.addEventListener(Event.ENTER_FRAME, onEnterFrame); + case COMPLETE(_): content.removeEventListener(Event.ENTER_FRAME, onEnterFrame); - for (item in items.iterator()) { - item.dispose(); + case PAUSE(paused): + this.paused = paused; + animateManager.playing = !paused; + case SPAWN(BRICK(bricks)): + drawBackground(); + for (brick in bricks) { + var item:IRenderItem = new BrickRenderItem(brick.rect, brick.type); + var config = config.getBrick(brick.type); + items[brick.id] = item; + if (config.layer > 2) { + upLayer.addChild(item.view); + } else { + groundLayer.addChild(item.view); + } } - items = new Map(); - clearLayer(entryLayer); - clearLayer(groundLayer); - clearLayer(upLayer); - clearLayer(upperLayer); - } - - public function onGameEvent(event:GameEvent):Void { - switch event { - case START(start): - animateManager.playing = true; - gridSize = start.level.size; - content.addEventListener(Event.ENTER_FRAME, onEnterFrame); - case COMPLETE(_): - content.removeEventListener(Event.ENTER_FRAME, onEnterFrame); - case PAUSE(paused): - this.paused = paused; - animateManager.playing = !paused; - case SPAWN(BRICK(bricks)): - drawBackground(); - for (brick in bricks) { - var item:IRenderItem = new BrickRenderItem(brick.rect, brick.type); - var config = config.getBrick(brick.type); - items[brick.id] = item; - if (config.layer > 2) { - upLayer.addChild(item.view); - } else { - groundLayer.addChild(item.view); - } - } - case SPAWN(EAGLE(id, rect, teamId)): - var item = new EagleRenderItem(rect, config.getColor(new PlayerId(teamId, -1))); - items.set(id, item); - entryLayer.addChild(item.view); - item.update(); - case SPAWN(TANK(id, rect, playerId, info)): - var item = new TankRenderItem(rect); - var tankConfig = config.getTank(info.type); - item.color = info.color; - item.skin = tankConfig.skin; - item.hits = info.hits; - item.bonus = info.bonus; - item.boat = info.boat; - item.name = info.name == null ? "" : info.name; - items.set(id, item); - entryLayer.addChild(item.view); - item.update(); - playAnimate(item.rect.center, AnimateBundle.tankSpawn()); - case SPAWN(BULLET(id, rect, playerId, skin, color)): - var item = new BulletRenderItem(rect); - item.color = color; - item.skin = skin; - items.set(id, item); - entryLayer.addChild(item.view); - item.update(); - case SPAWN(BONUS(id, rect, type)): - var item = new BonusRenderItem(rect, type); - items.set(id, item); - upperLayer.addChild(item.view); - item.update(); - case MOVE(EAGLE(id, position)): - if (items.exists(id)) { - var item = items[id]; - item.move(position); - } - case MOVE(BULLET(id, position)): - if (items.exists(id)) { - var item = items[id]; - item.move(position); - } - case MOVE(TANK(id, position)): - if (items.exists(id)) { - var item = items[id]; - item.move(position); - cast(item, TankRenderItem).moves = true; - } - case STOP(TANK(id)): - if (items.exists(id)) { - var item = items[id]; - cast(item, TankRenderItem).moves = false; - } - case CHANGE(TANK(id, type, hits, bonus, boat)): - if (items.exists(id)) { - var item:TankRenderItem = cast items[id]; - item.skin = config.getTank(type).skin; - item.hits = hits; - item.bonus = bonus; - item.boat = boat; - } - case CHANGE(TANK_PROTECT(id, state)): - if (items.exists(id)) { - var item:TankRenderItem = cast items[id]; - item.protect = state; - } - case CHANGE(EAGLE_PROTECT(id, state)): - if (items.exists(id)) { - var item:EagleRenderItem = cast items[id]; - item.protect = state; - } - case CHANGE(BRICK(id, type)): - if (items.exists(id)) { - var item:BrickRenderItem = cast items[id]; - item.type = type; - } - case DESTROY(TANK(id, shot)): - if (items.exists(id)) { - var item = items[id]; - entryLayer.removeChild(item.view); - playAnimate(item.rect.center, AnimateBundle.tankBoom()); - showScore(item.rect.center, shot.score); - items.remove(id); - } - case DESTROY(BULLET(id)): - if (items.exists(id)) { - var item = items[id]; - entryLayer.removeChild(item.view); - var rect = item.rect; - // move boom - var point = rect.center.add(new Point(rect.width * rect.direction.x, rect.height * rect.direction.y)); - playAnimate(point, AnimateBundle.bulletBoom()); - items.remove(id); - } - case DESTROY(EAGLE(id, shot)): - if (items.exists(id)) { - var item = items[id]; - playAnimate(item.rect.center, AnimateBundle.tankBoom()); - showScore(item.rect.center, shot.score); - cast(item, EagleRenderItem).death = true; - } - case DESTROY(BONUS(id, shot)): - if (items.exists(id)) { - var item = items[id]; - upperLayer.removeChild(item.view); - showScore(item.rect.center, shot.score); - items.remove(id); - } - case DESTROY(CELL(id, x, y, shot)): - var item:BrickRenderItem = cast items.get(id); - item.destroyCell(x, y); - case DESTROY(BRICK(id, shot)): - var item:BrickRenderItem = cast items.get(id); - item.destroy(); - case _: + case SPAWN(EAGLE(id, rect, teamId)): + var item = new EagleRenderItem(rect, config.getColor(new PlayerId(teamId, -1))); + items.set(id, item); + entryLayer.addChild(item.view); + item.update(); + case SPAWN(TANK(id, rect, playerId, info)): + var item = new TankRenderItem(rect); + var tankConfig = config.getTank(info.type); + item.color = info.color; + item.skin = tankConfig.skin; + item.hits = info.hits; + item.bonus = info.bonus; + item.boat = info.boat; + item.name = info.name == null ? "" : info.name; + items.set(id, item); + entryLayer.addChild(item.view); + item.update(); + playAnimate(item.rect.center, AnimateBundle.tankSpawn()); + case SPAWN(BULLET(id, rect, playerId, skin, color)): + var item = new BulletRenderItem(rect); + item.color = color; + item.skin = skin; + items.set(id, item); + entryLayer.addChild(item.view); + item.update(); + case SPAWN(BONUS(id, rect, type)): + var item = new BonusRenderItem(rect, type); + items.set(id, item); + upperLayer.addChild(item.view); + item.update(); + case MOVE(EAGLE(id, position)): + if (items.exists(id)) { + var item = items[id]; + item.move(position); } - #if cpp - flash.Lib.current.stage.invalidate(); - #end - } - - private function playAnimate(point:Point, animate:OnceAnimate):Promise { - animate.x = point.x - animate.width / 2; - animate.y = point.y - animate.height / 2; - upperLayer.addChild(animate); - return animate.play().then(function(animate:Animate):Void { - // ToDo: clean animates on reset - if (upperLayer.contains(animate)) { - upperLayer.removeChildSafety(animate); - } - animate.dispose(); - }); - } - - private function showScore(point:Point, score:Null):Void { - if (score != null && score != 0) { - var view:LabelView = new LabelView(); - view.style = "text"; - view.text = Std.string(score); - view.update(); - view.redraw(); - view.x = point.x - view.width / 2; - view.y = point.y - view.height / 2; - upperLayer.addChild(view.content); - Timer.delay(function() upperLayer.removeChildSafety(view.content), 1000); + case MOVE(BULLET(id, position)): + if (items.exists(id)) { + var item = items[id]; + item.move(position); } + case MOVE(TANK(id, position)): + if (items.exists(id)) { + var item = items[id]; + item.move(position); + cast(item, TankRenderItem).moves = true; + } + case STOP(TANK(id)): + if (items.exists(id)) { + var item = items[id]; + cast(item, TankRenderItem).moves = false; + } + case CHANGE(TANK(id, type, hits, bonus, boat)): + if (items.exists(id)) { + var item:TankRenderItem = cast items[id]; + item.skin = config.getTank(type).skin; + item.hits = hits; + item.bonus = bonus; + item.boat = boat; + } + case CHANGE(TANK_PROTECT(id, state)): + if (items.exists(id)) { + var item:TankRenderItem = cast items[id]; + item.protect = state; + } + case CHANGE(EAGLE_PROTECT(id, state)): + if (items.exists(id)) { + var item:EagleRenderItem = cast items[id]; + item.protect = state; + } + case CHANGE(BRICK(id, type)): + if (items.exists(id)) { + var item:BrickRenderItem = cast items[id]; + item.type = type; + } + case DESTROY(TANK(id, shot)): + if (items.exists(id)) { + var item = items[id]; + entryLayer.removeChild(item.view); + playAnimate(item.rect.center, AnimateBundle.tankBoom()); + showScore(item.rect.center, shot.score); + items.remove(id); + } + case DESTROY(BULLET(id)): + if (items.exists(id)) { + var item = items[id]; + entryLayer.removeChild(item.view); + var rect = item.rect; + // move boom + var point = rect.center.add(new Point(rect.width * rect.direction.x, rect.height * rect.direction.y)); + playAnimate(point, AnimateBundle.bulletBoom()); + items.remove(id); + } + case DESTROY(EAGLE(id, shot)): + if (items.exists(id)) { + var item = items[id]; + playAnimate(item.rect.center, AnimateBundle.tankBoom()); + showScore(item.rect.center, shot.score); + cast(item, EagleRenderItem).death = true; + } + case DESTROY(BONUS(id, shot)): + if (items.exists(id)) { + var item = items[id]; + upperLayer.removeChild(item.view); + showScore(item.rect.center, shot.score); + items.remove(id); + } + case DESTROY(CELL(id, x, y, shot)): + var item:BrickRenderItem = cast items.get(id); + item.destroyCell(x, y); + case DESTROY(BRICK(id, shot)): + var item:BrickRenderItem = cast items.get(id); + item.destroy(); + case _: } + #if cpp + flash.Lib.current.stage.invalidate(); + #end + } + + private function playAnimate(point:Point, animate:OnceAnimate):Promise { + animate.x = point.x - animate.width / 2; + animate.y = point.y - animate.height / 2; + upperLayer.addChild(animate); + return animate.play().then(function(animate:Animate):Void { + // ToDo: clean animates on reset + if (upperLayer.contains(animate)) { + upperLayer.removeChildSafety(animate); + } + animate.dispose(); + }); + } + + private function showScore(point:Point, score:Null):Void { + if (score != null && score != 0) { + var view:LabelView = new LabelView(); + view.style = "text"; + view.text = Std.string(score); + view.update(); + view.redraw(); + view.x = point.x - view.width / 2; + view.y = point.y - view.height / 2; + upperLayer.addChild(view.content); + Timer.delay(function() upperLayer.removeChildSafety(view.content), 1000); + } + } } diff --git a/src/client/haxe/ru/m/tankz/render/RenderUtil.hx b/src/client/haxe/ru/m/tankz/render/RenderUtil.hx index bf96c03..01c9141 100644 --- a/src/client/haxe/ru/m/tankz/render/RenderUtil.hx +++ b/src/client/haxe/ru/m/tankz/render/RenderUtil.hx @@ -5,25 +5,24 @@ import openfl.Assets; import ru.m.tankz.Type; class RenderUtil { + public static function eagleImage(death:Bool = false):BitmapData { + var suffix = death ? '-death' : ''; + return Assets.getBitmapData('resources/image/eagle/eagle${suffix}.png'); + } - public static function eagleImage(death:Bool = false):BitmapData { - var suffix = death ? '-death' : ''; - return Assets.getBitmapData('resources/image/eagle/eagle${suffix}.png'); - } + public static function tankImage(skin:String, frame:Int = 0):BitmapData { + return Assets.getBitmapData('resources/image/tank/${skin}-${frame}.png'); + } - public static function tankImage(skin:String, frame:Int = 0):BitmapData { - return Assets.getBitmapData('resources/image/tank/${skin}-${frame}.png'); - } + public static function bonusImage(type:BonusType):BitmapData { + return Assets.getBitmapData('resources/image/bonus/${type}.png'); + } - public static function bonusImage(type:BonusType):BitmapData { - return Assets.getBitmapData('resources/image/bonus/${type}.png'); - } + public static function bulletImage(skin:String):BitmapData { + return Assets.getBitmapData('resources/image/bullet/${skin}.png'); + } - public static function bulletImage(skin:String):BitmapData { - return Assets.getBitmapData('resources/image/bullet/${skin}.png'); - } - - public static function brickImage(type:BrickType, frame:Int = 0):BitmapData { - return Assets.getBitmapData('resources/image/map/${type}${frame > 0 ? ("-" + frame) : ""}.png'); - } + public static function brickImage(type:BrickType, frame:Int = 0):BitmapData { + return Assets.getBitmapData('resources/image/map/${type}${frame > 0 ? ("-" + frame) : ""}.png'); + } } diff --git a/src/client/haxe/ru/m/tankz/render/item/BitmapRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/BitmapRenderItem.hx index a7347f2..4e4f241 100644 --- a/src/client/haxe/ru/m/tankz/render/item/BitmapRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/BitmapRenderItem.hx @@ -7,26 +7,26 @@ import flash.display.PixelSnapping; import ru.m.geom.Rectangle; class BitmapRenderItem extends RenderItem { - public var image(default, set):BitmapData; + public var image(default, set):BitmapData; - private var bitmap:Bitmap; + private var bitmap:Bitmap; - public function new(rect:Rectangle) { - super(rect); - this.bitmap = new Bitmap(null, PixelSnapping.NEVER, false); - } - - override private function get_view():DisplayObject { - return bitmap; - } - - private function set_image(value:BitmapData):BitmapData { - if (image != value) { - image = value; - bitmap.bitmapData = image; - bitmap.width = rect.width; - bitmap.height = rect.height; - } - return image; + public function new(rect:Rectangle) { + super(rect); + this.bitmap = new Bitmap(null, PixelSnapping.NEVER, false); + } + + override private function get_view():DisplayObject { + return bitmap; + } + + private function set_image(value:BitmapData):BitmapData { + if (image != value) { + image = value; + bitmap.bitmapData = image; + bitmap.width = rect.width; + bitmap.height = rect.height; } + return image; + } } diff --git a/src/client/haxe/ru/m/tankz/render/item/BonusRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/BonusRenderItem.hx index 96581b4..80eed84 100644 --- a/src/client/haxe/ru/m/tankz/render/item/BonusRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/BonusRenderItem.hx @@ -4,31 +4,31 @@ import ru.m.geom.Rectangle; import ru.m.tankz.Type; class BonusRenderItem extends BitmapRenderItem { + public var type(default, set):BonusType; - public var type(default, set):BonusType; - private var d = -0.05; - private var alpha = 1.0; + private var d = -0.05; + private var alpha = 1.0; - public function new(rect:Rectangle, type:BonusType) { - super(rect); - this.type = type; - move(rect.position); + public function new(rect:Rectangle, type:BonusType) { + super(rect); + this.type = type; + move(rect.position); + } + + private function set_type(value:BonusType):BonusType { + if (type != value) { + type = value; + image = RenderUtil.bonusImage(type); } + return type; + } - private function set_type(value:BonusType):BonusType { - if (type != value) { - type = value; - image = RenderUtil.bonusImage(type); - } - return type; - } - - override public function update():Void { - super.update(); - alpha += d; - view.alpha = alpha; - if (alpha <= 0 || alpha >= 1.5) { - d = -d; - } + override public function update():Void { + super.update(); + alpha += d; + view.alpha = alpha; + if (alpha <= 0 || alpha >= 1.5) { + d = -d; } + } } diff --git a/src/client/haxe/ru/m/tankz/render/item/BrickRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/BrickRenderItem.hx index 46b064d..f1139a2 100644 --- a/src/client/haxe/ru/m/tankz/render/item/BrickRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/BrickRenderItem.hx @@ -7,112 +7,107 @@ import ru.m.geom.Rectangle; import ru.m.tankz.Type; class BrickBitmapBundle { + private var data:Map; - private var data:Map; + public function new() { + data = new Map(); + } - public function new() { - data = new Map(); - } - - private function resolve(type:BrickType, cells:Array, frame:Int):BitmapData { - return switch cells.length { - case 0: - null; - case 4: - type == "none" ? null : RenderUtil.brickImage(type, frame); - case _: - var image = RenderUtil.brickImage(type, frame); - var result = new BitmapData(image.width, image.height, true, 0x00000000); - for (point in cells) { - var rect = new flash.geom.Rectangle( - point.x * image.width / 2, - point.y * image.height / 2, - image.width / 2, - image.height / 2); - result.draw(image, null, null, null, rect); - } - return result; + private function resolve(type:BrickType, cells:Array, frame:Int):BitmapData { + return switch cells.length { + case 0: + null; + case 4: + type == "none" ? null : RenderUtil.brickImage(type, frame); + case _: + var image = RenderUtil.brickImage(type, frame); + var result = new BitmapData(image.width, image.height, true, 0x00000000); + for (point in cells) { + var rect = new flash.geom.Rectangle(point.x * image.width / 2, point.y * image.height / 2, image.width / 2, + image.height / 2); + result.draw(image, null, null, null, rect); } + return result; } + } - public function get(type:BrickType, cells:Array, frame:Int = 0):BitmapData { - var key:String = '${type}_${cells.map(function(point) return point.toString()).join(",")}_${frame}'; - if (!data.exists(key)) { - data.set(key, resolve(type, cells, frame)); - } - return data.get(key); + public function get(type:BrickType, cells:Array, frame:Int = 0):BitmapData { + var key:String = '${type}_${cells.map(function(point) return point.toString()).join(",")}_${frame}'; + if (!data.exists(key)) { + data.set(key, resolve(type, cells, frame)); } + return data.get(key); + } } class BrickRenderItem extends BitmapRenderItem { + private static var bundle:BrickBitmapBundle = new BrickBitmapBundle(); - private static var bundle:BrickBitmapBundle = new BrickBitmapBundle(); + public var type(default, set):BrickType; - public var type(default, set):BrickType; + private var cells:Array; - private var cells:Array; + private var frames:Int; + private var currentFrame:Int; + private var ticks:Int; - private var frames:Int; - private var currentFrame:Int; - private var ticks:Int; + private static function buildCells():Array { + return [ + new GridPoint(0, 0), + new GridPoint(0, 1), + new GridPoint(1, 0), + new GridPoint(1, 1), + ]; + } - private static function buildCells():Array { - return [ - new GridPoint(0, 0), - new GridPoint(0, 1), - new GridPoint(1, 0), - new GridPoint(1, 1), - ]; + public function new(rect:Rectangle, type:BrickType) { + super(rect); + cells = buildCells(); + this.frames = 1; + this.currentFrame = 0; + this.ticks = 0; + this.type = type; + move(rect.position); + } + + private function set_type(value:BrickType):BrickType { + if (type != value) { + type = value; + frames = switch type { + case "water": 2; + case _: 1; + } + cells = buildCells(); + redraw(); } + return type; + } - public function new(rect:Rectangle, type:BrickType) { - super(rect); - cells = buildCells(); - this.frames = 1; - this.currentFrame = 0; - this.ticks = 0; - this.type = type; - move(rect.position); - } + public function destroyCell(x:Int, y:Int):Void { + cells = cells.filter(function(point) return !(point.x == x && point.y == y)); + redraw(); + } - private function set_type(value:BrickType):BrickType { - if (type != value) { - type = value; - frames = switch type { - case "water": 2; - case _: 1; - } - cells = buildCells(); - redraw(); + public function destroy():Void { + cells = []; + redraw(); + } + + public function redraw():Void { + image = bundle.get(type, cells, currentFrame); + } + + override public function update():Void { + super.update(); + if (frames > 1) { + if (++ticks >= 30) { + ticks = 0; + currentFrame++; + if (currentFrame >= frames) { + currentFrame = 0; } - return type; - } - - public function destroyCell(x:Int, y:Int):Void { - cells = cells.filter(function(point) return !(point.x == x && point.y == y)); redraw(); + } } - - public function destroy():Void { - cells = []; - redraw(); - } - - public function redraw():Void { - image = bundle.get(type, cells, currentFrame); - } - - override public function update():Void { - super.update(); - if (frames > 1) { - if (++ticks >= 30) { - ticks = 0; - currentFrame++; - if (currentFrame >= frames) { - currentFrame = 0; - } - redraw(); - } - } - } + } } diff --git a/src/client/haxe/ru/m/tankz/render/item/BulletRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/BulletRenderItem.hx index 9d09fb9..98f7334 100644 --- a/src/client/haxe/ru/m/tankz/render/item/BulletRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/BulletRenderItem.hx @@ -5,23 +5,23 @@ import hw.view.utils.BitmapUtil; import ru.m.geom.Rectangle; class BulletRenderItem extends BitmapRenderItem { - public var color(default, default):Null; - public var skin(default, set):String; + public var color(default, default):Null; + public var skin(default, set):String; - public function new(rect:Rectangle) { - super(rect); - move(rect.position); - } + public function new(rect:Rectangle) { + super(rect); + move(rect.position); + } - private function set_skin(value:String):String { - if (skin != value) { - skin = value; - var image = RenderUtil.bulletImage(skin); - if (color != null) { - image = BitmapUtil.colorize(image, color); - } - this.image = image; - } - return skin; + private function set_skin(value:String):String { + if (skin != value) { + skin = value; + var image = RenderUtil.bulletImage(skin); + if (color != null) { + image = BitmapUtil.colorize(image, color); + } + this.image = image; } + return skin; + } } diff --git a/src/client/haxe/ru/m/tankz/render/item/EagleRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/EagleRenderItem.hx index 2062a23..1be0d62 100644 --- a/src/client/haxe/ru/m/tankz/render/item/EagleRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/EagleRenderItem.hx @@ -8,50 +8,50 @@ import ru.m.animate.Animate; import ru.m.geom.Rectangle; class EagleRenderItem extends BitmapRenderItem { - public var color(default, default):Color; - public var death(default, set):Bool = true; - public var protect(default, set):Bool; + public var color(default, default):Color; + public var death(default, set):Bool = true; + public var protect(default, set):Bool; - private var container:Sprite; - private var protectView:Animate; + private var container:Sprite; + private var protectView:Animate; - public function new(rect:Rectangle, color:Color) { - super(rect); - this.color = color; - container = new Sprite(); - container.addChild(bitmap); - protectView = AnimateBundle.tankProtect(); - protectView.visible = false; - container.addChild(protectView); - death = false; - move(rect.position); + public function new(rect:Rectangle, color:Color) { + super(rect); + this.color = color; + container = new Sprite(); + container.addChild(bitmap); + protectView = AnimateBundle.tankProtect(); + protectView.visible = false; + container.addChild(protectView); + death = false; + move(rect.position); + } + + override private function get_view():DisplayObject { + return container; + } + + private function set_protect(value:Bool):Bool { + if (protect != value) { + protect = value; + if (protect) { + protectView.x = (image.width - protectView.frames[0].image.width) / 2; + protectView.y = (image.height - protectView.frames[0].image.height) / 2; + } + protectView.visible = protect; + protectView.playing = protect; } + return protect; + } - override private function get_view():DisplayObject { - return container; - } - - private function set_protect(value:Bool):Bool { - if (protect != value) { - protect = value; - if (protect) { - protectView.x = (image.width - protectView.frames[0].image.width) / 2; - protectView.y = (image.height - protectView.frames[0].image.height) / 2; - } - protectView.visible = protect; - protectView.playing = protect; - } - return protect; - } - - private function set_death(value:Bool):Bool { - if (death != value) { - death = value; - image = RenderUtil.eagleImage(death); - if (!color.zero) { - bitmap.bitmapData = image = BitmapUtil.colorize(image, color); - } - } - return death; + private function set_death(value:Bool):Bool { + if (death != value) { + death = value; + image = RenderUtil.eagleImage(death); + if (!color.zero) { + bitmap.bitmapData = image = BitmapUtil.colorize(image, color); + } } + return death; + } } diff --git a/src/client/haxe/ru/m/tankz/render/item/IRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/IRenderItem.hx index 9f1d304..61f8585 100644 --- a/src/client/haxe/ru/m/tankz/render/item/IRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/IRenderItem.hx @@ -5,9 +5,9 @@ import ru.m.geom.Position; import ru.m.geom.Rectangle; interface IRenderItem { - public var view(get, null):DisplayObject; - public var rect(default, null):Rectangle; - public function move(position:Position):Void; - public function update():Void; - public function dispose():Void; + public var view(get, null):DisplayObject; + public var rect(default, null):Rectangle; + public function move(position:Position):Void; + public function update():Void; + public function dispose():Void; } diff --git a/src/client/haxe/ru/m/tankz/render/item/RenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/RenderItem.hx index 61c0994..d71c790 100644 --- a/src/client/haxe/ru/m/tankz/render/item/RenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/RenderItem.hx @@ -5,42 +5,51 @@ import ru.m.geom.Position; import ru.m.geom.Rectangle; class RenderItem implements IRenderItem { + public var view(get, null):DisplayObject; + public var content(get, null):DisplayObject; - public var view(get, null):DisplayObject; - public var content(get, null):DisplayObject; + public var rect(default, null):Rectangle; - public var rect(default, null):Rectangle; + public function new(rect:Rectangle) { + this.rect = rect.clone(); + } - public function new(rect:Rectangle) { - this.rect = rect.clone(); + private function get_view():DisplayObject { + throw "Not Implemented"; + } + + private function get_content():DisplayObject { + return null; + } + + public function move(position:Position):Void { + view.x = rect.x = position.x; + view.y = rect.y = position.y; + if (position.direction != null) { + rect.direction = position.direction; + if (content != null) { + content.rotation = rect.direction.angle; + content.x = -rect.width * (rect.direction.x + 1) / 2 + + rect.width * (rect.direction.y + 1) / 2 + + 0.5 * rect.width; + content.y = -rect.height * (rect.direction.x + 1) / 2 + - rect.height * (rect.direction.y + 1) / 2 + + 1.5 * rect.height; + } else { + view.rotation = rect.direction.angle; + view.x = rect.x + - rect.width * (rect.direction.x + 1) / 2 + + rect.width * (rect.direction.y + 1) / 2 + + 0.5 * rect.width; + view.y = rect.y + - rect.height * (rect.direction.x + 1) / 2 + - rect.height * (rect.direction.y + 1) / 2 + + 1.5 * rect.height; + } } + } - private function get_view():DisplayObject { - throw "Not Implemented"; - } + public function update():Void {} - private function get_content():DisplayObject { - return null; - } - - public function move(position:Position):Void { - view.x = rect.x = position.x; - view.y = rect.y = position.y; - if (position.direction != null) { - rect.direction = position.direction; - if (content != null) { - content.rotation = rect.direction.angle; - content.x = - rect.width * (rect.direction.x + 1) / 2 + rect.width * (rect.direction.y + 1) / 2 + 0.5 * rect.width; - content.y = - rect.height * (rect.direction.x + 1) / 2 - rect.height * (rect.direction.y + 1) / 2 + 1.5 * rect.height; - } else { - view.rotation = rect.direction.angle; - view.x = rect.x - rect.width * (rect.direction.x + 1) / 2 + rect.width * (rect.direction.y + 1) / 2 + 0.5 * rect.width; - view.y = rect.y - rect.height * (rect.direction.x + 1) / 2 - rect.height * (rect.direction.y + 1) / 2 + 1.5 * rect.height; - } - } - } - - public function update():Void {} - - public function dispose():Void {} + public function dispose():Void {} } diff --git a/src/client/haxe/ru/m/tankz/render/item/TankRenderItem.hx b/src/client/haxe/ru/m/tankz/render/item/TankRenderItem.hx index 5f0b439..fb1210e 100644 --- a/src/client/haxe/ru/m/tankz/render/item/TankRenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/item/TankRenderItem.hx @@ -15,159 +15,159 @@ import ru.m.animate.Animate; import ru.m.geom.Rectangle; class TankRenderItem extends BitmapRenderItem { - public var color(default, default):Color; - public var skin(default, set):String; - public var hits(default, set):Int; - public var bonus(default, set):Bool; - public var boat(default, set):Bool; - public var moves(default, set):Bool; - public var protect(default, set):Bool; - public var name(default, set):String; + public var color(default, default):Color; + public var skin(default, set):String; + public var hits(default, set):Int; + public var bonus(default, set):Bool; + public var boat(default, set):Bool; + public var moves(default, set):Bool; + public var protect(default, set):Bool; + public var name(default, set):String; - private var container:Sprite; - private var images:Array; - private var frame:Int; - private var protectView:Animate; - private var boatView:Shape; - private var nameView:TextField; + private var container:Sprite; + private var images:Array; + private var frame:Int; + private var protectView:Animate; + private var boatView:Shape; + private var nameView:TextField; - @:provide static var theme:ITheme; + @:provide static var theme:ITheme; - public function new(rect:Rectangle) { - super(rect); - container = new Sprite(); - container.addChild(bitmap); - protectView = AnimateBundle.tankProtect(); - protectView.visible = false; - container.addChild(protectView); - boatView = buildBoatView(); - boatView.visible = false; - container.addChild(boatView); - nameView = buildNameView(); - container.addChild(nameView); - move(rect.position); + public function new(rect:Rectangle) { + super(rect); + container = new Sprite(); + container.addChild(bitmap); + protectView = AnimateBundle.tankProtect(); + protectView.visible = false; + container.addChild(protectView); + boatView = buildBoatView(); + boatView.visible = false; + container.addChild(boatView); + nameView = buildNameView(); + container.addChild(nameView); + move(rect.position); + } + + private function buildNameView():TextField { + var result = new BitmapTextField(); + result.defaultTextFormat = new TextFormat(theme.font.name, 10, 0xffffff); + result.embedFonts = theme.font.embed; + result.autoSize = TextFieldAutoSize.LEFT; + result.shadowColor = 0x000000; + result.stroke = true; + return result; + } + + private function buildBoatView():Shape { + var result = new Shape(); + result.graphics.lineStyle(4, Color.fromString("green"), 0.8); + result.graphics.drawRoundRect(-1, -1, rect.width + 2, rect.height + 2, 10, 10); + return result; + } + + override private function get_view():DisplayObject { + return container; + } + + override private function get_content():DisplayObject { + return bitmap; + } + + private function redraw():Void { + var image1 = RenderUtil.tankImage(skin, 0); + var image2 = RenderUtil.tankImage(skin, 1); + var color1:Color = switch hits { + case 1: 0x869C43; + case 2: 0xDEAF80; + case 3: 0x5EA67A; + case _: color; } - - private function buildNameView():TextField { - var result = new BitmapTextField(); - result.defaultTextFormat = new TextFormat(theme.font.name, 10, 0xffffff); - result.embedFonts = theme.font.embed; - result.autoSize = TextFieldAutoSize.LEFT; - result.shadowColor = 0x000000; - result.stroke = true; - return result; + var color2:Color = color1; + if (bonus) { + color1 = 0xff00aa; } - - private function buildBoatView():Shape { - var result = new Shape(); - result.graphics.lineStyle(4, Color.fromString("green"), 0.8); - result.graphics.drawRoundRect(-1, -1, rect.width + 2, rect.height + 2, 10, 10); - return result; + if (!color1.zero) { + image1 = BitmapUtil.colorize(image1, color1); } - - override private function get_view():DisplayObject { - return container; + if (!color1.zero) { + image2 = BitmapUtil.colorize(image2, color2); } + images = [for (i in 0...6) image1].concat([for (i in 0...6) image2]); + frame = 0; + bitmap.bitmapData = images[frame]; + } - override private function get_content():DisplayObject { - return bitmap; + private function set_skin(value:String):String { + if (skin != value) { + skin = value; + redraw(); } + return skin; + } - private function redraw():Void { - var image1 = RenderUtil.tankImage(skin, 0); - var image2 = RenderUtil.tankImage(skin, 1); - var color1:Color = switch hits { - case 1: 0x869C43; - case 2: 0xDEAF80; - case 3: 0x5EA67A; - case _: color; - } - var color2:Color = color1; - if (bonus) { - color1 = 0xff00aa; - } - if (!color1.zero) { - image1 = BitmapUtil.colorize(image1, color1); - } - if (!color1.zero) { - image2 = BitmapUtil.colorize(image2, color2); - } - images = [for (i in 0...6) image1].concat([for (i in 0...6) image2]); + private function set_hits(value:Int):Int { + if (hits != value) { + hits = value; + redraw(); + } + return hits; + } + + private function set_bonus(value:Bool):Bool { + if (bonus != value) { + bonus = value; + redraw(); + } + return bonus; + } + + private function set_boat(value:Bool):Bool { + if (boat != value) { + boat = value; + boatView.visible = boat; + } + return boat; + } + + private function set_protect(value:Bool):Bool { + if (protect != value) { + protect = value; + if (protect) { + protectView.x = (images[0].width - protectView.frames[0].image.width) / 2; + protectView.y = (images[0].height - protectView.frames[0].image.height) / 2; + } + protectView.visible = protect; + protectView.playing = protect; + } + return protect; + } + + private function set_moves(value:Bool):Bool { + if (moves != value) { + moves = value; + bitmap.bitmapData = images[0]; + } + return moves; + } + + private function set_name(value:String):String { + if (name != value) { + name = value; + nameView.text = name; + nameView.x = (rect.width - nameView.width) / 2; + nameView.y = -nameView.height / 2; // (rect.height - nameView.height) / 2; + } + return name; + } + + override public function update():Void { + super.update(); + if (moves) { + frame++; + if (frame >= images.length) { frame = 0; - bitmap.bitmapData = images[frame]; - } - - private function set_skin(value:String):String { - if (skin != value) { - skin = value; - redraw(); - } - return skin; - } - - private function set_hits(value:Int):Int { - if (hits != value) { - hits = value; - redraw(); - } - return hits; - } - - private function set_bonus(value:Bool):Bool { - if (bonus != value) { - bonus = value; - redraw(); - } - return bonus; - } - - private function set_boat(value:Bool):Bool { - if (boat != value) { - boat = value; - boatView.visible = boat; - } - return boat; - } - - private function set_protect(value:Bool):Bool { - if (protect != value) { - protect = value; - if (protect) { - protectView.x = (images[0].width - protectView.frames[0].image.width) / 2; - protectView.y = (images[0].height - protectView.frames[0].image.height) / 2; - } - protectView.visible = protect; - protectView.playing = protect; - } - return protect; - } - - private function set_moves(value:Bool):Bool { - if (moves != value) { - moves = value; - bitmap.bitmapData = images[0]; - } - return moves; - } - - private function set_name(value:String):String { - if (name != value) { - name = value; - nameView.text = name; - nameView.x = (rect.width - nameView.width) / 2; - nameView.y = -nameView.height / 2; //(rect.height - nameView.height) / 2; - } - return name; - } - - override public function update():Void { - super.update(); - if (moves) { - frame++; - if (frame >= images.length) { - frame = 0; - } - bitmap.bitmapData = images[frame]; - } + } + bitmap.bitmapData = images[frame]; } + } } diff --git a/src/client/haxe/ru/m/tankz/sound/SoundManager.hx b/src/client/haxe/ru/m/tankz/sound/SoundManager.hx index 9137dc5..23ead19 100644 --- a/src/client/haxe/ru/m/tankz/sound/SoundManager.hx +++ b/src/client/haxe/ru/m/tankz/sound/SoundManager.hx @@ -10,119 +10,119 @@ import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.IGame; @:provide class SoundManager implements GameListener { - private static var TAG(default, never):String = "SoundManager"; + private static var TAG(default, never):String = "SoundManager"; - #if flash - private static var type:String = "mp3"; - #else - private static var type:String = "ogg"; - #end + #if flash + private static var type:String = "mp3"; + #else + private static var type:String = "ogg"; + #end - public var config(default, default):Config; - public var volume(default, set):Float = 1; - public var mute(default, set):Bool = false; + public var config(default, default):Config; + public var volume(default, set):Float = 1; + public var mute(default, set):Bool = false; - private var channels:Array; - private var transform:SoundTransform; + private var channels:Array; + private var transform:SoundTransform; - private var humanTanks:Array; - private var humanBullets:Array; - private var liveBonuses:Array; + private var humanTanks:Array; + private var humanBullets:Array; + private var liveBonuses:Array; - public function new() { - channels = []; - updateSoundTransform(); + public function new() { + channels = []; + updateSoundTransform(); + } + + private function updateSoundTransform():Void { + transform = new SoundTransform(mute ? 0 : volume); + for (channel in channels) { + channel.soundTransform = transform; } + } - private function updateSoundTransform():Void { - transform = new SoundTransform(mute ? 0 : volume); - for (channel in channels) { - channel.soundTransform = transform; + private function set_volume(value:Float):Float { + if (volume != value) { + volume = value; + updateSoundTransform(); + } + return volume; + } + + private function set_mute(value:Bool):Bool { + if (mute != value) { + mute = value; + updateSoundTransform(); + } + return mute; + } + + public function play(id:String):Void { + // L.d(TAG, 'play: ${id}'); + var sound:Sound = Assets.getSound('resources/sounds/${id}.${type}'); + if (sound != null) { + var channel = sound.play(0, 0, transform); + channel.addEventListener(Event.SOUND_COMPLETE, onSoundComplete); + channels.push(channel); + } else { + L.w(TAG, 'Sound "${id}" not found'); + } + } + + public function stopAll():Void { + for (channel in channels) { + channel.stop(); + } + channels = []; + } + + private function onSoundComplete(event:Event):Void { + channels.remove(event.currentTarget); + } + + public function onGameEvent(event:GameEvent):Void { + switch event { + case START(_): + play("start"); + humanTanks = []; + liveBonuses = []; + humanBullets = []; + case SPAWN(BULLET(id, _, playerId, _)): + if (config.isHuman(playerId)) { + play("shot"); + humanBullets.push(id); } - } - - private function set_volume(value:Float):Float { - if (volume != value) { - volume = value; - updateSoundTransform(); + case SPAWN(TANK(id, _, playerId, _)): + if (config.isHuman(playerId)) { + humanTanks.push(id); } - return volume; - } - - private function set_mute(value:Bool):Bool { - if (mute != value) { - mute = value; - updateSoundTransform(); + case SPAWN(BONUS(id, _, type)): + play("bonus_add"); + if (type == "live") { + liveBonuses.push(id); } - return mute; - } - - public function play(id:String):Void { - //L.d(TAG, 'play: ${id}'); - var sound:Sound = Assets.getSound('resources/sounds/${id}.${type}'); - if (sound != null) { - var channel = sound.play(0, 0, transform); - channel.addEventListener(Event.SOUND_COMPLETE, onSoundComplete); - channels.push(channel); + case HIT(TANK(_, _)): + play("bullet_hit"); + case HIT(CELL(_, _, shot)): + if (humanBullets.indexOf(shot.bulletId) > -1) { + // play("bullet_block"); + } + case DESTROY(TANK(id, _)): + if (humanTanks.indexOf(id) > -1) { + play("boom_player"); } else { - L.w(TAG, 'Sound "${id}" not found'); + play("boom_bot"); } - } - - public function stopAll():Void { - for (channel in channels) { - channel.stop(); - } - channels = []; - } - - private function onSoundComplete(event:Event):Void { - channels.remove(event.currentTarget); - } - - public function onGameEvent(event:GameEvent):Void { - switch event { - case START(_): - play("start"); - humanTanks = []; - liveBonuses = []; - humanBullets = []; - case SPAWN(BULLET(id, _, playerId, _)): - if (config.isHuman(playerId)) { - play("shot"); - humanBullets.push(id); - } - case SPAWN(TANK(id, _, playerId, _)): - if (config.isHuman(playerId)) { - humanTanks.push(id); - } - case SPAWN(BONUS(id, _, type)): - play("bonus_add"); - if (type == "live") { - liveBonuses.push(id); - } - case HIT(TANK(_, _)): - play("bullet_hit"); - case HIT(CELL(_, _, shot)): - if (humanBullets.indexOf(shot.bulletId) > -1) { - //play("bullet_block"); - } - case DESTROY(TANK(id, _)): - if (humanTanks.indexOf(id) > -1) { - play("boom_player"); - } else { - play("boom_bot"); - } - case DESTROY(EAGLE(_, _)): - play("boom_player"); - case DESTROY(BONUS(id, _)): - play("bonus_get"); - if (liveBonuses.indexOf(id) > -1) { - play("live"); - } else { - play("bonus_get"); - } - case _: + case DESTROY(EAGLE(_, _)): + play("boom_player"); + case DESTROY(BONUS(id, _)): + // play("bonus_get"); + if (liveBonuses.indexOf(id) > -1) { + play("live"); + } else { + play("bonus_get"); } + case _: } + } } diff --git a/src/client/haxe/ru/m/tankz/storage/GameStorage.hx b/src/client/haxe/ru/m/tankz/storage/GameStorage.hx index 08992d8..711bf56 100644 --- a/src/client/haxe/ru/m/tankz/storage/GameStorage.hx +++ b/src/client/haxe/ru/m/tankz/storage/GameStorage.hx @@ -4,19 +4,18 @@ import hw.storage.SharedObjectStorage; import ru.m.tankz.game.PackProgress; import ru.m.tankz.Type; -@:provide class GameStorage extends SharedObjectStorage { +@:provide class GameStorage extends SharedObjectStorage { + private static inline var VERSION = 1; - private static inline var VERSION = 1; + public function new() { + super('game_${VERSION}'); + } - public function new() { - super('game_${VERSION}'); - } + public function get(id:PackId):PackProgress { + return exists(id) ? read(id) : new PackProgress(id); + } - public function get(id:PackId):PackProgress { - return exists(id) ? read(id) : new PackProgress(id); - } - - public function set(progress:PackProgress):Void { - write(progress.id, progress); - } + public function set(progress:PackProgress):Void { + write(progress.id, progress); + } } diff --git a/src/client/haxe/ru/m/tankz/storage/NetworkStorage.hx b/src/client/haxe/ru/m/tankz/storage/NetworkStorage.hx index 9edd8ba..bf59c5b 100644 --- a/src/client/haxe/ru/m/tankz/storage/NetworkStorage.hx +++ b/src/client/haxe/ru/m/tankz/storage/NetworkStorage.hx @@ -3,19 +3,18 @@ package ru.m.tankz.storage; import hw.storage.SharedObjectStorage; @:provide class NetworkStorage extends SharedObjectStorage { + public var user(get, set):User; - public var user(get, set):User; + public function new() { + super("network"); + } - public function new() { - super("network"); - } + private inline function get_user():User { + return read("user"); + } - private inline function get_user():User { - return read("user"); - } - - private inline function set_user(value:User):User { - write("user", value); - return value; - } + private inline function set_user(value:User):User { + write("user", value); + return value; + } } diff --git a/src/client/haxe/ru/m/tankz/storage/RecordStorage.hx b/src/client/haxe/ru/m/tankz/storage/RecordStorage.hx index 3517a4a..44f0931 100644 --- a/src/client/haxe/ru/m/tankz/storage/RecordStorage.hx +++ b/src/client/haxe/ru/m/tankz/storage/RecordStorage.hx @@ -4,38 +4,37 @@ import haxe.DynamicAccess; import hw.storage.SharedObjectStorage; import ru.m.tankz.game.record.GameRecord; -@:provide class RecordStorage extends SharedObjectStorage { +@:provide class RecordStorage extends SharedObjectStorage { + private static inline var VERSION = 1; - private static inline var VERSION = 1; + public function new() { + super('record_${VERSION}'); + } - public function new() { - super('record_${VERSION}'); - } + public function save(record:GameRecord):Void { + L.d("RecordStorage", 'save $record'); + write('${record.info.id}.info', record.info); + write(record.info.id, record); + } - public function save(record:GameRecord):Void { - L.d("RecordStorage", 'save $record'); - write('${record.info.id}.info', record.info); - write(record.info.id, record); - } + override public function delete(id:String):Void { + super.delete(id); + super.delete('${id}.info'); + } - override public function delete(id:String):Void { - super.delete(id); - super.delete('${id}.info'); - } - - public function list():Array { - var result = []; - var data:DynamicAccess = so.data; - for (id in data.keys()) { - try { - if (StringTools.endsWith(id, '.info')) { - result.push(read(id)); - } - } catch (error:Dynamic) { - L.w("RecordStorage", 'read ', error); - delete(id); - } + public function list():Array { + var result = []; + var data:DynamicAccess = so.data; + for (id in data.keys()) { + try { + if (StringTools.endsWith(id, '.info')) { + result.push(read(id)); } - return result; + } catch (error:Dynamic) { + L.w("RecordStorage", 'read ', error); + delete(id); + } } + return result; + } } diff --git a/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx b/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx index d484492..850d3e5 100644 --- a/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx +++ b/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx @@ -11,105 +11,102 @@ import ru.m.tankz.control.Binding; import ru.m.tankz.control.Control; enum Setting { - CONTROL(index:Int, value:Binding); - DISPLAY_FPS(value:Bool); - ENABLE_NETWORK(value:Bool); + CONTROL(index:Int, value:Binding); + DISPLAY_FPS(value:Bool); + ENABLE_NETWORK(value:Bool); } @:provide class SettingsStorage extends SharedObjectStorage { + private static inline var VERSION = 4.1; - private static inline var VERSION = 4.1; + public var signal(default, null):Signal = new Signal(); - public var signal(default, null):Signal = new Signal(); + public var displayFPS(get, set):Bool; - public var displayFPS(get, set):Bool; + private function get_displayFPS():Bool { + return read("setting:display_fps"); + } - private function get_displayFPS():Bool { - return read("setting:display_fps"); - } + private function set_displayFPS(value:Bool):Bool { + write("setting:display_fps", value); + signal.emit(DISPLAY_FPS(value)); + return get_displayFPS(); + } - private function set_displayFPS(value:Bool):Bool { - write("setting:display_fps", value); - signal.emit(DISPLAY_FPS(value)); - return get_displayFPS(); - } + public var enableNetwork(get, set):Bool; - public var enableNetwork(get, set):Bool; + private function get_enableNetwork():Bool { + return read("setting:enable_network"); + } - private function get_enableNetwork():Bool { - return read("setting:enable_network"); - } + private function set_enableNetwork(value:Bool):Bool { + write("setting:enable_network", value); + signal.emit(ENABLE_NETWORK(value)); + return get_enableNetwork(); + } - private function set_enableNetwork(value:Bool):Bool { - write("setting:enable_network", value); - signal.emit(ENABLE_NETWORK(value)); - return get_enableNetwork(); - } + public function new() { + super('settings_${VERSION}'); + } - public function new() { - super('settings_${VERSION}'); - } + public function getBinding(index:Int):Binding { + return exists('action:$index') ? read('action:$index') : getDefaultBinding(index); + } - public function getBinding(index:Int):Binding { - return exists('action:$index') ? read('action:$index') : getDefaultBinding(index); - } + public function saveBinding(index:Int, value:Binding) { + write('action:$index', value); + signal.emit(CONTROL(index, value)); + } - public function saveBinding(index:Int, value:Binding) { - write('action:$index', value); - signal.emit(CONTROL(index, value)); - } + public static function getDefaultBinding(index:Int):Binding { + var binding = (Device.isMobile() ? mobileDefaults : defaults).get(index); + return binding != null ? ObjectUtil.clone(binding) : buildEmpty(); + } - public static function getDefaultBinding(index:Int):Binding { - var binding = (Device.isMobile() ? mobileDefaults : defaults).get(index); - return binding != null ? ObjectUtil.clone(binding) : buildEmpty(); - } - - public static function buildDeviceBinding(device:DeviceType):Binding { - return [ - MOVE(Direction.TOP) => {device: device, action: DIRECTION(Direction.TOP)}, - MOVE(Direction.LEFT) => {device: device, action: DIRECTION(Direction.LEFT)}, - MOVE(Direction.BOTTOM) => {device: device, action: DIRECTION(Direction.BOTTOM)}, - MOVE(Direction.RIGHT) => {device: device, action: DIRECTION(Direction.RIGHT)}, - SHOT(0) => {device: device, action: KEY(0)}, - SHOT(1) => {device: device, action: KEY(1)}, - SHOT(2) => {device: device, action: KEY(2)}, - ]; - } - - public static function buildEmpty():Binding { - return [ - MOVE(Direction.TOP) => null, - MOVE(Direction.LEFT) => null, - MOVE(Direction.BOTTOM) => null, - MOVE(Direction.RIGHT) => null, - SHOT(0) => null, - SHOT(1) => null, - SHOT(2) => null, - ]; - } - - private static var mobileDefaults:Map = [ - 0 => buildDeviceBinding(SCREEN), + public static function buildDeviceBinding(device:DeviceType):Binding { + return [ + MOVE(Direction.TOP) => {device: device, action: DIRECTION(Direction.TOP)}, + MOVE(Direction.LEFT) => {device: device, action: DIRECTION(Direction.LEFT)}, + MOVE(Direction.BOTTOM) => {device: device, action: DIRECTION(Direction.BOTTOM)}, + MOVE(Direction.RIGHT) => {device: device, action: DIRECTION(Direction.RIGHT)}, + SHOT(0) => {device: device, action: KEY(0)}, + SHOT(1) => {device: device, action: KEY(1)}, + SHOT(2) => {device: device, action: KEY(2)}, ]; + } - private static var defaults:Map = [ - 0 => [ - MOVE(Direction.TOP) => {device: KEYBOARD, action: KEY(Keyboard.W)}, - MOVE(Direction.LEFT) => {device: KEYBOARD, action: KEY(Keyboard.A)}, - MOVE(Direction.BOTTOM) => {device: KEYBOARD, action: KEY(Keyboard.S)}, - MOVE(Direction.RIGHT) => {device: KEYBOARD, action: KEY(Keyboard.D)}, - SHOT(0) => {device: KEYBOARD, action: KEY(Keyboard.SPACE)}, - SHOT(1) => {device: KEYBOARD, action: KEY(Keyboard.Q)}, - SHOT(2) => {device: KEYBOARD, action: KEY(Keyboard.E)}, - ], - 1 => [ - MOVE(Direction.TOP) => {device: KEYBOARD, action: KEY(Keyboard.UP)}, - MOVE(Direction.LEFT) => {device: KEYBOARD, action: KEY(Keyboard.LEFT)}, - MOVE(Direction.BOTTOM) => {device: KEYBOARD, action: KEY(Keyboard.DOWN)}, - MOVE(Direction.RIGHT) => {device: KEYBOARD, action: KEY(Keyboard.RIGHT)}, - SHOT(0) => {device: KEYBOARD, action: KEY(Keyboard.NUMPAD_0)}, - SHOT(1) => {device: KEYBOARD, action: KEY(Keyboard.NUMPAD_1)}, - SHOT(2) => {device: KEYBOARD, action: KEY(Keyboard.NUMPAD_2)}, - ], + public static function buildEmpty():Binding { + return [ + MOVE(Direction.TOP) => null, + MOVE(Direction.LEFT) => null, + MOVE(Direction.BOTTOM) => null, + MOVE(Direction.RIGHT) => null, + SHOT(0) => null, + SHOT(1) => null, + SHOT(2) => null, ]; + } + + private static var mobileDefaults:Map = [0 => buildDeviceBinding(SCREEN),]; + + private static var defaults:Map = [ + 0 => [ + MOVE(Direction.TOP) => {device: KEYBOARD, action: KEY(Keyboard.W)}, + MOVE(Direction.LEFT) => {device: KEYBOARD, action: KEY(Keyboard.A)}, + MOVE(Direction.BOTTOM) => {device: KEYBOARD, action: KEY(Keyboard.S)}, + MOVE(Direction.RIGHT) => {device: KEYBOARD, action: KEY(Keyboard.D)}, + SHOT(0) => {device: KEYBOARD, action: KEY(Keyboard.SPACE)}, + SHOT(1) => {device: KEYBOARD, action: KEY(Keyboard.Q)}, + SHOT(2) => {device: KEYBOARD, action: KEY(Keyboard.E)}, + ], + 1 => [ + MOVE(Direction.TOP) => {device: KEYBOARD, action: KEY(Keyboard.UP)}, + MOVE(Direction.LEFT) => {device: KEYBOARD, action: KEY(Keyboard.LEFT)}, + MOVE(Direction.BOTTOM) => {device: KEYBOARD, action: KEY(Keyboard.DOWN)}, + MOVE(Direction.RIGHT) => {device: KEYBOARD, action: KEY(Keyboard.RIGHT)}, + SHOT(0) => {device: KEYBOARD, action: KEY(Keyboard.NUMPAD_0)}, + SHOT(1) => {device: KEYBOARD, action: KEY(Keyboard.NUMPAD_1)}, + SHOT(2) => {device: KEYBOARD, action: KEY(Keyboard.NUMPAD_2)}, + ], + ]; } diff --git a/src/client/haxe/ru/m/tankz/view/ClientView.hx b/src/client/haxe/ru/m/tankz/view/ClientView.hx index 971f13b..4f2fe56 100644 --- a/src/client/haxe/ru/m/tankz/view/ClientView.hx +++ b/src/client/haxe/ru/m/tankz/view/ClientView.hx @@ -11,34 +11,35 @@ import ru.m.tankz.network.NetworkManager; import ru.m.tankz.sound.SoundManager; @:template class ClientView extends VGroupView { - @:view("switcher") var switcherView:FrameSwitcher; + @:view("switcher") var switcherView:FrameSwitcher; - @:provide var network:NetworkManager; - @:provide var resources:IResources; - @:provide var switcher:FrameSwitcher; - @:provide var soundManager:SoundManager; - @:provide static var bus:IControlBus; + @:provide var network:NetworkManager; + @:provide var resources:IResources; + @:provide var switcher:FrameSwitcher; + @:provide var soundManager:SoundManager; - public function new():Void { - super(); - resources.text.put('version', '${Const.VERSION}'); - resources.text.put('name', '${Const.NAME}'); - switcher = switcherView; - } + @:provide static var bus:IControlBus; - public function launch():Void { - content.stage.stageFocusRect = false; - bus.signal.connect(onDeviceAction); + public function new():Void { + super(); + resources.text.put('version', '${Const.VERSION}'); + resources.text.put('name', '${Const.NAME}'); + switcher = switcherView; + } + + public function launch():Void { + content.stage.stageFocusRect = false; + bus.signal.connect(onDeviceAction); + switcher.change(MenuFrame.ID); + } + + private function onDeviceAction(type:DeviceType, action:DeviceAction, state:Bool):Void { + switch [type, action, state] { + case [KEYBOARD, KEY(Keyboard.ESCAPE), true]: switcher.change(MenuFrame.ID); + case [KEYBOARD, KEY(Keyboard.M), true]: + soundManager.mute = !soundManager.mute; + case _: } - - private function onDeviceAction(type:DeviceType, action:DeviceAction, state:Bool):Void { - switch [type, action, state] { - case [KEYBOARD, KEY(Keyboard.ESCAPE), true]: - switcher.change(MenuFrame.ID); - case [KEYBOARD, KEY(Keyboard.M), true]: - soundManager.mute = !soundManager.mute; - case _: - } - } + } } diff --git a/src/client/haxe/ru/m/tankz/view/GameFrame.hx b/src/client/haxe/ru/m/tankz/view/GameFrame.hx index 548034f..b1adf9a 100644 --- a/src/client/haxe/ru/m/tankz/view/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/GameFrame.hx @@ -33,161 +33,161 @@ import ru.m.tankz.render.IRender; using ru.m.tankz.view.ViewUtil; @:template class GameFrame extends FrameView implements GameListener { - public static inline var ID = "game"; + public static inline var ID = "game"; - private static inline var TAG = "GameFrame"; + private static inline var TAG = "GameFrame"; - @:provide static var soundManager:SoundManager; - @:provide static var switcher:FrameSwitcher; - @:provide static var gameStorage:GameStorage; - @:provide static var settings:SettingsStorage; - @:provide static var bus:IControlBus; + @:provide static var soundManager:SoundManager; + @:provide static var switcher:FrameSwitcher; + @:provide static var gameStorage:GameStorage; + @:provide static var settings:SettingsStorage; + @:provide static var bus:IControlBus; - @:view private var render:IRender; - @:view private var teams:DataView; - @:view private var level:TextView; - @:view private var gamepad(default, null):GamepadView; + @:view private var render:IRender; + @:view private var teams:DataView; + @:view private var level:TextView; + @:view private var gamepad(default, null):GamepadView; - private var gamepadPlayerId:PlayerId; + private var gamepadPlayerId:PlayerId; - private var game:IGame; - private var recorder:GameRecord; + private var game:IGame; + private var recorder:GameRecord; - public function new() { - super(id, new DefaultLayout()); - bus.connect(gamepad); + public function new() { + super(id, new DefaultLayout()); + bus.connect(gamepad); + } + + override public function onShow(data:GameInit):Void { + gamepad.visible = false; + game = switch data { + case LOCAL(start): new LocalGame(start); + case NETWORK(network): new NetworkGame(network); + case RECORD(record): new GamePlayer(record); } - - override public function onShow(data:GameInit):Void { - gamepad.visible = false; - game = switch data { - case LOCAL(start): new LocalGame(start); - case NETWORK(network): new NetworkGame(network); - case RECORD(record): new GamePlayer(record); + soundManager.config = game.config; + render.config = game.config; + game.connect(render); + game.connect(soundManager); + game.connect(this); + game.start(); + // TODO: + for (control in game.controls) { + if (Std.is(control, HumanControl)) { + if (cast(control, HumanControl).hasDevice(SCREEN)) { + gamepadPlayerId = control.playerId; + gamepad.visible = true; + break; } - soundManager.config = game.config; - render.config = game.config; - game.connect(render); - game.connect(soundManager); - game.connect(this); - game.start(); - // TODO: - for (control in game.controls) { - if (Std.is(control, HumanControl)) { - if (cast(control, HumanControl).hasDevice(SCREEN)) { - gamepadPlayerId = control.playerId; - gamepad.visible = true; - break; - } + } + } + bus.signal.connect(onDeviceAction); + } + + private function onDeviceAction(type:DeviceType, action:DeviceAction, state:Bool):Void { + switch [type, action, state] { + case [KEYBOARD, KEY(Keyboard.P), true]: + game.pause = !game.pause; + case _: + } + } + + private function stop():Void { + bus.signal.disconnect(onDeviceAction); + if (game != null) { + game.dispose(); + game = null; + } + render.reset(); + } + + private function findTeamView(id:TeamId):Null { + for (view in teams.dataViews) { + if (view.teamId == id) { + return view; + } + } + return null; + } + + private function findPlayerView(id:PlayerId):Null { + var teamView = findTeamView(id.team); + if (teamView != null) { + for (view in teamView.dataViews) { + if (view.playerId == id) { + return view; + } + } + } + return null; + } + + public function onGameEvent(event:GameEvent):Void { + switch event { + case START(start): + level.text = start.level.toLevelLabel(); + teams.data = [for (team in start.state.teams) team]; + // TODO: PlayerState default tank? + for (teamView in teams.dataViews) { + for (playerView in teamView.dataViews) { + var tank = game.config.getPlayerTank(playerView.playerId); + playerView.tank = { + type: tank.type, + skin: tank.skin, + hits: 0, + bonus: false, + boat: false, + color: game.config.getColor(playerView.playerId), + }; + } + } + case CHANGE(TEAM_LIFE(teamId, life)): + var view = findPlayerView([teamId, -1]); + if (view != null) { + view.life = life; + } + case CHANGE(TEAM_SCORE(teamId, score)): + var view = findPlayerView([teamId, -1]); + if (view != null) { + view.score = score; + } + case CHANGE(PLAYER_LIFE(playerId, life)): + var view = findPlayerView(playerId); + if (view != null) { + view.life = life; + } + case CHANGE(PLAYER_SCORE(playerId, score)): + var view = findPlayerView(playerId); + if (view != null) { + view.score = score; + } + case SPAWN(TANK(id, rect, playerId, info)): + if (gamepadPlayerId != null && playerId == gamepadPlayerId) { + var tankConfig = game.config.getTank(info.type); + gamepad.weapons = tankConfig.weapons; + } + case PAUSE(paused): + if (paused) { + PausePopup.instance.show().then(function(action) { + switch action { + case EXIT: + switcher.change(LevelFrame.ID, game.level.packId); + case RESUME | null: + game.pause = false; } + }); + } else { + PausePopup.instance.close(null); } - bus.signal.connect(onDeviceAction); - } - - private function onDeviceAction(type:DeviceType, action:DeviceAction, state:Bool):Void { - switch [type, action, state] { - case [KEYBOARD, KEY(Keyboard.P), true]: - game.pause = !game.pause; - case _: - } - } - - private function stop():Void { - bus.signal.disconnect(onDeviceAction); - if (game != null) { - game.dispose(); - game = null; - } - render.reset(); - } - - private function findTeamView(id:TeamId):Null { - for (view in teams.dataViews) { - if (view.teamId == id) { - return view; - } - } - return null; - } - - private function findPlayerView(id:PlayerId):Null { - var teamView = findTeamView(id.team); - if (teamView != null) { - for (view in teamView.dataViews) { - if (view.playerId == id) { - return view; - } - } - } - return null; - } - - public function onGameEvent(event:GameEvent):Void { - switch event { - case START(start): - level.text = start.level.toLevelLabel(); - teams.data = [for (team in start.state.teams) team]; - // TODO: PlayerState default tank? - for (teamView in teams.dataViews) { - for (playerView in teamView.dataViews) { - var tank = game.config.getPlayerTank(playerView.playerId); - playerView.tank = { - type: tank.type, - skin: tank.skin, - hits: 0, - bonus: false, - boat: false, - color: game.config.getColor(playerView.playerId), - }; - } - } - case CHANGE(TEAM_LIFE(teamId, life)): - var view = findPlayerView([teamId, -1]); - if (view != null) { - view.life = life; - } - case CHANGE(TEAM_SCORE(teamId, score)): - var view = findPlayerView([teamId, -1]); - if (view != null) { - view.score = score; - } - case CHANGE(PLAYER_LIFE(playerId, life)): - var view = findPlayerView(playerId); - if (view != null) { - view.life = life; - } - case CHANGE(PLAYER_SCORE(playerId, score)): - var view = findPlayerView(playerId); - if (view != null) { - view.score = score; - } - case SPAWN(TANK(id, rect, playerId, info)): - if (gamepadPlayerId != null && playerId == gamepadPlayerId) { - var tankConfig = game.config.getTank(info.type); - gamepad.weapons = tankConfig.weapons; - } - case PAUSE(paused): - if (paused) { - PausePopup.instance.show().then(function(action) { - switch action { - case EXIT: - switcher.change(LevelFrame.ID, game.level.packId); - case RESUME | null: - game.pause = false; - } - }); - } else { - PausePopup.instance.close(null); - } - case COMPLETE(result): - stop(); - switcher.change(ResultFrame.ID, result); - case _: - } - } - - override public function onHide():Void { + case COMPLETE(result): stop(); - soundManager.stopAll(); + switcher.change(ResultFrame.ID, result); + case _: } + } + + override public function onHide():Void { + stop(); + soundManager.stopAll(); + } } diff --git a/src/client/haxe/ru/m/tankz/view/LevelFrame.hx b/src/client/haxe/ru/m/tankz/view/LevelFrame.hx index 25f564d..826829d 100644 --- a/src/client/haxe/ru/m/tankz/view/LevelFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/LevelFrame.hx @@ -15,49 +15,49 @@ import ru.m.tankz.Type.PackId; using ru.m.tankz.view.ViewUtil; @:template class LevelFrame extends FrameView { - public static inline var ID = "level"; + public static inline var ID = "level"; - @:provide static var switcher:FrameSwitcher; - @:provide static var storage:GameStorage; - @:provide static var configBundle:IConfigBundle; - @:provide static var levelBundle:ILevelBundle; + @:provide static var switcher:FrameSwitcher; + @:provide static var storage:GameStorage; + @:provide static var configBundle:IConfigBundle; + @:provide static var levelBundle:ILevelBundle; - @:view var header:LabelView; - @:view var levels:DataView; + @:view var header:LabelView; + @:view var levels:DataView; - private var pack:LevelPack; - private var config(get, never):Config; + private var pack:LevelPack; + private var config(get, never):Config; - public function new() { - super(ID); - } - - private function get_config():Config { - return configBundle.get(pack.id.type); - } - - override public function onShow(data:PackId):Void { - header.text = data.toPackLabel(); - pack = levelBundle.get(data); - levels.data = pack.data; - } - - private function levelViewFactory(index:Int, level:LevelConfig):ButtonView { - var progress = storage.get(pack.id); - var result = new ButtonView(); - result.style = "button.level"; - var presetsLine = [for (p in config.presets) progress.isPresetCompleted(level.id, p.id) ? '*' : '_'].join(''); - result.text = '${level.id}\n${presetsLine}'; - result.disabled = !progress.isLevelAvailable(level.id); - return result; - } - - private function onLevelSelect(index:Int, level:LevelConfig, view:ButtonView):Void { - if (storage.get(pack.id).isLevelAvailable(level.id)) { - switcher.change(StartFrame.ID, { - state: new GameState(pack.id.type), - level: level, - }); - } + public function new() { + super(ID); + } + + private function get_config():Config { + return configBundle.get(pack.id.type); + } + + override public function onShow(data:PackId):Void { + header.text = data.toPackLabel(); + pack = levelBundle.get(data); + levels.data = pack.data; + } + + private function levelViewFactory(index:Int, level:LevelConfig):ButtonView { + var progress = storage.get(pack.id); + var result = new ButtonView(); + result.style = "button.level"; + var presetsLine = [for (p in config.presets) progress.isPresetCompleted(level.id, p.id) ? '*' : '_'].join(''); + result.text = '${level.id}\n${presetsLine}'; + result.disabled = !progress.isLevelAvailable(level.id); + return result; + } + + private function onLevelSelect(index:Int, level:LevelConfig, view:ButtonView):Void { + if (storage.get(pack.id).isLevelAvailable(level.id)) { + switcher.change(StartFrame.ID, { + state: new GameState(pack.id.type), + level: level, + }); } + } } diff --git a/src/client/haxe/ru/m/tankz/view/MenuFrame.hx b/src/client/haxe/ru/m/tankz/view/MenuFrame.hx index 1a065a8..3cce130 100644 --- a/src/client/haxe/ru/m/tankz/view/MenuFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/MenuFrame.hx @@ -19,76 +19,76 @@ import ru.m.update.Updater; using ru.m.tankz.view.ViewUtil; @:template class MenuFrame extends FrameView { + public static var ID(default, never):String = "menu"; - public static var ID(default, never):String = "menu"; + @:provide static var gameInit:GameInit; + @:provide static var switcher:FrameSwitcher; + @:provide static var network:NetworkManager; + @:provide static var appUpdater:Updater; + @:provide static var levelBundle:ILevelBundle; + @:provide static var settings:SettingsStorage; - @:provide static var gameInit:GameInit; - @:provide static var switcher:FrameSwitcher; - @:provide static var network:NetworkManager; - @:provide static var appUpdater:Updater; - @:provide static var levelBundle:ILevelBundle; - @:provide static var settings:SettingsStorage; + @:view var packs:DataView; + @:view("update") var updateButton:ButtonView; + @:view("network") var networkButton:ButtonView; - @:view var packs:DataView; - @:view("update") var updateButton:ButtonView; - @:view("network") var networkButton:ButtonView; + public function new() { + super(ID); + } - public function new() { - super(ID); + override public function onShow(data:Dynamic):Void { + super.onShow(data); + appUpdater.check().then(function(update:Bool) { + updateButton.visible = update; + if (update) { + updateButton.text = 'Update ${appUpdater.bundle.version}'; + } + }).catchError(function(error) {}); + var list = levelBundle.list(); + list.sort(function(a:PackId, b:PackId) return a.toPackLabel() > b.toPackLabel() ? 1 : -1); + packs.data = list; + networkButton.visible = settings.enableNetwork; + settings.signal.connect(onSettingChange); + } + + override public function onHide():Void { + super.onHide(); + settings.signal.disconnect(onSettingChange); + } + + private function onSettingChange(setting:Setting):Void { + switch setting { + case ENABLE_NETWORK(value): + networkButton.visible = value; + case _: } + } - override public function onShow(data:Dynamic):Void { - super.onShow(data); - appUpdater.check().then(function(update:Bool) { - updateButton.visible = update; - if (update) { - updateButton.text = 'Update ${appUpdater.bundle.version}'; - } - }).catchError(function(error) {}); - var list = levelBundle.list(); - list.sort(function(a:PackId, b:PackId) return a.toPackLabel() > b.toPackLabel() ? 1 : -1); - packs.data = list; - networkButton.visible = settings.enableNetwork; - settings.signal.connect(onSettingChange); - } + private function startGame(packId:PackId):Void { + gameInit = LOCAL({state: new GameState(packId.type), level: null}); + switcher.change(LevelFrame.ID, packId); + } - override public function onHide():Void { - super.onHide(); - settings.signal.disconnect(onSettingChange); - } - - private function onSettingChange(setting:Setting):Void { - switch setting { - case ENABLE_NETWORK(value): networkButton.visible = value; - case _: + private function startNetwork():Void { + switch network.state { + case ONLINE(user): + if (network.room != null) { + switcher.change(RoomFrame.ID, network.room); + network.joinGame(network.room.game.id, true); + } else { + switcher.change(RoomListFrame.ID); } + case CONNECTED: + LoginPopup.instance.show().then(function(user):Void { + if (user != null) { + switcher.change(RoomListFrame.ID); + } + }); + case _: } + } - private function startGame(packId:PackId):Void { - gameInit = LOCAL({state: new GameState(packId.type), level: null}); - switcher.change(LevelFrame.ID, packId); - } - - private function startNetwork():Void { - switch network.state { - case ONLINE(user): - if (network.room != null) { - switcher.change(RoomFrame.ID, network.room); - network.joinGame(network.room.game.id, true); - } else { - switcher.change(RoomListFrame.ID); - } - case CONNECTED: - LoginPopup.instance.show().then(function(user):Void { - if (user != null) { - switcher.change(RoomListFrame.ID); - } - }); - case _: - } - } - - private function appUpdate():Void { - appUpdater.download(); - } + private function appUpdate():Void { + appUpdater.download(); + } } diff --git a/src/client/haxe/ru/m/tankz/view/RecordFrame.hx b/src/client/haxe/ru/m/tankz/view/RecordFrame.hx index b319314..f022826 100644 --- a/src/client/haxe/ru/m/tankz/view/RecordFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/RecordFrame.hx @@ -7,21 +7,20 @@ import ru.m.tankz.game.record.GameRecord; import ru.m.tankz.storage.RecordStorage; @:template class RecordFrame extends FrameView { + public static var ID(default, never):String = "record"; - public static var ID(default, never):String = "record"; + @:provide static var switcher:FrameSwitcher; + @:provide static var recordStorage:RecordStorage; - @:provide static var switcher:FrameSwitcher; - @:provide static var recordStorage:RecordStorage; + @:view var data:VListView; - @:view var data:VListView; + public function new() { + super(ID); + } - public function new() { - super(ID); - } - - override public function onShow(_:Dynamic):Void { - var data = recordStorage.list(); - data.sort(function(a:GameRecordInfo, b:GameRecordInfo) return Std.int(b.date.getTime() - a.date.getTime())); - this.data.data = data; - } + override public function onShow(_:Dynamic):Void { + var data = recordStorage.list(); + data.sort(function(a:GameRecordInfo, b:GameRecordInfo) return Std.int(b.date.getTime() - a.date.getTime())); + this.data.data = data; + } } diff --git a/src/client/haxe/ru/m/tankz/view/ResultFrame.hx b/src/client/haxe/ru/m/tankz/view/ResultFrame.hx index d885b73..83ddacb 100644 --- a/src/client/haxe/ru/m/tankz/view/ResultFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/ResultFrame.hx @@ -15,51 +15,53 @@ import ru.m.tankz.view.result.ResultPlayerView; using ru.m.tankz.view.ViewUtil; @:template class ResultFrame extends FrameView { - public static var ID(default, never):String = "result"; + public static var ID(default, never):String = "result"; - @:view("result") var resultView:DataView; - @:view("level") var levelLabel:LabelView; - @:view("next") var nextButton:ButtonView; + @:view("result") var resultView:DataView; + @:view("level") var levelLabel:LabelView; + @:view("next") var nextButton:ButtonView; - @:provide var frames:FrameSwitcher; - @:provide static var levelBundle:ILevelBundle; - @:provide static var gameStorage:GameStorage; + @:provide var frames:FrameSwitcher; - private var result:Result; + @:provide static var levelBundle:ILevelBundle; + @:provide static var gameStorage:GameStorage; - public function new() { - super(ID); + private var result:Result; + + public function new() { + super(ID); + } + + override public function onShow(data:Result):Void { + result = data; + resultView.data = result.state.humans; + for (view in resultView.dataViews) { + view.winner = view.data.id.team == data.winner; } + levelLabel.text = data.level.toLevelLabel(); + nextButton.disabled = !gameStorage.get(result.level.packId) + .isPresetAvailable(result.level.id + 1, result.state.presetId); + nextButton.text = 'Next #${result.level.id + 1}'; + } - override public function onShow(data:Result):Void { - result = data; - resultView.data = result.state.humans; - for (view in resultView.dataViews) { - view.winner = view.data.id.team == data.winner; - } - levelLabel.text = data.level.toLevelLabel(); - nextButton.disabled = !gameStorage.get(result.level.packId).isPresetAvailable(result.level.id + 1, result.state.presetId); - nextButton.text = 'Next #${result.level.id + 1}'; - } + private function levels():Void { + frames.change(LevelFrame.ID, result.level.packId); + } - private function levels():Void { - frames.change(LevelFrame.ID, result.level.packId); - } + private function restart():Void { + result.state.clean(); + frames.change(GameFrame.ID, LOCAL({state: result.state, level: result.level})); + } - private function restart():Void { + private function next():Void { + var pack = levelBundle.get(result.level.packId); + if (pack.data.length > result.level.id + 1) { + var level = pack.data[result.level.id + 1]; + var progress = gameStorage.get(pack.id); + if (progress.isPresetAvailable(level.id, result.state.presetId)) { result.state.clean(); - frames.change(GameFrame.ID, LOCAL({state: result.state, level: result.level})); - } - - private function next():Void { - var pack = levelBundle.get(result.level.packId); - if (pack.data.length > result.level.id + 1) { - var level = pack.data[result.level.id + 1]; - var progress = gameStorage.get(pack.id); - if (progress.isPresetAvailable(level.id, result.state.presetId)) { - result.state.clean(); - frames.change(GameFrame.ID, LOCAL({state: result.state, level: level})); - } - } + frames.change(GameFrame.ID, LOCAL({state: result.state, level: level})); + } } + } } diff --git a/src/client/haxe/ru/m/tankz/view/SettingsFrame.hx b/src/client/haxe/ru/m/tankz/view/SettingsFrame.hx index 7b57b07..0a8357c 100644 --- a/src/client/haxe/ru/m/tankz/view/SettingsFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/SettingsFrame.hx @@ -6,34 +6,36 @@ import hw.view.frame.FrameView; import ru.m.tankz.storage.SettingsStorage; @:template class SettingsFrame extends FrameView { - public static var ID(default, never):String = "settings"; + public static var ID(default, never):String = "settings"; - @:view("fps") var fpsButton:ToggleButtonView; - @:view("network") var networkButton:ToggleButtonView; + @:view("fps") var fpsButton:ToggleButtonView; + @:view("network") var networkButton:ToggleButtonView; - @:provide static var switcher:FrameSwitcher; - @:provide static var settings:SettingsStorage; + @:provide static var switcher:FrameSwitcher; + @:provide static var settings:SettingsStorage; - public function new() { - super(ID); - } - - override public function onShow(data:Dynamic):Void { - super.onShow(data); - fpsButton.on = settings.displayFPS; - networkButton.on = settings.enableNetwork; - settings.signal.connect(onSettingChange); - } - - override public function onHide():Void { - settings.signal.disconnect(onSettingChange); - } - - private function onSettingChange(setting:Setting):Void { - switch setting { - case DISPLAY_FPS(value): fpsButton.on = value; - case ENABLE_NETWORK(value): networkButton.on = value; - case _: - } + public function new() { + super(ID); + } + + override public function onShow(data:Dynamic):Void { + super.onShow(data); + fpsButton.on = settings.displayFPS; + networkButton.on = settings.enableNetwork; + settings.signal.connect(onSettingChange); + } + + override public function onHide():Void { + settings.signal.disconnect(onSettingChange); + } + + private function onSettingChange(setting:Setting):Void { + switch setting { + case DISPLAY_FPS(value): + fpsButton.on = value; + case ENABLE_NETWORK(value): + networkButton.on = value; + case _: } + } } diff --git a/src/client/haxe/ru/m/tankz/view/StartFrame.hx b/src/client/haxe/ru/m/tankz/view/StartFrame.hx index 473c8bc..e29d08b 100644 --- a/src/client/haxe/ru/m/tankz/view/StartFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/StartFrame.hx @@ -19,116 +19,115 @@ using haxe.EnumTools.EnumValueTools; using ru.m.tankz.view.ViewUtil; @:template class StartFrame extends FrameView { + public static var ID(default, never):String = "start"; - public static var ID(default, never):String = "start"; + @:provide static var switcher:FrameSwitcher; + @:provide static var storage:GameStorage; - @:provide static var switcher:FrameSwitcher; - @:provide static var storage:GameStorage; + private var progress:PackProgress; - private var progress:PackProgress; + @:view var header:LabelView; + @:view("presets") var presetsView:DataView; + @:view("teams") var teamsView:DataView, DataView>; - @:view var header:LabelView; - @:view("presets") var presetsView:DataView; - @:view("teams") var teamsView:DataView, DataView>; + private var humanIndex:Int = 0; + private var humanTotal:Int = 2; - private var humanIndex:Int = 0; - private var humanTotal:Int = 2; + private var start:Start; - private var start:Start; + public function new() { + super(ID); + } - public function new() { - super(ID); + override public function onShow(data:Start):Void { + super.onShow(data); + start = data; + this.progress = storage.get(start.level.packId); + header.text = start.level.toLevelLabel(); + presetsView.data = start.state.config.presets; + teamsView.data = defaultControls(start.state.config); + } + + private static function defaultControls(config:Config):Array> { + var result:Array> = []; + var preset = config.getPreset(0); + var human = false; + for (team in preset.teams) { + if (team.id != "bot") { // ToDo: + var controls:Array = []; + for (player in team.players) { + var playerId = new PlayerId(team.id, player.index); + var control:PlayerControl = { + playerId: playerId, + color: config.getColor(playerId), + controller: NONE, + } + if (!human) { + control.controller = HUMAN(0); + control.name = ControllerParser.defaultName(control.controller); + human = true; + } + controls.push(control); + } + result.push(controls); + } } + return result; + } - override public function onShow(data:Start):Void { - super.onShow(data); - start = data; - this.progress = storage.get(start.level.packId); - header.text = start.level.toLevelLabel(); - presetsView.data = start.state.config.presets; - teamsView.data = defaultControls(start.state.config); - } + private function teamViewFactory(index:Int, value:Array):DataView { + var result = new DataView(); + result.style = "light"; + result.geometry.padding = 5; + result.factory = slotViewFactory; + result.data = value; + return result; + } - private static function defaultControls(config:Config):Array> { - var result:Array> = []; - var preset = config.getPreset(0); - var human = false; - for (team in preset.teams) { - if (team.id != "bot") { // ToDo: - var controls:Array = []; - for (player in team.players) { - var playerId = new PlayerId(team.id, player.index); - var control:PlayerControl = { - playerId: playerId, - color: config.getColor(playerId), - controller: NONE, - } - if (!human) { - control.controller = HUMAN(0); - control.name = ControllerParser.defaultName(control.controller); - human = true; - } - controls.push(control); - } - result.push(controls); + private function slotViewFactory(index:Int, value:PlayerControl):SlotView { + var result = new SlotView(); + result.select.onSelect.connect(function(controller:Controller) setController(value, controller)); + result.control = value; + result.tank = start.state.config.getPlayerTank(value.playerId).skin; + return result; + } + + private function setController(value:PlayerControl, controller:Controller):Void { + switch controller { + case NONE: + case _: + for (teamView in teamsView.dataViews) { + for (view in teamView.dataViews) { + if (view.control.controller.equals(controller)) { + view.control.controller = NONE; + view.select.selected = NONE; + view.control.name = null; } - } - return result; - } - - private function teamViewFactory(index:Int, value:Array):DataView { - var result = new DataView(); - result.style = "light"; - result.geometry.padding = 5; - result.factory = slotViewFactory; - result.data = value; - return result; - } - - private function slotViewFactory(index:Int, value:PlayerControl):SlotView { - var result = new SlotView(); - result.select.onSelect.connect(function(controller:Controller) setController(value, controller)); - result.control = value; - result.tank = start.state.config.getPlayerTank(value.playerId).skin; - return result; - } - - private function setController(value:PlayerControl, controller:Controller):Void { - switch controller { - case NONE: - case _: - for (teamView in teamsView.dataViews) { - for (view in teamView.dataViews) { - if (view.control.controller.equals(controller)) { - view.control.controller = NONE; - view.select.selected = NONE; - view.control.name = null; - } - } - } - } - value.controller = controller; - value.name = ControllerParser.defaultName(controller); - } - - private function presetViewFactory(index:Int, value:GamePreset):ButtonView { - var result = new ButtonView(); - result.style = 'button${!progress.isPresetCompleted(start.level.id, value.id) ? ".active" : ""}'; - result.geometry.height = "100%"; - result.text = value.name == "default" ? "start" : value.name; - result.disabled = !progress.isPresetAvailable(start.level.id, value.id); - return result; - } - - private function onPresetSelect(value:GamePreset):Void { - if (progress.isPresetAvailable(start.level.id, value.id)) { - start.state.presetId = value.id; - var controls = []; - for (item in teamsView.data) { - controls = controls.concat(item); - } - start.state.controls = controls; - switcher.change(GameFrame.ID, LOCAL(start)); + } } } + value.controller = controller; + value.name = ControllerParser.defaultName(controller); + } + + private function presetViewFactory(index:Int, value:GamePreset):ButtonView { + var result = new ButtonView(); + result.style = 'button${!progress.isPresetCompleted(start.level.id, value.id) ? ".active" : ""}'; + result.geometry.height = "100%"; + result.text = value.name == "default" ? "start" : value.name; + result.disabled = !progress.isPresetAvailable(start.level.id, value.id); + return result; + } + + private function onPresetSelect(value:GamePreset):Void { + if (progress.isPresetAvailable(start.level.id, value.id)) { + start.state.presetId = value.id; + var controls = []; + for (item in teamsView.data) { + controls = controls.concat(item); + } + start.state.controls = controls; + switcher.change(GameFrame.ID, LOCAL(start)); + } + } } diff --git a/src/client/haxe/ru/m/tankz/view/ViewUtil.hx b/src/client/haxe/ru/m/tankz/view/ViewUtil.hx index cae7b56..77f5a45 100644 --- a/src/client/haxe/ru/m/tankz/view/ViewUtil.hx +++ b/src/client/haxe/ru/m/tankz/view/ViewUtil.hx @@ -8,55 +8,53 @@ import ru.m.tankz.control.Binding; import ru.m.tankz.control.Control; class KeyboardMap { + private var data:Map; - private var data:Map; - - public function new() { - this.data = new Map(); - var data = Assets.getText("resources/keyboard.txt"); - for (line in data.split("\n")) { - var arr = line.split("\t"); - if (arr.length == 2) { - this.data.set(Std.parseInt(arr[1]), arr[0]); - } - } - + public function new() { + this.data = new Map(); + var data = Assets.getText("resources/keyboard.txt"); + for (line in data.split("\n")) { + var arr = line.split("\t"); + if (arr.length == 2) { + this.data.set(Std.parseInt(arr[1]), arr[0]); + } } + } - private static var instance:KeyboardMap; + private static var instance:KeyboardMap; - public static function getName(key:Int):String { - if (instance == null) instance = new KeyboardMap(); - return key == -1 ? "(NONE)" : instance.data.exists(key) ? instance.data.get(key) : Std.string(key); - } + public static function getName(key:Int):String { + if (instance == null) + instance = new KeyboardMap(); + return key == -1 ? "(NONE)" : instance.data.exists(key) ? instance.data.get(key) : Std.string(key); + } } class ViewUtil { - - public static function toLevelLabel(level:LevelConfig, oneline:Bool = false):String { - var result:Array = ['${level.packId.type} #${level.id}']; - if (level.name != null) { - result.push(level.name); - } - return result.join(oneline ? " " : "\n"); + public static function toLevelLabel(level:LevelConfig, oneline:Bool = false):String { + var result:Array = ['${level.packId.type} #${level.id}']; + if (level.name != null) { + result.push(level.name); } + return result.join(oneline ? " " : "\n"); + } - public static function toPackLabel(packId:PackId, separator=" #"):String { - return packId.name != PackId.DEFAULT ? '${packId.type}${separator}${packId.name}' : packId.type; - } + public static function toPackLabel(packId:PackId, separator = " #"):String { + return packId.name != PackId.DEFAULT ? '${packId.type}${separator}${packId.name}' : packId.type; + } - public static function toActionLabel(action:TankAction):String { - return switch (action) { - case MOVE(d): 'MOVE_$d'; - case SHOT(w): 'SHOT_$w'; - case x: '$x'; - } + public static function toActionLabel(action:TankAction):String { + return switch (action) { + case MOVE(d): 'MOVE_$d'; + case SHOT(w): 'SHOT_$w'; + case x: '$x'; } + } - public static function toBindLabel(bind:BindAction):String { - return bind == null ? "(NONE)" : Std.string(bind.device) + " " + switch bind.action { - case KEY(code): KeyboardMap.getName(code); - case DIRECTION(direction): Std.string(direction); - }; - } + public static function toBindLabel(bind:BindAction):String { + return bind == null ? "(NONE)" : Std.string(bind.device) + " " + switch bind.action { + case KEY(code): KeyboardMap.getName(code); + case DIRECTION(direction): Std.string(direction); + }; + } } diff --git a/src/client/haxe/ru/m/tankz/view/common/NetworkStateView.hx b/src/client/haxe/ru/m/tankz/view/common/NetworkStateView.hx index a0c720f..b0a3967 100644 --- a/src/client/haxe/ru/m/tankz/view/common/NetworkStateView.hx +++ b/src/client/haxe/ru/m/tankz/view/common/NetworkStateView.hx @@ -9,56 +9,55 @@ import ru.m.tankz.network.NetworkManager; import ru.m.tankz.view.popup.LoginPopup; @:template class NetworkStateView extends HGroupView { + @:view("state") var stateView:SpriteView; + @:view("user") var userLabel:LabelView; + @:view("login") var loginButton:ButtonView; + @:view("logout") var logoutButton:ButtonView; - @:view("state") var stateView:SpriteView; - @:view("user") var userLabel:LabelView; - @:view("login") var loginButton:ButtonView; - @:view("logout") var logoutButton:ButtonView; + @:provide static var network:NetworkManager; - @:provide static var network:NetworkManager; + public function new():Void { + super(); + network.stateSignal.connect(onConnectionChange); + } - public function new():Void { - super(); - network.stateSignal.connect(onConnectionChange); + private function onConnectionChange(state:ConnectionState):Void { + visible = true; + stateView.visible = true; + userLabel.text = ""; + loginButton.visible = false; + logoutButton.visible = false; + var skin:SpriteSkin = cast stateView.skin; + switch state { + case OFFLINE: + skin.background.color = "black"; + stateView.visible = false; + visible = false; + case CONNECT: + skin.background.color = "yellow"; + case CONNECTED: + skin.background.color = "gray"; + loginButton.visible = true; + case LOGIN: + skin.background.color = "yellow"; + case ONLINE(user): + skin.background.color = "green"; + userLabel.text = user.name; + logoutButton.visible = true; + case ERROR(error): + skin.background.color = "red"; + userLabel.text = Std.string(error).substr(0, 10); } + stateView.toRedraw(); + } - private function onConnectionChange(state:ConnectionState):Void { - visible = true; - stateView.visible = true; - userLabel.text = ""; - loginButton.visible = false; - logoutButton.visible = false; - var skin:SpriteSkin = cast stateView.skin; - switch state { - case OFFLINE: - skin.background.color = "black"; - stateView.visible = false; - visible = false; - case CONNECT: - skin.background.color = "yellow"; - case CONNECTED: - skin.background.color = "gray"; - loginButton.visible = true; - case LOGIN: - skin.background.color = "yellow"; - case ONLINE(user): - skin.background.color = "green"; - userLabel.text = user.name; - logoutButton.visible = true; - case ERROR(error): - skin.background.color = "red"; - userLabel.text = Std.string(error).substr(0, 10); - } - stateView.toRedraw(); - } + private function login():Void { + LoginPopup.instance.show().then(function(user:User):Void { + L.d("Login", 'user: $user'); + }); + } - private function login():Void { - LoginPopup.instance.show().then(function(user:User):Void { - L.d("Login", 'user: $user'); - }); - } - - private function logout():Void { - network.logout(); - } + private function logout():Void { + network.logout(); + } } diff --git a/src/client/haxe/ru/m/tankz/view/common/PackView.hx b/src/client/haxe/ru/m/tankz/view/common/PackView.hx index c3897ce..72b08e1 100644 --- a/src/client/haxe/ru/m/tankz/view/common/PackView.hx +++ b/src/client/haxe/ru/m/tankz/view/common/PackView.hx @@ -9,29 +9,28 @@ import ru.m.tankz.Type; using ru.m.tankz.view.ViewUtil; @:template class PackView extends VGroupView { + public var data(default, set):PackId; - public var data(default, set):PackId; + @:view var label:LabelView; + @:view var state:LabelView; - @:view var label:LabelView; - @:view var state:LabelView; + @:provide static var gameStorage:GameStorage; + @:provide static var levelBundle:ILevelBundle; - @:provide static var gameStorage:GameStorage; - @:provide static var levelBundle:ILevelBundle; - - private function set_data(value:PackId):PackId { - if (data != value) { - data = value; - label.text = data.toPackLabel("\n"); - var progress = gameStorage.get(data).progress; - var total = levelBundle.get(data).data.length; - state.text = '${progress}/${total}'; - } - return data; + private function set_data(value:PackId):PackId { + if (data != value) { + data = value; + label.text = data.toPackLabel("\n"); + var progress = gameStorage.get(data).progress; + var total = levelBundle.get(data).data.length; + state.text = '${progress}/${total}'; } + return data; + } - public static function factory(index:Int, value:PackId):PackView { - var result = new PackView(); - result.data = value; - return result; - } + public static function factory(index:Int, value:PackId):PackView { + var result = new PackView(); + result.data = value; + return result; + } } diff --git a/src/client/haxe/ru/m/tankz/view/common/RecordView.hx b/src/client/haxe/ru/m/tankz/view/common/RecordView.hx index 3c2441a..74dc906 100644 --- a/src/client/haxe/ru/m/tankz/view/common/RecordView.hx +++ b/src/client/haxe/ru/m/tankz/view/common/RecordView.hx @@ -9,38 +9,38 @@ import ru.m.tankz.game.record.GameRecord; import ru.m.tankz.storage.RecordStorage; @:template class RecordView extends HGroupView implements IListItemView { - @:view var date:LabelView; - @:view var type:LabelView; - @:view var level:LabelView; - @:view var preset:LabelView; + @:view var date:LabelView; + @:view var type:LabelView; + @:view var level:LabelView; + @:view var preset:LabelView; - public var item_index(default, default):Int; - public var data(default, set):GameRecordInfo; + public var item_index(default, default):Int; + public var data(default, set):GameRecordInfo; - @:provide var recordStorage:RecordStorage; - @:provide var switcher:FrameSwitcher; + @:provide var recordStorage:RecordStorage; + @:provide var switcher:FrameSwitcher; - private function set_data(value:GameRecordInfo):GameRecordInfo { - if (data != value) { - data = value; - date.text = data.date.toString(); - type.text = data.type; - level.text = Std.string(data.levelId); - preset.text = Std.string(data.presetId); - } - return data; + private function set_data(value:GameRecordInfo):GameRecordInfo { + if (data != value) { + data = value; + date.text = data.date.toString(); + type.text = data.type; + level.text = Std.string(data.levelId); + preset.text = Std.string(data.presetId); } + return data; + } - private function play():Void { - var record = recordStorage.read(data.id); - switcher.change(GameFrame.ID, RECORD(record)); - } + private function play():Void { + var record = recordStorage.read(data.id); + switcher.change(GameFrame.ID, RECORD(record)); + } - private function delete():Void { - recordStorage.delete(data.id); - // ToDo: - var list = cast(parent.parent.parent, ListView); - list.data.splice(item_index, 1); - list.toUpdate(); - } + private function delete():Void { + recordStorage.delete(data.id); + // ToDo: + var list = cast(parent.parent.parent, ListView); + list.data.splice(item_index, 1); + list.toUpdate(); + } } diff --git a/src/client/haxe/ru/m/tankz/view/common/SlotView.hx b/src/client/haxe/ru/m/tankz/view/common/SlotView.hx index 52c992e..4d019bf 100644 --- a/src/client/haxe/ru/m/tankz/view/common/SlotView.hx +++ b/src/client/haxe/ru/m/tankz/view/common/SlotView.hx @@ -10,39 +10,38 @@ import ru.m.tankz.control.Controller; import ru.m.tankz.control.PlayerControl; @:template class SlotView extends HGroupView { + @:view("tank") public var tankView:ImageView; + @:view("slot") public var slotLabel:LabelView; + @:view("select") public var select:SelectView; - @:view("tank") public var tankView:ImageView; - @:view("slot") public var slotLabel:LabelView; - @:view("select") public var select:SelectView; + public var control(default, set):PlayerControl; + public var tank(default, set):String; - public var control(default, set):PlayerControl; - public var tank(default, set):String; + private function set_control(value:PlayerControl):PlayerControl { + control = value; + slotLabel.text = '${control.playerId.team} #${control.playerId.index}'; + var skin:SpriteSkin = cast slotLabel.skin; + skin.border.color = value.color; + skin.border.alpha = 0.8; + skin.background.color = value.color; + skin.background.alpha = 0.2; + select.selected = control.controller; + tankView.color = value.color; + return control; + } - private function set_control(value:PlayerControl):PlayerControl { - control = value; - slotLabel.text = '${control.playerId.team} #${control.playerId.index}'; - var skin:SpriteSkin = cast slotLabel.skin; - skin.border.color = value.color; - skin.border.alpha = 0.8; - skin.background.color = value.color; - skin.background.alpha = 0.2; - select.selected = control.controller; - tankView.color = value.color; - return control; + private function set_tank(value:String):String { + if (tank != value) { + tank = value; + tankView.image = Assets.getBitmapData('resources/image/tank/${tank}-0.png'); } + return tank; + } - private function set_tank(value:String):String { - if (tank != value) { - tank = value; - tankView.image = Assets.getBitmapData('resources/image/tank/${tank}-0.png'); - } - return tank; - } - - private function onControllerSelect(value:Controller):Void { - select.currentView.style = switch value { - case HUMAN(_): "button.active"; - case _: "button"; - } + private function onControllerSelect(value:Controller):Void { + select.currentView.style = switch value { + case HUMAN(_): "button.active"; + case _: "button"; } + } } diff --git a/src/client/haxe/ru/m/tankz/view/common/TankView.hx b/src/client/haxe/ru/m/tankz/view/common/TankView.hx index 2d9f611..d066305 100644 --- a/src/client/haxe/ru/m/tankz/view/common/TankView.hx +++ b/src/client/haxe/ru/m/tankz/view/common/TankView.hx @@ -6,20 +6,19 @@ import ru.m.tankz.render.RenderUtil; import ru.m.tankz.Type.TankInfo; class TankView extends ImageView { + public var tank(null, set):TankInfo; - public var tank(null, set):TankInfo; + public function new() { + super(); + style = "icon.tank"; + fillType = FillType.CONTAIN; + } - public function new() { - super(); - style = "icon.tank"; - fillType = FillType.CONTAIN; - } - - private function set_tank(value:TankInfo):TankInfo { - if (value != null) { - color = value.color; - image = RenderUtil.tankImage(value.skin); - } - return value; + private function set_tank(value:TankInfo):TankInfo { + if (value != null) { + color = value.color; + image = RenderUtil.tankImage(value.skin); } + return value; + } } diff --git a/src/client/haxe/ru/m/tankz/view/game/PlayerView.hx b/src/client/haxe/ru/m/tankz/view/game/PlayerView.hx index e08edce..c5d8864 100644 --- a/src/client/haxe/ru/m/tankz/view/game/PlayerView.hx +++ b/src/client/haxe/ru/m/tankz/view/game/PlayerView.hx @@ -7,46 +7,45 @@ import ru.m.tankz.Type; import ru.m.tankz.view.common.TankView; @:template class PlayerView extends VGroupView { + @:view("title") public var titleView:LabelView; + @:view("tank") public var tankView:TankView; + @:view("life") public var lifeLabel:LabelView; + @:view("score") public var scoreLabel:LabelView; - @:view("title") public var titleView:LabelView; - @:view("tank") public var tankView:TankView; - @:view("life") public var lifeLabel:LabelView; - @:view("score") public var scoreLabel:LabelView; + public var playerId(default, default):PlayerId; + public var state(null, set):PlayerState; + public var tank(null, set):TankInfo; + public var life(null, set):Int; + public var score(null, set):Int; - public var playerId(default, default):PlayerId; - public var state(null, set):PlayerState; - public var tank(null, set):TankInfo; - public var life(null, set):Int; - public var score(null, set):Int; + private function set_state(value:PlayerState):PlayerState { + playerId = value.id; + titleView.text = value.name != null ? value.name : playerId.format(); + life = value.life; + score = value.score; + tank = value.tank; + return state; + } - private function set_state(value:PlayerState):PlayerState { - playerId = value.id; - titleView.text = value.name != null ? value.name : playerId.format(); - life = value.life; - score = value.score; - tank = value.tank; - return state; - } + private function set_tank(value:TankInfo):TankInfo { + tank = value; + tankView.tank = tank; + return tank; + } - private function set_tank(value:TankInfo):TankInfo { - tank = value; - tankView.tank = tank; - return tank; - } + private function set_life(value:Int):Int { + lifeLabel.text = '${value}'; + return value; + } - private function set_life(value:Int):Int { - lifeLabel.text = '${value}'; - return value; - } + private function set_score(value:Int):Int { + scoreLabel.text = '${value}$'; + return value; + } - private function set_score(value:Int):Int { - scoreLabel.text = '${value}$'; - return value; - } - - public static function factory(index:Int, data:PlayerState):PlayerView { - var result = new PlayerView(); - result.state = data; - return result; - } + public static function factory(index:Int, data:PlayerState):PlayerView { + var result = new PlayerView(); + result.state = data; + return result; + } } diff --git a/src/client/haxe/ru/m/tankz/view/game/TeamView.hx b/src/client/haxe/ru/m/tankz/view/game/TeamView.hx index 86783d6..01a1802 100644 --- a/src/client/haxe/ru/m/tankz/view/game/TeamView.hx +++ b/src/client/haxe/ru/m/tankz/view/game/TeamView.hx @@ -5,32 +5,31 @@ import ru.m.tankz.game.GameState; import ru.m.tankz.Type; class TeamView extends DataView { + public var teamId(default, default):TeamId; + public var state(default, set):TeamState; - public var teamId(default, default):TeamId; - public var state(default, set):TeamState; + private function new():Void { + super(); + factory = PlayerView.factory; + layout.margin = 5; + geometry.width = "100%"; + } - private function new():Void { - super(); - factory = PlayerView.factory; - layout.margin = 5; - geometry.width = "100%"; + private function set_state(value:TeamState):TeamState { + teamId = value.id; + var players = [for (player in value.players) player].filter(function(player) return player.life > 0); + if (value.life > 0) { + var teamState = new PlayerState([value.id, -1]); + teamState.life = value.life; + players.unshift(teamState); } + data = players; + return value; + } - private function set_state(value:TeamState):TeamState { - teamId = value.id; - var players = [for (player in value.players) player].filter(function(player) return player.life > 0); - if (value.life > 0) { - var teamState = new PlayerState([value.id, -1]); - teamState.life = value.life; - players.unshift(teamState); - } - data = players; - return value; - } - - public static inline function viewFactory(index:Int, data:TeamState):TeamView { - var result = new TeamView(); - result.state = data; - return result; - } + public static inline function viewFactory(index:Int, data:TeamState):TeamView { + var result = new TeamView(); + result.state = data; + return result; + } } diff --git a/src/client/haxe/ru/m/tankz/view/gamepad/CircleActionArea.hx b/src/client/haxe/ru/m/tankz/view/gamepad/CircleActionArea.hx index bb854c1..1bfdf40 100644 --- a/src/client/haxe/ru/m/tankz/view/gamepad/CircleActionArea.hx +++ b/src/client/haxe/ru/m/tankz/view/gamepad/CircleActionArea.hx @@ -6,19 +6,19 @@ import ru.m.geom.Circle; import ru.m.geom.Point; class CircleActionArea implements IActionArea { - public var action(default, null):DeviceAction; - public var circle(default, null):Circle; + public var action(default, null):DeviceAction; + public var circle(default, null):Circle; - public function new(action:DeviceAction, circle:Circle) { - this.action = action; - this.circle = circle; - } + public function new(action:DeviceAction, circle:Circle) { + this.action = action; + this.circle = circle; + } - public function contain(point:Point):Bool { - return circle.contain(point); - } + public function contain(point:Point):Bool { + return circle.contain(point); + } - public function draw(graphics:Graphics):Void { - graphics.drawCircle(circle.x, circle.y, circle.radius); - } + public function draw(graphics:Graphics):Void { + graphics.drawCircle(circle.x, circle.y, circle.radius); + } } diff --git a/src/client/haxe/ru/m/tankz/view/gamepad/DefaultActionAreaBuilder.hx b/src/client/haxe/ru/m/tankz/view/gamepad/DefaultActionAreaBuilder.hx index cb2b5c1..06ccfcb 100644 --- a/src/client/haxe/ru/m/tankz/view/gamepad/DefaultActionAreaBuilder.hx +++ b/src/client/haxe/ru/m/tankz/view/gamepad/DefaultActionAreaBuilder.hx @@ -5,38 +5,27 @@ import ru.m.geom.Direction; import ru.m.geom.Rectangle; class DefaultActionAreaBuilder implements IActionAreaBuilder { - public function new() { - } + public function new() {} - public function build(width:Float, height:Float):Array { - var areas:Array = []; - var size = Math.min(width, height) / 7; - var padding = size / 2; - // top - areas.push(new RectangleActionArea( - DIRECTION(Direction.TOP), - new Rectangle(padding + size, height - size * 3 - padding, size, size) - )); - // left - areas.push(new RectangleActionArea( - DIRECTION(Direction.LEFT), - new Rectangle(padding, height - size * 2 - padding, size, size) - )); - // bottom - areas.push(new RectangleActionArea( - DIRECTION(Direction.BOTTOM), - new Rectangle(padding + size, height - size - padding, size, size) - )); - // right - areas.push(new RectangleActionArea( - DIRECTION(Direction.RIGHT), - new Rectangle(padding + size * 2, height - size * 2 - padding, size, size) - )); - // button - areas.push(new RectangleActionArea( - KEY(0), - new Rectangle(width - size * 1.5 - padding, height - size * 2 - padding, size, size) - )); - return areas; - } + public function build(width:Float, height:Float):Array { + var areas:Array = []; + var size = Math.min(width, height) / 7; + var padding = size / 2; + // top + areas.push(new RectangleActionArea(DIRECTION(Direction.TOP), + new Rectangle(padding + size, height - size * 3 - padding, size, size))); + // left + areas.push(new RectangleActionArea(DIRECTION(Direction.LEFT), + new Rectangle(padding, height - size * 2 - padding, size, size))); + // bottom + areas.push(new RectangleActionArea(DIRECTION(Direction.BOTTOM), + new Rectangle(padding + size, height - size - padding, size, size))); + // right + areas.push(new RectangleActionArea(DIRECTION(Direction.RIGHT), + new Rectangle(padding + size * 2, height - size * 2 - padding, size, size))); + // button + areas.push(new RectangleActionArea(KEY(0), + new Rectangle(width - size * 1.5 - padding, height - size * 2 - padding, size, size))); + return areas; + } } diff --git a/src/client/haxe/ru/m/tankz/view/gamepad/GamepadSkin.hx b/src/client/haxe/ru/m/tankz/view/gamepad/GamepadSkin.hx index 65e908c..2173daa 100644 --- a/src/client/haxe/ru/m/tankz/view/gamepad/GamepadSkin.hx +++ b/src/client/haxe/ru/m/tankz/view/gamepad/GamepadSkin.hx @@ -6,32 +6,31 @@ import hw.view.skin.ISkin; import ru.m.control.DeviceAction; @:style class GamepadSkin implements ISkin { + @:style(0xffffff) public var color(default, default):Null; + @:style(0x00ff00) public var activeColor(default, default):Null; - @:style(0xffffff) public var color(default, default):Null; - @:style(0x00ff00) public var activeColor(default, default):Null; + public function new(?color:Color) { + this.color = color; + } - public function new(?color:Color) { - this.color = color; - } - - public function draw(view:GamepadView):Void { - var actives = [for (item in view.activeAreas.iterator()) item]; - var graphics:Graphics = view.content.graphics; - graphics.clear(); - for (area in view.areas) { - switch area.action { - case KEY(code): - if (view.weapons.length < code + 1) { - continue; - } - case _: - } - var color = actives.indexOf(area) > -1 ? activeColor : color; - graphics.lineStyle(2, color); - graphics.beginFill(color, 0.2); - area.draw(graphics); - } - graphics.lineStyle(); - graphics.endFill(); + public function draw(view:GamepadView):Void { + var actives = [for (item in view.activeAreas.iterator()) item]; + var graphics:Graphics = view.content.graphics; + graphics.clear(); + for (area in view.areas) { + switch area.action { + case KEY(code): + if (view.weapons.length < code + 1) { + continue; + } + case _: + } + var color = actives.indexOf(area) > -1 ? activeColor : color; + graphics.lineStyle(2, color); + graphics.beginFill(color, 0.2); + area.draw(graphics); } + graphics.lineStyle(); + graphics.endFill(); + } } diff --git a/src/client/haxe/ru/m/tankz/view/gamepad/GamepadView.hx b/src/client/haxe/ru/m/tankz/view/gamepad/GamepadView.hx index 0c79023..71c23b8 100644 --- a/src/client/haxe/ru/m/tankz/view/gamepad/GamepadView.hx +++ b/src/client/haxe/ru/m/tankz/view/gamepad/GamepadView.hx @@ -12,117 +12,116 @@ import ru.m.geom.Point; import ru.m.tankz.config.Config; class GamepadView extends SpriteView implements IControlDevice { + public var type(default, null):DeviceType; + public var signal(default, null):Signal2; - public var type(default, null):DeviceType; - public var signal(default, null):Signal2; + public var areas(default, null):Array; + public var activeAreas(default, null):Map; - public var areas(default, null):Array; - public var activeAreas(default, null):Map; + public var weapons(default, set):Array; - public var weapons(default, set):Array; + private function set_weapons(value:Array):Array { + weapons = value; + toRedraw(); + return weapons; + } - private function set_weapons(value:Array):Array { - weapons = value; + private var builder:IActionAreaBuilder; + + private var actionLayer:Sprite; + + public function new() { + super(); + style = "gamepad"; + type = SCREEN; + builder = new SmartActionAreaBuilder(); + signal = new Signal2(); + areas = []; + weapons = []; + activeAreas = new Map(); + skin = new GamepadSkin(); + actionLayer = new Sprite(); + actionLayer.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); + actionLayer.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin); + content.addChild(actionLayer); + } + + private function onMouseDown(event:MouseEvent):Void { + onMouseMove(event); + stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); + stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); + } + + private function onMouseMove(event:MouseEvent):Void { + var point = new Point(event.localX, event.localY); + updateTouch(-1, point); + } + + private function onMouseUp(event:MouseEvent):Void { + endTouch(-1); + stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); + stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); + } + + private function onTouchBegin(event:TouchEvent):Void { + onTouchMove(event); + stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); + stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd); + } + + private function onTouchMove(event:TouchEvent):Void { + var point = new Point(event.localX, event.localY); + updateTouch(event.touchPointID, point); + } + + private function onTouchEnd(event:TouchEvent):Void { + endTouch(event.touchPointID); + if (Lambda.count(activeAreas) == 0) { + stage.removeEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); + stage.removeEventListener(TouchEvent.TOUCH_END, onTouchEnd); + } + } + + private function updateTouch(pointID:Int, point:Point):Void { + if (activeAreas.exists(pointID)) { + var area = activeAreas[pointID]; + if (!area.contain(point)) { + activeAreas.remove(pointID); + signal.emit(area.action, false); toRedraw(); - return weapons; - } - - private var builder:IActionAreaBuilder; - - private var actionLayer:Sprite; - - public function new() { - super(); - style = "gamepad"; - type = SCREEN; - builder = new SmartActionAreaBuilder(); - signal = new Signal2(); - areas = []; - weapons = []; - activeAreas = new Map(); - skin = new GamepadSkin(); - actionLayer = new Sprite(); - actionLayer.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); - actionLayer.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin); - content.addChild(actionLayer); - } - - private function onMouseDown(event:MouseEvent):Void { - onMouseMove(event); - stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); - stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); - } - - private function onMouseMove(event:MouseEvent):Void { - var point = new Point(event.localX, event.localY); - updateTouch(-1, point); - } - - private function onMouseUp(event:MouseEvent):Void { - endTouch(-1); - stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); - stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); - } - - private function onTouchBegin(event:TouchEvent):Void { - onTouchMove(event); - stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); - stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd); - } - - private function onTouchMove(event:TouchEvent):Void { - var point = new Point(event.localX, event.localY); - updateTouch(event.touchPointID, point); - } - - private function onTouchEnd(event:TouchEvent):Void { - endTouch(event.touchPointID); - if (Lambda.count(activeAreas) == 0) { - stage.removeEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); - stage.removeEventListener(TouchEvent.TOUCH_END, onTouchEnd); + } + } else { + for (area in areas) { + if (area.contain(point)) { + activeAreas[pointID] = area; + signal.emit(area.action, true); + toRedraw(); + break; } + } } + } - private function updateTouch(pointID:Int, point:Point):Void { - if (activeAreas.exists(pointID)) { - var area = activeAreas[pointID]; - if (!area.contain(point)) { - activeAreas.remove(pointID); - signal.emit(area.action, false); - toRedraw(); - } - } else { - for (area in areas) { - if (area.contain(point)) { - activeAreas[pointID] = area; - signal.emit(area.action, true); - toRedraw(); - break; - } - } - } + private function endTouch(pointID:Int):Void { + if (activeAreas.exists(pointID)) { + signal.emit(activeAreas[pointID].action, false); + activeAreas.remove(pointID); + toRedraw(); } + } - private function endTouch(pointID:Int):Void { - if (activeAreas.exists(pointID)) { - signal.emit(activeAreas[pointID].action, false); - activeAreas.remove(pointID); - toRedraw(); - } - } + override public function update():Void { + super.update(); + areas = builder.build(width, height); + actionLayer.graphics.clear(); + actionLayer.graphics.beginFill(0, 0.0); + actionLayer.graphics.drawRect(0, 0, width, height); + actionLayer.graphics.endFill(); + } - override public function update():Void { - super.update(); - areas = builder.build(width, height); - actionLayer.graphics.clear(); - actionLayer.graphics.beginFill(0, 0.0); - actionLayer.graphics.drawRect(0, 0, width, height); - actionLayer.graphics.endFill(); - } - - public function dispose():Void { - actionLayer.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); - actionLayer.removeEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin); - stage = null; - } + public function dispose():Void { + actionLayer.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); + actionLayer.removeEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin); + stage = null; + } } diff --git a/src/client/haxe/ru/m/tankz/view/gamepad/IActionArea.hx b/src/client/haxe/ru/m/tankz/view/gamepad/IActionArea.hx index a3172bb..c204b78 100644 --- a/src/client/haxe/ru/m/tankz/view/gamepad/IActionArea.hx +++ b/src/client/haxe/ru/m/tankz/view/gamepad/IActionArea.hx @@ -5,7 +5,7 @@ import ru.m.control.DeviceAction; import ru.m.geom.Point; interface IActionArea { - public var action(default, null):DeviceAction; - public function contain(point:Point):Bool; - public function draw(graphics:Graphics):Void; + public var action(default, null):DeviceAction; + public function contain(point:Point):Bool; + public function draw(graphics:Graphics):Void; } diff --git a/src/client/haxe/ru/m/tankz/view/gamepad/IActionAreaBuilder.hx b/src/client/haxe/ru/m/tankz/view/gamepad/IActionAreaBuilder.hx index 4c491bb..f16b123 100644 --- a/src/client/haxe/ru/m/tankz/view/gamepad/IActionAreaBuilder.hx +++ b/src/client/haxe/ru/m/tankz/view/gamepad/IActionAreaBuilder.hx @@ -1,5 +1,5 @@ package ru.m.tankz.view.gamepad; interface IActionAreaBuilder { - public function build(width:Float, height:Float):Array; + public function build(width:Float, height:Float):Array; } diff --git a/src/client/haxe/ru/m/tankz/view/gamepad/RectangleActionArea.hx b/src/client/haxe/ru/m/tankz/view/gamepad/RectangleActionArea.hx index d3f0c12..21c9bcf 100644 --- a/src/client/haxe/ru/m/tankz/view/gamepad/RectangleActionArea.hx +++ b/src/client/haxe/ru/m/tankz/view/gamepad/RectangleActionArea.hx @@ -6,19 +6,19 @@ import ru.m.geom.Point; import ru.m.geom.Rectangle; class RectangleActionArea implements IActionArea { - public var action(default, null):DeviceAction; - public var rectangle(default, null):Rectangle; + public var action(default, null):DeviceAction; + public var rectangle(default, null):Rectangle; - public function new(action:DeviceAction, rectangle:Rectangle) { - this.action = action; - this.rectangle = rectangle; - } + public function new(action:DeviceAction, rectangle:Rectangle) { + this.action = action; + this.rectangle = rectangle; + } - public function contain(point:Point):Bool { - return rectangle.contain(point); - } + public function contain(point:Point):Bool { + return rectangle.contain(point); + } - public function draw(graphics:Graphics):Void { - graphics.drawRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height); - } + public function draw(graphics:Graphics):Void { + graphics.drawRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height); + } } diff --git a/src/client/haxe/ru/m/tankz/view/gamepad/RhombusActionArea.hx b/src/client/haxe/ru/m/tankz/view/gamepad/RhombusActionArea.hx index 7057e66..f011ecf 100644 --- a/src/client/haxe/ru/m/tankz/view/gamepad/RhombusActionArea.hx +++ b/src/client/haxe/ru/m/tankz/view/gamepad/RhombusActionArea.hx @@ -6,28 +6,28 @@ import ru.m.geom.Point; import ru.m.geom.Rectangle; class RhombusActionArea implements IActionArea { - public var action(default, null):DeviceAction; - public var rectangle(default, null):Rectangle; + public var action(default, null):DeviceAction; + public var rectangle(default, null):Rectangle; - private var center:Point; - private var distance:Float; + private var center:Point; + private var distance:Float; - public function new(action:DeviceAction, rectangle:Rectangle) { - this.action = action; - this.rectangle = rectangle; - center = rectangle.center; - distance = Math.max(rectangle.width / 2, rectangle.height / 2); - } + public function new(action:DeviceAction, rectangle:Rectangle) { + this.action = action; + this.rectangle = rectangle; + center = rectangle.center; + distance = Math.max(rectangle.width / 2, rectangle.height / 2); + } - public function contain(point:Point):Bool { - return Math.abs(point.x - center.x) + Math.abs(point.y - center.y) < distance; - } + public function contain(point:Point):Bool { + return Math.abs(point.x - center.x) + Math.abs(point.y - center.y) < distance; + } - public function draw(graphics:Graphics):Void { - graphics.moveTo(rectangle.x + rectangle.width / 2, rectangle.top); - graphics.lineTo(rectangle.right, rectangle.y + rectangle.height / 2); - graphics.lineTo(rectangle.x + rectangle.width / 2, rectangle.bottom); - graphics.lineTo(rectangle.left, rectangle.y + rectangle.height / 2); - graphics.lineTo(rectangle.x + rectangle.width / 2, rectangle.top); - } + public function draw(graphics:Graphics):Void { + graphics.moveTo(rectangle.x + rectangle.width / 2, rectangle.top); + graphics.lineTo(rectangle.right, rectangle.y + rectangle.height / 2); + graphics.lineTo(rectangle.x + rectangle.width / 2, rectangle.bottom); + graphics.lineTo(rectangle.left, rectangle.y + rectangle.height / 2); + graphics.lineTo(rectangle.x + rectangle.width / 2, rectangle.top); + } } diff --git a/src/client/haxe/ru/m/tankz/view/gamepad/SmartActionAreaBuilder.hx b/src/client/haxe/ru/m/tankz/view/gamepad/SmartActionAreaBuilder.hx index 8d44a71..8d6313e 100644 --- a/src/client/haxe/ru/m/tankz/view/gamepad/SmartActionAreaBuilder.hx +++ b/src/client/haxe/ru/m/tankz/view/gamepad/SmartActionAreaBuilder.hx @@ -7,43 +7,30 @@ import ru.m.geom.Direction; import ru.m.geom.Rectangle; class SmartActionAreaBuilder implements IActionAreaBuilder { - public function new() { - } + public function new() {} - public function build(width:Float, height:Float):Array { - var areas:Array = []; - var size = Math.min(width, height) / 5; - var padding = Box.fromArray([size / 4, size / 3]); - // top - areas.push(new RhombusActionArea( - DIRECTION(Direction.TOP), - new Rectangle(padding.left + size * 0.5, height - size * 2 - padding.bottom, size, size ) - )); - // left - areas.push(new RhombusActionArea( - DIRECTION(Direction.LEFT), - new Rectangle(padding.left, height - size * 1.5 - padding.bottom, size, size) - )); - // bottom - areas.push(new RhombusActionArea( - DIRECTION(Direction.BOTTOM), - new Rectangle(padding.left + size * 0.5, height - size - padding.bottom, size, size) - )); - // right - areas.push(new RhombusActionArea( - DIRECTION(Direction.RIGHT), - new Rectangle(padding.left + size, height - size * 1.5 - padding.bottom, size, size) - )); - // key 0 - areas.push(new CircleActionArea( - KEY(0), - new Circle(width - size * 0.5 - padding.right, height - size * 0.5 - padding.bottom, size / 2) - )); - // key 1 - areas.push(new CircleActionArea( - KEY(1), - new Circle(width - size * 0.5 - padding.right, height - size * 1.5 - padding.bottom, size / 2) - )); - return areas; - } + public function build(width:Float, height:Float):Array { + var areas:Array = []; + var size = Math.min(width, height) / 5; + var padding = Box.fromArray([size / 4, size / 3]); + // top + areas.push(new RhombusActionArea(DIRECTION(Direction.TOP), + new Rectangle(padding.left + size * 0.5, height - size * 2 - padding.bottom, size, size))); + // left + areas.push(new RhombusActionArea(DIRECTION(Direction.LEFT), + new Rectangle(padding.left, height - size * 1.5 - padding.bottom, size, size))); + // bottom + areas.push(new RhombusActionArea(DIRECTION(Direction.BOTTOM), + new Rectangle(padding.left + size * 0.5, height - size - padding.bottom, size, size))); + // right + areas.push(new RhombusActionArea(DIRECTION(Direction.RIGHT), + new Rectangle(padding.left + size, height - size * 1.5 - padding.bottom, size, size))); + // key 0 + areas.push(new CircleActionArea(KEY(0), + new Circle(width - size * 0.5 - padding.right, height - size * 0.5 - padding.bottom, size / 2))); + // key 1 + areas.push(new CircleActionArea(KEY(1), + new Circle(width - size * 0.5 - padding.right, height - size * 1.5 - padding.bottom, size / 2))); + return areas; + } } diff --git a/src/client/haxe/ru/m/tankz/view/network/RoomFrame.hx b/src/client/haxe/ru/m/tankz/view/network/RoomFrame.hx index f8ed938..ee3feb6 100644 --- a/src/client/haxe/ru/m/tankz/view/network/RoomFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/network/RoomFrame.hx @@ -11,39 +11,38 @@ import ru.m.tankz.proto.room.RoomProto; import ru.m.tankz.proto.room.RoomSlotProto; @:template class RoomFrame extends FrameView { + public static inline var ID = "room"; - public static inline var ID = "room"; + @:view var start:ButtonView; + @:view var info:TextView; + @:view var slots:DataView; - @:view var start:ButtonView; - @:view var info:TextView; - @:view var slots:DataView; + @:provide var switcher:FrameSwitcher; + @:provide var network:NetworkManager; - @:provide var switcher:FrameSwitcher; - @:provide var network:NetworkManager; + public function new() { + super(ID); + } - public function new() { - super(ID); + private function refresh(room:RoomProto):Void { + if (room != null) { + start.visible = room.creator.uuid == network.user.uuid; + info.text = '${room.game.type} #${room.game.level}'; + slots.data = room.slots; + if (room.game.started) { + switcher.change(GameFrame.ID, NETWORK(network)); + } + } else { + Timer.delay(function() switcher.change(RoomListFrame.ID), 1); } + } - private function refresh(room:RoomProto):Void { - if (room != null) { - start.visible = room.creator.uuid == network.user.uuid; - info.text = '${room.game.type} #${room.game.level}'; - slots.data = room.slots; - if (room.game.started) { - switcher.change(GameFrame.ID, NETWORK(network)); - } - } else { - Timer.delay(function() switcher.change(RoomListFrame.ID), 1); - } - } + override public function onShow(data:RoomProto):Void { + refresh(data); + network.roomSignal.connect(refresh); + } - override public function onShow(data:RoomProto):Void { - refresh(data); - network.roomSignal.connect(refresh); - } - - override public function onHide():Void { - network.roomSignal.disconnect(refresh); - } + override public function onHide():Void { + network.roomSignal.disconnect(refresh); + } } diff --git a/src/client/haxe/ru/m/tankz/view/network/RoomItemView.hx b/src/client/haxe/ru/m/tankz/view/network/RoomItemView.hx index 3bef406..cff4be5 100644 --- a/src/client/haxe/ru/m/tankz/view/network/RoomItemView.hx +++ b/src/client/haxe/ru/m/tankz/view/network/RoomItemView.hx @@ -9,34 +9,33 @@ import hw.view.list.ListView; import ru.m.tankz.proto.room.RoomProto; @:template class RoomItemView extends HGroupView implements IListItemView { + public var item_index(default, default):Int; + public var data(default, set):RoomProto; - public var item_index(default, default):Int; - public var data(default, set):RoomProto; + @:view("creator") var creatorView:LabelView; + @:view("type") var typeView:LabelView; + @:view("users") var usersView:LabelView; + @:view("join") var joinButton:ButtonView; - @:view("creator") var creatorView:LabelView; - @:view("type") var typeView:LabelView; - @:view("users") var usersView:LabelView; - @:view("join") var joinButton:ButtonView; + @:provide static var network:NetworkManager; - @:provide static var network:NetworkManager; + private function set_data(value:RoomProto):RoomProto { + data = value; + creatorView.style = value.creator.uuid == network.user.uuid ? "text.box.active" : "text.box"; + creatorView.text = value.creator.name; + typeView.text = '${value.game.type} #${value.game.level}'; + var used = value.slots.filter(function(slot:RoomSlotProto) return slot.hasUser()).length; + usersView.text = value.game.started ? 'started' : '${used}/${value.slots.length}'; + return data; + } - private function set_data(value:RoomProto):RoomProto { - data = value; - creatorView.style = value.creator.uuid == network.user.uuid ? "text.box.active" : "text.box"; - creatorView.text = value.creator.name; - typeView.text = '${value.game.type} #${value.game.level}'; - var used = value.slots.filter(function(slot:RoomSlotProto) return slot.hasUser()).length; - usersView.text = value.game.started ? 'started' : '${used}/${value.slots.length}'; - return data; - } + private function join():Void { + network.joinGame(data.game.id, true); + } - private function join():Void { - network.joinGame(data.game.id, true); - } - - public static function factory(index:Int, value:RoomProto):RoomItemView { - var result = new RoomItemView(); - result.data = value; - return result; - } + public static function factory(index:Int, value:RoomProto):RoomItemView { + var result = new RoomItemView(); + result.data = value; + return result; + } } diff --git a/src/client/haxe/ru/m/tankz/view/network/RoomListFrame.hx b/src/client/haxe/ru/m/tankz/view/network/RoomListFrame.hx index dadf4e6..087ed10 100644 --- a/src/client/haxe/ru/m/tankz/view/network/RoomListFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/network/RoomListFrame.hx @@ -8,44 +8,44 @@ import ru.m.tankz.proto.room.RoomProto; import ru.m.tankz.view.popup.CreateGamePopup; @:template class RoomListFrame extends FrameView { - public static inline var ID = "room_list"; + public static inline var ID = "room_list"; - @:view var games:DataView; + @:view var games:DataView; - @:provide var switcher:FrameSwitcher; - @:provide var network:NetworkManager; + @:provide var switcher:FrameSwitcher; + @:provide var network:NetworkManager; - public function new() { - super(ID); - } - - override public function onShow(_:Dynamic):Void { - network.listRoomSignal.connect(onRoomList); - network.roomSignal.connect(onRoom); - network.listGame(true); - } - - override public function onHide():Void { - network.listRoomSignal.disconnect(onRoomList); - network.roomSignal.disconnect(onRoom); - network.listGame(false); - } - - private function create():Void { - CreateGamePopup.instance.show().then(function(result) { - if (result != null) { - network.createGame(result.type, result.level.id); - } - }); - } - - private function onRoomList(data:Array):Void { - games.data = data; - } - - private function onRoom(room:RoomProto):Void { - if (room != null) { - switcher.change(RoomFrame.ID, room); - } + public function new() { + super(ID); + } + + override public function onShow(_:Dynamic):Void { + network.listRoomSignal.connect(onRoomList); + network.roomSignal.connect(onRoom); + network.listGame(true); + } + + override public function onHide():Void { + network.listRoomSignal.disconnect(onRoomList); + network.roomSignal.disconnect(onRoom); + network.listGame(false); + } + + private function create():Void { + CreateGamePopup.instance.show().then(function(result) { + if (result != null) { + network.createGame(result.type, result.level.id); + } + }); + } + + private function onRoomList(data:Array):Void { + games.data = data; + } + + private function onRoom(room:RoomProto):Void { + if (room != null) { + switcher.change(RoomFrame.ID, room); } + } } diff --git a/src/client/haxe/ru/m/tankz/view/network/SlotItemView.hx b/src/client/haxe/ru/m/tankz/view/network/SlotItemView.hx index d6c27e7..60f30d4 100644 --- a/src/client/haxe/ru/m/tankz/view/network/SlotItemView.hx +++ b/src/client/haxe/ru/m/tankz/view/network/SlotItemView.hx @@ -9,38 +9,37 @@ import ru.m.tankz.network.NetworkManager; import ru.m.tankz.proto.room.RoomSlotProto; @:template class SlotItemView extends HGroupView implements IListItemView { + public var item_index(default, default):Int; + public var data(default, set):RoomSlotProto; - public var item_index(default, default):Int; - public var data(default, set):RoomSlotProto; + @:view("type") var typeView:LabelView; + @:view("user") var userView:LabelView; + @:view("select") var selectButton:ButtonView; - @:view("type") var typeView:LabelView; - @:view("user") var userView:LabelView; - @:view("select") var selectButton:ButtonView; + @:provide static var network:NetworkManager; + @:provide static var configBundle:IConfigBundle; - @:provide static var network:NetworkManager; - @:provide static var configBundle:IConfigBundle; + private function set_data(value:RoomSlotProto):RoomSlotProto { + data = value; + typeView.text = '${value.slot.team} #${value.slot.index}'; + userView.text = value.hasUser() ? value.user.name : "(NONE)"; + userView.visible = value.hasUser(); + selectButton.visible = !value.hasUser(); + userView.style = (value.hasUser() && value.user.uuid == network.user.uuid) ? "text.box.active" : "text.box"; + var config = configBundle.get(network.room.game.type); + var color = config.getColor([value.slot.team, value.slot.index]); + typeView.font.color = color; + return data; + } - private function set_data(value:RoomSlotProto):RoomSlotProto { - data = value; - typeView.text = '${value.slot.team} #${value.slot.index}'; - userView.text = value.hasUser() ? value.user.name : "(NONE)"; - userView.visible = value.hasUser(); - selectButton.visible = !value.hasUser(); - userView.style = (value.hasUser() && value.user.uuid == network.user.uuid) ? "text.box.active" : "text.box"; - var config = configBundle.get(network.room.game.type); - var color = config.getColor([value.slot.team, value.slot.index]); - typeView.font.color = color; - return data; - } + private function select():Void { + network.selectSlot(data.slot); + } - private function select():Void { - network.selectSlot(data.slot); - } - - public static function factory(index:Int, value:RoomSlotProto):SlotItemView { - var result = new SlotItemView(); - result.index = index; - result.data = value; - return result; - } + public static function factory(index:Int, value:RoomSlotProto):SlotItemView { + var result = new SlotItemView(); + result.index = index; + result.data = value; + return result; + } } diff --git a/src/client/haxe/ru/m/tankz/view/popup/CreateGamePopup.hx b/src/client/haxe/ru/m/tankz/view/popup/CreateGamePopup.hx index 873557e..954abe6 100644 --- a/src/client/haxe/ru/m/tankz/view/popup/CreateGamePopup.hx +++ b/src/client/haxe/ru/m/tankz/view/popup/CreateGamePopup.hx @@ -9,66 +9,65 @@ import ru.m.tankz.config.Config; import ru.m.tankz.Type; private typedef Result = { - var type:GameType; - var level:LevelConfig; + var type:GameType; + var level:LevelConfig; } @:template class CreateGamePopup extends PopupView { + @:view("type") var typeView:DataView; + @:view("level") var levelView:DataView; - @:view("type") var typeView:DataView; - @:view("level") var levelView:DataView; + @:provide static var configBundle:IConfigBundle; + @:provide static var levelBundle:ILevelBundle; - @:provide static var configBundle:IConfigBundle; - @:provide static var levelBundle:ILevelBundle; + private var type:GameType; + private var level:LevelConfig; - private var type:GameType; - private var level:LevelConfig; + override private function onShow():Void { + super.onShow(); + onGameTypeSelect(0, "classic", typeView.dataViews[0]); + } - override private function onShow():Void { - super.onShow(); - onGameTypeSelect(0, "classic", typeView.dataViews[0]); + private function submit():Void { + close({type: type, level: level}); + } + + private function gameTypeViewFactory(index:Int, type:GameType):ToggleButtonView { + var result = new ToggleButtonView(); + result.text = type; + result.on = type == this.type; + return result; + } + + private function onGameTypeSelect(index:Int, value:GameType, view:ToggleButtonView):Void { + this.type = value; + for (v in typeView.dataViews) { + v.on = v == view; } + levelView.data = levelBundle.get(new PackId(value)).data; + onLevelSelect(0, levelView.data[0], levelView.dataViews[0]); + } - private function submit():Void { - close({type:type, level:level}); + private function levelViewFactory(index:Int, value:LevelConfig):ToggleButtonView { + var result = new ToggleButtonView(); + result.style = "button.level"; + result.text = Std.string(value.id); + return result; + } + + private function onLevelSelect(index:Int, level:LevelConfig, view:ToggleButtonView):Void { + this.level = level; + for (v in levelView.dataViews) { + v.on = v == view; } + } - private function gameTypeViewFactory(index:Int, type:GameType):ToggleButtonView { - var result = new ToggleButtonView(); - result.text = type; - result.on = type == this.type; - return result; - } - - private function onGameTypeSelect(index:Int, value:GameType, view:ToggleButtonView):Void { - this.type = value; - for (v in typeView.dataViews) { - v.on = v == view; - } - levelView.data = levelBundle.get(new PackId(value)).data; - onLevelSelect(0, levelView.data[0], levelView.dataViews[0]); - } - - private function levelViewFactory(index:Int, value:LevelConfig):ToggleButtonView { - var result = new ToggleButtonView(); - result.style = "button.level"; - result.text = Std.string(value.id); - return result; - } - - private function onLevelSelect(index:Int, level:LevelConfig, view:ToggleButtonView):Void { - this.level = level; - for (v in levelView.dataViews) { - v.on = v == view; - } - } - - public static var instance(get, null):CreateGamePopup; - - private static function get_instance():CreateGamePopup { - if (instance == null) { - instance = new CreateGamePopup(); - } - return instance; + public static var instance(get, null):CreateGamePopup; + + private static function get_instance():CreateGamePopup { + if (instance == null) { + instance = new CreateGamePopup(); } + return instance; + } } diff --git a/src/client/haxe/ru/m/tankz/view/popup/LoginPopup.hx b/src/client/haxe/ru/m/tankz/view/popup/LoginPopup.hx index 0db094a..ce025fc 100644 --- a/src/client/haxe/ru/m/tankz/view/popup/LoginPopup.hx +++ b/src/client/haxe/ru/m/tankz/view/popup/LoginPopup.hx @@ -7,32 +7,34 @@ import hw.view.text.TextView; import ru.m.tankz.network.NetworkManager; @:singleton @:template class LoginPopup extends PopupView { + @:view var username:InputView; + @:view var password:InputView; + @:view var error:TextView; - @:view var username:InputView; - @:view var password:InputView; - @:view var error:TextView; + @:provide static var network:NetworkManager; - @:provide static var network:NetworkManager; + override private function onShow():Void { + super.onShow(); + network.stateSignal.connect(onStateChange); + } - override private function onShow():Void { - super.onShow(); - network.stateSignal.connect(onStateChange); + override private function onClose():Void { + super.onClose(); + network.stateSignal.disconnect(onStateChange); + } + + private function onStateChange(state:ConnectionState):Void { + switch state { + case ONLINE(user): + close(user); + case ERROR(error): + this.error.text = LoggerUtil.printError(error); + case _: + this.error.text = null; } + } - override private function onClose():Void { - super.onClose(); - network.stateSignal.disconnect(onStateChange); - } - - private function onStateChange(state:ConnectionState):Void { - switch state { - case ONLINE(user): close(user); - case ERROR(error): this.error.text = LoggerUtil.printError(error); - case _: this.error.text = null; - } - } - - private function submit():Void { - network.login(username.text); - } + private function submit():Void { + network.login(username.text); + } } diff --git a/src/client/haxe/ru/m/tankz/view/popup/PausePopup.hx b/src/client/haxe/ru/m/tankz/view/popup/PausePopup.hx index d08d7a0..3fe7e2d 100644 --- a/src/client/haxe/ru/m/tankz/view/popup/PausePopup.hx +++ b/src/client/haxe/ru/m/tankz/view/popup/PausePopup.hx @@ -3,10 +3,8 @@ package ru.m.tankz.view.popup; import hw.view.popup.PopupView; enum Action { - RESUME; - EXIT; + RESUME; + EXIT; } -@:singleton @:template class PausePopup extends PopupView { - -} +@:singleton @:template class PausePopup extends PopupView {} diff --git a/src/client/haxe/ru/m/tankz/view/result/FragView.hx b/src/client/haxe/ru/m/tankz/view/result/FragView.hx index 00a4b58..74bb369 100644 --- a/src/client/haxe/ru/m/tankz/view/result/FragView.hx +++ b/src/client/haxe/ru/m/tankz/view/result/FragView.hx @@ -7,33 +7,32 @@ import ru.m.tankz.render.RenderUtil; import ru.m.tankz.view.common.TankView; @:template class FragView extends HGroupView { + @:view("tank") var tankView:TankView; + @:view("title") var titleView:LabelView; + @:view("score") var scoreView:LabelView; - @:view("tank") var tankView:TankView; - @:view("title") var titleView:LabelView; - @:view("score") var scoreView:LabelView; + public var data(default, set):Frag; - public var data(default, set):Frag; - - private function set_data(value:Frag):Frag { - data = value; - titleView.text = data.playerId.format(); - scoreView.text = data.score.format(); - switch data.target { - case TANK(tank): - tankView.tank = tank; - case EAGLE(color): - tankView.image = RenderUtil.eagleImage(); - tankView.color = color; - case BONUS(type): - tankView.image = RenderUtil.bonusImage(type); - titleView.text = type; - } - return data; + private function set_data(value:Frag):Frag { + data = value; + titleView.text = data.playerId.format(); + scoreView.text = data.score.format(); + switch data.target { + case TANK(tank): + tankView.tank = tank; + case EAGLE(color): + tankView.image = RenderUtil.eagleImage(); + tankView.color = color; + case BONUS(type): + tankView.image = RenderUtil.bonusImage(type); + titleView.text = type; } + return data; + } - public static function factory(index:Int, data:Frag):FragView { - var result = new FragView(); - result.data = data; - return result; - } + public static function factory(index:Int, data:Frag):FragView { + var result = new FragView(); + result.data = data; + return result; + } } diff --git a/src/client/haxe/ru/m/tankz/view/result/ResultPlayerView.hx b/src/client/haxe/ru/m/tankz/view/result/ResultPlayerView.hx index f4bd8a2..6de1bad 100644 --- a/src/client/haxe/ru/m/tankz/view/result/ResultPlayerView.hx +++ b/src/client/haxe/ru/m/tankz/view/result/ResultPlayerView.hx @@ -8,39 +8,38 @@ import ru.m.tankz.game.GameState; import ru.m.tankz.view.common.TankView; @:template class ResultPlayerView extends VGroupView { + @:view("player") var playerView:HGroupView; + @:view("tank") var tankView:TankView; + @:view("title") var titleView:LabelView; + @:view("score") var scoreView:LabelView; + @:view("frags") var fragsView:DataView; - @:view("player") var playerView:HGroupView; - @:view("tank") var tankView:TankView; - @:view("title") var titleView:LabelView; - @:view("score") var scoreView:LabelView; - @:view("frags") var fragsView:DataView; + public var data(default, set):PlayerState; + public var winner(default, set):Bool; - public var data(default, set):PlayerState; - public var winner(default, set):Bool; + private function set_data(value:PlayerState):PlayerState { + data = value; + titleView.text = data.name != null ? '${data.id.format()} * ${data.name}' : data.id.format(); + var additionalScore = Lambda.fold(data.frags, function(frag:Frag, score:Int) return score + frag.score, 0); + scoreView.text = '${data.score}$ (+${additionalScore}$)'; + tankView.color = value.color; + var frags = data.frags.slice(0); + frags.reverse(); + fragsView.data = frags; + tankView.tank = value.tank; + return data; + } - private function set_data(value:PlayerState):PlayerState { - data = value; - titleView.text = data.name != null ? '${data.id.format()} * ${data.name}' : data.id.format(); - var additionalScore = Lambda.fold(data.frags, function(frag:Frag, score:Int) return score + frag.score, 0); - scoreView.text = '${data.score}$ (+${additionalScore}$)'; - tankView.color = value.color; - var frags = data.frags.slice(0); - frags.reverse(); - fragsView.data = frags; - tankView.tank = value.tank; - return data; - } + private function set_winner(value:Bool):Bool { + winner = value; + style = winner ? "result.winner" : "result.loser"; + playerView.style = winner ? "player.winner" : "player.loser"; + return winner; + } - private function set_winner(value:Bool):Bool { - winner = value; - style = winner ? "result.winner" : "result.loser"; - playerView.style = winner ? "player.winner" : "player.loser"; - return winner; - } - - public static function factory(index:Int, data:PlayerState):ResultPlayerView { - var result = new ResultPlayerView(); - result.data = data; - return result; - } + public static function factory(index:Int, data:PlayerState):ResultPlayerView { + var result = new ResultPlayerView(); + result.data = data; + return result; + } } diff --git a/src/client/haxe/ru/m/tankz/view/settings/ActionView.hx b/src/client/haxe/ru/m/tankz/view/settings/ActionView.hx index b3c4c08..4156179 100755 --- a/src/client/haxe/ru/m/tankz/view/settings/ActionView.hx +++ b/src/client/haxe/ru/m/tankz/view/settings/ActionView.hx @@ -9,32 +9,31 @@ import ru.m.tankz.control.Control; using ru.m.tankz.view.ViewUtil; typedef ActionItem = { - var action:TankAction; - var bind:BindAction; + var action:TankAction; + var bind:BindAction; } @:template class ActionView extends HGroupView implements IListItemView { + public var item_index(default, default):Int; + public var data(default, set):ActionItem; - public var item_index(default, default):Int; - public var data(default, set):ActionItem; + public var edit(default, set):Bool; - public var edit(default, set):Bool; + @:view var action(default, null):LabelView; + @:view var key(default, null):LabelView; - @:view var action(default, null):LabelView; - @:view var key(default, null):LabelView; + private function set_data(value:ActionItem):ActionItem { + data = value; + action.text = data.action.toActionLabel(); + key.text = data.bind.toBindLabel(); + return data; + } - private function set_data(value:ActionItem):ActionItem { - data = value; - action.text = data.action.toActionLabel(); - key.text = data.bind.toBindLabel(); - return data; - } - - private function set_edit(value:Bool):Bool { - if (edit != value) { - edit = value; - action.style = key.style = edit ? "text.box.active" : "text.box"; - } - return edit; + private function set_edit(value:Bool):Bool { + if (edit != value) { + edit = value; + action.style = key.style = edit ? "text.box.active" : "text.box"; } + return edit; + } } diff --git a/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.hx b/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.hx index 0a848a1..b064501 100644 --- a/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.hx +++ b/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.hx @@ -14,127 +14,125 @@ import ru.m.tankz.storage.SettingsStorage; import ru.m.tankz.view.settings.ActionView; class BindEditor { + private var editViews:Array; - private var editViews:Array; + @:provide static var bus:IControlBus; - @:provide static var bus:IControlBus; + private var def:Deferred; - private var def:Deferred; + public function new() { + editViews = []; + bus.signal.connect(onBusAction); + } - public function new() { - editViews = []; - bus.signal.connect(onBusAction); + private function onBusAction(device:DeviceType, action:DeviceAction, on:Bool):Void { + if (on && editViews.length > 0) { + var view = editViews.shift(); + view.edit = false; + view.data.bind = {device: device, action: action}; + view.data = view.data; + if (editViews.length > 0) { + editViews[0].edit = true; + } else { + def.resolve(true); + } } + } - private function onBusAction(device:DeviceType, action:DeviceAction, on:Bool):Void { - if (on && editViews.length > 0) { - var view = editViews.shift(); - view.edit = false; - view.data.bind = {device: device, action: action}; - view.data = view.data; - if (editViews.length > 0) { - editViews[0].edit = true; - } else { - def.resolve(true); - } - } + public function push(views:Array):Promise { + for (view in editViews) { + view.edit = false; } - - public function push(views:Array):Promise { - for (view in editViews) { - view.edit = false; - } - editViews = views.slice(0); - if (editViews.length > 0) { - editViews[0].edit = true; - } - def = new Deferred(); - return def.promise(); + editViews = views.slice(0); + if (editViews.length > 0) { + editViews[0].edit = true; } + def = new Deferred(); + return def.promise(); + } - public static var i(get, null):BindEditor; + public static var i(get, null):BindEditor; - private static function get_i():BindEditor { - if (i == null) { - i = new BindEditor(); - } - return i; + private static function get_i():BindEditor { + if (i == null) { + i = new BindEditor(); } + return i; + } } @:template class SettingsEditor extends VGroupView { + public var controlIndex(default, set):Int; - public var controlIndex(default, set): Int; + @:view var label:LabelView; + @:view var list:DataView; + @:view var panel:GroupView; - @:view var label:LabelView; - @:view var list:DataView; - @:view var panel:GroupView; + @:provide static var storage:SettingsStorage; + @:provide static var bus:IControlBus; - @:provide static var storage:SettingsStorage; - @:provide static var bus:IControlBus; + private function refresh():Void { + label.text = 'Player ${controlIndex + 1}'; + var binding = storage.getBinding(controlIndex); + list.data = bindingToArray(binding); + } - private function refresh():Void { - label.text = 'Player ${controlIndex+1}'; - var binding = storage.getBinding(controlIndex); - list.data = bindingToArray(binding); + private function set_controlIndex(value:Int):Int { + this.controlIndex = value; + refresh(); + return this.controlIndex; + } + + private function viewFactory(index:Int, value:ActionItem) { + var view = new ActionView(); + view.item_index = index; + view.data = value; + return view; + } + + private function onItemSelect(index:Int, value:ActionItem, view:ActionView):Void { + BindEditor.i.push([view]).then(function(_) save()); + } + + private function screen():Void { + list.data = bindingToArray(SettingsStorage.buildDeviceBinding(SCREEN)); + list.toUpdate(); + save(); + } + + private function change():Void { + BindEditor.i.push(list.dataViews).then(function(_) save()); + } + + private function clear():Void { + list.data = bindingToArray(SettingsStorage.getDefaultBinding(-1)); + list.toUpdate(); + save(); + } + + private function default_():Void { + list.data = bindingToArray(SettingsStorage.getDefaultBinding(controlIndex)); + list.toUpdate(); + save(); + } + + private function save():Void { + storage.saveBinding(controlIndex, arrayToBinding(list.data)); + } + + private static function bindingToArray(binding:Binding):Array { + var result:Array = []; + for (action in binding.keys()) { + result.push({action: action, bind: binding.get(action)}); } + return result; + } - private function set_controlIndex(value: Int): Int { - this.controlIndex = value; - refresh(); - return this.controlIndex; - } - - private function viewFactory(index:Int, value:ActionItem) { - var view = new ActionView(); - view.item_index = index; - view.data = value; - return view; - } - - private function onItemSelect(index:Int, value:ActionItem, view:ActionView):Void { - BindEditor.i.push([view]).then(function(_) save()); - } - - private function screen():Void { - list.data = bindingToArray(SettingsStorage.buildDeviceBinding(SCREEN)); - list.toUpdate(); - save(); - } - - private function change():Void { - BindEditor.i.push(list.dataViews).then(function(_) save()); - } - - private function clear():Void { - list.data = bindingToArray(SettingsStorage.getDefaultBinding(-1)); - list.toUpdate(); - save(); - } - - private function default_():Void { - list.data = bindingToArray(SettingsStorage.getDefaultBinding(controlIndex)); - list.toUpdate(); - save(); - } - - private function save():Void { - storage.saveBinding(controlIndex, arrayToBinding(list.data)); - } - - private static function bindingToArray(binding:Binding):Array { - var result:Array = []; - for (action in binding.keys()) { - result.push({action: action, bind: binding.get(action)}); - } - return result; - } - - private static function arrayToBinding(array:Array):Binding { - var result = new Binding(); - for (item in array) { - result.set(item.action, item.bind); - } - return result; + private static function arrayToBinding(array:Array):Binding { + var result = new Binding(); + for (item in array) { + result.set(item.action, item.bind); } + return result; + } } diff --git a/src/client/haxe/ru/m/update/Updater.hx b/src/client/haxe/ru/m/update/Updater.hx index 2a37f87..afa82cf 100644 --- a/src/client/haxe/ru/m/update/Updater.hx +++ b/src/client/haxe/ru/m/update/Updater.hx @@ -8,79 +8,76 @@ import ru.m.Device; import ru.m.update.Version; @:enum abstract PackageType(String) from String to String { - var APK = "apk"; - var DEB = "deb"; - var EXE = "exe"; - var ARCHIVE = "archive"; + var APK = "apk"; + var DEB = "deb"; + var EXE = "exe"; + var ARCHIVE = "archive"; } typedef PackageInfo = { - var platform:Platform; - var type:PackageType; - var path:String; - var filename:String; - var url:String; - var version:String; + var platform:Platform; + var type:PackageType; + var path:String; + var filename:String; + var url:String; + var version:String; } typedef PackagesBundle = { - var name:String; - var version:String; - var packages:Array; + var name:String; + var version:String; + var packages:Array; } class Updater { + private static inline var TAG = "Update"; - private static inline var TAG = "Update"; + public var type(get, null):PackageType; + public var bundle(default, null):PackagesBundle; - public var type(get, null):PackageType; - public var bundle(default, null):PackagesBundle; + private var url:String; + private var version:Version; - private var url:String; - private var version:Version; + public function new(version:String, url:String) { + this.url = url; + this.version = version; + } - public function new(version:String, url:String) { - this.url = url; - this.version = version; + private function get_type():PackageType { + return switch Device.platform { + case ANDROID: APK; + case LINUX: DEB; + case WINDOWS: EXE; + case _: null; } + } - private function get_type():PackageType { - return switch Device.platform { - case ANDROID: APK; - case LINUX: DEB; - case WINDOWS: EXE; - case _: null; + private function resolveBundle():Promise { + return bundle != null ? Promise.promise(bundle) : new JsonLoader().GET(url).then(function(bundle) { + this.bundle = bundle; + return this.bundle; + }); + } + + public function check():Promise { + return resolveBundle().then(function(bundle:PackagesBundle):Bool { + this.bundle = bundle; + return Lambda.exists(bundle.packages, + function(item) return (item.platform == Device.platform && item.type == type + && version < Version.fromString(item.version))); + }); + } + + public function download():Promise { + return resolveBundle().then(function(bundle:PackagesBundle) { + for (item in bundle.packages) { + if (item.platform == Device.platform && item.type == type) { + L.i(TAG, 'download: ${item.url}'); + Lib.getURL(new URLRequest(item.url)); + return true; } - } - - private function resolveBundle():Promise { - return bundle != null ? Promise.promise(bundle) : new JsonLoader().GET(url).then(function(bundle) { - this.bundle = bundle; - return this.bundle; - }); - } - - public function check():Promise { - return resolveBundle().then(function(bundle:PackagesBundle):Bool { - this.bundle = bundle; - return Lambda.exists(bundle.packages, function(item) return ( - item.platform == Device.platform && - item.type == type && - version < Version.fromString(item.version) - )); - }); - } - - public function download():Promise { - return resolveBundle().then(function(bundle:PackagesBundle) { - for (item in bundle.packages) { - if (item.platform == Device.platform && item.type == type) { - L.i(TAG, 'download: ${item.url}'); - Lib.getURL(new URLRequest(item.url)); - return true; - } - } - return false; - }); - } + } + return false; + }); + } } diff --git a/src/client/haxe/ru/m/update/Version.hx b/src/client/haxe/ru/m/update/Version.hx index 49af272..3e9428e 100644 --- a/src/client/haxe/ru/m/update/Version.hx +++ b/src/client/haxe/ru/m/update/Version.hx @@ -1,52 +1,46 @@ package ru.m.update; abstract Version(Array) { + public function new(mayor:Int, minor:Int, patch:Int, snapshot:Bool = false) { + this = [mayor, minor, patch, snapshot ? -1 : 0,]; + } - public function new(mayor:Int, minor:Int, patch:Int, snapshot:Bool = false) { - this = [ - mayor, - minor, - patch, - snapshot ? -1 : 0, - ]; + @:arrayAccess public inline function get(key:Int) + return this[key]; + + public function compare(other:Version):Int { + if (other == null) { + return 1; } - - @:arrayAccess public inline function get(key:Int) return this[key]; - - public function compare(other:Version):Int { - if (other == null) { - return 1; - } - for (i in 0...4) { - var d = this[i] - other[i]; - if (d != 0) { - return d; - } - } - return 0; + for (i in 0...4) { + var d = this[i] - other[i]; + if (d != 0) { + return d; + } } + return 0; + } - @:op(A > B) static function gt(a:Version, b:Version):Bool return a.compare(b) > 0; + @:op(A > B) static function gt(a:Version, b:Version):Bool + return a.compare(b) > 0; - @:op(A == B) static function eq(a:Version, b:Version):Bool return a.compare(b) == 0; + @:op(A == B) static function eq(a:Version, b:Version):Bool + return a.compare(b) == 0; - @:op(A < B) static function lt(a:Version, b:Version):Bool return a.compare(b) < 0; + @:op(A < B) static function lt(a:Version, b:Version):Bool + return a.compare(b) < 0; - @:from public static function fromString(value:String):Version { - var r = ~/(\d+)\.(\d+)\.(\d+)(-SNAPSHOT)?/; - return if (r.match(value)) { - new Version( - Std.parseInt(r.matched(1)), - Std.parseInt(r.matched(2)), - Std.parseInt(r.matched(3)), - r.matched(4) != null - ); - } else { - new Version(0, 0, 0); - } + @:from public static function fromString(value:String):Version { + var r = ~/(\d+)\.(\d+)\.(\d+)(-SNAPSHOT)?/; + return if (r.match(value)) { + new Version(Std.parseInt(r.matched(1)), Std.parseInt(r.matched(2)), Std.parseInt(r.matched(3)), + r.matched(4) != null); + } else { + new Version(0, 0, 0); } + } - @:to public function toString():String { - return '${this[0]}.${this[1]}.${this[2]}${this[3] < 0 ? "-SNAPSHOT" : ""}'; - } + @:to public function toString():String { + return '${this[0]}.${this[1]}.${this[2]}${this[3] < 0 ? "-SNAPSHOT" : ""}'; + } } diff --git a/src/common/haxe/ru/m/Base64.hx b/src/common/haxe/ru/m/Base64.hx index 00d1fe6..f2c2521 100644 --- a/src/common/haxe/ru/m/Base64.hx +++ b/src/common/haxe/ru/m/Base64.hx @@ -4,46 +4,43 @@ import haxe.io.Bytes; import haxe.crypto.BaseCode; class Base64 { - private inline static var BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - private static var codec:BaseCode; + private inline static var BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + private static var codec:BaseCode; - public function new() { + public function new() {} + static function getCodec():BaseCode { + if (codec == null) { + var bytes = Bytes.ofString(BASE64); + codec = new BaseCode(bytes); } + return codec; + } - static function getCodec():BaseCode { - if (codec == null) { - var bytes = Bytes.ofString(BASE64); - codec = new BaseCode(bytes); - } - return codec; - } - - public static function encodeBase64(content:haxe.io.Bytes):String { - var suffix = switch (content.length % 3){ - case 2: "="; - case 1: "=="; - default: ""; - }; - - var bytes = getCodec().encodeBytes(content); - return bytes.toString() + suffix; - } - - private static function removeNullbits(s:String):String { - var len = s.length; - while (len > 0 && s.charAt(len - 1) == "=") { - len--; - if (len <= 0) { - return ""; - } - } - return s.substr(0, len); - } - - public static function decodeBase64(content:String):Bytes { - var bytes:Bytes = Bytes.ofString(removeNullbits(content)); - return getCodec().decodeBytes(bytes); + public static function encodeBase64(content:haxe.io.Bytes):String { + var suffix = switch (content.length % 3) { + case 2: "="; + case 1: "=="; + default: ""; + }; + + var bytes = getCodec().encodeBytes(content); + return bytes.toString() + suffix; + } + + private static function removeNullbits(s:String):String { + var len = s.length; + while (len > 0 && s.charAt(len - 1) == "=") { + len--; + if (len <= 0) { + return ""; + } } + return s.substr(0, len); + } + public static function decodeBase64(content:String):Bytes { + var bytes:Bytes = Bytes.ofString(removeNullbits(content)); + return getCodec().decodeBytes(bytes); + } } diff --git a/src/common/haxe/ru/m/Timer.hx b/src/common/haxe/ru/m/Timer.hx index 7c58c38..01874b0 100644 --- a/src/common/haxe/ru/m/Timer.hx +++ b/src/common/haxe/ru/m/Timer.hx @@ -1,60 +1,55 @@ package ru.m; #if neko - import haxe.Log; import haxe.PosInfos; import neko.vm.Thread; class Timer { + private var sleep:Float; + private var stopped:Bool; - private var sleep:Float; - private var stopped:Bool; + public function new(time_ms:Int) { + this.sleep = time_ms / 1000.0; + this.stopped = false; + Thread.create(function() { + while (!stopped) { + Sys.sleep(sleep); + try { + run(); + } catch (error:Dynamic) { + trace(hw.log.BaseLogger.LoggerUtil.printError(error)); + } + } + }); + } - public function new(time_ms:Int) { - this.sleep = time_ms / 1000.0; - this.stopped = false; - Thread.create(function() { - while (!stopped) { - Sys.sleep(sleep); - try { - run(); - } catch (error:Dynamic) { - trace(hw.log.BaseLogger.LoggerUtil.printError(error)); - } - } - }); - } + public function stop() { + stopped = true; + } - public function stop() { - stopped = true; - } + public dynamic function run() {} - public dynamic function run() {} + public static function delay(f:Void->Void, time_ms:Int) { + var t = new Timer(time_ms); + t.run = function() { + t.stop(); + f(); + }; + return t; + } - public static function delay(f:Void -> Void, time_ms:Int) { - var t = new Timer(time_ms); - t.run = function() { - t.stop(); - f(); - }; - return t; - } + public static function measure(f:Void->T, ?pos:PosInfos):T { + var t0 = stamp(); + var r = f(); + Log.trace((stamp() - t0) + "s", pos); + return r; + } - public static function measure(f:Void -> T, ?pos:PosInfos):T { - var t0 = stamp(); - var r = f(); - Log.trace((stamp() - t0) + "s", pos); - return r; - } - - public static inline function stamp():Float { - return Sys.time(); - } + public static inline function stamp():Float { + return Sys.time(); + } } - #else - typedef Timer = haxe.Timer; - #end diff --git a/src/common/haxe/ru/m/User.hx b/src/common/haxe/ru/m/User.hx index e1df4e4..8179a2b 100644 --- a/src/common/haxe/ru/m/User.hx +++ b/src/common/haxe/ru/m/User.hx @@ -1,6 +1,6 @@ package ru.m; typedef User = { - var uuid:String; - var name:String; + var uuid:String; + var name:String; } diff --git a/src/common/haxe/ru/m/connect/BaseConnection.hx b/src/common/haxe/ru/m/connect/BaseConnection.hx index f0280ba..bf38c69 100755 --- a/src/common/haxe/ru/m/connect/BaseConnection.hx +++ b/src/common/haxe/ru/m/connect/BaseConnection.hx @@ -8,45 +8,45 @@ import protohx.Message; import ru.m.connect.IConnection; class BaseConnection implements IConnection { - public var handler(default, null):Signal; - public var sendHandler(default, null):Signal; - public var receiveHandler(default, null):Signal; - public var connected(default, null):Bool; - public var queue(default, null):PacketQueue; + public var handler(default, null):Signal; + public var sendHandler(default, null):Signal; + public var receiveHandler(default, null):Signal; + public var connected(default, null):Bool; + public var queue(default, null):PacketQueue; - private var connectDeferred:Deferred>; + private var connectDeferred:Deferred>; - public function new(inputFactory:Class) { - queue = new PacketQueue(inputFactory); - handler = new Signal(); - sendHandler = new Signal(); - receiveHandler = new Signal(); + public function new(inputFactory:Class) { + queue = new PacketQueue(inputFactory); + handler = new Signal(); + sendHandler = new Signal(); + receiveHandler = new Signal(); + } + + public function connect():Promise> { + throw "Not implemented"; + } + + public function disconnect():Void { + throw "Not implemented"; + } + + public function pushData(bytes:Bytes):Void { + #if proto_debug L.d('Proto', 'pushData: ${bytes.length}'); #end + queue.addBytes(bytes); + while (queue.hasMsg()) { + var packet:I = queue.popMsg(); + receive(packet); } + } - public function connect():Promise> { - throw "Not implemented"; - } + public function send(packet:O):Void { + #if proto_debug L.d('Proto', 'send: ${packet}'); #end + sendHandler.emit(packet); + } - public function disconnect():Void { - throw "Not implemented"; - } - - public function pushData(bytes:Bytes):Void { - #if proto_debug L.d('Proto', 'pushData: ${bytes.length}'); #end - queue.addBytes(bytes); - while (queue.hasMsg()) { - var packet:I = queue.popMsg(); - receive(packet); - } - } - - public function send(packet:O):Void { - #if proto_debug L.d('Proto', 'send: ${packet}'); #end - sendHandler.emit(packet); - } - - public function receive(packet:I):Void { - #if proto_debug L.d('Proto', 'receive: ${packet}'); #end - receiveHandler.emit(packet); - } + public function receive(packet:I):Void { + #if proto_debug L.d('Proto', 'receive: ${packet}'); #end + receiveHandler.emit(packet); + } } diff --git a/src/common/haxe/ru/m/connect/IConnection.hx b/src/common/haxe/ru/m/connect/IConnection.hx index 8f77ff2..bcd1114 100755 --- a/src/common/haxe/ru/m/connect/IConnection.hx +++ b/src/common/haxe/ru/m/connect/IConnection.hx @@ -6,19 +6,19 @@ import promhx.Promise; import protohx.Message; enum ConnectionEvent { - CONNECTED; - DISCONNECTED; - ERROR(error:Dynamic); + CONNECTED; + DISCONNECTED; + ERROR(error:Dynamic); } interface IConnection { - public var connected(default, null):Bool; - public var handler(default, null):Signal; - public var sendHandler(default, null):Signal; - public var receiveHandler(default, null):Signal; + public var connected(default, null):Bool; + public var handler(default, null):Signal; + public var sendHandler(default, null):Signal; + public var receiveHandler(default, null):Signal; - public function connect():Promise>; - public function disconnect():Void; - public function send(packet:O):Void; - public function pushData(bytes:Bytes):Void; + public function connect():Promise>; + public function disconnect():Void; + public function send(packet:O):Void; + public function pushData(bytes:Bytes):Void; } diff --git a/src/common/haxe/ru/m/connect/PacketQueue.hx b/src/common/haxe/ru/m/connect/PacketQueue.hx index 1dcd130..d102bbf 100755 --- a/src/common/haxe/ru/m/connect/PacketQueue.hx +++ b/src/common/haxe/ru/m/connect/PacketQueue.hx @@ -7,65 +7,64 @@ import haxe.io.BytesInput; import protohx.Message; class PacketQueue { + public var packetClass(default, null):Class

; - public var packetClass(default, null):Class

; + private var buffer:BytesBuffer; + private var msgs:List

; - private var buffer:BytesBuffer; - private var msgs:List

; + public function new(packetClass:Class

) { + this.packetClass = packetClass; + msgs = new List

(); + buffer = new BytesBuffer(); + } - public function new(packetClass:Class

) { - this.packetClass = packetClass; - msgs = new List

(); - buffer = new BytesBuffer(); - } + public inline function hasMsg():Bool { + return !msgs.isEmpty(); + } - public inline function hasMsg():Bool { - return !msgs.isEmpty(); - } + public inline function popMsg():P { + return msgs.pop(); + } - public inline function popMsg():P { - return msgs.pop(); - } + public inline function addMsg(msg:P):Void { + msgs.add(msg); + } - public inline function addMsg(msg:P):Void { - msgs.add(msg); - } - - private function readPackage():Null

{ - var bytes = buffer.getBytes(); - var input = new BytesInput(bytes); - input.bigEndian = false; - if (input.length > 1) { - var packetSize = input.readUInt16(); - if (input.length >= packetSize + 2) { - var packet:P = Type.createInstance(packetClass, []); - try { - packet.mergeFrom(input.read(packetSize)); - buffer = new BytesBuffer(); - buffer.add(input.read(input.length - (packetSize + 2))); - return packet; - } catch (error:Dynamic) { - L.w("PacketQueue", "readPackage ", error); - buffer = new BytesBuffer(); - return null; - } - } + private function readPackage():Null

{ + var bytes = buffer.getBytes(); + var input = new BytesInput(bytes); + input.bigEndian = false; + if (input.length > 1) { + var packetSize = input.readUInt16(); + if (input.length >= packetSize + 2) { + var packet:P = Type.createInstance(packetClass, []); + try { + packet.mergeFrom(input.read(packetSize)); + buffer = new BytesBuffer(); + buffer.add(input.read(input.length - (packetSize + 2))); + return packet; + } catch (error:Dynamic) { + L.w("PacketQueue", "readPackage ", error); + buffer = new BytesBuffer(); + return null; } - buffer = new BytesBuffer(); - buffer.add(bytes); - return null; + } } + buffer = new BytesBuffer(); + buffer.add(bytes); + return null; + } - public function addBytes(bytes:Bytes):Void { - buffer.add(bytes); - var packet = readPackage(); - while (packet != null) { - msgs.add(packet); - packet = readPackage(); - } + public function addBytes(bytes:Bytes):Void { + buffer.add(bytes); + var packet = readPackage(); + while (packet != null) { + msgs.add(packet); + packet = readPackage(); } + } - public function clean():Void { - buffer = new BytesBuffer(); - } + public function clean():Void { + buffer = new BytesBuffer(); + } } diff --git a/src/common/haxe/ru/m/connect/PacketUtil.hx b/src/common/haxe/ru/m/connect/PacketUtil.hx index be47c1c..2070851 100644 --- a/src/common/haxe/ru/m/connect/PacketUtil.hx +++ b/src/common/haxe/ru/m/connect/PacketUtil.hx @@ -5,16 +5,15 @@ import haxe.io.BytesOutput; import protohx.Message; class PacketUtil { + public static function fromBytes(bytes:Bytes, factory:Class

):P { + var packet:P = Type.createInstance(factory, []); + packet.mergeFrom(bytes); + return packet; + } - public static function fromBytes(bytes:Bytes, factory:Class

):P { - var packet:P = Type.createInstance(factory, []); - packet.mergeFrom(bytes); - return packet; - } - - public static function toBytes(packet:P):Bytes { - var out = new BytesOutput(); - packet.writeTo(out); - return out.getBytes(); - } + public static function toBytes(packet:P):Bytes { + var out = new BytesOutput(); + packet.writeTo(out); + return out.getBytes(); + } } diff --git a/src/common/haxe/ru/m/connect/WebSocketTools.hx b/src/common/haxe/ru/m/connect/WebSocketTools.hx index 88c303f..5e02450 100644 --- a/src/common/haxe/ru/m/connect/WebSocketTools.hx +++ b/src/common/haxe/ru/m/connect/WebSocketTools.hx @@ -3,23 +3,21 @@ package ru.m.connect; import haxe.io.BytesOutput; import protohx.Message; - class WebSocketTools { + public static function packet2string(packet:Message):String { + var b = new BytesOutput(); + packet.writeTo(b); + var data = b.getBytes(); + var res = new BytesOutput(); + // res.writeUInt16(data.length); + res.write(data); + return Base64.encodeBase64(res.getBytes()); + } - public static function packet2string(packet:Message):String { - var b = new BytesOutput(); - packet.writeTo(b); - var data = b.getBytes(); - var res = new BytesOutput(); - //res.writeUInt16(data.length); - res.write(data); - return Base64.encodeBase64(res.getBytes()); - } - - public static function string2packet(data:String, packetClass:Class

):P { - var bytes = Base64.decodeBase64(data); - var packet:P = Type.createInstance(packetClass, []); - packet.mergeFrom(bytes); - return packet; - } -} \ No newline at end of file + public static function string2packet(data:String, packetClass:Class

):P { + var bytes = Base64.decodeBase64(data); + var packet:P = Type.createInstance(packetClass, []); + packet.mergeFrom(bytes); + return packet; + } +} diff --git a/src/common/haxe/ru/m/connect/desktop/DesktopConnection.hx b/src/common/haxe/ru/m/connect/desktop/DesktopConnection.hx index b264ebc..829646b 100644 --- a/src/common/haxe/ru/m/connect/desktop/DesktopConnection.hx +++ b/src/common/haxe/ru/m/connect/desktop/DesktopConnection.hx @@ -10,67 +10,66 @@ import sys.net.Host; import sys.net.Socket; class DesktopConnection extends BaseConnection { + private var host:String; + private var port:Int; + private var socket:Socket; + private var reader:Thread; - private var host:String; - private var port:Int; - private var socket:Socket; - private var reader:Thread; + public function new(host:String, port:Int, inputFactory:Class) { + super(inputFactory); + this.host = host; + this.port = port; + connected = false; + socket = new Socket(); + socket.setFastSend(true); + socket.output.bigEndian = false; + socket.input.bigEndian = false; + sendHandler.connect(_send); + } - public function new(host:String, port:Int, inputFactory:Class) { - super(inputFactory); - this.host = host; - this.port = port; - connected = false; - socket = new Socket(); - socket.setFastSend(true); - socket.output.bigEndian = false; - socket.input.bigEndian = false; - sendHandler.connect(_send); + override public function connect():Promise> { + connectDeferred = new Deferred(); + try { + if (connected) { + connectDeferred.resolve(this); + } else { + socket.connect(new Host(host), port); + connected = true; + reader = Thread.create(_read); + connectDeferred.resolve(this); + handler.emit(ConnectionEvent.CONNECTED); + } + } catch (error:Dynamic) { + handler.emit(ConnectionEvent.ERROR(error)); + Timer.delay(function() connectDeferred.throwError(error), 1); } + return connectDeferred.promise(); + } - override public function connect():Promise> { - connectDeferred = new Deferred(); - try { - if (connected) { - connectDeferred.resolve(this); - } else { - socket.connect(new Host(host), port); - connected = true; - reader = Thread.create(_read); - connectDeferred.resolve(this); - handler.emit(ConnectionEvent.CONNECTED); - } - } catch (error:Dynamic) { - handler.emit(ConnectionEvent.ERROR(error)); - Timer.delay(function() connectDeferred.throwError(error), 1); - } - return connectDeferred.promise(); - } + override public function disconnect():Void { + socket.close(); + connected = false; + handler.emit(DISCONNECTED); + } - override public function disconnect():Void { - socket.close(); - connected = false; - handler.emit(DISCONNECTED); + private function _read():Void { + try { + while (connected) { + socket.waitForRead(); + var size = socket.input.readUInt16(); + var data = socket.input.read(size); + var packet:I = PacketUtil.fromBytes(data, queue.packetClass); + receiveHandler.emit(packet); + } + } catch (error:Dynamic) { + handler.emit(ERROR(error)); } + } - private function _read():Void { - try { - while (connected) { - socket.waitForRead(); - var size = socket.input.readUInt16(); - var data = socket.input.read(size); - var packet:I = PacketUtil.fromBytes(data, queue.packetClass); - receiveHandler.emit(packet); - } - } catch (error:Dynamic) { - handler.emit(ERROR(error)); - } - } - - private function _send(packet:O):Void { - var bytes = PacketUtil.toBytes(packet); - socket.output.writeUInt16(bytes.length); - socket.output.write(bytes); - socket.output.flush(); - } + private function _send(packet:O):Void { + var bytes = PacketUtil.toBytes(packet); + socket.output.writeUInt16(bytes.length); + socket.output.write(bytes); + socket.output.flush(); + } } diff --git a/src/common/haxe/ru/m/connect/fake/FakeConnection.hx b/src/common/haxe/ru/m/connect/fake/FakeConnection.hx index bd44fd4..9d22c83 100644 --- a/src/common/haxe/ru/m/connect/fake/FakeConnection.hx +++ b/src/common/haxe/ru/m/connect/fake/FakeConnection.hx @@ -5,14 +5,13 @@ import promhx.Promise; import protohx.Message; class FakeConnection extends BaseConnection { + override public function connect():Promise> { + handler.emit(ConnectionEvent.CONNECTED); + var promise:Promise> = cast Promise.promise(this); + return promise; + } - override public function connect():Promise> { - handler.emit(ConnectionEvent.CONNECTED); - var promise:Promise> = cast Promise.promise(this); - return promise; - } - - override public function disconnect():Void { - handler.emit(ConnectionEvent.DISCONNECTED); - } + override public function disconnect():Void { + handler.emit(ConnectionEvent.DISCONNECTED); + } } diff --git a/src/common/haxe/ru/m/connect/flash/FlashConnection.hx b/src/common/haxe/ru/m/connect/flash/FlashConnection.hx index a798c66..ea6319b 100755 --- a/src/common/haxe/ru/m/connect/flash/FlashConnection.hx +++ b/src/common/haxe/ru/m/connect/flash/FlashConnection.hx @@ -14,76 +14,75 @@ import protohx.Message; import ru.m.connect.IConnection; class FlashConnection extends BaseConnection { + private var host:String; + private var port:Int; + private var socket:Socket; - private var host:String; - private var port:Int; - private var socket:Socket; + public function new(host:String, port:Int, inputFactory:Class) { + super(inputFactory); + this.host = host; + this.port = port; + connected = false; + socket = new Socket(); + socket.addEventListener(IOErrorEvent.IO_ERROR, onError); + socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError); + socket.addEventListener(Event.CLOSE, onClose); + socket.addEventListener(Event.CONNECT, onConnect); + socket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData); + socket.endian = Endian.LITTLE_ENDIAN; + sendHandler.connect(_send); + } - public function new(host:String, port:Int, inputFactory:Class) { - super(inputFactory); - this.host = host; - this.port = port; - connected = false; - socket = new Socket(); - socket.addEventListener(IOErrorEvent.IO_ERROR, onError); - socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError); - socket.addEventListener(Event.CLOSE, onClose); - socket.addEventListener(Event.CONNECT, onConnect); - socket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData); - socket.endian = Endian.LITTLE_ENDIAN; - sendHandler.connect(_send); + override public function connect():Promise> { + socket.connect(host, port); + connectDeferred = new Deferred(); + return connectDeferred.promise(); + } + + override public function disconnect():Void { + if (socket.connected) { + socket.close(); + connected = false; + handler.emit(ConnectionEvent.DISCONNECTED); } + } - override public function connect():Promise> { - socket.connect(host, port); - connectDeferred = new Deferred(); - return connectDeferred.promise(); + private function onError(event:ErrorEvent):Void { + socket.close(); + connected = false; + handler.emit(ConnectionEvent.ERROR(event)); + if (connectDeferred != null) { + connectDeferred.throwError(event); + connectDeferred = null; } + } - override public function disconnect():Void { - if (socket.connected) { - socket.close(); - connected = false; - handler.emit(ConnectionEvent.DISCONNECTED); - } + private function onConnect(_):Void { + connected = true; + handler.emit(ConnectionEvent.CONNECTED); + if (connectDeferred != null) { + connectDeferred.resolve(this); + connectDeferred = null; } + } - private function onError(event:ErrorEvent):Void { - socket.close(); - connected = false; - handler.emit(ConnectionEvent.ERROR(event)); - if (connectDeferred != null) { - connectDeferred.throwError(event); - connectDeferred = null; - } - } + private function onClose(_):Void { + socket.close(); + connected = false; + handler.emit(ConnectionEvent.DISCONNECTED); + } - private function onConnect(_):Void { - connected = true; - handler.emit(ConnectionEvent.CONNECTED); - if (connectDeferred != null) { - connectDeferred.resolve(this); - connectDeferred = null; - } - } + private function onSocketData(_):Void { + var data = new flash.utils.ByteArray(); + socket.readBytes(data); + var bytes = Bytes.ofData(data); + pushData(bytes); + } - private function onClose(_):Void { - socket.close(); - connected = false; - handler.emit(ConnectionEvent.DISCONNECTED); - } - - private function onSocketData(_):Void { - var data = new flash.utils.ByteArray(); - socket.readBytes(data); - var bytes = Bytes.ofData(data); - pushData(bytes); - } - - private function _send(packet:O):Void { - var bytes = PacketUtil.toBytes(packet); - socket.writeShort(bytes.length); - socket.writeBytes(bytes.getData()); - socket.flush(); - } + private function _send(packet:O):Void { + var bytes = PacketUtil.toBytes(packet); + socket.writeShort(bytes.length); + socket.writeBytes(bytes.getData()); + socket.flush(); + } } diff --git a/src/common/haxe/ru/m/connect/js/JsConnection.hx b/src/common/haxe/ru/m/connect/js/JsConnection.hx index 51aad1d..a7a0adc 100644 --- a/src/common/haxe/ru/m/connect/js/JsConnection.hx +++ b/src/common/haxe/ru/m/connect/js/JsConnection.hx @@ -10,82 +10,81 @@ import protohx.Message; import ru.m.connect.IConnection; class JsConnection extends BaseConnection { + private var host:String; + private var port:Int; + private var socket:WebSocket; - private var host:String; - private var port:Int; - private var socket:WebSocket; + public function new(host:String, port:Int, inputFactory:Class) { + super(inputFactory); + this.host = host; + this.port = port; + connected = false; + } - public function new(host:String, port:Int, inputFactory:Class) { - super(inputFactory); - this.host = host; - this.port = port; - connected = false; + public static function isSecured():Bool { + return Browser.location.protocol == "https:"; + } + + private function buildSocket(host:String, port:Int):WebSocket { + var protocol = isSecured() ? "wss:" : "ws:"; + return new WebSocket('$protocol//$host:$port'); + } + + override public function connect():Promise> { + var self = this; + socket = buildSocket(host, port); + socket.binaryType = BinaryType.ARRAYBUFFER; + socket.onopen = this.onConnect; + socket.onclose = this.onClose; + socket.onerror = this.onError; + socket.onmessage = this.onSocketData; + connectDeferred = new Deferred(); + return connectDeferred.promise(); + } + + override public function disconnect():Void { + socket.close(1000); + connected = false; + } + + private function onError(event:Dynamic):Void { + socket.close(1000); + connected = false; + handler.emit(ConnectionEvent.ERROR(event)); + } + + private function onConnect(_):Void { + connected = true; + handler.emit(ConnectionEvent.CONNECTED); + connectDeferred.resolve(this); + } + + private function onClose(_):Void { + socket.close(); + connected = false; + handler.emit(ConnectionEvent.DISCONNECTED); + } + + private function onSocketData(event:Dynamic):Void { + var packet:I = null; + try { + var bytes = Bytes.ofData(event.data); + packet = PacketUtil.fromBytes(bytes, queue.packetClass); + } catch (error:Dynamic) { + handler.emit(ConnectionEvent.ERROR(error)); } - - public static function isSecured():Bool { - return Browser.location.protocol == "https:"; + if (packet != null) { + receive(packet); } + } - private function buildSocket(host:String, port:Int):WebSocket { - var protocol = isSecured() ? "wss:" : "ws:"; - return new WebSocket('$protocol//$host:$port'); - } - - override public function connect():Promise> { - var self = this; - socket = buildSocket(host, port); - socket.binaryType = BinaryType.ARRAYBUFFER; - socket.onopen = this.onConnect; - socket.onclose = this.onClose; - socket.onerror = this.onError; - socket.onmessage = this.onSocketData; - connectDeferred = new Deferred(); - return connectDeferred.promise(); - } - - override public function disconnect():Void { - socket.close(1000); - connected = false; - } - - private function onError(event:Dynamic):Void { - socket.close(1000); - connected = false; - handler.emit(ConnectionEvent.ERROR(event)); - } - - private function onConnect(_):Void { - connected = true; - handler.emit(ConnectionEvent.CONNECTED); - connectDeferred.resolve(this); - } - - private function onClose(_):Void { - socket.close(); - connected = false; - handler.emit(ConnectionEvent.DISCONNECTED); - } - - private function onSocketData(event:Dynamic):Void { - var packet:I = null; - try { - var bytes = Bytes.ofData(event.data); - packet = PacketUtil.fromBytes(bytes, queue.packetClass); - } catch (error:Dynamic) { - handler.emit(ConnectionEvent.ERROR(error)); - } - if (packet != null) { - receive(packet); - } - } - - override public function send(packet:O):Void { - if (connected) { - super.send(packet); - var bytes = PacketUtil.toBytes(packet); - socket.send(bytes.getData()); - } else { - L.w("Connection", "closed"); - } + override public function send(packet:O):Void { + if (connected) { + super.send(packet); + var bytes = PacketUtil.toBytes(packet); + socket.send(bytes.getData()); + } else { + L.w("Connection", "closed"); } + } } diff --git a/src/common/haxe/ru/m/connect/neko/NekoConnection.hx b/src/common/haxe/ru/m/connect/neko/NekoConnection.hx index 24dd0e4..3ddaa01 100755 --- a/src/common/haxe/ru/m/connect/neko/NekoConnection.hx +++ b/src/common/haxe/ru/m/connect/neko/NekoConnection.hx @@ -4,53 +4,52 @@ import protohx.Message; import sys.net.Socket; class NekoConnection extends BaseConnection { + public var socket(default, null):Socket; - public var socket(default, null):Socket; + private var sendQueue:Array; + private var timer:Timer; - private var sendQueue:Array; - private var timer:Timer; + public function new(socket:Socket, i:Class) { + super(i); + this.socket = socket; + socket.setFastSend(true); + socket.output.bigEndian = false; + socket.input.bigEndian = false; + sendHandler.connect(pushPacket); + sendQueue = []; + timer = new Timer(1); + timer.run = sendRun; + } - public function new(socket:Socket, i:Class) { - super(i); - this.socket = socket; - socket.setFastSend(true); - socket.output.bigEndian = false; - socket.input.bigEndian = false; - sendHandler.connect(pushPacket); - sendQueue = []; - timer = new Timer(1); - timer.run = sendRun; + private function sendPacket(packet:O):Void { + try { + var bytes = PacketUtil.toBytes(packet); + socket.output.writeUInt16(bytes.length); + socket.output.write(bytes); + socket.output.flush(); + } catch (error:Dynamic) { + L.e('Proto', 'Error send packet: ${packet}', error); } + } - private function sendPacket(packet:O):Void { - try { - var bytes = PacketUtil.toBytes(packet); - socket.output.writeUInt16(bytes.length); - socket.output.write(bytes); - socket.output.flush(); - } catch (error:Dynamic) { - L.e('Proto', 'Error send packet: ${packet}', error); - } + private function sendRun():Void { + if (sendQueue.length > 0) { + for (packet in sendQueue) { + sendPacket(packet); + } + sendQueue = []; } + } - private function sendRun():Void { - if (sendQueue.length > 0) { - for (packet in sendQueue) { - sendPacket(packet); - } - sendQueue = []; - } - } + private function pushPacket(packet:O):Void { + sendQueue.push(packet); + } - private function pushPacket(packet:O):Void { - sendQueue.push(packet); - } - - override public function disconnect():Void { - if (timer != null) { - timer.stop(); - timer = null; - } - super.disconnect(); + override public function disconnect():Void { + if (timer != null) { + timer.stop(); + timer = null; } + super.disconnect(); + } } diff --git a/src/common/haxe/ru/m/connect/neko/NekoWSConnection.hx b/src/common/haxe/ru/m/connect/neko/NekoWSConnection.hx index 5938bbc..979be49 100644 --- a/src/common/haxe/ru/m/connect/neko/NekoWSConnection.hx +++ b/src/common/haxe/ru/m/connect/neko/NekoWSConnection.hx @@ -8,171 +8,166 @@ import protohx.Message; import sys.net.Socket; class NekoWSConnection extends NekoConnection { + private var opened:Bool; - private var opened:Bool; + public function new(socket:Socket, i:Class) { + super(socket, i); + opened = false; + } - public function new(socket:Socket, i:Class) { - super(socket, i); - opened = false; + override private function sendPacket(packet:O):Void { + var data = PacketUtil.toBytes(packet); + writeData(data, socket); + } + + override public function pushData(bytes:Bytes):Void { + if (!opened) { + var str:String = bytes.getString(0, bytes.length); + if (StringTools.startsWith(str, "GET")) { + var r = ~/Sec-WebSocket-Key:\s*([A-z0-9=+\/]+)/; + r.match(str); + opened = true; + sendServerHandShake(socket, r.matched(1)); + } + } else { + var data = parseData(bytes); + if (data != null) { + var packet:I = PacketUtil.fromBytes(data, queue.packetClass); + receive(packet); + } + } + } + + private function encodeBase64(content:String):String { + var suffix = switch (content.length % 3) { + case 2: "="; + case 1: "=="; + default: ""; + }; + return BaseCode.encode(content, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") + suffix; + } + + private function hex2data(hex:String):String { + var data = ""; + for (i in 0...Std.int(hex.length / 2)) { + data += String.fromCharCode(Std.parseInt("0x" + hex.substr(i * 2, 2))); + } + return data; + } + + private function sendServerHandShake(socket:sys.net.Socket, inpKey:String) { + var outKey = encodeBase64(hex2data(Sha1.encode(StringTools.trim(inpKey) + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))); + + var s = "HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + + "Sec-WebSocket-Accept: " + outKey + "\r\n" + "\r\n"; + + socket.output.writeString(s); + } + + private function writeData(data:Bytes, socket:sys.net.Socket, isServer = true):Void { + socket.output.writeByte(130); + + var len = 0; + if (data.length < 126) + len = data.length; + else if (data.length < 65536) + len = 126; + else + len = 127; + + socket.output.writeByte(len | (!isServer ? 0x80 : 0x00)); + + if (data.length >= 126) { + if (data.length < 65536) { + socket.output.writeByte((data.length >> 8) & 0xFF); + socket.output.writeByte(data.length & 0xFF); + } else { + socket.output.writeByte((data.length >> 24) & 0xFF); + socket.output.writeByte((data.length >> 16) & 0xFF); + socket.output.writeByte((data.length >> 8) & 0xFF); + socket.output.writeByte(data.length & 0xFF); + } } - override private function sendPacket(packet:O):Void { - var data = PacketUtil.toBytes(packet); - writeData(data, socket); + if (isServer) { + socket.output.writeBytes(data, 0, data.length); + } else { + var mask = [Std.random(256), Std.random(256), Std.random(256), Std.random(256)]; + socket.output.writeByte(mask[0]); + socket.output.writeByte(mask[1]); + socket.output.writeByte(mask[2]); + socket.output.writeByte(mask[3]); + var maskedData = new BytesBuffer(); + for (i in 0...data.length) { + maskedData.addByte(data.get(i) ^ mask[i % 4]); + } + socket.output.writeBytes(maskedData.getBytes(), 0, maskedData.length); + } + } + + private function parseData(bytes:Bytes):Bytes { + var p = 0; + var opcode = bytes.get(p++); + + if (opcode == 0x00) { + var data = new BytesBuffer(); + var b:Int; + while ((b = bytes.get(p++)) != 0xFF) { + data.addByte(b); + } + return data.getBytes(); } - override public function pushData(bytes:Bytes):Void { - if (!opened) { - var str:String = bytes.getString(0, bytes.length); - if (StringTools.startsWith(str, "GET")) { - var r = ~/Sec-WebSocket-Key:\s*([A-z0-9=+\/]+)/; - r.match(str); - opened = true; - sendServerHandShake(socket, r.matched(1)); - } - } else { - var data = parseData(bytes); - if (data != null) { - var packet:I = PacketUtil.fromBytes(data, queue.packetClass); - receive(packet); - } + // 130 = binary data + if (opcode == 130) { + var len = bytes.get(p++); + + // mask + if (len & 0x80 != 0) { + len &= 0x7F; + + if (len == 126) { + var b2 = bytes.get(p++); + var b3 = bytes.get(p++); + len = (b2 << 8) + b3; + } else if (len == 127) { + var b2 = bytes.get(p++); + var b3 = bytes.get(p++); + var b4 = bytes.get(p++); + var b5 = bytes.get(p++); + len = (b2 << 24) + (b3 << 16) + (b4 << 8) + b5; } + + // Lib.println("len = " + len); + + // direct array init not work corectly! + var mask = []; + mask.push(bytes.get(p++)); + mask.push(bytes.get(p++)); + mask.push(bytes.get(p++)); + mask.push(bytes.get(p++)); + + // Lib.println("mask = " + mask); + + var data = new BytesBuffer(); + for (i in 0...len) { + data.addByte(bytes.get(p++) ^ mask[i % 4]); + } + + // Lib.println("readed = " + data.toString()); + return data.getBytes(); + } else { + throw "Expected masked data."; + } } - private function encodeBase64(content:String):String { - var suffix = switch (content.length % 3) - { - case 2: "="; - case 1: "=="; - default: ""; - }; - return BaseCode.encode(content, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") + suffix; - } - - private function hex2data(hex:String):String { - var data = ""; - for (i in 0...Std.int(hex.length / 2)) { - data += String.fromCharCode(Std.parseInt("0x" + hex.substr(i * 2, 2))); - } - return data; - } - - private function sendServerHandShake(socket:sys.net.Socket, inpKey:String) { - var outKey = encodeBase64(hex2data(Sha1.encode(StringTools.trim(inpKey) + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))); - - var s = "HTTP/1.1 101 Switching Protocols\r\n" - + "Upgrade: websocket\r\n" - + "Connection: Upgrade\r\n" - + "Sec-WebSocket-Accept: " + outKey + "\r\n" - + "\r\n"; - - socket.output.writeString(s); - } - - private function writeData(data:Bytes, socket:sys.net.Socket, isServer = true):Void { - socket.output.writeByte(130); - - var len = 0; - if (data.length < 126) len = data.length; - else if (data.length < 65536) len = 126; - else len = 127; - - socket.output.writeByte(len | (!isServer ? 0x80 : 0x00)); - - if (data.length >= 126) { - if (data.length < 65536) { - socket.output.writeByte((data.length >> 8) & 0xFF); - socket.output.writeByte(data.length & 0xFF); - } - else { - socket.output.writeByte((data.length >> 24) & 0xFF); - socket.output.writeByte((data.length >> 16) & 0xFF); - socket.output.writeByte((data.length >> 8) & 0xFF); - socket.output.writeByte(data.length & 0xFF); - } - } - - if (isServer) { - socket.output.writeBytes(data, 0, data.length); - } - else { - var mask = [ Std.random(256), Std.random(256), Std.random(256), Std.random(256) ]; - socket.output.writeByte(mask[0]); - socket.output.writeByte(mask[1]); - socket.output.writeByte(mask[2]); - socket.output.writeByte(mask[3]); - var maskedData = new BytesBuffer(); - for (i in 0...data.length) { - maskedData.addByte(data.get(i) ^ mask[i % 4]); - } - socket.output.writeBytes(maskedData.getBytes(), 0, maskedData.length); - } - } - - private function parseData(bytes:Bytes):Bytes { - var p = 0; - var opcode = bytes.get(p++); - - if (opcode == 0x00) { - var data = new BytesBuffer(); - var b:Int; - while ((b = bytes.get(p++)) != 0xFF) { - data.addByte(b); - } - return data.getBytes(); - } - - // 130 = binary data - if (opcode == 130) { - var len = bytes.get(p++); - - // mask - if (len & 0x80 != 0) { - len &= 0x7F; - - if (len == 126) { - var b2 = bytes.get(p++); - var b3 = bytes.get(p++); - len = (b2 << 8) + b3; - } - else if (len == 127) { - var b2 = bytes.get(p++); - var b3 = bytes.get(p++); - var b4 = bytes.get(p++); - var b5 = bytes.get(p++); - len = (b2 << 24) + (b3 << 16) + (b4 << 8) + b5; - } - - //Lib.println("len = " + len); - - // direct array init not work corectly! - var mask = []; - mask.push(bytes.get(p++)); - mask.push(bytes.get(p++)); - mask.push(bytes.get(p++)); - mask.push(bytes.get(p++)); - - //Lib.println("mask = " + mask); - - var data = new BytesBuffer(); - for (i in 0...len) { - data.addByte(bytes.get(p++) ^ mask[i % 4]); - } - - //Lib.println("readed = " + data.toString()); - return data.getBytes(); - } else { - throw "Expected masked data."; - } - } - - if (opcode == 136) { - //socket.close(); - opened = false; - return null; - } else { - throw "Unsupported websocket opcode: " + opcode; - } - return null; + if (opcode == 136) { + // socket.close(); + opened = false; + return null; + } else { + throw "Unsupported websocket opcode: " + opcode; } + return null; + } } diff --git a/src/common/haxe/ru/m/geom/Circle.hx b/src/common/haxe/ru/m/geom/Circle.hx index a1d640e..a6e68ca 100644 --- a/src/common/haxe/ru/m/geom/Circle.hx +++ b/src/common/haxe/ru/m/geom/Circle.hx @@ -1,41 +1,39 @@ package ru.m.geom; abstract Circle(Array) { - public var x(get, set):Float; - public var y(get, set):Float; - public var radius(get, set):Float; + public var x(get, set):Float; + public var y(get, set):Float; + public var radius(get, set):Float; - public function new(x:Float = 0, y:Float = 0, radius:Float = 0) { - this = [ - x, y, radius, - ]; - } + public function new(x:Float = 0, y:Float = 0, radius:Float = 0) { + this = [x, y, radius,]; + } - private inline function get_x():Float { - return this[0]; - } + private inline function get_x():Float { + return this[0]; + } - private inline function set_x(value:Float):Float { - return this[0] = value; - } + private inline function set_x(value:Float):Float { + return this[0] = value; + } - private inline function get_y():Float { - return this[1]; - } + private inline function get_y():Float { + return this[1]; + } - private inline function set_y(value:Float):Float { - return this[1] = value; - } + private inline function set_y(value:Float):Float { + return this[1] = value; + } - private inline function get_radius():Float { - return this[2]; - } + private inline function get_radius():Float { + return this[2]; + } - private inline function set_radius(value:Float):Float { - return this[2] = value; - } + private inline function set_radius(value:Float):Float { + return this[2] = value; + } - public function contain(point:Point):Bool { - return Math.sqrt(Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2)) < radius; - } + public function contain(point:Point):Bool { + return Math.sqrt(Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2)) < radius; + } } diff --git a/src/common/haxe/ru/m/geom/Direction.hx b/src/common/haxe/ru/m/geom/Direction.hx index 4f88a77..7de7cbb 100644 --- a/src/common/haxe/ru/m/geom/Direction.hx +++ b/src/common/haxe/ru/m/geom/Direction.hx @@ -1,72 +1,74 @@ package ru.m.geom; abstract Direction(Array) { - private static var directions:Map = new Map(); + private static var directions:Map = new Map(); - public static var LEFT(default, never) = Direction.from(-1, 0); - public static var TOP(default, never) = Direction.from(0, -1); - public static var RIGHT(default, never) = Direction.from(1, 0); - public static var BOTTOM(default, never) = Direction.from(0, 1); + public static var LEFT(default, never) = Direction.from(-1, 0); + public static var TOP(default, never) = Direction.from(0, -1); + public static var RIGHT(default, never) = Direction.from(1, 0); + public static var BOTTOM(default, never) = Direction.from(0, 1); - public var x(get, never):Int; - public var y(get, never):Int; - public var angle(get, never):Int; + public var x(get, never):Int; + public var y(get, never):Int; + public var angle(get, never):Int; - inline public function new(value:Array) { - this = value; + inline public function new(value:Array) { + this = value; + } + + inline private function get_x():Int + return this[0]; + + inline private function get_y():Int + return this[1]; + + inline private function get_angle():Int { + return switch this { + case [-1, 0]: 180; + case [0, -1]: 270; + case [1, 0]: 0; + case [0, 1]: 90; + case _: 0; } + } - inline private function get_x():Int return this[0]; + public function equals(other:Direction):Bool { + return other.x == x && other.y == y; + } - inline private function get_y():Int return this[1]; + public function reverse():Direction { + return from(-x, -y); + } - inline private function get_angle():Int { - return switch this { - case [-1, 0]: 180; - case [0, -1]: 270; - case [1, 0]: 0; - case [0, 1]: 90; - case _: 0; - } + @:from inline static public function fromArray(value:Array):Direction { + return new Direction(value); + } + + @:from inline static public function fromString(value:String):Direction { + return switch value.toUpperCase() { + case "LEFT": LEFT; + case "TOP": TOP; + case "RIGHT": RIGHT; + case "BOTTOM": BOTTOM; + case _: null; } + } - public function equals(other:Direction):Bool { - return other.x == x && other.y == y; - } + @:to inline public function toString():String { + return (switch this { + case [-1, 0]: "LEFT"; + case [0, -1]: "TOP"; + case [1, 0]: "RIGHT"; + case [0, 1]: "BOTTOM"; + case _: null; + }); + } - public function reverse():Direction { - return from(-x, -y); - } - - @:from inline static public function fromArray(value:Array):Direction { - return new Direction(value); - } - - @:from inline static public function fromString(value:String):Direction { - return switch value.toUpperCase() { - case "LEFT": LEFT; - case "TOP": TOP; - case "RIGHT": RIGHT; - case "BOTTOM": BOTTOM; - case _: null; - } - } - - @:to inline public function toString():String { - return (switch this { - case [-1, 0]: "LEFT"; - case [0, -1]: "TOP"; - case [1, 0]: "RIGHT"; - case [0, 1]: "BOTTOM"; - case _: null; - }); - } - - inline static public function from(x:Int, y:Int):Direction { - var key = x + y * 10; - if (!directions.exists(key)) { - directions.set(key, new Direction([x, y])); - } - return directions.get(key); + inline static public function from(x:Int, y:Int):Direction { + var key = x + y * 10; + if (!directions.exists(key)) { + directions.set(key, new Direction([x, y])); } + return directions.get(key); + } } diff --git a/src/common/haxe/ru/m/geom/GridPoint.hx b/src/common/haxe/ru/m/geom/GridPoint.hx index 2929992..5a3e678 100644 --- a/src/common/haxe/ru/m/geom/GridPoint.hx +++ b/src/common/haxe/ru/m/geom/GridPoint.hx @@ -1,27 +1,34 @@ package ru.m.geom; abstract GridPoint({x:Int, y:Int}) { - public var x(get, set):Int; - public var y(get, set):Int; + public var x(get, set):Int; + public var y(get, set):Int; - public function new(x:Int, y:Int) { - this = {x: x, y: y}; - } + public function new(x:Int, y:Int) { + this = {x: x, y: y}; + } - private inline function get_x():Int return this.x; - private inline function get_y():Int return this.y; - private inline function set_x(value:Int):Int return this.x = value; - private inline function set_y(value:Int):Int return this.y = value; + private inline function get_x():Int + return this.x; - @:to inline public function toInt():Int { - return (this.x << 16) + this.y; - } + private inline function get_y():Int + return this.y; - @:to inline public function toPoint():Point { - return new Point(this.x, this.y); - } + private inline function set_x(value:Int):Int + return this.x = value; - public function toString():String { - return '${this.x}:${this.y}'; - } + private inline function set_y(value:Int):Int + return this.y = value; + + @:to inline public function toInt():Int { + return (this.x << 16) + this.y; + } + + @:to inline public function toPoint():Point { + return new Point(this.x, this.y); + } + + public function toString():String { + return '${this.x}:${this.y}'; + } } diff --git a/src/common/haxe/ru/m/geom/Line.hx b/src/common/haxe/ru/m/geom/Line.hx index 9dfd943..93ff4e3 100644 --- a/src/common/haxe/ru/m/geom/Line.hx +++ b/src/common/haxe/ru/m/geom/Line.hx @@ -1,40 +1,34 @@ package ru.m.geom; class Line { + public var point1(default, null):Point; + public var point2(default, null):Point; + public var center(get, null):Point; - public var point1(default, null):Point; - public var point2(default, null):Point; - public var center(get, null):Point; + public function new(point1:Point, point2:Point) { + this.point1 = point1; + this.point2 = point2; + } - public function new(point1:Point, point2:Point) { - this.point1 = point1; - this.point2 = point2; - } + private function get_center():Point { + return new Point(point1.x + (point2.x - point1.x) / 2, point1.y + (point2.y - point1.y) / 2); + } - private function get_center():Point { - return new Point( - point1.x + (point2.x - point1.x) / 2, - point1.y + (point2.y - point1.y) / 2 - ); - } + public function move(point:Point):Line { + return new Line(point1.add(point), point2.add(point)); + } - public function move(point:Point):Line { - return new Line(point1.add(point), point2.add(point)); - } + public function setLength(value:Float):Line { + var center = this.center; + var width = point2.x - point1.x; + var height = point2.y - point1.y; + var kW = width > 0 ? (width + height) / width : 0; + var kH = height > 0 ? (width + height) / height : 0; + return new Line(center.add(new Point(-kW * value / 2, -kH * value / 2)), + center.add(new Point(kW * value / 2, kH * value / 2))); + } - public function setLength(value:Float):Line { - var center = this.center; - var width = point2.x - point1.x; - var height = point2.y - point1.y; - var kW = width > 0 ? (width + height) / width : 0; - var kH = height > 0 ? (width + height) / height : 0; - return new Line( - center.add(new Point(-kW * value / 2, -kH * value / 2)), - center.add(new Point(kW * value / 2, kH * value / 2)) - ); - } - - public function toString():String { - return 'Line{point1=$point1,point2=$point2}'; - } + public function toString():String { + return 'Line{point1=$point1,point2=$point2}'; + } } diff --git a/src/common/haxe/ru/m/geom/Point.hx b/src/common/haxe/ru/m/geom/Point.hx index 862fd0f..31f46bb 100644 --- a/src/common/haxe/ru/m/geom/Point.hx +++ b/src/common/haxe/ru/m/geom/Point.hx @@ -1,23 +1,30 @@ package ru.m.geom; abstract Point(Array) { - public var x(get, set):Float; - public var y(get, set):Float; + public var x(get, set):Float; + public var y(get, set):Float; - public function new(x:Float, y:Float) { - this = [x, y]; - } + public function new(x:Float, y:Float) { + this = [x, y]; + } - private inline function get_x():Float return this[0]; - private inline function get_y():Float return this[1]; - private inline function set_x(value:Float):Float return this[0] = value; - private inline function set_y(value:Float):Float return this[1] = value; + private inline function get_x():Float + return this[0]; - public function add(point:Point):Point { - return new Point(x + point.x, y + point.y); - } + private inline function get_y():Float + return this[1]; - public function clone():Point { - return new Point(x, y); - } + private inline function set_x(value:Float):Float + return this[0] = value; + + private inline function set_y(value:Float):Float + return this[1] = value; + + public function add(point:Point):Point { + return new Point(x + point.x, y + point.y); + } + + public function clone():Point { + return new Point(x, y); + } } diff --git a/src/common/haxe/ru/m/geom/Position.hx b/src/common/haxe/ru/m/geom/Position.hx index 3b64cd2..612a7f8 100644 --- a/src/common/haxe/ru/m/geom/Position.hx +++ b/src/common/haxe/ru/m/geom/Position.hx @@ -1,7 +1,7 @@ package ru.m.geom; typedef Position = { - var x:Float; - var y:Float; - @:optional var direction:Direction; + var x:Float; + var y:Float; + @:optional var direction:Direction; } diff --git a/src/common/haxe/ru/m/geom/Rectangle.hx b/src/common/haxe/ru/m/geom/Rectangle.hx index 66fe0f8..ac9bba1 100644 --- a/src/common/haxe/ru/m/geom/Rectangle.hx +++ b/src/common/haxe/ru/m/geom/Rectangle.hx @@ -1,165 +1,153 @@ package ru.m.geom; abstract Rectangle(Array) { - public var x(get, set):Float; - public var y(get, set):Float; - public var width(get, set):Float; - public var height(get, set):Float; - public var center(get, set):Point; - public var direction(get, set):Direction; - public var left(get, never):Float; - public var right(get, never):Float; - public var top(get, never):Float; - public var bottom(get, never):Float; - public var position(get, set):Position; + public var x(get, set):Float; + public var y(get, set):Float; + public var width(get, set):Float; + public var height(get, set):Float; + public var center(get, set):Point; + public var direction(get, set):Direction; + public var left(get, never):Float; + public var right(get, never):Float; + public var top(get, never):Float; + public var bottom(get, never):Float; + public var position(get, set):Position; - public function new(x:Float = 0, y:Float = 0, width:Float = 0, height:Float = 0, direction:Direction = null) { - if (direction == null) { - direction = Direction.RIGHT; - } - this = [ - x, y, width, height, - direction.x, direction.y, - ]; + public function new(x:Float = 0, y:Float = 0, width:Float = 0, height:Float = 0, direction:Direction = null) { + if (direction == null) { + direction = Direction.RIGHT; } + this = [x, y, width, height, direction.x, direction.y,]; + } - private inline function get_x():Float { - return this[0]; - } + private inline function get_x():Float { + return this[0]; + } - private inline function set_x(value:Float):Float { - return this[0] = value; - } + private inline function set_x(value:Float):Float { + return this[0] = value; + } - private inline function get_y():Float { - return this[1]; - } + private inline function get_y():Float { + return this[1]; + } - private inline function set_y(value:Float):Float { - return this[1] = value; - } + private inline function set_y(value:Float):Float { + return this[1] = value; + } - private inline function get_width():Float { - return this[2]; - } + private inline function get_width():Float { + return this[2]; + } - private inline function set_width(value:Float):Float { - return this[2] = value; - } + private inline function set_width(value:Float):Float { + return this[2] = value; + } - private inline function get_height():Float { - return this[3]; - } + private inline function get_height():Float { + return this[3]; + } - private inline function set_height(value:Float):Float { - return this[3] = value; - } + private inline function set_height(value:Float):Float { + return this[3] = value; + } - private function get_center():Point { - return new Point(x + width / 2, y + height / 2); - } + private function get_center():Point { + return new Point(x + width / 2, y + height / 2); + } - private function set_center(value:Point):Point { - x = value.x - width / 2; - y = value.y - height / 2; - return value; - } + private function set_center(value:Point):Point { + x = value.x - width / 2; + y = value.y - height / 2; + return value; + } - public function getSide(direction:Direction):Line { - if (direction.x != 0) { - var x = x + (direction.x * -1 + 1) / 2 * width; - return new Line( - new Point(x, y), - new Point(x, y + height) - ); - } else if (direction.y != 0) { - var y = y + (direction.y * -1 + 1) / 2 * height; - return new Line( - new Point(x, y), - new Point(x + width, y) - ); - } else { - return null; - } + public function getSide(direction:Direction):Line { + if (direction.x != 0) { + var x = x + (direction.x * -1 + 1) / 2 * width; + return new Line(new Point(x, y), new Point(x, y + height)); + } else if (direction.y != 0) { + var y = y + (direction.y * -1 + 1) / 2 * height; + return new Line(new Point(x, y), new Point(x + width, y)); + } else { + return null; } + } - private function get_direction():Direction { - return [Std.int(this[4]), Std.int(this[5])]; - } + private function get_direction():Direction { + return [Std.int(this[4]), Std.int(this[5])]; + } - public function set_direction(value:Direction):Direction { - if (direction != value) { - if (direction != null && direction.x * value.x == 0 && direction.y * value.y == 0) { - var w = width; - var h = height; - width = h; - height = w; - } - this[4] = value.x; - this[5] = value.y; - } - return direction; + public function set_direction(value:Direction):Direction { + if (direction != value) { + if (direction != null && direction.x * value.x == 0 && direction.y * value.y == 0) { + var w = width; + var h = height; + width = h; + height = w; + } + this[4] = value.x; + this[5] = value.y; } + return direction; + } - public function contain(point:Point):Bool { - return point.x >= left && point.y >= top && point.x <= right && point.y <= bottom; - } + public function contain(point:Point):Bool { + return point.x >= left && point.y >= top && point.x <= right && point.y <= bottom; + } - public function intersection(rect:Rectangle):Bool { - return !(rect.left > right || - rect.right < left || - rect.top > bottom || - rect.bottom < top); - } + public function intersection(rect:Rectangle):Bool { + return !(rect.left > right || rect.right < left || rect.top > bottom || rect.bottom < top); + } - public function intersection2(line:Line):Bool { - // ToDo: line to rect? - return contain(line.point1) || contain(line.point2) || contain(line.center); - } + public function intersection2(line:Line):Bool { + // ToDo: line to rect? + return contain(line.point1) || contain(line.point2) || contain(line.center); + } - public function lean(rect:Rectangle):Void { - var side = rect.getSide(direction); - if (direction.x != 0) { - x = side.point1.x - width * (direction.x + 1) / 2 - direction.x; - } else if (direction.y != 0) { - y = side.point1.y - height * (direction.y + 1) / 2 - direction.y; - } + public function lean(rect:Rectangle):Void { + var side = rect.getSide(direction); + if (direction.x != 0) { + x = side.point1.x - width * (direction.x + 1) / 2 - direction.x; + } else if (direction.y != 0) { + y = side.point1.y - height * (direction.y + 1) / 2 - direction.y; } + } - public function clone():Rectangle { - var rect = new Rectangle(x, y, width, height); - rect.direction = direction; - return rect; - } + public function clone():Rectangle { + var rect = new Rectangle(x, y, width, height); + rect.direction = direction; + return rect; + } - public function toString():String { - return 'Rectangle{x=$x,y=$y,width=$width,height=$height}'; - } + public function toString():String { + return 'Rectangle{x=$x,y=$y,width=$width,height=$height}'; + } - private function get_left():Float { - return x; - } + private function get_left():Float { + return x; + } - private function get_right():Float { - return x + width; - } + private function get_right():Float { + return x + width; + } - private function get_top():Float { - return y; - } + private function get_top():Float { + return y; + } - private function get_bottom():Float { - return y + height; - } + private function get_bottom():Float { + return y + height; + } - private function get_position():Position { - return {x:x, y:y, direction:direction}; - } + private function get_position():Position { + return {x: x, y: y, direction: direction}; + } - private function set_position(position:Position):Position { - x = position.x; - y = position.y; - direction = position.direction; - return position; - } + private function set_position(position:Position):Position { + x = position.x; + y = position.y; + direction = position.direction; + return position; + } } diff --git a/src/common/haxe/ru/m/tankz/Type.hx b/src/common/haxe/ru/m/tankz/Type.hx index 8146605..106edee 100644 --- a/src/common/haxe/ru/m/tankz/Type.hx +++ b/src/common/haxe/ru/m/tankz/Type.hx @@ -3,104 +3,103 @@ package ru.m.tankz; import hw.color.Color; typedef GameType = String; - typedef TeamId = String; - typedef BrickType = String; - typedef BrickIndex = Int; - typedef TankType = String; - typedef BonusType = String; typedef TankInfo = { - var type:TankType; - var skin:String; - var hits:Int; - var bonus:Bool; - var boat:Bool; - var color:Color; - @:optional var name:String; + var type:TankType; + var skin:String; + var hits:Int; + var bonus:Bool; + var boat:Bool; + var color:Color; + @:optional var name:String; } abstract PlayerId(Array) { - public var team(get, never):TeamId; - public var index(get, never):Int; + public var team(get, never):TeamId; + public var index(get, never):Int; - public function new(team:TeamId, index:Int) { - this = [team, index]; + public function new(team:TeamId, index:Int) { + this = [team, index]; + } + + private inline function get_team():TeamId + return this[0]; + + private inline function get_index():Int + return this[1]; + + public function compare(other:PlayerId):Int { + if (other == null) { + return 1; } - - private inline function get_team():TeamId return this[0]; - - private inline function get_index():Int return this[1]; - - public function compare(other:PlayerId):Int { - if (other == null) { - return 1; - } - if (other.team != team) { - return team > other.team ? 1 : -1; - } - return index - other.index; + if (other.team != team) { + return team > other.team ? 1 : -1; } + return index - other.index; + } - public function format():String { - return index > -1 ? '${team} #${index}' : team; - } + public function format():String { + return index > -1 ? '${team} #${index}' : team; + } - @:from static public inline function fromArray(value:Array):PlayerId { - return new PlayerId(value[0], value[1]); - } + @:from static public inline function fromArray(value:Array):PlayerId { + return new PlayerId(value[0], value[1]); + } - @:to public inline function toString():String { - return '${team}:${index}'; - } + @:to public inline function toString():String { + return '${team}:${index}'; + } - @:op(X == Y) static public inline function equals(x:PlayerId, y:PlayerId):Bool { - return x.team == y.team && x.index == y.index; - } + @:op(X == Y) static public inline function equals(x:PlayerId, y:PlayerId):Bool { + return x.team == y.team && x.index == y.index; + } } abstract PackId({type:GameType, name:String}) { - public static inline var DEFAULT = "standard"; + public static inline var DEFAULT = "standard"; - public var type(get, never):GameType; - public var name(get, never):String; + public var type(get, never):GameType; + public var name(get, never):String; - public function new(type:GameType, name:String = DEFAULT) { - this = {type: type, name: name}; - } + public function new(type:GameType, name:String = DEFAULT) { + this = {type: type, name: name}; + } - private inline function get_type():GameType return this.type; + private inline function get_type():GameType + return this.type; - private inline function get_name():String return this.name; + private inline function get_name():String + return this.name; - @:from static public inline function fromArray(value:Array):PackId { - return new PackId(value[0], value[1]); - } + @:from static public inline function fromArray(value:Array):PackId { + return new PackId(value[0], value[1]); + } - @:from static public function fromString(value:String):PackId { - return fromArray(value.split("_")); - } + @:from static public function fromString(value:String):PackId { + return fromArray(value.split("_")); + } - @:to public inline function toString():String { - return '${type}_${name}'; - } + @:to public inline function toString():String { + return '${type}_${name}'; + } - @:op(X == Y) static public inline function equals(x:PackId, y:PackId):Bool { - return x.type == y.type && x.name == y.name; - } + @:op(X == Y) static public inline function equals(x:PackId, y:PackId):Bool { + return x.type == y.type && x.name == y.name; + } } typedef LevelId = Int; - typedef PresetId = Int; abstract Score(Int) from Int to Int { + public function new(value:Int) + this = value; - public function new(value:Int) this = value; - - public inline function format():String return '${this}$'; + public inline function format():String + return '${this}$'; } diff --git a/src/common/haxe/ru/m/tankz/bonus/ArmorEagleBonus.hx b/src/common/haxe/ru/m/tankz/bonus/ArmorEagleBonus.hx index 3c767e1..3177281 100644 --- a/src/common/haxe/ru/m/tankz/bonus/ArmorEagleBonus.hx +++ b/src/common/haxe/ru/m/tankz/bonus/ArmorEagleBonus.hx @@ -11,53 +11,47 @@ import ru.m.tankz.Type; using ru.m.tankz.game.GameUtil; class ArmorEagleBonus extends BaseBonus { + public static inline var CLASS = "armor.eagle"; - public static inline var CLASS = "armor.eagle"; + private static var brickMap(default, never) = [[1, 1, 1, 1], [1, 0, 0, 1], [1, 0, 0, 1], [1, 1, 1, 1],]; - private static var brickMap(default, never) = [ - [1, 1, 1, 1], - [1, 0, 0, 1], - [1, 0, 0, 1], - [1, 1, 1, 1], - ]; - - override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { - for (team in game.teams) { - if (team.eagleId > 0) { - var brickType = team.id == playerId.team ? "armor" : "none"; - applyEagleArmor(team.eagleId, brickType, config.duration, game, engine); - } - } + override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { + for (team in game.teams) { + if (team.eagleId > 0) { + var brickType = team.id == playerId.team ? "armor" : "none"; + applyEagleArmor(team.eagleId, brickType, config.duration, game, engine); + } } + } - private function getEagleBricksIds(eagle:Eagle, map:LevelMap):Array { - var result:Array = []; - var center = eagle.rect.center; - var cx:Int = Math.round(center.x / map.cellWidth - brickMap.length / 2); - var cy:Int = Math.round(center.y / map.cellHeight - brickMap[0].length / 2); - for (x in 0...brickMap.length) { - for (y in 0...brickMap[0].length) { - if (brickMap[x][y] > 0) { - var brick = map.getBrick(new Point(cx + x, cy + y)); - if (brick != null) { - result.push(brick.id); - } - } - } + private function getEagleBricksIds(eagle:Eagle, map:LevelMap):Array { + var result:Array = []; + var center = eagle.rect.center; + var cx:Int = Math.round(center.x / map.cellWidth - brickMap.length / 2); + var cy:Int = Math.round(center.y / map.cellHeight - brickMap[0].length / 2); + for (x in 0...brickMap.length) { + for (y in 0...brickMap[0].length) { + if (brickMap[x][y] > 0) { + var brick = map.getBrick(new Point(cx + x, cy + y)); + if (brick != null) { + result.push(brick.id); + } } - return result; + } } + return result; + } - private function applyEagleArmor(eagleId:Int, brickType:BrickType, duration:Int, game:IGame, engine:IEngine):Void { - var eagle:Eagle = engine.getEntity(eagleId); - var bricks:Array = getEagleBricksIds(eagle, engine.map); - for (brickId in bricks) { - game.gameEventSignal.emit(CHANGE(BRICK(brickId, brickType))); - } - game.ticker.emit(function() { - for (brickId in bricks) { - game.gameEventSignal.emit(CHANGE(BRICK(brickId, "brick"))); - } - }, Std.int(duration * 1000), '$CLASS.${eagle.id}'); + private function applyEagleArmor(eagleId:Int, brickType:BrickType, duration:Int, game:IGame, engine:IEngine):Void { + var eagle:Eagle = engine.getEntity(eagleId); + var bricks:Array = getEagleBricksIds(eagle, engine.map); + for (brickId in bricks) { + game.gameEventSignal.emit(CHANGE(BRICK(brickId, brickType))); } + game.ticker.emit(function() { + for (brickId in bricks) { + game.gameEventSignal.emit(CHANGE(BRICK(brickId, "brick"))); + } + }, Std.int(duration * 1000), '$CLASS.${eagle.id}'); + } } diff --git a/src/common/haxe/ru/m/tankz/bonus/BaseBonus.hx b/src/common/haxe/ru/m/tankz/bonus/BaseBonus.hx index b4a8526..539ce8f 100644 --- a/src/common/haxe/ru/m/tankz/bonus/BaseBonus.hx +++ b/src/common/haxe/ru/m/tankz/bonus/BaseBonus.hx @@ -6,19 +6,19 @@ import ru.m.tankz.game.IGame; import ru.m.tankz.Type; class BaseBonus implements IBonus { - public var type(get, null):BonusType; + public var type(get, null):BonusType; - private var config:BonusConfig; + private var config:BonusConfig; - public function new(config:BonusConfig) { - this.config = config; - } + public function new(config:BonusConfig) { + this.config = config; + } - private inline function get_type():BonusType { - return config != null ? config.type : ""; - } + private inline function get_type():BonusType { + return config != null ? config.type : ""; + } - public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { - throw "Not Implemented"; - } + public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { + throw "Not Implemented"; + } } diff --git a/src/common/haxe/ru/m/tankz/bonus/BoatBonus.hx b/src/common/haxe/ru/m/tankz/bonus/BoatBonus.hx index 4118761..24bb640 100644 --- a/src/common/haxe/ru/m/tankz/bonus/BoatBonus.hx +++ b/src/common/haxe/ru/m/tankz/bonus/BoatBonus.hx @@ -8,12 +8,11 @@ import ru.m.tankz.Type; using ru.m.tankz.game.GameUtil; class BoatBonus extends BaseBonus { + public static inline var CLASS = "boat"; - public static inline var CLASS = "boat"; - - override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { - var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId); - tank.boat = true; - game.emitTankChange(tank); - } + override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { + var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId); + tank.boat = true; + game.emitTankChange(tank); + } } diff --git a/src/common/haxe/ru/m/tankz/bonus/BonusFactory.hx b/src/common/haxe/ru/m/tankz/bonus/BonusFactory.hx index fcadfee..694c62d 100644 --- a/src/common/haxe/ru/m/tankz/bonus/BonusFactory.hx +++ b/src/common/haxe/ru/m/tankz/bonus/BonusFactory.hx @@ -3,25 +3,24 @@ package ru.m.tankz.bonus; import ru.m.tankz.config.Config.BonusConfig; class BonusFactory { + private var classes:Map>; - private var classes:Map>; + public function new() { + classes = [ + DestroyTeamBonus.CLASS => DestroyTeamBonus, + FreezeTeamBonus.CLASS => FreezeTeamBonus, + LifeBonus.CLASS => LifeBonus, + ArmorEagleBonus.CLASS => ArmorEagleBonus, + ProtectEagleBonus.CLASS => ProtectEagleBonus, + ProtectTankBonus.CLASS => ProtectTankBonus, + UpgradeTankBonus.CLASS => UpgradeTankBonus, + SuicideTankBonus.CLASS => SuicideTankBonus, + BoatBonus.CLASS => BoatBonus, + ]; + } - public function new() { - classes = [ - DestroyTeamBonus.CLASS => DestroyTeamBonus, - FreezeTeamBonus.CLASS => FreezeTeamBonus, - LifeBonus.CLASS => LifeBonus, - ArmorEagleBonus.CLASS => ArmorEagleBonus, - ProtectEagleBonus.CLASS => ProtectEagleBonus, - ProtectTankBonus.CLASS => ProtectTankBonus, - UpgradeTankBonus.CLASS => UpgradeTankBonus, - SuicideTankBonus.CLASS => SuicideTankBonus, - BoatBonus.CLASS => BoatBonus, - ]; - } - - public function build(config:BonusConfig):IBonus { - var bonusClass = classes.exists(config.factory) ? classes[config.factory] : classes[SuicideTankBonus.CLASS]; - return Type.createInstance(bonusClass, [config]); - } + public function build(config:BonusConfig):IBonus { + var bonusClass = classes.exists(config.factory) ? classes[config.factory] : classes[SuicideTankBonus.CLASS]; + return Type.createInstance(bonusClass, [config]); + } } diff --git a/src/common/haxe/ru/m/tankz/bonus/DestroyTeamBonus.hx b/src/common/haxe/ru/m/tankz/bonus/DestroyTeamBonus.hx index 215bbdd..a4c956d 100644 --- a/src/common/haxe/ru/m/tankz/bonus/DestroyTeamBonus.hx +++ b/src/common/haxe/ru/m/tankz/bonus/DestroyTeamBonus.hx @@ -9,15 +9,14 @@ import ru.m.tankz.Type; using ru.m.tankz.game.GameUtil; class DestroyTeamBonus extends BaseBonus { + public static inline var CLASS = "destroy.team"; - public static inline var CLASS = "destroy.team"; - - override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { - var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId); - if (tank != null) { - for (t in engine.getTanks(tank.playerId.team.alienTank())) { - game.gameEventSignal.emit(DESTROY(TANK(t.id, {tankId: tank.id}))); - } - } + override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { + var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId); + if (tank != null) { + for (t in engine.getTanks(tank.playerId.team.alienTank())) { + game.gameEventSignal.emit(DESTROY(TANK(t.id, {tankId: tank.id}))); + } } + } } diff --git a/src/common/haxe/ru/m/tankz/bonus/FreezeTeamBonus.hx b/src/common/haxe/ru/m/tankz/bonus/FreezeTeamBonus.hx index a37388e..f6c7668 100644 --- a/src/common/haxe/ru/m/tankz/bonus/FreezeTeamBonus.hx +++ b/src/common/haxe/ru/m/tankz/bonus/FreezeTeamBonus.hx @@ -7,14 +7,13 @@ import ru.m.tankz.Type; using ru.m.tankz.game.GameUtil; class FreezeTeamBonus extends BaseBonus { + public static inline var CLASS = "freeze.team"; - public static inline var CLASS = "freeze.team"; - - override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { - for (team in game.teams) { - if (team.id != playerId.team) { - game.freezeTeam(engine, team.id, config.duration); - } - } + override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { + for (team in game.teams) { + if (team.id != playerId.team) { + game.freezeTeam(engine, team.id, config.duration); + } } + } } diff --git a/src/common/haxe/ru/m/tankz/bonus/IBonus.hx b/src/common/haxe/ru/m/tankz/bonus/IBonus.hx index 51ca089..28df6ea 100644 --- a/src/common/haxe/ru/m/tankz/bonus/IBonus.hx +++ b/src/common/haxe/ru/m/tankz/bonus/IBonus.hx @@ -5,6 +5,6 @@ import ru.m.tankz.game.IGame; import ru.m.tankz.Type; interface IBonus { - public var type(get, null):BonusType; - public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void; + public var type(get, null):BonusType; + public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void; } diff --git a/src/common/haxe/ru/m/tankz/bonus/LifeBonus.hx b/src/common/haxe/ru/m/tankz/bonus/LifeBonus.hx index 00ce2cb..5fdb293 100644 --- a/src/common/haxe/ru/m/tankz/bonus/LifeBonus.hx +++ b/src/common/haxe/ru/m/tankz/bonus/LifeBonus.hx @@ -7,10 +7,9 @@ import ru.m.tankz.Type; using ru.m.tankz.game.GameUtil; class LifeBonus extends BaseBonus { + public static inline var CLASS = "life"; - public static inline var CLASS = "life"; - - override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { - game.changeLife(playerId, 1); - } + override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { + game.changeLife(playerId, 1); + } } diff --git a/src/common/haxe/ru/m/tankz/bonus/ProtectEagleBonus.hx b/src/common/haxe/ru/m/tankz/bonus/ProtectEagleBonus.hx index 8acf558..5f3c135 100644 --- a/src/common/haxe/ru/m/tankz/bonus/ProtectEagleBonus.hx +++ b/src/common/haxe/ru/m/tankz/bonus/ProtectEagleBonus.hx @@ -9,14 +9,13 @@ import ru.m.tankz.Type; using ru.m.tankz.game.GameUtil; class ProtectEagleBonus extends BaseBonus { + public static inline var CLASS = "protect.eagle"; - public static inline var CLASS = "protect.eagle"; - - override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { - var team:Team = game.getTeam(playerId.team); - if (team.eagleId > 0) { - var eagle:Eagle = cast(engine.entities[team.eagleId], Eagle); - game.protectEagle(eagle, config.duration); - } + override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { + var team:Team = game.getTeam(playerId.team); + if (team.eagleId > 0) { + var eagle:Eagle = cast(engine.entities[team.eagleId], Eagle); + game.protectEagle(eagle, config.duration); } + } } diff --git a/src/common/haxe/ru/m/tankz/bonus/ProtectTankBonus.hx b/src/common/haxe/ru/m/tankz/bonus/ProtectTankBonus.hx index 41d9549..9e04b11 100644 --- a/src/common/haxe/ru/m/tankz/bonus/ProtectTankBonus.hx +++ b/src/common/haxe/ru/m/tankz/bonus/ProtectTankBonus.hx @@ -8,13 +8,12 @@ import ru.m.tankz.Type; using ru.m.tankz.game.GameUtil; class ProtectTankBonus extends BaseBonus { + public static inline var CLASS = "protect.tank"; - public static inline var CLASS = "protect.tank"; - - override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { - var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId); - if (tank != null) { - game.protectTank(tank, config.duration); - } + override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { + var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId); + if (tank != null) { + game.protectTank(tank, config.duration); } + } } diff --git a/src/common/haxe/ru/m/tankz/bonus/SuicideTankBonus.hx b/src/common/haxe/ru/m/tankz/bonus/SuicideTankBonus.hx index f3d4d0e..2999851 100644 --- a/src/common/haxe/ru/m/tankz/bonus/SuicideTankBonus.hx +++ b/src/common/haxe/ru/m/tankz/bonus/SuicideTankBonus.hx @@ -9,13 +9,12 @@ import ru.m.tankz.Type; using ru.m.tankz.game.GameUtil; class SuicideTankBonus extends BaseBonus { + public static inline var CLASS = "suicide.tank"; - public static inline var CLASS = "suicide.tank"; - - override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { - var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId); - if (tank != null) { - game.gameEventSignal.emit(DESTROY(TANK(tank.id, {tankId: tank.id}))); - } + override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { + var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId); + if (tank != null) { + game.gameEventSignal.emit(DESTROY(TANK(tank.id, {tankId: tank.id}))); } + } } diff --git a/src/common/haxe/ru/m/tankz/bonus/UpgradeTankBonus.hx b/src/common/haxe/ru/m/tankz/bonus/UpgradeTankBonus.hx index 6094bc6..3c74f3f 100644 --- a/src/common/haxe/ru/m/tankz/bonus/UpgradeTankBonus.hx +++ b/src/common/haxe/ru/m/tankz/bonus/UpgradeTankBonus.hx @@ -8,13 +8,12 @@ import ru.m.tankz.Type; using ru.m.tankz.game.GameUtil; class UpgradeTankBonus extends BaseBonus { + public static inline var CLASS = "upgrade.tank"; - public static inline var CLASS = "upgrade.tank"; - - override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { - var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId); - if (tank != null) { - game.upgradeTank(tank, config.value); - } + override public function apply(playerId:PlayerId, game:IGame, engine:IEngine):Void { + var tank:Tank = engine.getEntity(game.getPlayer(playerId).tankId); + if (tank != null) { + game.upgradeTank(tank, config.value); } + } } diff --git a/src/common/haxe/ru/m/tankz/bot/BotControl.hx b/src/common/haxe/ru/m/tankz/bot/BotControl.hx index 41837f7..c57bbd7 100644 --- a/src/common/haxe/ru/m/tankz/bot/BotControl.hx +++ b/src/common/haxe/ru/m/tankz/bot/BotControl.hx @@ -6,52 +6,52 @@ import ru.m.tankz.control.Control; import ru.m.tankz.core.Tank; class BotControl extends Control { - private var shotTimer:Timer; - private var turnTimer:Timer; + private var shotTimer:Timer; + private var turnTimer:Timer; - private var tank(get, null):Tank; + private var tank(get, null):Tank; - private inline function get_tank():Tank { - return handler == null || tankId == -1 ? null : engine.getEntity(tankId); + private inline function get_tank():Tank { + return handler == null || tankId == -1 ? null : engine.getEntity(tankId); + } + + override public function stop():Void { + super.stop(); + if (shotTimer != null) { + shotTimer.stop(); + shotTimer = null; } - - override public function stop():Void { - super.stop(); - if (shotTimer != null) { - shotTimer.stop(); - shotTimer = null; - } - if (turnTimer != null) { - turnTimer.stop(); - turnTimer = null; - } + if (turnTimer != null) { + turnTimer.stop(); + turnTimer = null; } + } - private function _shot():Void { - if (shotTimer != null) { - shotTimer.stop(); - shotTimer = null; - } - action(SHOT(0)); + private function _shot():Void { + if (shotTimer != null) { + shotTimer.stop(); + shotTimer = null; } + action(SHOT(0)); + } - public function shot(delay:Int = 100):Void { - if (shotTimer == null) { - shotTimer = Timer.delay(function() _shot(), delay); - } + public function shot(delay:Int = 100):Void { + if (shotTimer == null) { + shotTimer = Timer.delay(function() _shot(), delay); } + } - private function _turn(direction:Direction):Void { - if (turnTimer != null) { - turnTimer.stop(); - turnTimer = null; - } - action(MOVE(direction)); + private function _turn(direction:Direction):Void { + if (turnTimer != null) { + turnTimer.stop(); + turnTimer = null; } + action(MOVE(direction)); + } - public function turn(direction:Direction, delay:Int = 300):Void { - if (turnTimer == null) { - turnTimer = Timer.delay(function() _turn(direction), delay); - } + public function turn(direction:Direction, delay:Int = 300):Void { + if (turnTimer == null) { + turnTimer = Timer.delay(function() _turn(direction), delay); } + } } diff --git a/src/common/haxe/ru/m/tankz/bot/BotHelper.hx b/src/common/haxe/ru/m/tankz/bot/BotHelper.hx index 70d4f8e..d0e166a 100644 --- a/src/common/haxe/ru/m/tankz/bot/BotHelper.hx +++ b/src/common/haxe/ru/m/tankz/bot/BotHelper.hx @@ -8,40 +8,34 @@ import ru.m.tankz.engine.IEngine; import ru.m.tankz.Type; class BotHelper { - - public static function findEagle(team:TeamId, engine:IEngine):Null { - for (entity in engine.entities) { - switch (EntityTypeResolver.of(entity)) { - case EntityType.EAGLE(eagle): - if (eagle.team != team) { - return eagle; - } - case _: - } - } - return null; + public static function findEagle(team:TeamId, engine:IEngine):Null { + for (entity in engine.entities) { + switch (EntityTypeResolver.of(entity)) { + case EntityType.EAGLE(eagle): + if (eagle.team != team) { + return eagle; + } + case _: + } } + return null; + } - public static function getDirectionTo(entity:Entity, target:Entity):Direction { - var x:Float = target.rect.center.x - entity.rect.center.x; - var y:Float = target.rect.center.y - entity.rect.center.y; - var xD:Direction = Direction.from(Std.int(x / Math.abs(x)), 0); - var yD:Direction = Direction.from(0, Std.int(y / Math.abs(y))); - return Math.abs(x) > Math.abs(y) ? xD : yD; - } + public static function getDirectionTo(entity:Entity, target:Entity):Direction { + var x:Float = target.rect.center.x - entity.rect.center.x; + var y:Float = target.rect.center.y - entity.rect.center.y; + var xD:Direction = Direction.from(Std.int(x / Math.abs(x)), 0); + var yD:Direction = Direction.from(0, Std.int(y / Math.abs(y))); + return Math.abs(x) > Math.abs(y) ? xD : yD; + } - public static function randomDirection():Direction { - return [ - Direction.TOP, - Direction.BOTTOM, - Direction.LEFT, - Direction.RIGHT, - ][Math.floor(Math.random() * 4)]; - } + public static function randomDirection():Direction { + return [Direction.TOP, Direction.BOTTOM, Direction.LEFT, Direction.RIGHT,][Math.floor(Math.random() * 4)]; + } - public static function getDistance(entity:Entity, target:Entity):Float { - var x:Float = target.rect.center.x - entity.rect.center.x; - var y:Float = target.rect.center.y - entity.rect.center.y; - return Math.abs(x) + Math.abs(y); - } + public static function getDistance(entity:Entity, target:Entity):Float { + var x:Float = target.rect.center.x - entity.rect.center.x; + var y:Float = target.rect.center.y - entity.rect.center.y; + return Math.abs(x) + Math.abs(y); + } } diff --git a/src/common/haxe/ru/m/tankz/bot/HardBotControl.hx b/src/common/haxe/ru/m/tankz/bot/HardBotControl.hx index 6311423..a9dc42e 100644 --- a/src/common/haxe/ru/m/tankz/bot/HardBotControl.hx +++ b/src/common/haxe/ru/m/tankz/bot/HardBotControl.hx @@ -6,87 +6,90 @@ import ru.m.tankz.core.EntityType; import ru.m.tankz.core.Tank; class HardBotControl extends BotControl { - public static inline var BOT_TYPE = "hard"; + public static inline var BOT_TYPE = "hard"; - private var actionTimer:Timer; + private var actionTimer:Timer; - override public function onCollision(with:EntityType):Void { - if (tank == null) { - return; - } - switch (with) { - case TANK(t): - if (t.playerId.team != tank.playerId.team) { - shot(); - } - case CELL(cell): - if (cell.layer == 2 && cell.armor > -1 && cell.armor <= tank.weapon.config.bullet.piercing) { - shot(); - } - case EAGLE(eagle): - if (eagle.team != tank.playerId.team) { - shot(); - } - case _: - } - calcTurn(); + override public function onCollision(with:EntityType):Void { + if (tank == null) { + return; } - - override public function start():Void { - super.start(); - if (handler == null) return; - turn(tank.rect.direction); - if (actionTimer == null) { - actionTimer = new Timer(500); - actionTimer.run = nextAction; + switch (with) { + case TANK(t): + if (t.playerId.team != tank.playerId.team) { + shot(); } + case CELL(cell): + if (cell.layer == 2 && cell.armor > -1 && cell.armor <= tank.weapon.config.bullet.piercing) { + shot(); + } + case EAGLE(eagle): + if (eagle.team != tank.playerId.team) { + shot(); + } + case _: } + calcTurn(); + } - override public function stop():Void { - super.stop(); - if (actionTimer != null) { - actionTimer.stop(); - actionTimer = null; - } + override public function start():Void { + super.start(); + if (handler == null) + return; + turn(tank.rect.direction); + if (actionTimer == null) { + actionTimer = new Timer(500); + actionTimer.run = nextAction; } + } - private function nextAction():Void { - if (tank == null) { - return; //ToDo: stop? - } - var enemy:Tank = null; - var distance:Float = Math.POSITIVE_INFINITY; - for (entity in engine.entities.iterator()) { - switch EntityTypeResolver.of(entity) { - case TANK(t): - if (t.playerId.team != tank.playerId.team) { - var d = BotHelper.getDistance(tank, t); - if (d < distance && (Math.abs(t.rect.x - tank.rect.x) < tank.rect.width / 2 || Math.abs(t.rect.y - tank.rect.y) < tank.rect.height / 2)) { - enemy = t; - distance = d; - } - } - case _: + override public function stop():Void { + super.stop(); + if (actionTimer != null) { + actionTimer.stop(); + actionTimer = null; + } + } + + private function nextAction():Void { + if (tank == null) { + return; // ToDo: stop? + } + var enemy:Tank = null; + var distance:Float = Math.POSITIVE_INFINITY; + for (entity in engine.entities.iterator()) { + switch EntityTypeResolver.of(entity) { + case TANK(t): + if (t.playerId.team != tank.playerId.team) { + var d = BotHelper.getDistance(tank, t); + if (d < distance + && (Math.abs(t.rect.x - tank.rect.x) < tank.rect.width / 2 + || Math.abs(t.rect.y - tank.rect.y) < tank.rect.height / 2)) { + enemy = t; + distance = d; } - } - if (enemy != null) { - var d = BotHelper.getDirectionTo(tank, enemy); - if (d != tank.rect.direction) { - turn(BotHelper.getDirectionTo(tank, enemy), 1); - } else { - shot(); - } - } else if (Math.random() > 0.8) { - calcTurn(); - } + } + case _: + } } + if (enemy != null) { + var d = BotHelper.getDirectionTo(tank, enemy); + if (d != tank.rect.direction) { + turn(BotHelper.getDirectionTo(tank, enemy), 1); + } else { + shot(); + } + } else if (Math.random() > 0.8) { + calcTurn(); + } + } - private function calcTurn():Void { - var eagle:Eagle = BotHelper.findEagle(playerId.team, engine); - if (eagle != null && Math.random() > 0.5) { - turn(BotHelper.getDirectionTo(tank, eagle)); - } else { - turn(BotHelper.randomDirection()); - } + private function calcTurn():Void { + var eagle:Eagle = BotHelper.findEagle(playerId.team, engine); + if (eagle != null && Math.random() > 0.5) { + turn(BotHelper.getDirectionTo(tank, eagle)); + } else { + turn(BotHelper.randomDirection()); } + } } diff --git a/src/common/haxe/ru/m/tankz/bot/StupidBotControl.hx b/src/common/haxe/ru/m/tankz/bot/StupidBotControl.hx index f89539a..68042c8 100644 --- a/src/common/haxe/ru/m/tankz/bot/StupidBotControl.hx +++ b/src/common/haxe/ru/m/tankz/bot/StupidBotControl.hx @@ -6,50 +6,55 @@ import ru.m.tankz.core.Eagle; import ru.m.tankz.core.EntityType; class StupidBotControl extends BotControl { - public static inline var BOT_TYPE = "stupid"; + public static inline var BOT_TYPE = "stupid"; - private var turnRandomTimer:Timer; + private var turnRandomTimer:Timer; - override public function onCollision(with:EntityType):Void { - switch (with) { - case TANK(_): calcTurn(); - case CELL(_): calcTurn(); - case EAGLE(_): calcTurn(); - case _: - } + override public function onCollision(with:EntityType):Void { + switch (with) { + case TANK(_): + calcTurn(); + case CELL(_): + calcTurn(); + case EAGLE(_): + calcTurn(); + case _: } + } - override public function start():Void { - super.start(); - if (handler == null) return; - action(MOVE(tank.rect.direction)); - if (turnRandomTimer == null) { - turnRandomTimer = new Timer(2000); - turnRandomTimer.run = calcTurn; - } - shot(1000 + Math.round(Math.random() * 4000)); + override public function start():Void { + super.start(); + if (handler == null) + return; + action(MOVE(tank.rect.direction)); + if (turnRandomTimer == null) { + turnRandomTimer = new Timer(2000); + turnRandomTimer.run = calcTurn; } + shot(1000 + Math.round(Math.random() * 4000)); + } - override public function stop():Void { - super.stop(); - if (turnRandomTimer != null) { - turnRandomTimer.stop(); - turnRandomTimer = null; - } + override public function stop():Void { + super.stop(); + if (turnRandomTimer != null) { + turnRandomTimer.stop(); + turnRandomTimer = null; } + } - override private function _shot():Void { - super._shot(); - shot(1000 + Math.round(Math.random() * 4000)); - } + override private function _shot():Void { + super._shot(); + shot(1000 + Math.round(Math.random() * 4000)); + } - private function calcTurn():Void { - if (handler == null || tank == null) return; - var eagle:Eagle = BotHelper.findEagle(playerId.team, engine); - if (eagle != null && Math.random() > 0.5) { - turn(BotHelper.getDirectionTo(tank, eagle)); - } else { - turn(BotHelper.randomDirection()); - } + private function calcTurn():Void { + if (handler == null || tank == null) + return; + var eagle:Eagle = BotHelper.findEagle(playerId.team, engine); + if (eagle != null && Math.random() > 0.5) { + turn(BotHelper.getDirectionTo(tank, eagle)); + } else { + turn(BotHelper.randomDirection()); } + } } diff --git a/src/common/haxe/ru/m/tankz/bundle/CachedLevelBundle.hx b/src/common/haxe/ru/m/tankz/bundle/CachedLevelBundle.hx index daeddc2..142dc28 100644 --- a/src/common/haxe/ru/m/tankz/bundle/CachedLevelBundle.hx +++ b/src/common/haxe/ru/m/tankz/bundle/CachedLevelBundle.hx @@ -6,44 +6,43 @@ import ru.m.tankz.config.Config; import ru.m.tankz.Type; class CachedLevelBundle implements ILevelBundle { + private var storage:IStorage; + private var cache:Map; + private var source:ILevelSource; - private var storage:IStorage; - private var cache:Map; - private var source:ILevelSource; + public function new(source:ILevelSource, storage:IStorage = null) { + this.storage = storage; + this.cache = new Map(); + this.source = source; + } - public function new(source:ILevelSource, storage:IStorage = null) { - this.storage = storage; - this.cache = new Map(); - this.source = source; + public function load():Void { + for (packId in list()) { + get(packId); } + } - public function load():Void { - for (packId in list()) { - get(packId); - } + public function get(id:PackId):LevelPack { + if (cache.exists(id)) { + return cache.get(id); } - - public function get(id:PackId):LevelPack { - if (cache.exists(id)) { - return cache.get(id); - } - if (storage != null && storage.exists(id)) { - var result:LevelPack = storage.read(id); - var meta = source.resolveMeta(id); - if (result.meta != null && result.meta.date.getTime() == meta.date.getTime()) { - cache.set(id, result); - return result; - } - } - var result = source.resolve(id); - if (storage != null) { - storage.write(id, result); - } + if (storage != null && storage.exists(id)) { + var result:LevelPack = storage.read(id); + var meta = source.resolveMeta(id); + if (result.meta != null && result.meta.date.getTime() == meta.date.getTime()) { cache.set(id, result); return result; + } } + var result = source.resolve(id); + if (storage != null) { + storage.write(id, result); + } + cache.set(id, result); + return result; + } - public function list():Array { - return source.list(); - } + public function list():Array { + return source.list(); + } } diff --git a/src/common/haxe/ru/m/tankz/bundle/IConfigBundle.hx b/src/common/haxe/ru/m/tankz/bundle/IConfigBundle.hx index f6907c3..9da8160 100644 --- a/src/common/haxe/ru/m/tankz/bundle/IConfigBundle.hx +++ b/src/common/haxe/ru/m/tankz/bundle/IConfigBundle.hx @@ -4,5 +4,5 @@ import ru.m.tankz.config.Config; import ru.m.tankz.Type; interface IConfigBundle { - public function get(type:GameType):Config; + public function get(type:GameType):Config; } diff --git a/src/common/haxe/ru/m/tankz/bundle/ILevelBundle.hx b/src/common/haxe/ru/m/tankz/bundle/ILevelBundle.hx index 1533fb8..2484fe6 100644 --- a/src/common/haxe/ru/m/tankz/bundle/ILevelBundle.hx +++ b/src/common/haxe/ru/m/tankz/bundle/ILevelBundle.hx @@ -4,13 +4,13 @@ import ru.m.tankz.config.Config; import ru.m.tankz.Type; interface ILevelSource { - public function resolve(id:PackId):LevelPack; - public function resolveMeta(id:PackId):LevelPackMeta; - public function list():Array; + public function resolve(id:PackId):LevelPack; + public function resolveMeta(id:PackId):LevelPackMeta; + public function list():Array; } interface ILevelBundle { - public function load():Void; - public function get(id:PackId):LevelPack; - public function list():Array; + public function load():Void; + public function get(id:PackId):LevelPack; + public function list():Array; } diff --git a/src/common/haxe/ru/m/tankz/config/Config.hx b/src/common/haxe/ru/m/tankz/config/Config.hx index e7e71a3..888cdce 100644 --- a/src/common/haxe/ru/m/tankz/config/Config.hx +++ b/src/common/haxe/ru/m/tankz/config/Config.hx @@ -5,274 +5,267 @@ import ru.m.tankz.control.Controller; import ru.m.tankz.Type; typedef GameConfig = { - var levels:Int; - var friendlyFire:Bool; - @:optional var alignToGrid:Bool; - @:optional var bonusSpawnInterval:Null; + var levels:Int; + var friendlyFire:Bool; + @:optional var alignToGrid:Bool; + @:optional var bonusSpawnInterval:Null; } typedef SpawnPoint = { - var team:TeamId; - var type:String; - var index:Int; - var x:Int; - var y:Int; - var direction:String; + var team:TeamId; + var type:String; + var index:Int; + var x:Int; + var y:Int; + var direction:String; } typedef CellSize = { - var width:Float; - var height:Float; + var width:Float; + var height:Float; } typedef GridSize = { - var width:Int; - var height:Int; + var width:Int; + var height:Int; } typedef MapConfig = { - var cell:CellSize; - var grid:GridSize; + var cell:CellSize; + var grid:GridSize; } typedef BrickConfig = { - var type:BrickType; - var index:Int; - var layer:Int; - var armor:Float; + var type:BrickType; + var index:Int; + var layer:Int; + var armor:Float; } typedef BulletConfig = { - var width:Float; - var height:Float; - var speed:Float; - var piercing:Int; - var layer:Int; - var skin:String; + var width:Float; + var height:Float; + var speed:Float; + var piercing:Int; + var layer:Int; + var skin:String; } typedef WeaponConfig = { - var bullet:BulletConfig; - var count:Int; - var queue:Int; - var delay:Int; + var bullet:BulletConfig; + var count:Int; + var queue:Int; + var delay:Int; } typedef TankConfig = { - var type:TankType; - var width:Float; - var height:Float; - var speed:Float; - var weapons:Array; - var skin:String; - @:optinal var hits:Int; - @:optinal var upgrade:TankType; - @:optinal var downgrade:TankType; - @:optinal var score:Null; + var type:TankType; + var width:Float; + var height:Float; + var speed:Float; + var weapons:Array; + var skin:String; + @:optinal var hits:Int; + @:optinal var upgrade:TankType; + @:optinal var downgrade:TankType; + @:optinal var score:Null; } typedef BonusConfig = { - var type:BonusType; - var factory:String; - @:optional var duration:Null; - @:optional var value:Null; - @:optinal var score:Null; + var type:BonusType; + var factory:String; + @:optional var duration:Null; + @:optional var value:Null; + @:optinal var score:Null; } typedef TankSpawn = { - var type:TankType; - var rate:Float; + var type:TankType; + var rate:Float; } typedef PlayerConfig = { - var index:Int; - var tanks:Array; - @:optional var bonus:Float; - @:optional var protect:Float; - @:optional var life:Int; - @:optional var color:Null; - @:optional var control:String; - @:optional var saveState:Bool; + var index:Int; + var tanks:Array; + @:optional var bonus:Float; + @:optional var protect:Float; + @:optional var life:Int; + @:optional var color:Null; + @:optional var control:String; + @:optional var saveState:Bool; } typedef EagleConfig = { - @:optional var score:Null; + @:optional var score:Null; } typedef TeamConfig = { - var id:TeamId; - var players:Array; - @:optional var eagle:EagleConfig; - @:optional var life:Int; - @:optional var spawnInterval:Int; - @:optional var color:Null; + var id:TeamId; + var players:Array; + @:optional var eagle:EagleConfig; + @:optional var life:Int; + @:optional var spawnInterval:Int; + @:optional var color:Null; } typedef GamePreset = { - var id:PresetId; - var name:String; - var teams:Array; + var id:PresetId; + var name:String; + var teams:Array; } typedef LevelConfig = { - @:optional var packId:PackId; - @:optional var id:LevelId; - var data:Array; - @:optional var name:String; - @:optional var points:Array; - @:optional var size:{width:Int, height:Int}; + @:optional var packId:PackId; + @:optional var id:LevelId; + var data:Array; + @:optional var name:String; + @:optional var points:Array; + @:optional var size:{width:Int, height:Int}; } typedef LevelPackMeta = { - var id:PackId; - var author:String; - var date:Date; + var id:PackId; + var author:String; + var date:Date; } typedef LevelPack = { - var id:PackId; - var meta:LevelPackMeta; - var data:Array; + var id:PackId; + var meta:LevelPackMeta; + var data:Array; } typedef ConfigSource = { - var game:GameConfig; - var map:MapConfig; - var bricks:Array; - var presets:Array; - var points:Array; - var tanks:Array; - var bonuses:Array; + var game:GameConfig; + var map:MapConfig; + var bricks:Array; + var presets:Array; + var points:Array; + var tanks:Array; + var bonuses:Array; } class Config { - public var type(default, null):String; - public var game(default, null):GameConfig; - public var map(default, null):MapConfig; - public var bricks(default, null):Array; - public var tanks(default, null):Array; - public var presets(default, null):Array; - public var points(default, null):Array; - public var bonuses(default, null):Array; + public var type(default, null):String; + public var game(default, null):GameConfig; + public var map(default, null):MapConfig; + public var bricks(default, null):Array; + public var tanks(default, null):Array; + public var presets(default, null):Array; + public var points(default, null):Array; + public var bonuses(default, null):Array; - private var brickMap:Map; - private var brickMapByIndex:Map; - private var tankMap:Map; - private var presetsMap:Map; - private var bonusMap:Map; - private var teamsMap:Map; - private var playersMap:Map; + private var brickMap:Map; + private var brickMapByIndex:Map; + private var tankMap:Map; + private var presetsMap:Map; + private var bonusMap:Map; + private var teamsMap:Map; + private var playersMap:Map; - public static function fromSource(type:GameType, source:ConfigSource):Config { - return new Config(type, source.game, source.map, source.bricks, source.presets, source.points, source.tanks, source.bonuses); + public static function fromSource(type:GameType, source:ConfigSource):Config { + return new Config(type, source.game, source.map, source.bricks, source.presets, source.points, source.tanks, + source.bonuses); + } + + public function new(type:String, game:GameConfig, map:MapConfig, bricks:Array, + presets:Array, points:Array, tanks:Array, bonuses:Array) { + this.type = type; + this.game = game; + this.map = map; + this.bricks = bricks; + this.presets = presets; + this.points = points; + this.tanks = tanks; + this.bonuses = bonuses; + init(); + } + + private function init() { + brickMap = new Map(); + brickMapByIndex = new Map(); + for (item in bricks) { + brickMap.set(item.type, item); + brickMapByIndex.set(item.index, item); } - - public function new( - type:String, - game:GameConfig, - map:MapConfig, - bricks:Array, - presets:Array, - points:Array, - tanks:Array, - bonuses:Array - ) { - this.type = type; - this.game = game; - this.map = map; - this.bricks = bricks; - this.presets = presets; - this.points = points; - this.tanks = tanks; - this.bonuses = bonuses; - init(); + presetsMap = new Map(); + for (preset in presets) { + presetsMap.set(preset.id, preset); } - - private function init() { - brickMap = new Map(); - brickMapByIndex = new Map(); - for (item in bricks) { - brickMap.set(item.type, item); - brickMapByIndex.set(item.index, item); - } - presetsMap = new Map(); - for (preset in presets) { - presetsMap.set(preset.id, preset); - } - tankMap = new Map(); - for (item in tanks) { - tankMap.set(item.type, item); - } - bonusMap = new Map(); - for (item in bonuses) { - bonusMap.set(item.type, item); - } - teamsMap = new Map(); - playersMap = new Map(); - for (preset in presets) { - for (team in preset.teams) { - teamsMap.set(team.id, team); - for (player in team.players) { - playersMap.set(new PlayerId(team.id, player.index), player); - } - } + tankMap = new Map(); + for (item in tanks) { + tankMap.set(item.type, item); + } + bonusMap = new Map(); + for (item in bonuses) { + bonusMap.set(item.type, item); + } + teamsMap = new Map(); + playersMap = new Map(); + for (preset in presets) { + for (team in preset.teams) { + teamsMap.set(team.id, team); + for (player in team.players) { + playersMap.set(new PlayerId(team.id, player.index), player); } + } } + } - public function getBrick(type:BrickType):BrickConfig { - return brickMap.get(type); - } + public function getBrick(type:BrickType):BrickConfig { + return brickMap.get(type); + } - public function getBrickByIndex(index:Int):BrickConfig { - return brickMapByIndex.get(index); - } + public function getBrickByIndex(index:Int):BrickConfig { + return brickMapByIndex.get(index); + } - public function getPreset(id:PresetId):GamePreset { - return presetsMap.get(id); - } + public function getPreset(id:PresetId):GamePreset { + return presetsMap.get(id); + } - public function getTank(type:TankType):TankConfig { - return tankMap.get(type); - } + public function getTank(type:TankType):TankConfig { + return tankMap.get(type); + } - public function getBonus(type:BonusType):BonusConfig { - return bonusMap.get(type); - } + public function getBonus(type:BonusType):BonusConfig { + return bonusMap.get(type); + } - public function getTeam(team:TeamId):TeamConfig { - return teamsMap.get(team); - } + public function getTeam(team:TeamId):TeamConfig { + return teamsMap.get(team); + } - public function getPlayer(playerId:PlayerId):PlayerConfig { - return playersMap.get(playerId); - } + public function getPlayer(playerId:PlayerId):PlayerConfig { + return playersMap.get(playerId); + } - public function getPlayerTank(playerId:PlayerId):TankConfig { - return getTank(getPlayer(playerId.index == -1 ? [playerId.team, 0] : playerId).tanks[0].type); - } + public function getPlayerTank(playerId:PlayerId):TankConfig { + return getTank(getPlayer(playerId.index == -1 ? [playerId.team, 0] : playerId).tanks[0].type); + } - public function getColor(playerId:PlayerId):Null { - var player = getPlayer(playerId); - if (player != null && player.color != null) { - return player.color; - } - var team = getTeam(playerId.team); - if (team != null) { - return team.color; - } - return null; + public function getColor(playerId:PlayerId):Null { + var player = getPlayer(playerId); + if (player != null && player.color != null) { + return player.color; } + var team = getTeam(playerId.team); + if (team != null) { + return team.color; + } + return null; + } - public function getPoint(teamId:TeamId, type:String, index:Int = -1):SpawnPoint { - for (point in points) { - if (point.team == teamId && point.type == type && point.index == index) { - return point; - } - } - return null; + public function getPoint(teamId:TeamId, type:String, index:Int = -1):SpawnPoint { + for (point in points) { + if (point.team == teamId && point.type == type && point.index == index) { + return point; + } } + return null; + } - public function isHuman(playerId:PlayerId) { - return ControllerParser.fromString(getPlayer(playerId).control).match(HUMAN(_)); - } + public function isHuman(playerId:PlayerId) { + return ControllerParser.fromString(getPlayer(playerId).control).match(HUMAN(_)); + } } diff --git a/src/common/haxe/ru/m/tankz/control/BaseControlFactory.hx b/src/common/haxe/ru/m/tankz/control/BaseControlFactory.hx index 4cb9b3f..32b5f93 100644 --- a/src/common/haxe/ru/m/tankz/control/BaseControlFactory.hx +++ b/src/common/haxe/ru/m/tankz/control/BaseControlFactory.hx @@ -5,26 +5,25 @@ import ru.m.tankz.bot.StupidBotControl; import ru.m.tankz.Type; class BaseControlFactory implements IControlFactory { + public function new() {} - public function new() {} - - public function build(id:PlayerId, controller:Controller):Control { - return switch controller { - case Controller.HUMAN(index): buildHuman(id, index); - case Controller.BOT(type): buildBot(id, type); - case Controller.NONE: null; - } + public function build(id:PlayerId, controller:Controller):Control { + return switch controller { + case Controller.HUMAN(index): buildHuman(id, index); + case Controller.BOT(type): buildBot(id, type); + case Controller.NONE: null; } + } - private function buildHuman(id:PlayerId, index:Int):Control { - return null; - } + private function buildHuman(id:PlayerId, index:Int):Control { + return null; + } - private function buildBot(id:PlayerId, type:String):Control { - return switch type { - case StupidBotControl.BOT_TYPE: new StupidBotControl(id); - case HardBotControl.BOT_TYPE: new HardBotControl(id); - case _: null; - } + private function buildBot(id:PlayerId, type:String):Control { + return switch type { + case StupidBotControl.BOT_TYPE: new StupidBotControl(id); + case HardBotControl.BOT_TYPE: new HardBotControl(id); + case _: null; } + } } diff --git a/src/common/haxe/ru/m/tankz/control/Control.hx b/src/common/haxe/ru/m/tankz/control/Control.hx index 60cc5e3..65363cc 100644 --- a/src/common/haxe/ru/m/tankz/control/Control.hx +++ b/src/common/haxe/ru/m/tankz/control/Control.hx @@ -8,43 +8,44 @@ import ru.m.tankz.game.IGame; import ru.m.tankz.Type; enum TankAction { - MOVE(direction:Direction); - STOP; - SHOT(weapon:Int); + MOVE(direction:Direction); + STOP; + SHOT(weapon:Int); } class Control { - public var playerId(default, null):PlayerId; - public var tankId(default, default):Int; - private var handler:IGame; - private var engine:IEngine; + public var playerId(default, null):PlayerId; + public var tankId(default, default):Int; - public function new(playerId:PlayerId) { - this.playerId = playerId; - this.tankId = -1; + private var handler:IGame; + private var engine:IEngine; + + public function new(playerId:PlayerId) { + this.playerId = playerId; + this.tankId = -1; + } + + public function bind(handler:IGame, engine:IEngine):Void { + this.handler = handler; + this.engine = engine; + } + + public function action(action:TankAction):Void { + if (tankId > -1 && handler != null) { + handler.gameEventSignal.emit(GameEvent.ACTION(tankId, action)); } + } - public function bind(handler:IGame, engine:IEngine):Void { - this.handler = handler; - this.engine = engine; - } + public function onCollision(with:EntityType):Void {} - public function action(action:TankAction):Void { - if (tankId > -1 && handler != null) { - handler.gameEventSignal.emit(GameEvent.ACTION(tankId, action)); - } - } + public function start():Void {} - public function onCollision(with:EntityType):Void {} + public function stop():Void {} - public function start():Void {} - - public function stop():Void {} - - public function dispose():Void { - stop(); - handler = null; - engine = null; - tankId = -1; - } + public function dispose():Void { + stop(); + handler = null; + engine = null; + tankId = -1; + } } diff --git a/src/common/haxe/ru/m/tankz/control/Controller.hx b/src/common/haxe/ru/m/tankz/control/Controller.hx index 30becbc..897d2ac 100644 --- a/src/common/haxe/ru/m/tankz/control/Controller.hx +++ b/src/common/haxe/ru/m/tankz/control/Controller.hx @@ -1,28 +1,27 @@ package ru.m.tankz.control; enum Controller { - NONE; - HUMAN(index:Int); - BOT(type:String); + NONE; + HUMAN(index:Int); + BOT(type:String); } class ControllerParser { - - public static function fromString(value:String):Controller { - return switch value { - case null: NONE; - case x: switch x.split("-") { - case ["human", index]: HUMAN(Std.parseInt(index)); - case ["bot", type]: BOT(type); - case _: NONE; - } + public static function fromString(value:String):Controller { + return switch value { + case null: NONE; + case x: switch x.split("-") { + case ["human", index]: HUMAN(Std.parseInt(index)); + case ["bot", type]: BOT(type); + case _: NONE; } } + } - public static function defaultName(controller:Controller):String { - return switch controller { - case HUMAN(index): 'Player ${index + 1}'; - case BOT(_) | NONE: null; - } + public static function defaultName(controller:Controller):String { + return switch controller { + case HUMAN(index): 'Player ${index + 1}'; + case BOT(_) | NONE: null; } + } } diff --git a/src/common/haxe/ru/m/tankz/control/IControlFactory.hx b/src/common/haxe/ru/m/tankz/control/IControlFactory.hx index 11f2181..cf8acec 100644 --- a/src/common/haxe/ru/m/tankz/control/IControlFactory.hx +++ b/src/common/haxe/ru/m/tankz/control/IControlFactory.hx @@ -4,5 +4,5 @@ import ru.m.tankz.control.Control; import ru.m.tankz.Type; interface IControlFactory { - public function build(id:PlayerId, controller:Controller):Control; + public function build(id:PlayerId, controller:Controller):Control; } diff --git a/src/common/haxe/ru/m/tankz/control/NoneControlFactory.hx b/src/common/haxe/ru/m/tankz/control/NoneControlFactory.hx index a235a21..d377ba7 100644 --- a/src/common/haxe/ru/m/tankz/control/NoneControlFactory.hx +++ b/src/common/haxe/ru/m/tankz/control/NoneControlFactory.hx @@ -4,10 +4,9 @@ import ru.m.tankz.control.Control; import ru.m.tankz.Type; class NoneControlFactory implements IControlFactory { + public function new() {} - public function new() {} - - public function build(id:PlayerId, controller:Controller):Control { - return null; - } + public function build(id:PlayerId, controller:Controller):Control { + return null; + } } diff --git a/src/common/haxe/ru/m/tankz/control/PlayerControl.hx b/src/common/haxe/ru/m/tankz/control/PlayerControl.hx index f8d8654..7461fbe 100644 --- a/src/common/haxe/ru/m/tankz/control/PlayerControl.hx +++ b/src/common/haxe/ru/m/tankz/control/PlayerControl.hx @@ -4,8 +4,8 @@ import hw.color.Color; import ru.m.tankz.Type; typedef PlayerControl = { - var playerId:PlayerId; - var controller:Controller; - @:optional var color:Color; - @:optional var name:String; + var playerId:PlayerId; + var controller:Controller; + @:optional var color:Color; + @:optional var name:String; } diff --git a/src/common/haxe/ru/m/tankz/core/Bonus.hx b/src/common/haxe/ru/m/tankz/core/Bonus.hx index 04f6899..a98b0ac 100644 --- a/src/common/haxe/ru/m/tankz/core/Bonus.hx +++ b/src/common/haxe/ru/m/tankz/core/Bonus.hx @@ -4,11 +4,10 @@ import ru.m.geom.Rectangle; import ru.m.tankz.config.Config; class Bonus extends Entity { + public var config(default, null):BonusConfig; - public var config(default, null):BonusConfig; - - public function new(id:Int, rect:Rectangle, config:BonusConfig) { - super(id, rect); - this.config = config; - } + public function new(id:Int, rect:Rectangle, config:BonusConfig) { + super(id, rect); + this.config = config; + } } diff --git a/src/common/haxe/ru/m/tankz/core/Bullet.hx b/src/common/haxe/ru/m/tankz/core/Bullet.hx index f68b7d4..8c84496 100644 --- a/src/common/haxe/ru/m/tankz/core/Bullet.hx +++ b/src/common/haxe/ru/m/tankz/core/Bullet.hx @@ -7,21 +7,21 @@ import ru.m.tankz.config.Config; import ru.m.tankz.Type; class Bullet extends MobileEntity { - public var playerId(default, null):PlayerId; - public var tankId(get, null):Int; - public var tank(default, default):Tank; - public var weapon(default, default):Weapon; - public var config(default, null):BulletConfig; - public var color(default, default):Color; + public var playerId(default, null):PlayerId; + public var tankId(get, null):Int; + public var tank(default, default):Tank; + public var weapon(default, default):Weapon; + public var config(default, null):BulletConfig; + public var color(default, default):Color; - public function new(id:Int, rect:Rectangle, playerId:PlayerId, config:BulletConfig) { - super(id, rect, config.speed, Direction.RIGHT); - this.playerId = playerId; - this.config = config; - this.layer = this.config.layer; - } + public function new(id:Int, rect:Rectangle, playerId:PlayerId, config:BulletConfig) { + super(id, rect, config.speed, Direction.RIGHT); + this.playerId = playerId; + this.config = config; + this.layer = this.config.layer; + } - private inline function get_tankId():Int { - return tank.id; - } + private inline function get_tankId():Int { + return tank.id; + } } diff --git a/src/common/haxe/ru/m/tankz/core/Eagle.hx b/src/common/haxe/ru/m/tankz/core/Eagle.hx index b63d7be..bc7272d 100644 --- a/src/common/haxe/ru/m/tankz/core/Eagle.hx +++ b/src/common/haxe/ru/m/tankz/core/Eagle.hx @@ -6,24 +6,23 @@ import ru.m.tankz.config.Config; import ru.m.tankz.Type; class Eagle extends Entity { + public var team(default, null):TeamId; + public var config(default, null):EagleConfig; + public var color(default, default):Color; + public var death(default, default):Bool; + public var protect(default, default):Bool; - public var team(default, null):TeamId; - public var config(default, null):EagleConfig; - public var color(default, default):Color; - public var death(default, default):Bool; - public var protect(default, default):Bool; + public var score(get, null):Int; - public var score(get, null):Int; + public function new(id:Int, rect:Rectangle, team:TeamId, config:EagleConfig) { + super(id, rect); + this.team = team; + this.config = config; + this.death = false; + this.protect = false; + } - public function new(id:Int, rect:Rectangle, team:TeamId, config:EagleConfig) { - super(id, rect); - this.team = team; - this.config = config; - this.death = false; - this.protect = false; - } - - private inline function get_score():Int { - return config != null ? config.score : 0; - } + private inline function get_score():Int { + return config != null ? config.score : 0; + } } diff --git a/src/common/haxe/ru/m/tankz/core/Entity.hx b/src/common/haxe/ru/m/tankz/core/Entity.hx index 172591d..e9743a7 100755 --- a/src/common/haxe/ru/m/tankz/core/Entity.hx +++ b/src/common/haxe/ru/m/tankz/core/Entity.hx @@ -4,18 +4,17 @@ import ru.m.geom.Rectangle; import Type; class Entity { + public var id(default, null):Int; + public var type(default, null):String; + public var rect(default, null):Rectangle; - public var id(default, null):Int; - public var type(default, null):String; - public var rect(default, null):Rectangle; + public function new(id:Int, rect:Rectangle) { + this.id = id; + this.type = Type.getClassName(Type.getClass(this)).split('.').pop().toLowerCase(); + this.rect = rect; + } - public function new(id:Int, rect:Rectangle) { - this.id = id; - this.type = Type.getClassName(Type.getClass(this)).split('.').pop().toLowerCase(); - this.rect = rect; - } - - public function toString():String { - return '$type($id)'; - } + public function toString():String { + return '$type($id)'; + } } diff --git a/src/common/haxe/ru/m/tankz/core/EntityType.hx b/src/common/haxe/ru/m/tankz/core/EntityType.hx index 6a2a1c5..686bfad 100644 --- a/src/common/haxe/ru/m/tankz/core/EntityType.hx +++ b/src/common/haxe/ru/m/tankz/core/EntityType.hx @@ -4,30 +4,29 @@ import Type; import ru.m.tankz.map.Grid; enum EntityType { - EAGLE(eagle:Eagle); - TANK(tank:Tank); - BULLET(bullet:Bullet); - CELL(cell:GridCell); - BONUS(bonus:Bonus); + EAGLE(eagle:Eagle); + TANK(tank:Tank); + BULLET(bullet:Bullet); + CELL(cell:GridCell); + BONUS(bonus:Bonus); } class EntityTypeResolver { - - public static function of(entity:Dynamic):EntityType { - return switch Type.typeof(entity) { - case TClass(Eagle): EAGLE(cast entity); - case TClass(Tank): TANK(cast entity); - case TClass(Bullet): BULLET(cast entity); - case TClass(GridCell): CELL(cast entity); - case TClass(Bonus): BONUS(cast entity); - case x: null; - } + public static function of(entity:Dynamic):EntityType { + return switch Type.typeof(entity) { + case TClass(Eagle): EAGLE(cast entity); + case TClass(Tank): TANK(cast entity); + case TClass(Bullet): BULLET(cast entity); + case TClass(GridCell): CELL(cast entity); + case TClass(Bonus): BONUS(cast entity); + case x: null; } + } - public static function as(entity:Entity, type:Class):Null { - if (Std.is(entity, type)) { - return cast entity; - } - return null; + public static function as(entity:Entity, type:Class):Null { + if (Std.is(entity, type)) { + return cast entity; } + return null; + } } diff --git a/src/common/haxe/ru/m/tankz/core/MobileEntity.hx b/src/common/haxe/ru/m/tankz/core/MobileEntity.hx index 8bcc7b8..c6058cc 100755 --- a/src/common/haxe/ru/m/tankz/core/MobileEntity.hx +++ b/src/common/haxe/ru/m/tankz/core/MobileEntity.hx @@ -3,34 +3,35 @@ package ru.m.tankz.core; import ru.m.geom.Direction; import ru.m.geom.Rectangle; - class MobileEntity extends Entity { - public var mx(default, default):Float; - public var my(default, default):Float; + public var mx(default, default):Float; + public var my(default, default):Float; - public var layer(get, null):Int; - private function get_layer():Int return layer; + public var layer(get, null):Int; - public var speed(default, null):Float; + private function get_layer():Int + return layer; - public function new(id:Int, rect:Rectangle, speed:Float, direction:Direction) { - super(id, rect); - this.speed = speed; - this.layer = 0; - this.mx = 0; - this.my = 0; + public var speed(default, null):Float; + + public function new(id:Int, rect:Rectangle, speed:Float, direction:Direction) { + super(id, rect); + this.speed = speed; + this.layer = 0; + this.mx = 0; + this.my = 0; + } + + public function move(direction:Direction):Void { + if (this.rect.direction != direction) { + this.rect.direction = direction; } + mx = rect.direction.x * speed; + my = rect.direction.y * speed; + } - public function move(direction:Direction):Void { - if (this.rect.direction != direction) { - this.rect.direction = direction; - } - mx = rect.direction.x * speed; - my = rect.direction.y * speed; - } - - public function stop():Void { - mx = 0; - my = 0; - } + public function stop():Void { + mx = 0; + my = 0; + } } diff --git a/src/common/haxe/ru/m/tankz/core/Tank.hx b/src/common/haxe/ru/m/tankz/core/Tank.hx index ba9f2b6..50a4bd1 100755 --- a/src/common/haxe/ru/m/tankz/core/Tank.hx +++ b/src/common/haxe/ru/m/tankz/core/Tank.hx @@ -7,61 +7,62 @@ import ru.m.tankz.config.Config; import ru.m.tankz.Type; class Tank extends MobileEntity { - public var playerId(default, null):PlayerId; - public var config(default, set):TankConfig; - public var color(default, default):Color; - public var name(default, default):String; - public var hits(default, default):Int; - public var bonus(default, default):Bool; - public var protect(default, default):Bool; - public var freezing(default, default):Bool; - public var boat(default, default):Bool; + public var playerId(default, null):PlayerId; + public var config(default, set):TankConfig; + public var color(default, default):Color; + public var name(default, default):String; + public var hits(default, default):Int; + public var bonus(default, default):Bool; + public var protect(default, default):Bool; + public var freezing(default, default):Bool; + public var boat(default, default):Bool; - public var weapons(default, null):Array; - public var weapon(get, null):Weapon; - public var info(get, null):TankInfo; + public var weapons(default, null):Array; + public var weapon(get, null):Weapon; + public var info(get, null):TankInfo; - override function get_layer():Int return layer + (boat ? 1 : 0); + override function get_layer():Int + return layer + (boat ? 1 : 0); - public function new(id:Int, rect:Rectangle, playerId:PlayerId, config:TankConfig) { - super(id, rect, config.speed, Direction.RIGHT); - this.protect = false; - this.freezing = false; - this.playerId = playerId; - this.config = config; - this.layer = 1; + public function new(id:Int, rect:Rectangle, playerId:PlayerId, config:TankConfig) { + super(id, rect, config.speed, Direction.RIGHT); + this.protect = false; + this.freezing = false; + this.playerId = playerId; + this.config = config; + this.layer = 1; + } + + private function get_weapon():Weapon { + return weapons[0]; + } + + private function set_config(value:TankConfig):TankConfig { + var d = rect.direction; + rect = new Rectangle(rect.x, rect.y, value.width, value.height); + rect.direction = d; + speed = value.speed; + config = value; + hits = config.hits; + weapons = config.weapons.map(function(weaponConfig) return new Weapon(weaponConfig)); + return value; + } + + private function get_info():TankInfo { + return { + type: config.type, + skin: config.skin, + hits: hits, + bonus: bonus, + boat: boat, + color: color, + name: name, } + } - private function get_weapon():Weapon { - return weapons[0]; - } - - private function set_config(value:TankConfig):TankConfig { - var d = rect.direction; - rect = new Rectangle(rect.x, rect.y, value.width, value.height); - rect.direction = d; - speed = value.speed; - config = value; - hits = config.hits; - weapons = config.weapons.map(function(weaponConfig) return new Weapon(weaponConfig)); - return value; - } - - private function get_info():TankInfo { - return { - type: config.type, - skin: config.skin, - hits: hits, - bonus: bonus, - boat: boat, - color: color, - name: name, - } - } - - override public function move(direction:Direction):Void { - if (!freezing) { - super.move(direction); - } + override public function move(direction:Direction):Void { + if (!freezing) { + super.move(direction); } + } } diff --git a/src/common/haxe/ru/m/tankz/core/Weapon.hx b/src/common/haxe/ru/m/tankz/core/Weapon.hx index da753b2..4d24603 100644 --- a/src/common/haxe/ru/m/tankz/core/Weapon.hx +++ b/src/common/haxe/ru/m/tankz/core/Weapon.hx @@ -4,38 +4,37 @@ import ru.m.tankz.engine.ITicker; import ru.m.tankz.config.Config; class Weapon { + public var config(default, null):WeaponConfig; + public var count(default, default):Int; + public var queue(default, default):Int; + public var available(get, null):Bool; - public var config(default, null):WeaponConfig; - public var count(default, default):Int; - public var queue(default, default):Int; - public var available(get, null):Bool; + private var lastShotTime:Int; - private var lastShotTime:Int; + public function new(config:WeaponConfig) { + this.config = config; + this.count = this.config.count; + this.queue = 0; + this.lastShotTime = 0; + } - public function new(config:WeaponConfig) { - this.config = config; - this.count = this.config.count; - this.queue = 0; - this.lastShotTime = 0; + private function get_available():Bool { + return (count < 0 || count > 0) && (config.queue < 0 || queue < config.queue); + } + + public function use(ticker:ITicker):Bool { + if (available && ticker.time > lastShotTime + config.delay) { + lastShotTime = ticker.time; + queue++; + if (count > 0) { + count--; + } + return true; } + return false; + } - private function get_available():Bool { - return (count < 0 || count > 0) && (config.queue < 0 || queue < config.queue); - } - - public function use(ticker:ITicker):Bool { - if (available && ticker.time > lastShotTime + config.delay) { - lastShotTime = ticker.time; - queue++; - if (count > 0) { - count--; - } - return true; - } - return false; - } - - public function release():Void { - queue--; - } + public function release():Void { + queue--; + } } diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index b03c594..46a5d9c 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -14,159 +14,165 @@ import ru.m.tankz.map.Grid; import ru.m.tankz.map.LevelMap; @:dispatcher(EngineListener) class Engine implements IEngine { + public var config(default, default):Config; + public var map(default, null):LevelMap; + public var ticker(default, null):ITicker; + public var entities(default, null):Map; - public var config(default, default):Config; - public var map(default, null):LevelMap; - public var ticker(default, null):ITicker; - public var entities(default, null):Map; + public var allEntities(default, null):Map; - public var allEntities(default, null):Map; + public function new(config:Config, size:GridSize = null) { + this.config = config; + map = new LevelMap(config.map, size); + allEntities = new Map(); + entities = new Map(); + ticker = new Ticker(); + } - public function new(config:Config, size:GridSize = null) { - this.config = config; - map = new LevelMap(config.map, size); - allEntities = new Map(); - entities = new Map(); - ticker = new Ticker(); + public function getEntity(entityId:Int):T { + return cast allEntities.get(entityId); + } + + public function spawn(entity:Entity):Void { + allEntities.set(entity.id, entity); + entities.set(entity.id, entity); + spawnSignal.emit(EntityTypeResolver.of(entity)); + } + + public function destroy(entityId:Int):Void { + if (entities.exists(entityId)) { + var entity = entities[entityId]; + destroySignal.emit(EntityTypeResolver.of(entity)); + entities.remove(entityId); } + } - public function getEntity(entityId:Int):T { - return cast allEntities.get(entityId); + public function destroyCell(x:Int, y:Int):Void { + var cell = map.grid.cells.get(new GridPoint(x, y)); + cell.destroyed = true; + destroySignal.emit(EntityTypeResolver.of(cell)); + } + + public function move(entityId:Int, direction:Direction):Void { + if (entities.exists(entityId)) { + ticker.cancel('slide.tank.${entityId}'); + cast(entities.get(entityId), MobileEntity).move(direction); } + } - public function spawn(entity:Entity):Void { - allEntities.set(entity.id, entity); - entities.set(entity.id, entity); - spawnSignal.emit(EntityTypeResolver.of(entity)); + public function stop(entityId:Int):Void { + var entity:MobileEntity = getEntity(entityId); + if (entity != null) { + var center = entity.rect.center; + var brick = map.getPointBrick(center); + if (brick.config.type == "ace") { + ticker.emit(function() { + entity.stop(); + moveSignal.emit(EntityTypeResolver.of(entity), false); + }, 300, 'slide.tank.${entity.id}'); + } else { + entity.stop(); + moveSignal.emit(EntityTypeResolver.of(entity), false); + } } + } - public function destroy(entityId:Int):Void { - if (entities.exists(entityId)) { - var entity = entities[entityId]; - destroySignal.emit(EntityTypeResolver.of(entity)); - entities.remove(entityId); - } - } + public function update():Void { + var d:Float = ticker.tick(); - public function destroyCell(x:Int, y:Int):Void { - var cell = map.grid.cells.get(new GridPoint(x, y)); - cell.destroyed = true; - destroySignal.emit(EntityTypeResolver.of(cell)); - } + for (ent in entities) + if (Std.is(ent, MobileEntity)) { + var entityType:EntityType = EntityTypeResolver.of(ent); + var entity:MobileEntity = cast ent; - public function move(entityId:Int, direction:Direction):Void { - if (entities.exists(entityId)) { - ticker.cancel('slide.tank.${entityId}'); - cast(entities.get(entityId), MobileEntity).move(direction); - } - } - - public function stop(entityId:Int):Void { - var entity:MobileEntity = getEntity(entityId); - if (entity != null) { - var center = entity.rect.center; - var brick = map.getPointBrick(center); - if (brick.config.type == "ace") { - ticker.emit(function() { - entity.stop(); - moveSignal.emit(EntityTypeResolver.of(entity), false); - }, 300, 'slide.tank.${entity.id}'); - } else { - entity.stop(); - moveSignal.emit(EntityTypeResolver.of(entity), false); + if (config.game.alignToGrid) { + if (Std.is(entity, Tank)) { + if (entity.rect.direction.x != 0) { + entity.rect.y = Math.round((entity.rect.y + entity.rect.height / 2) / map.cellHeight) * map.cellHeight + - entity.rect.height / 2; } + if (entity.rect.direction.y != 0) { + entity.rect.x = Math.round((entity.rect.x + entity.rect.width / 2) / map.cellWidth) * map.cellWidth + - entity.rect.width / 2; + } + } } - } - public function update():Void { - var d:Float = ticker.tick(); + if (entity.mx != 0 || entity.my != 0) { + var side:Line = entity.rect.getSide(entity.rect.direction.reverse()); + var step:Point = new Point(entity.rect.direction.x * map.cellWidth / 4, + entity.rect.direction.y * map.cellHeight / 4); + var end:Point = side.center.add(new Point(entity.mx * (d / 30), entity.my * (d / 30))); + var c:Int = Math.floor(Math.abs(((end.x - side.center.x) / (map.cellWidth / 4) + + (end.y - side.center.y) / (map.cellHeight / 4)))); - for (ent in entities) if (Std.is(ent, MobileEntity)) { - var entityType:EntityType = EntityTypeResolver.of(ent); - var entity:MobileEntity = cast ent; + var withCollision:EntityType = null; - if (config.game.alignToGrid) { - if (Std.is(entity, Tank)) { - if (entity.rect.direction.x != 0) { - entity.rect.y = Math.round((entity.rect.y + entity.rect.height / 2) / map.cellHeight) * map.cellHeight - entity.rect.height / 2; - } - if (entity.rect.direction.y != 0) { - entity.rect.x = Math.round((entity.rect.x + entity.rect.width / 2) / map.cellWidth) * map.cellWidth - entity.rect.width / 2; - } + while (c-- >= 0) { + side = side.move(step); + var cells = map.grid.getCells(side); + + var collision:Bool = false; + for (cell in cells) { + if (cell.getCollision(entity.layer)) { + collision = true; + withCollision = EntityTypeResolver.of(cell); + // fix position + if (cells.filter(function(c:GridCell) return c.getCollision(entity.layer)).length == 1) { + if (entity.mx != 0) { + var d = entity.rect.center.y - cell.rect.center.y; + entity.rect.y += d / Math.abs(d); + } else if (entity.my != 0) { + var d = entity.rect.center.x - cell.rect.center.x; + entity.rect.x += d / Math.abs(d); + } + moveSignal.emit(entityType, true); } + break; + } } + if (withCollision != null) + break; - if (entity.mx != 0 || entity.my != 0) { - var side:Line = entity.rect.getSide(entity.rect.direction.reverse()); - var step:Point = new Point(entity.rect.direction.x * map.cellWidth / 4, entity.rect.direction.y * map.cellHeight / 4); - var end:Point = side.center.add(new Point(entity.mx * (d / 30), entity.my * (d / 30))); - var c:Int = Math.floor(Math.abs(((end.x - side.center.x) / (map.cellWidth / 4) + (end.y - side.center.y) / (map.cellHeight / 4)))); - - var withCollision:EntityType = null; - - while (c-- >= 0) { - side = side.move(step); - var cells = map.grid.getCells(side); - - var collision:Bool = false; - for (cell in cells) { - if (cell.getCollision(entity.layer)) { - collision = true; - withCollision = EntityTypeResolver.of(cell); - // fix position - if (cells.filter(function(c:GridCell) return c.getCollision(entity.layer)).length == 1) { - if (entity.mx != 0) { - var d = entity.rect.center.y - cell.rect.center.y; - entity.rect.y += d / Math.abs(d); - } else if (entity.my != 0) { - var d = entity.rect.center.x - cell.rect.center.x; - entity.rect.x += d / Math.abs(d); - } - moveSignal.emit(entityType, true); - } - break; - } - } - if (withCollision != null) break; - - for (other in entities.iterator()) { - if (other != ent && other != null) { - if (other.rect.intersection2(side)) { - withCollision = EntityTypeResolver.of(other); - } - } - } - if (withCollision != null) break; - } - - entity.rect.x += entity.mx * (d / 30); - entity.rect.y += entity.my * (d / 30); - moveSignal.emit(entityType, true); - - if (withCollision != null) { - collisionSignal.emit(entityType, withCollision); + for (other in entities.iterator()) { + if (other != ent && other != null) { + if (other.rect.intersection2(side)) { + withCollision = EntityTypeResolver.of(other); } + } } - } - } + if (withCollision != null) + break; + } - public function dispose():Void { - allEntities = new Map(); - entities = new Map(); - //map = null; - spawnSignal.dispose(); - collisionSignal.dispose(); - moveSignal.dispose(); - } + entity.rect.x += entity.mx * (d / 30); + entity.rect.y += entity.my * (d / 30); + moveSignal.emit(entityType, true); - public function getTanks(filter:Tank->Bool):Array { - var result = []; - for (entity in entities) { - var tank:Tank = EntityTypeResolver.as(entity, Tank); - if (tank != null && filter(tank)) { - result.push(tank); - } + if (withCollision != null) { + collisionSignal.emit(entityType, withCollision); + } } - return result; + } + } + + public function dispose():Void { + allEntities = new Map(); + entities = new Map(); + // map = null; + spawnSignal.dispose(); + collisionSignal.dispose(); + moveSignal.dispose(); + } + + public function getTanks(filter:Tank->Bool):Array { + var result = []; + for (entity in entities) { + var tank:Tank = EntityTypeResolver.as(entity, Tank); + if (tank != null && filter(tank)) { + result.push(tank); + } } + return result; + } } diff --git a/src/common/haxe/ru/m/tankz/engine/ICaller.hx b/src/common/haxe/ru/m/tankz/engine/ICaller.hx index fa6fa0c..f5d9d83 100644 --- a/src/common/haxe/ru/m/tankz/engine/ICaller.hx +++ b/src/common/haxe/ru/m/tankz/engine/ICaller.hx @@ -1,6 +1,6 @@ package ru.m.tankz.engine; interface ICaller { - public function start(calback:Void -> Void):Void; - public function stop():Void; + public function start(calback:Void->Void):Void; + public function stop():Void; } diff --git a/src/common/haxe/ru/m/tankz/engine/IEngine.hx b/src/common/haxe/ru/m/tankz/engine/IEngine.hx index 14b4214..2fe770b 100644 --- a/src/common/haxe/ru/m/tankz/engine/IEngine.hx +++ b/src/common/haxe/ru/m/tankz/engine/IEngine.hx @@ -9,42 +9,42 @@ import ru.m.tankz.core.Tank; import ru.m.tankz.map.LevelMap; interface IEngine { - public var entities(default, null):Map; - public var config(default, default):Config; - public var map(default, null):LevelMap; - public var ticker(default, null):ITicker; + public var entities(default, null):Map; + public var config(default, default):Config; + public var map(default, null):LevelMap; + public var ticker(default, null):ITicker; - public var spawnSignal(default, null):Signal1; - public var collisionSignal(default, null):Signal2; - public var moveSignal(default, null):Signal2; - public var destroySignal(default, null):Signal1; + public var spawnSignal(default, null):Signal1; + public var collisionSignal(default, null):Signal2; + public var moveSignal(default, null):Signal2; + public var destroySignal(default, null):Signal1; - public function getEntity(entityId:Int):T; + public function getEntity(entityId:Int):T; - public function spawn(entity:Entity):Void; + public function spawn(entity:Entity):Void; - public function move(entityId:Int, direction:Direction):Void; + public function move(entityId:Int, direction:Direction):Void; - public function stop(entityId:Int):Void; + public function stop(entityId:Int):Void; - public function destroy(entityId:Int):Void; + public function destroy(entityId:Int):Void; - public function destroyCell(x:Int, y:Int):Void; + public function destroyCell(x:Int, y:Int):Void; - public function update():Void; + public function update():Void; - public function getTanks(filter:Tank->Bool):Array; + public function getTanks(filter:Tank->Bool):Array; - public function connect(listener:EngineListener):Void; + public function connect(listener:EngineListener):Void; - public function disconnect(listener:EngineListener):Void; + public function disconnect(listener:EngineListener):Void; - public function dispose():Void; + public function dispose():Void; } interface EngineListener { - public function onSpawn(entity:EntityType):Void; - public function onCollision(entity:EntityType, with:EntityType):Void; - public function onMove(entity:EntityType, move:Bool):Void; - public function onDestroy(entity:EntityType):Void; + public function onSpawn(entity:EntityType):Void; + public function onCollision(entity:EntityType, with:EntityType):Void; + public function onMove(entity:EntityType, move:Bool):Void; + public function onDestroy(entity:EntityType):Void; } diff --git a/src/common/haxe/ru/m/tankz/engine/ITicker.hx b/src/common/haxe/ru/m/tankz/engine/ITicker.hx index d62927d..1a2159e 100644 --- a/src/common/haxe/ru/m/tankz/engine/ITicker.hx +++ b/src/common/haxe/ru/m/tankz/engine/ITicker.hx @@ -1,12 +1,12 @@ package ru.m.tankz.engine; interface ITicker { - public var time(get, null):Int; - public var running(default, null):Bool; + public var time(get, null):Int; + public var running(default, null):Bool; - public function start():Void; - public function stop():Void; - public function tick():Int; - public function emit(f:Void->Void, delay:Int, ?key:String):Void; - public function cancel(key:String):Void; + public function start():Void; + public function stop():Void; + public function tick():Int; + public function emit(f:Void->Void, delay:Int, ?key:String):Void; + public function cancel(key:String):Void; } diff --git a/src/common/haxe/ru/m/tankz/engine/Ticker.hx b/src/common/haxe/ru/m/tankz/engine/Ticker.hx index d9d9028..cc2ca1e 100644 --- a/src/common/haxe/ru/m/tankz/engine/Ticker.hx +++ b/src/common/haxe/ru/m/tankz/engine/Ticker.hx @@ -1,98 +1,98 @@ package ru.m.tankz.engine; typedef Action = { - var id:Int; - var time:Int; - var action:Void->Void; + var id:Int; + var time:Int; + var action:Void->Void; } class Ticker implements ITicker { - public var time(get, null):Int; - public var running(default, null):Bool; + public var time(get, null):Int; + public var running(default, null):Bool; - private var passed:Int; - private var last_tick:Int; - private var actions:Array; - private var actionsByKey:Map; - private var actionId = 0; + private var passed:Int; + private var last_tick:Int; + private var actions:Array; + private var actionsByKey:Map; + private var actionId = 0; - private static var TIME = Timer.stamp(); + private static var TIME = Timer.stamp(); - private inline static function now():Int { - return Std.int((Timer.stamp() - TIME) * 1000); + private inline static function now():Int { + return Std.int((Timer.stamp() - TIME) * 1000); + } + + public function new() { + passed = 0; + last_tick = 0; + running = false; + actions = []; + actionsByKey = new Map(); + } + + private function get_time():Int { + return passed; + } + + public function start():Void { + last_tick = now(); + running = true; + } + + public function stop():Void { + running = false; + } + + public function tick():Int { + if (!running) { + return 0; } - - public function new() { - passed = 0; - last_tick = 0; - running = false; - actions = []; - actionsByKey = new Map(); + var now = now(); + var result = now - last_tick; + last_tick = now; + passed += result; + if (actions.length > 0) { + runActions(); } + /*if (result > 100) { + L.w("Ticker", 'Long tick: ${result}'); + }*/ + return result; + } - private function get_time():Int { - return passed; + private function runActions():Void { + var it = actions.iterator(); + var action = it.next(); + var i = 0; + while (action != null && time >= action.time) { + i++; + action = it.next(); } + if (i > 0) { + var timeActions = actions.slice(0, i); + actions = actions.slice(i); + for (action in timeActions) { + // L.d("Ticker", 'action: ${action.id} ${action.time} on ${time}'); + action.action(); + } + } + } - public function start():Void { - last_tick = now(); - running = true; + public function emit(fun:Void->Void, delay:Int, ?key:String):Void { + var action:Action = {action: fun, time: time + delay, id: ++actionId}; + // L.d("Ticker", 'emit: ${action.id} ${action.time}'); + if (key != null) { + cancel(key); + actionsByKey[key] = action; } + actions.push(action); + actions.sort(function(a, b) return a.time - b.time); + } - public function stop():Void { - running = false; - } - - public function tick():Int { - if (!running) { - return 0; - } - var now = now(); - var result = now - last_tick; - last_tick = now; - passed += result; - if (actions.length > 0) { - runActions(); - } - /*if (result > 100) { - L.w("Ticker", 'Long tick: ${result}'); - }*/ - return result; - } - - private function runActions():Void { - var it = actions.iterator(); - var action = it.next(); - var i = 0; - while (action != null && time >= action.time) { - i++; - action = it.next(); - } - if (i > 0) { - var timeActions = actions.slice(0, i); - actions = actions.slice(i); - for (action in timeActions) { - //L.d("Ticker", 'action: ${action.id} ${action.time} on ${time}'); - action.action(); - } - } - } - - public function emit(fun:Void->Void, delay:Int, ?key:String):Void { - var action:Action = {action:fun, time:time+delay, id:++actionId}; - //L.d("Ticker", 'emit: ${action.id} ${action.time}'); - if (key != null) { - cancel(key); - actionsByKey[key] = action; - } - actions.push(action); - actions.sort(function(a, b) return a.time - b.time); - } - - public function cancel(key:String):Void { - if (actionsByKey.exists(key)) { - actions.remove(actionsByKey[key]); - actionsByKey.remove(key); - } + public function cancel(key:String):Void { + if (actionsByKey.exists(key)) { + actions.remove(actionsByKey[key]); + actionsByKey.remove(key); } + } } diff --git a/src/common/haxe/ru/m/tankz/engine/TimerCaller.hx b/src/common/haxe/ru/m/tankz/engine/TimerCaller.hx index 86f2451..d07193a 100644 --- a/src/common/haxe/ru/m/tankz/engine/TimerCaller.hx +++ b/src/common/haxe/ru/m/tankz/engine/TimerCaller.hx @@ -1,24 +1,23 @@ package ru.m.tankz.engine; class TimerCaller implements ICaller { + private var interval:Int; + private var timer:Timer; - private var interval:Int; - private var timer:Timer; + public function new(interval:Int = 30) { + this.interval = interval; + } - public function new(interval:Int = 30) { - this.interval = interval; - } - - public function start(calback:Void -> Void):Void { - stop(); - timer = new Timer(interval); - timer.run = calback; - } - - public function stop():Void { - if (timer != null) { - timer.stop(); - timer = null; - } + public function start(calback:Void->Void):Void { + stop(); + timer = new Timer(interval); + timer.run = calback; + } + + public function stop():Void { + if (timer != null) { + timer.stop(); + timer = null; } + } } diff --git a/src/common/haxe/ru/m/tankz/game/EntityBuilder.hx b/src/common/haxe/ru/m/tankz/game/EntityBuilder.hx index b4068a9..ef2770b 100644 --- a/src/common/haxe/ru/m/tankz/game/EntityBuilder.hx +++ b/src/common/haxe/ru/m/tankz/game/EntityBuilder.hx @@ -12,59 +12,57 @@ import ru.m.tankz.core.Tank; import ru.m.tankz.Type; typedef EntityPoint = { - var x:Int; - var y:Int; - var direction:String; + var x:Int; + var y:Int; + var direction:String; } class EntityBuilder { + private var config:Config; + private var entityId:Int; - private var config:Config; - private var entityId:Int; + public function new(config:Config) { + this.config = config; + this.entityId = 1; + } - public function new(config:Config) { - this.config = config; - this.entityId = 1; - } + public function buildRect(point:EntityPoint, width:Float, height:Float):Rectangle { + return new Rectangle((point.x + 1) * config.map.cell.width - width / 2, + (point.y + 1) * config.map.cell.height - height / 2, width, height, Direction.fromString(point.direction)); + } - public function buildRect(point:EntityPoint, width:Float, height:Float):Rectangle { - return new Rectangle( - (point.x + 1) * config.map.cell.width - width / 2, - (point.y + 1) * config.map.cell.height - height / 2, - width, - height, - Direction.fromString(point.direction) - ); - } + public function buildEagle(point:EntityPoint, teamId:TeamId):Eagle { + var eageleConfig = config.getTeam(teamId).eagle; + var eagle = new Eagle(++entityId, buildRect(point, config.map.cell.width * 2, config.map.cell.height * 2), teamId, + eageleConfig); + eagle.color = config.getColor(new PlayerId(teamId, -1)); + return eagle; + } - public function buildEagle(point:EntityPoint, teamId:TeamId):Eagle { - var eageleConfig = config.getTeam(teamId).eagle; - var eagle = new Eagle(++entityId, buildRect(point, config.map.cell.width * 2, config.map.cell.height * 2), teamId, eageleConfig); - eagle.color = config.getColor(new PlayerId(teamId, -1)); - return eagle; - } + public function buildTank(point:EntityPoint, playerId:PlayerId, info:TankInfo):Tank { + var playerConfig = config.getPlayer(playerId); + var tankConfig = config.getTank(info.type); + var tank = new Tank(++entityId, buildRect(point, tankConfig.width, tankConfig.height), playerId, tankConfig); + tank.color = info.color; + tank.hits = info.hits; + tank.name = info.name; + tank.bonus = info.bonus; + tank.boat = info.boat; + return tank; + } - public function buildTank(point:EntityPoint, playerId:PlayerId, info:TankInfo):Tank { - var playerConfig = config.getPlayer(playerId); - var tankConfig = config.getTank(info.type); - var tank = new Tank(++entityId, buildRect(point, tankConfig.width, tankConfig.height), playerId, tankConfig); - tank.color = info.color; - tank.hits = info.hits; - tank.name = info.name; - tank.bonus = info.bonus; - tank.boat = info.boat; - return tank; - } + public function buildBullet(point:Point, direction:Direction, playerId:PlayerId, bulletConfig:BulletConfig):Bullet { + var bullet = new Bullet(++entityId, + new Rectangle(point.x - bulletConfig.width / 2, point.y - bulletConfig.height / 2, bulletConfig.width, + bulletConfig.height, direction), + playerId, bulletConfig); + return bullet; + } - public function buildBullet(point:Point, direction:Direction, playerId:PlayerId, bulletConfig:BulletConfig):Bullet { - var bullet = new Bullet(++entityId, new Rectangle(point.x - bulletConfig.width / 2, point.y - bulletConfig.height / 2, bulletConfig.width, bulletConfig.height, direction), playerId, bulletConfig); - return bullet; - } - - public function buildBonus(point:EntityPoint, type:BonusType):Bonus { - var bonusConfig = config.getBonus(type); - var bonus = new Bonus(++entityId, buildRect(point, config.map.cell.width * 2, config.map.cell.height * 2), bonusConfig); - return bonus; - } + public function buildBonus(point:EntityPoint, type:BonusType):Bonus { + var bonusConfig = config.getBonus(type); + var bonus = new Bonus(++entityId, buildRect(point, config.map.cell.width * 2, config.map.cell.height * 2), + bonusConfig); + return bonus; + } } - diff --git a/src/common/haxe/ru/m/tankz/game/EventUtil.hx b/src/common/haxe/ru/m/tankz/game/EventUtil.hx index 6dbea7b..86ff3c9 100644 --- a/src/common/haxe/ru/m/tankz/game/EventUtil.hx +++ b/src/common/haxe/ru/m/tankz/game/EventUtil.hx @@ -11,58 +11,58 @@ import ru.m.tankz.map.Brick; import ru.m.tankz.map.LevelMap; class EventUtil { + public static function buildBricksSpawn(map:LevelMap):GameEvent { + var bricks = map.bricks.map(function(item:Brick):BrickInfo { + return { + id: item.id, + x: item.cellY, + y: item.cellY, + rect: item.rect, + type: item.config.type, + } + }); + return SPAWN(BRICK(bricks)); + } - public static function buildBricksSpawn(map:LevelMap):GameEvent { - var bricks = map.bricks.map(function(item:Brick):BrickInfo { - return { - id: item.id, - x: item.cellY, - y: item.cellY, - rect: item.rect, - type: item.config.type, - } - }); - return SPAWN(BRICK(bricks)); - } - - public static function buildCellsDestroyed(map:LevelMap):Array { - var result = []; - for (brick in map.bricks) { - for (cell in brick.cells) { - if (cell.destroyed) { - result.push(DESTROY(CELL(brick.id, cell.cellX - brick.cellX * 2, cell.cellY - brick.cellY * 2, {tankId: -1}))); - } - } + public static function buildCellsDestroyed(map:LevelMap):Array { + var result = []; + for (brick in map.bricks) { + for (cell in brick.cells) { + if (cell.destroyed) { + result.push(DESTROY(CELL(brick.id, cell.cellX - brick.cellX * 2, cell.cellY - brick.cellY * 2, + {tankId: -1}))); } - return result; + } } + return result; + } - public static function buildEagleSpawn(eagle:Eagle):GameEvent { - return SPAWN(EAGLE(eagle.id, eagle.rect, eagle.team)); - } + public static function buildEagleSpawn(eagle:Eagle):GameEvent { + return SPAWN(EAGLE(eagle.id, eagle.rect, eagle.team)); + } - public static function buildTankSpawn(tank:Tank):GameEvent { - return SPAWN(TANK(tank.id, tank.rect.clone(), tank.playerId, tank.info)); - } + public static function buildTankSpawn(tank:Tank):GameEvent { + return SPAWN(TANK(tank.id, tank.rect.clone(), tank.playerId, tank.info)); + } - public static function buildBonusSpawn(bonus:Bonus):GameEvent { - return SPAWN(BONUS(bonus.id, bonus.rect.clone(), bonus.config.type)); - } + public static function buildBonusSpawn(bonus:Bonus):GameEvent { + return SPAWN(BONUS(bonus.id, bonus.rect.clone(), bonus.config.type)); + } - public static function buildBulletSpawn(bullet:Bullet):GameEvent { - return SPAWN(BULLET(bullet.id, bullet.rect.clone(), bullet.playerId, bullet.config.skin, bullet.color)); - } + public static function buildBulletSpawn(bullet:Bullet):GameEvent { + return SPAWN(BULLET(bullet.id, bullet.rect.clone(), bullet.playerId, bullet.config.skin, bullet.color)); + } - public static function buildMove(entity:Entity):GameEvent { - return switch EntityTypeResolver.of(entity) { - case EAGLE(eagle): - MOVE(EAGLE(entity.id, entity.rect.position)); - case TANK(tank): - MOVE(TANK(entity.id, entity.rect.position)); - case BULLET(bullet): - MOVE(BULLET(entity.id, entity.rect.position)); - case _: - null; - } + public static function buildMove(entity:Entity):GameEvent { + return switch EntityTypeResolver.of(entity) { + case EAGLE(eagle): + MOVE(EAGLE(entity.id, entity.rect.position)); + case TANK(tank): + MOVE(TANK(entity.id, entity.rect.position)); + case BULLET(bullet): + MOVE(BULLET(entity.id, entity.rect.position)); + case _: + null; } + } } diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index a846b91..bc0b250 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -16,128 +16,125 @@ import ru.m.tankz.game.IGame; import ru.m.tankz.Type; @:dispatcher(GameListener) class Game implements IGame implements GameListener { + private static var TAG(default, never):String = "Game"; - private static var TAG(default, never):String = "Game"; + public var type(default, null):GameType; + public var teams(default, null):Map; + public var config(default, null):Config; + public var winner(default, null):Null; + public var state(default, null):GameState; + public var level(default, null):LevelConfig; + public var engine(default, null):IEngine; + public var controlFactory(default, null):IControlFactory; + public var pause(default, set):Bool; + public var controls(default, null):Map; + public var ticker(default, null):ITicker; - public var type(default, null):GameType; - public var teams(default, null):Map; - public var config(default, null):Config; - public var winner(default, null):Null; - public var state(default, null):GameState; - public var level(default, null):LevelConfig; - public var engine(default, null):IEngine; - public var controlFactory(default, null):IControlFactory; - public var pause(default, set):Bool; - public var controls(default, null):Map; - public var ticker(default, null):ITicker; + @:provide var configBundle:IConfigBundle; - @:provide var configBundle:IConfigBundle; + public function new(type:GameType) { + this.type = type; + this.teams = new Map(); + this.config = configBundle.get(type); + this.controlFactory = new NoneControlFactory(); + this.pause = false; + this.controls = new Map(); + connect(this); + } - public function new(type:GameType) { - this.type = type; - this.teams = new Map(); - this.config = configBundle.get(type); - this.controlFactory = new NoneControlFactory(); - this.pause = false; - this.controls = new Map(); - connect(this); + private function set_pause(value:Bool):Bool { + if (pause != value) { + pause = value; + changePause(pause); } + return pause; + } - private function set_pause(value:Bool):Bool { - if (pause != value) { - pause = value; - changePause(pause); + private function changePause(value:Bool):Void {} + + public inline function getTeam(teamId:TeamId):Team { + return teams[teamId]; + } + + public inline function getPlayer(playerId:PlayerId):Player { + return teams[playerId.team].players[playerId.index]; + } + + public function onGameEvent(event:GameEvent):Void { + switch event { + case START(start): + onStart(start); + case COMPLETE(result): + this.state = result.state; + this.winner = result.winner; + case SPAWN(TANK(id, rect, playerId, info)): + if (controls.exists(playerId)) { + var control = controls[playerId]; + control.tankId = id; + control.start(); } - return pause; - } - - private function changePause(value:Bool):Void {} - - public inline function getTeam(teamId:TeamId):Team { - return teams[teamId]; - } - - public inline function getPlayer(playerId:PlayerId):Player { - return teams[playerId.team].players[playerId.index]; - } - - public function onGameEvent(event:GameEvent):Void { - switch event { - case START(start): - onStart(start); - case COMPLETE(result): - this.state = result.state; - this.winner = result.winner; - case SPAWN(TANK(id, rect, playerId, info)): - if (controls.exists(playerId)) { - var control = controls[playerId]; - control.tankId = id; - control.start(); - } - case DESTROY(TANK(id, shot)): - for (control in controls) { - if (control.tankId == id) { - control.stop(); - control.tankId = -1; - break; - } - } - case _: - } - } - - private function onStart(start:Start):Void { - this.state = start.state; - this.level = start.level; - // ToDo: Spawner not in Team? - var points:Array = level != null && level.points != null ? level.points : config.points; - for (teamConfig in state.preset.teams) { - var teamPoints = points.filter(function(p:SpawnPoint) return p.team == teamConfig.id); - var team:Team = new Team(teamConfig, teamPoints, state.teams[teamConfig.id]); - teams[team.id] = team; - } - var controlsById:Map = new Map(); - for (control in state.controls) { - controlsById[control.playerId] = control; - } - for (team in teams.iterator()) { - for (player in team.players.iterator()) { - var controller = ControllerParser.fromString(player.config.control); - var playerControl = controlsById.get(player.id); - if (playerControl != null) { - if (playerControl.color != null) { - player.state.color = playerControl.color; - } - if (playerControl.name != null) { - player.state.name = playerControl.name; - } - if (playerControl.controller != null && !playerControl.controller.match(NONE)) { - controller = playerControl.controller; - } - } - var control = controlFactory.build(player.id, controller); - if (control != null) { - controls[player.id] = control; - control.bind(this, engine); - } else { - // ToDo: remove player - player.state.life = 0; - } - } - } - } - - public function start():Void { - } - - public function update():Void { - } - - public function dispose():Void { + case DESTROY(TANK(id, shot)): for (control in controls) { - control.dispose(); + if (control.tankId == id) { + control.stop(); + control.tankId = -1; + break; + } } - controls = new Map(); - gameEventSignal.dispose(); + case _: } + } + + private function onStart(start:Start):Void { + this.state = start.state; + this.level = start.level; + // ToDo: Spawner not in Team? + var points:Array = level != null && level.points != null ? level.points : config.points; + for (teamConfig in state.preset.teams) { + var teamPoints = points.filter(function(p:SpawnPoint) return p.team == teamConfig.id); + var team:Team = new Team(teamConfig, teamPoints, state.teams[teamConfig.id]); + teams[team.id] = team; + } + var controlsById:Map = new Map(); + for (control in state.controls) { + controlsById[control.playerId] = control; + } + for (team in teams.iterator()) { + for (player in team.players.iterator()) { + var controller = ControllerParser.fromString(player.config.control); + var playerControl = controlsById.get(player.id); + if (playerControl != null) { + if (playerControl.color != null) { + player.state.color = playerControl.color; + } + if (playerControl.name != null) { + player.state.name = playerControl.name; + } + if (playerControl.controller != null && !playerControl.controller.match(NONE)) { + controller = playerControl.controller; + } + } + var control = controlFactory.build(player.id, controller); + if (control != null) { + controls[player.id] = control; + control.bind(this, engine); + } else { + // ToDo: remove player + player.state.life = 0; + } + } + } + } + + public function start():Void {} + + public function update():Void {} + + public function dispose():Void { + for (control in controls) { + control.dispose(); + } + controls = new Map(); + gameEventSignal.dispose(); + } } diff --git a/src/common/haxe/ru/m/tankz/game/GameEvent.hx b/src/common/haxe/ru/m/tankz/game/GameEvent.hx index 676cc31..6db9382 100644 --- a/src/common/haxe/ru/m/tankz/game/GameEvent.hx +++ b/src/common/haxe/ru/m/tankz/game/GameEvent.hx @@ -8,83 +8,83 @@ import ru.m.tankz.control.Control; import ru.m.tankz.Type; typedef Start = { - var state:GameState; - var level:LevelConfig; + var state:GameState; + var level:LevelConfig; } typedef Result = { - var state:GameState; - var level:LevelConfig; - var winner:TeamId; + var state:GameState; + var level:LevelConfig; + var winner:TeamId; } typedef BrickInfo = { - var id:Int; - var x:Int; - var y:Int; - var rect:Rectangle; - var type:BrickType; + var id:Int; + var x:Int; + var y:Int; + var rect:Rectangle; + var type:BrickType; } enum SpawnEvent { - BRICK(bricks:Array); - EAGLE(id:Int, rect:Rectangle, teamId:TeamId); - TANK(id:Int, rect:Rectangle, playerId:PlayerId, info:TankInfo); - BULLET(id:Int, rect:Rectangle, playerId:PlayerId, skin:String, color:Color); - BONUS(id:Int, rect:Rectangle, type:BonusType); + BRICK(bricks:Array); + EAGLE(id:Int, rect:Rectangle, teamId:TeamId); + TANK(id:Int, rect:Rectangle, playerId:PlayerId, info:TankInfo); + BULLET(id:Int, rect:Rectangle, playerId:PlayerId, skin:String, color:Color); + BONUS(id:Int, rect:Rectangle, type:BonusType); } typedef Shot = { - var tankId:Int; - @:optional var bulletId:Null; - @:optional var score:Null; + var tankId:Int; + @:optional var bulletId:Null; + @:optional var score:Null; } enum HitEvent { - TANK(id:Int, shot:Shot); - CELL(cellX:Int, cellY:Int, shot:Shot); + TANK(id:Int, shot:Shot); + CELL(cellX:Int, cellY:Int, shot:Shot); } enum DestroyEvent { - EAGLE(id:Int, shot:Shot); - TANK(id:Int, shot:Shot); - BONUS(id:Int, shot:Shot); - BULLET(id:Int); - CELL(id:Int, x:Int, y:Int, shot:Shot); - BRICK(id:Int, shot:Shot); + EAGLE(id:Int, shot:Shot); + TANK(id:Int, shot:Shot); + BONUS(id:Int, shot:Shot); + BULLET(id:Int); + CELL(id:Int, x:Int, y:Int, shot:Shot); + BRICK(id:Int, shot:Shot); } enum MoveEvent { - EAGLE(id:Int, position:Position); - TANK(id:Int, position:Position); - BULLET(id:Int, position:Position); + EAGLE(id:Int, position:Position); + TANK(id:Int, position:Position); + BULLET(id:Int, position:Position); } enum StopEvent { - TANK(id:Int); + TANK(id:Int); } enum ChangeEvent { - TANK(id:Int, type:TankType, hits:Int, bonus:Bool, boat:Bool); - TANK_PROTECT(id:Int, state:Bool); - TANK_FREEZE(id:Int, state:Bool); - EAGLE_PROTECT(id:Int, state:Bool); - PLAYER_SCORE(playerId:PlayerId, value:Int); - PLAYER_LIFE(playerId:PlayerId, value:Int); - TEAM_SCORE(teamId:TeamId, value:Int); - TEAM_LIFE(teamId:TeamId, value:Int); - BRICK(id:Int, type:BrickType); + TANK(id:Int, type:TankType, hits:Int, bonus:Bool, boat:Bool); + TANK_PROTECT(id:Int, state:Bool); + TANK_FREEZE(id:Int, state:Bool); + EAGLE_PROTECT(id:Int, state:Bool); + PLAYER_SCORE(playerId:PlayerId, value:Int); + PLAYER_LIFE(playerId:PlayerId, value:Int); + TEAM_SCORE(teamId:TeamId, value:Int); + TEAM_LIFE(teamId:TeamId, value:Int); + BRICK(id:Int, type:BrickType); } enum GameEvent { - START(start:Start); - SPAWN(event:SpawnEvent); - MOVE(event:MoveEvent); - STOP(event:StopEvent); - HIT(event:HitEvent); - DESTROY(event:DestroyEvent); - CHANGE(event:ChangeEvent); - COMPLETE(result:Result); - ACTION(tankId:Int, action:TankAction); - PAUSE(paused:Bool); + START(start:Start); + SPAWN(event:SpawnEvent); + MOVE(event:MoveEvent); + STOP(event:StopEvent); + HIT(event:HitEvent); + DESTROY(event:DestroyEvent); + CHANGE(event:ChangeEvent); + COMPLETE(result:Result); + ACTION(tankId:Int, action:TankAction); + PAUSE(paused:Bool); } diff --git a/src/common/haxe/ru/m/tankz/game/GameRunner.hx b/src/common/haxe/ru/m/tankz/game/GameRunner.hx index d872f20..0a52e2a 100644 --- a/src/common/haxe/ru/m/tankz/game/GameRunner.hx +++ b/src/common/haxe/ru/m/tankz/game/GameRunner.hx @@ -21,386 +21,390 @@ import ru.m.tankz.Type; import ru.m.tankz.game.GameUtil; class GameRunner extends Game implements EngineListener { - private var updater:ICaller; + private var updater:ICaller; - private var builder:EntityBuilder; - private var bonuses:BonusFactory; + private var builder:EntityBuilder; + private var bonuses:BonusFactory; - public function new(start:Start, ?updater:ICaller) { - super(start.state.type); - this.updater = updater != null ? updater : new TimerCaller(); - this.level = start.level; - this.state = start.state; - builder = new EntityBuilder(config); - bonuses = new BonusFactory(); - engine = new Engine(config, level.size); - ticker = engine.ticker; - engine.connect(this); + public function new(start:Start, ?updater:ICaller) { + super(start.state.type); + this.updater = updater != null ? updater : new TimerCaller(); + this.level = start.level; + this.state = start.state; + builder = new EntityBuilder(config); + bonuses = new BonusFactory(); + engine = new Engine(config, level.size); + ticker = engine.ticker; + engine.connect(this); + } + + override function changePause(value:Bool):Void { + if (engine != null) { + if (value) { + engine.ticker.stop(); + } else { + engine.ticker.start(); + } + gameEventSignal.emit(PAUSE(value)); } + } - override function changePause(value:Bool):Void { - if (engine != null) { - if (value) { - engine.ticker.stop(); + override public function update():Void { + super.update(); + engine.update(); + } + + override public function start():Void { + super.start(); + gameEventSignal.emit(START({level: level, state: state})); + updater.start(update); + } + + override public function dispose():Void { + super.dispose(); + updater.stop(); + } + + public function newPlayerTank(playerId:PlayerId):TankInfo { + var player = getPlayer(playerId); + var spawn = player.config.tanks[Math.floor(Math.random() * player.config.tanks.length)]; + var tank = config.getTank(spawn.type); + var bonus = Math.random() < player.config.bonus; + return { + type: tank.type, + skin: tank.skin, + hits: tank.hits, + bonus: bonus, + boat: false, + color: player.state.color, + name: player.state.name, + } + } + + override private function onStart(start:Start):Void { + super.onStart(start); + var mapData = level.data.map(function(index:BrickIndex) return config.getBrickByIndex(index)); + engine.map.setData(mapData); + for (team in teams.iterator()) { + team.spawner.runner = spawn; + for (player in team.players.iterator()) { + if (team.tryRespawn(player.id)) { + team.spawner.push(engine.ticker, player.id, + player.state.tank != null ? player.state.tank : newPlayerTank(player.id)); + } + } + if (team.config.eagle != null) { + var point = team.spawner.getPoint("eagle"); + var eagle = builder.buildEagle(point, team.id); + engine.spawn(eagle); + gameEventSignal.emit(EventUtil.buildEagleSpawn(eagle)); + } + } + gameEventSignal.emit(EventUtil.buildBricksSpawn(engine.map)); + // for (i in 0...10) spawnBonus(); + if (config.game.bonusSpawnInterval != null) { + ticker.emit(function() spawnBonus(), config.game.bonusSpawnInterval, "bonus"); + } + } + + private function spawn(task:SpawnTask):Void { + var player = getPlayer(task.playerId); + var tank = builder.buildTank(task.point, task.playerId, task.tank); + if (getTeam(player.id.team).freezing) { + tank.freezing = true; + } + engine.spawn(tank); + gameEventSignal.emit(EventUtil.buildTankSpawn(tank)); + if (player.config.protect > 0) { + GameUtil.protectTank(this, tank, player.config.protect); + } + } + + private function checkComplete():Void { + var actives:Array = []; + for (team in teams.iterator()) { + if (team.isAlive) { + if (team.eagleId > -1) { + var eagle:Eagle = engine.getEntity(team.eagleId); + if (!eagle.death) { + actives.push(team.id); + } + } else { + actives.push(team.id); + } + } + } + switch actives { + case [winner]: + complete(winner); + case []: + complete(null); + case _: + } + } + + private function complete(winner:TeamId):Void { + engine.ticker.emit(function() { + gameEventSignal.emit(COMPLETE({state: state, level: level, winner: winner})); + }, 3000, "complete"); + } + + public function onSpawn(entity:EntityType):Void {} + + private static function buildShot(bullet:Bullet, score:Null = null):Shot { + return { + tankId: bullet.tank.id, + bulletId: bullet.id, + score: score, + } + } + + public function onCollision(entity:EntityType, with:EntityType):Void { + switch entity { + case EntityType.TANK(tank): + if (controls.exists(tank.playerId)) { + controls[tank.playerId].onCollision(with); + } + case _: + } + switch [entity, with] { + case [TANK(tank), TANK(other_tank)]: + tank.rect.lean(other_tank.rect); + GameUtil.emitTankMove(this, tank); + case [TANK(tank), EAGLE(eagle)]: + tank.rect.lean(eagle.rect); + GameUtil.emitTankMove(this, tank); + case [TANK(tank), CELL(cell)]: + tank.rect.lean(cell.rect); + GameUtil.emitTankMove(this, tank); + case [BULLET(bullet), BULLET(other_bullet)]: + if (bullet.playerId != other_bullet.playerId && bullet.layer > 0 && other_bullet.layer > 0) { + gameEventSignal.emit(DESTROY(BULLET(bullet.id))); + gameEventSignal.emit(DESTROY(BULLET(other_bullet.id))); + } + case [BULLET(bullet), CELL(cell)]: + bullet.rect.lean(cell.rect); + gameEventSignal.emit(HIT(CELL(cell.cellX, cell.cellY, buildShot(bullet)))); + gameEventSignal.emit(DESTROY(BULLET(bullet.id))); + case [TANK(tank), BONUS(bonus)]: + gameEventSignal.emit(DESTROY(BONUS(bonus.id, {tankId: tank.id, score: bonus.config.score}))); + case [BULLET(bullet), TANK(tank)] | [TANK(tank), BULLET(bullet)]: + if (bullet.playerId == tank.playerId + || (!config.game.friendlyFire && tank.playerId.team == bullet.playerId.team)) { + // Nothing + } else { + if (!tank.protect) { + if (tank.boat) { + tank.boat = false; + GameUtil.emitTankChange(this, tank); + } else if (tank.hits > 0) { + tank.hits--; + if (tank.bonus) { + tank.bonus = false; + spawnBonus(); + } + gameEventSignal.emit(HIT(TANK(tank.id, buildShot(bullet)))); + GameUtil.emitTankChange(this, tank); + } else if (tank.config.downgrade != null) { + tank.config = config.getTank(tank.config.downgrade); + gameEventSignal.emit(HIT(TANK(tank.id, buildShot(bullet)))); + GameUtil.emitTankChange(this, tank); } else { - engine.ticker.start(); + var score = tank.config.score; + if (score != null && tank.playerId.team == bullet.playerId.team) { + score = Math.round(score * -0.5); + } + gameEventSignal.emit(DESTROY(TANK(tank.id, buildShot(bullet, score)))); } - gameEventSignal.emit(PAUSE(value)); + } + gameEventSignal.emit(DESTROY(BULLET(bullet.id))); } + case [BULLET(bullet), EAGLE(eagle)]: + if (!eagle.death) { + if (!eagle.protect) { + var score = eagle.config.score; + if (score != null && eagle.team == bullet.playerId.team) { + score = Math.round(score * -0.5); + } + gameEventSignal.emit(DESTROY(EAGLE(eagle.id, buildShot(bullet, score)))); + } + gameEventSignal.emit(DESTROY(BULLET(bullet.id))); + } + case _: } + } - override public function update():Void { - super.update(); - engine.update(); + public function onMove(entity:EntityType, move:Bool):Void { + switch entity { + case TANK(tank): + GameUtil.emitTankMove(this, tank, move); + case BULLET(bullet): + gameEventSignal.emit(MOVE(BULLET(bullet.id, + {x: bullet.rect.x, y: bullet.rect.y, direction: bullet.rect.direction}))); + case _: } + } - override public function start():Void { - super.start(); - gameEventSignal.emit(START({level:level, state:state})); - updater.start(update); + public function onDestroy(entity:EntityType):Void {} + + private function spawnBonus(type:BonusType = null):Void { + if (type == null) { + type = config.bonuses[Math.floor(Math.random() * config.bonuses.length)].type; } + var point = { + x: Math.floor(Math.random() * (engine.map.gridWidth - 1)), + y: Math.floor(Math.random() * (engine.map.gridHeight - 1)), + direction: "right", + } + var bonus = builder.buildBonus(point, type); + engine.spawn(bonus); + gameEventSignal.emit(EventUtil.buildBonusSpawn(bonus)); + if (config.game.bonusSpawnInterval != null) { + ticker.emit(function() spawnBonus(), config.game.bonusSpawnInterval, "bonus"); + } + } - override public function dispose():Void { - super.dispose(); + private function applyBonus(tank:Tank, bonus:Bonus):Void { + var bonus = bonuses.build(bonus.config); + bonus.apply(tank.playerId, this, engine); + } + + override public function onGameEvent(event:GameEvent):Void { + if (pause) { + switch event { + case ACTION(_): + return; + case _: + } + } + super.onGameEvent(event); + switch event { + case START(_): + engine.ticker.start(); + case COMPLETE(_): + engine.ticker.stop(); updater.stop(); - } - - public function newPlayerTank(playerId:PlayerId):TankInfo { + case ACTION(tankId, SHOT(index)): + var tank:Tank = cast engine.entities.get(tankId); + var player = getPlayer(tank.playerId); + if (!tank.freezing) { + var weapon:Weapon = tank.weapons.length > index - 1 ? tank.weapons[index] : null; + if (weapon != null && weapon.use(ticker)) { + var rect = tank.rect; + var point = rect.center.add(new Point(rect.width / 4 * rect.direction.x, + rect.height / 4 * rect.direction.y)); + var bullet = builder.buildBullet(point, rect.direction, player.id, weapon.config.bullet); + // ToDo: mine color + if (bullet.config.skin == "mine") { + bullet.color = config.getColor(player.id); + } + bullet.tank = tank; + bullet.weapon = weapon; + bullet.move(bullet.rect.direction); + engine.spawn(bullet); + gameEventSignal.emit(EventUtil.buildBulletSpawn(bullet)); + } + } + case ACTION(tankId, MOVE(direction)): + engine.move(tankId, direction); + case ACTION(tankId, STOP): + engine.stop(tankId); + case SPAWN(EAGLE(id, rect, teamId)): + var team = getTeam(teamId); + team.eagleId = id; + case SPAWN(TANK(id, rect, playerId, info)): var player = getPlayer(playerId); - var spawn = player.config.tanks[Math.floor(Math.random() * player.config.tanks.length)]; - var tank = config.getTank(spawn.type); - var bonus = Math.random() < player.config.bonus; - return { - type:tank.type, - skin:tank.skin, - hits:tank.hits, - bonus:bonus, - boat:false, - color:player.state.color, - name:player.state.name, + player.tankId = id; + player.state.tank = info; + case CHANGE(BRICK(id, type)): + engine.map.bricksById[id].config = config.getBrick(type); + case CHANGE(TANK(id, type, hits, bonus, boat)): + var tank:Tank = engine.getEntity(id); + getPlayer(tank.playerId).state.tank = tank.info; + case DESTROY(EAGLE(id, shot)): + var eagle:Eagle = engine.getEntity(id); + eagle.death = true; + var shooter = getPlayer(cast(engine.getEntity(shot.tankId), Tank).playerId); + shooter.state.frags.push({ + playerId: new PlayerId(eagle.team, -1), + target: EAGLE(eagle.color), + score: shot.score, + }); + if (shot.score != null) { + var tank:Tank = engine.getEntity(shot.tankId); + GameUtil.changeScore(this, tank.playerId, shot.score); } - } - - override private function onStart(start:Start):Void { - super.onStart(start); - var mapData = level.data.map(function(index:BrickIndex) return config.getBrickByIndex(index)); - engine.map.setData(mapData); - for (team in teams.iterator()) { - team.spawner.runner = spawn; - for (player in team.players.iterator()) { - if (team.tryRespawn(player.id)) { - team.spawner.push(engine.ticker, player.id, player.state.tank != null ? player.state.tank : newPlayerTank(player.id)); - } - } - if (team.config.eagle != null) { - var point = team.spawner.getPoint("eagle"); - var eagle = builder.buildEagle(point, team.id); - engine.spawn(eagle); - gameEventSignal.emit(EventUtil.buildEagleSpawn(eagle)); + checkComplete(); + case DESTROY(TANK(id, shot)): + var tank:Tank = engine.getEntity(id); + var team = getTeam(tank.playerId.team); + var player = getPlayer(tank.playerId); + player.tankId = -1; + team.onDestroy(player.id); + if (player.state.life > 0) { + GameUtil.changeLife(this, player.id, -1); + } else if (team.state.life > 0) { + GameUtil.changeTeamLife(this, team.id, -1); + } + var respawn:Bool = team.tryRespawn(player.id); + if (respawn) { + team.spawner.push(engine.ticker, player.id, newPlayerTank(player.id)); + } + if (!team.isAlive) { + checkComplete(); + } + if (tank.bonus && shot.bulletId != null) { + spawnBonus(); + } + var shooter = getPlayer(cast(engine.getEntity(shot.tankId), Tank).playerId); + shooter.state.frags.push({ + playerId: player.id, + target: TANK(tank.info), + score: shot.score, + }); + if (shot.score != null) { + GameUtil.changeScore(this, shooter.id, shot.score); + } + engine.destroy(id); + case DESTROY(BONUS(id, shot)): + var bonus:Bonus = engine.getEntity(id); + var tank:Tank = engine.getEntity(shot.tankId); + applyBonus(tank, bonus); + var shooter = getPlayer(tank.playerId); + shooter.state.frags.push({ + playerId: shooter.id, + target: BONUS(bonus.config.type), + score: shot.score, + }); + if (shot.score != null) { + GameUtil.changeScore(this, tank.playerId, shot.score); + } + engine.destroy(id); + case DESTROY(BULLET(id)): + var bullet:Bullet = engine.getEntity(id); + bullet.weapon.release(); + var side:Line = bullet.rect.getSide(bullet.rect.direction.reverse()).move( // ToDo: move + new Point(bullet.rect.direction.x * 5, bullet.rect.direction.y * 5)); + var cells = engine.map.grid.getCells(side.setLength(engine.map.grid.cellWidth * 3)); + for (cell in cells) { + if (cell.armor > 0) { + var shot = buildShot(bullet); + if (cell.armor == bullet.config.piercing) { + engine.destroyCell(cell.cellX, cell.cellY); + var brick = engine.map.getCellBrick(cell.position); + gameEventSignal.emit(DESTROY(CELL(brick.id, cell.cellX - brick.cellX * 2, cell.cellY - brick.cellY * 2, + shot))); + } else if (cell.armor < bullet.config.piercing) { + var brick = engine.map.getCellBrick(cell.position); + for (cell in brick.cells) { + engine.destroyCell(cell.cellX, cell.cellY); + } + gameEventSignal.emit(DESTROY(BRICK(brick.id, shot))); } + } } - gameEventSignal.emit(EventUtil.buildBricksSpawn(engine.map)); - //for (i in 0...10) spawnBonus(); - if (config.game.bonusSpawnInterval != null) { - ticker.emit(function() spawnBonus(), config.game.bonusSpawnInterval, "bonus"); - } - } - - private function spawn(task:SpawnTask):Void { - var player = getPlayer(task.playerId); - var tank = builder.buildTank(task.point, task.playerId, task.tank); - if (getTeam(player.id.team).freezing) { - tank.freezing = true; - } - engine.spawn(tank); - gameEventSignal.emit(EventUtil.buildTankSpawn(tank)); - if (player.config.protect > 0) { - GameUtil.protectTank(this, tank, player.config.protect); - } - } - - private function checkComplete():Void { - var actives:Array = []; - for (team in teams.iterator()) { - if (team.isAlive) { - if (team.eagleId > -1) { - var eagle:Eagle = engine.getEntity(team.eagleId); - if (!eagle.death) { - actives.push(team.id); - } - } else { - actives.push(team.id); - } - } - } - switch actives { - case [winner]: complete(winner); - case []: complete(null); - case _: - } - } - - private function complete(winner:TeamId):Void { - engine.ticker.emit(function() { - gameEventSignal.emit(COMPLETE({state: state, level: level, winner: winner})); - }, 3000, "complete"); - } - - public function onSpawn(entity:EntityType):Void { - } - - private static function buildShot(bullet:Bullet, score:Null = null):Shot { - return { - tankId: bullet.tank.id, - bulletId: bullet.id, - score: score, - } - } - - public function onCollision(entity:EntityType, with:EntityType):Void { - switch entity { - case EntityType.TANK(tank): - if (controls.exists(tank.playerId)) { - controls[tank.playerId].onCollision(with); - } - case _: - } - switch [entity, with] { - case [TANK(tank), TANK(other_tank)]: - tank.rect.lean(other_tank.rect); - GameUtil.emitTankMove(this, tank); - case [TANK(tank), EAGLE(eagle)]: - tank.rect.lean(eagle.rect); - GameUtil.emitTankMove(this, tank); - case [TANK(tank), CELL(cell)]: - tank.rect.lean(cell.rect); - GameUtil.emitTankMove(this, tank); - case [BULLET(bullet), BULLET(other_bullet)]: - if (bullet.playerId != other_bullet.playerId && bullet.layer > 0 && other_bullet.layer > 0) { - gameEventSignal.emit(DESTROY(BULLET(bullet.id))); - gameEventSignal.emit(DESTROY(BULLET(other_bullet.id))); - } - case [BULLET(bullet), CELL(cell)]: - bullet.rect.lean(cell.rect); - gameEventSignal.emit(HIT(CELL(cell.cellX, cell.cellY, buildShot(bullet)))); - gameEventSignal.emit(DESTROY(BULLET(bullet.id))); - case [TANK(tank), BONUS(bonus)]: - gameEventSignal.emit(DESTROY(BONUS(bonus.id, {tankId: tank.id, score: bonus.config.score}))); - case [BULLET(bullet), TANK(tank)] | [TANK(tank), BULLET(bullet)]: - if (bullet.playerId == tank.playerId || (!config.game.friendlyFire && tank.playerId.team == bullet.playerId.team)) { - // Nothing - } else { - if (!tank.protect) { - if (tank.boat) { - tank.boat = false; - GameUtil.emitTankChange(this, tank); - } else if (tank.hits > 0) { - tank.hits--; - if (tank.bonus) { - tank.bonus = false; - spawnBonus(); - } - gameEventSignal.emit(HIT(TANK(tank.id, buildShot(bullet)))); - GameUtil.emitTankChange(this, tank); - } else if (tank.config.downgrade != null) { - tank.config = config.getTank(tank.config.downgrade); - gameEventSignal.emit(HIT(TANK(tank.id, buildShot(bullet)))); - GameUtil.emitTankChange(this, tank); - } else { - var score = tank.config.score; - if (score != null && tank.playerId.team == bullet.playerId.team) { - score = Math.round(score * -0.5); - } - gameEventSignal.emit(DESTROY(TANK(tank.id, buildShot(bullet, score)))); - } - } - gameEventSignal.emit(DESTROY(BULLET(bullet.id))); - } - case [BULLET(bullet), EAGLE(eagle)]: - if (!eagle.death) { - if (!eagle.protect) { - var score = eagle.config.score; - if (score != null && eagle.team == bullet.playerId.team) { - score = Math.round(score * -0.5); - } - gameEventSignal.emit(DESTROY(EAGLE(eagle.id, buildShot(bullet, score)))); - } - gameEventSignal.emit(DESTROY(BULLET(bullet.id))); - } - case _: - } - } - - public function onMove(entity:EntityType, move:Bool):Void { - switch entity { - case TANK(tank): - GameUtil.emitTankMove(this, tank, move); - case BULLET(bullet): - gameEventSignal.emit(MOVE(BULLET(bullet.id, {x:bullet.rect.x, y:bullet.rect.y, direction:bullet.rect.direction}))); - case _: - } - } - - public function onDestroy(entity:EntityType):Void { - } - - private function spawnBonus(type:BonusType = null):Void { - if (type == null) { - type = config.bonuses[Math.floor(Math.random() * config.bonuses.length)].type; - } - var point = { - x: Math.floor(Math.random() * (engine.map.gridWidth - 1)), - y: Math.floor(Math.random() * (engine.map.gridHeight - 1)), - direction: "right", - } - var bonus = builder.buildBonus(point, type); - engine.spawn(bonus); - gameEventSignal.emit(EventUtil.buildBonusSpawn(bonus)); - if (config.game.bonusSpawnInterval != null) { - ticker.emit(function() spawnBonus(), config.game.bonusSpawnInterval, "bonus"); - } - } - - private function applyBonus(tank:Tank, bonus:Bonus):Void { - var bonus = bonuses.build(bonus.config); - bonus.apply(tank.playerId, this, engine); - } - - override public function onGameEvent(event:GameEvent):Void { - if (pause) { - switch event { - case ACTION(_): return; - case _: - } - } - super.onGameEvent(event); - switch event { - case START(_): - engine.ticker.start(); - case COMPLETE(_): - engine.ticker.stop(); - updater.stop(); - case ACTION(tankId, SHOT(index)): - var tank:Tank = cast engine.entities.get(tankId); - var player = getPlayer(tank.playerId); - if (!tank.freezing) { - var weapon:Weapon = tank.weapons.length > index - 1 ? tank.weapons[index] : null; - if (weapon != null && weapon.use(ticker)) { - var rect = tank.rect; - var point = rect.center.add(new Point(rect.width / 4 * rect.direction.x, rect.height / 4 * rect.direction.y)); - var bullet = builder.buildBullet(point, rect.direction, player.id, weapon.config.bullet); - // ToDo: mine color - if (bullet.config.skin == "mine") { - bullet.color = config.getColor(player.id); - } - bullet.tank = tank; - bullet.weapon = weapon; - bullet.move(bullet.rect.direction); - engine.spawn(bullet); - gameEventSignal.emit(EventUtil.buildBulletSpawn(bullet)); - } - } - case ACTION(tankId, MOVE(direction)): - engine.move(tankId, direction); - case ACTION(tankId, STOP): - engine.stop(tankId); - case SPAWN(EAGLE(id, rect, teamId)): - var team = getTeam(teamId); - team.eagleId = id; - case SPAWN(TANK(id, rect, playerId, info)): - var player = getPlayer(playerId); - player.tankId = id; - player.state.tank = info; - case CHANGE(BRICK(id, type)): - engine.map.bricksById[id].config = config.getBrick(type); - case CHANGE(TANK(id, type, hits, bonus, boat)): - var tank:Tank = engine.getEntity(id); - getPlayer(tank.playerId).state.tank = tank.info; - case DESTROY(EAGLE(id, shot)): - var eagle:Eagle = engine.getEntity(id); - eagle.death = true; - var shooter = getPlayer(cast(engine.getEntity(shot.tankId), Tank).playerId); - shooter.state.frags.push({ - playerId: new PlayerId(eagle.team, -1), - target: EAGLE(eagle.color), - score: shot.score, - }); - if (shot.score != null) { - var tank:Tank = engine.getEntity(shot.tankId); - GameUtil.changeScore(this, tank.playerId, shot.score); - } - checkComplete(); - case DESTROY(TANK(id, shot)): - var tank:Tank = engine.getEntity(id); - var team = getTeam(tank.playerId.team); - var player = getPlayer(tank.playerId); - player.tankId = -1; - team.onDestroy(player.id); - if (player.state.life > 0) { - GameUtil.changeLife(this, player.id, -1); - } else if (team.state.life > 0) { - GameUtil.changeTeamLife(this, team.id, -1); - } - var respawn:Bool = team.tryRespawn(player.id); - if (respawn) { - team.spawner.push(engine.ticker, player.id, newPlayerTank(player.id)); - } - if (!team.isAlive) { - checkComplete(); - } - if (tank.bonus && shot.bulletId != null) { - spawnBonus(); - } - var shooter = getPlayer(cast(engine.getEntity(shot.tankId), Tank).playerId); - shooter.state.frags.push({ - playerId: player.id, - target: TANK(tank.info), - score: shot.score, - }); - if (shot.score != null) { - GameUtil.changeScore(this, shooter.id, shot.score); - } - engine.destroy(id); - case DESTROY(BONUS(id, shot)): - var bonus:Bonus = engine.getEntity(id); - var tank:Tank = engine.getEntity(shot.tankId); - applyBonus(tank, bonus); - var shooter = getPlayer(tank.playerId); - shooter.state.frags.push({ - playerId: shooter.id, - target: BONUS(bonus.config.type), - score: shot.score, - }); - if (shot.score != null) { - GameUtil.changeScore(this, tank.playerId, shot.score); - } - engine.destroy(id); - case DESTROY(BULLET(id)): - var bullet:Bullet = engine.getEntity(id); - bullet.weapon.release(); - var side:Line = bullet.rect.getSide(bullet.rect.direction.reverse()).move( - // ToDo: move - new Point(bullet.rect.direction.x * 5, bullet.rect.direction.y * 5) - ); - var cells = engine.map.grid.getCells(side.setLength(engine.map.grid.cellWidth * 3)); - for (cell in cells) { - if (cell.armor > 0) { - var shot = buildShot(bullet); - if (cell.armor == bullet.config.piercing) { - engine.destroyCell(cell.cellX, cell.cellY); - var brick = engine.map.getCellBrick(cell.position); - gameEventSignal.emit(DESTROY(CELL(brick.id, cell.cellX - brick.cellX * 2, cell.cellY - brick.cellY * 2, shot))); - } else if (cell.armor < bullet.config.piercing) { - var brick = engine.map.getCellBrick(cell.position); - for (cell in brick.cells) { - engine.destroyCell(cell.cellX, cell.cellY); - } - gameEventSignal.emit(DESTROY(BRICK(brick.id, shot))); - } - } - } - engine.destroy(id); - case _: - } + engine.destroy(id); + case _: } + } } diff --git a/src/common/haxe/ru/m/tankz/game/GameState.hx b/src/common/haxe/ru/m/tankz/game/GameState.hx index 9d63279..c7d6c2e 100644 --- a/src/common/haxe/ru/m/tankz/game/GameState.hx +++ b/src/common/haxe/ru/m/tankz/game/GameState.hx @@ -8,151 +8,151 @@ import ru.m.tankz.control.PlayerControl; import ru.m.tankz.Type; enum FragTarget { - TANK(tank:TankInfo); - EAGLE(color:Color); - BONUS(type:BonusType); + TANK(tank:TankInfo); + EAGLE(color:Color); + BONUS(type:BonusType); } typedef Frag = { - var playerId:PlayerId; - var target:FragTarget; - var score:Score; + var playerId:PlayerId; + var target:FragTarget; + var score:Score; } class PlayerState { - public var id:PlayerId; - public var tank:TankInfo; - public var color:Color; - public var name:String; - public var life:Int; - public var score:Int; - public var frags:Array; + public var id:PlayerId; + public var tank:TankInfo; + public var color:Color; + public var name:String; + public var life:Int; + public var score:Int; + public var frags:Array; - public function new(id:PlayerId) { - this.id = id; - this.tank = null; - this.life = 0; - this.score = 0; - this.frags = []; - } + public function new(id:PlayerId) { + this.id = id; + this.tank = null; + this.life = 0; + this.score = 0; + this.frags = []; + } } class TeamState { - public var id:TeamId; - public var players:Map; - public var life:Int; + public var id:TeamId; + public var players:Map; + public var life:Int; - public function new(id:TeamId) { - this.id = id; - this.life = 0; - this.players = new Map(); - } + public function new(id:TeamId) { + this.id = id; + this.life = 0; + this.players = new Map(); + } } class GameState { + public var type:GameType; + public var presetId:PresetId; + public var controls:Array; + public var players:Map; + public var humans(get, null):Array; + public var teams:Map; + public var preset(get, null):GamePreset; + public var config(get, null):Config; - public var type:GameType; - public var presetId:PresetId; - public var controls:Array; - public var players:Map; - public var humans(get, null):Array; - public var teams:Map; - public var preset(get, null):GamePreset; - public var config(get, null):Config; + @:provide static private var configBundle:IConfigBundle; - @:provide static private var configBundle:IConfigBundle; - - public function new(type:GameType, presetId:PresetId = 0, state:GameState = null, controls:Array = null) { - this.type = type; - this.presetId = presetId; - this.controls = controls == null ? [] : controls; - if (state == null) { - this.teams = new Map(); - this.players = new Map(); - for (team in preset.teams) { - var teamState = new TeamState(team.id); - for (player in team.players) { - var playerId = new PlayerId(team.id, player.index); - var playerState = new PlayerState(playerId); - playerState.life = config.getPlayer(playerId).life; - players[playerId] = playerState; - teamState.players[player.index] = playerState; - } - teams[team.id] = teamState; - } - } else { - this.teams = state.teams; - this.players = state.players; + public function new(type:GameType, presetId:PresetId = 0, state:GameState = null, + controls:Array = null) { + this.type = type; + this.presetId = presetId; + this.controls = controls == null ? [] : controls; + if (state == null) { + this.teams = new Map(); + this.players = new Map(); + for (team in preset.teams) { + var teamState = new TeamState(team.id); + for (player in team.players) { + var playerId = new PlayerId(team.id, player.index); + var playerState = new PlayerState(playerId); + playerState.life = config.getPlayer(playerId).life; + players[playerId] = playerState; + teamState.players[player.index] = playerState; } + teams[team.id] = teamState; + } + } else { + this.teams = state.teams; + this.players = state.players; } + } - public function get_humans():Array { - var humanControls = controls.filter(function(control:PlayerControl):Bool { - return switch control.controller { - case HUMAN(_): true; - case _: false; - } - }); - humanControls.sort(function(a, b) return switch [a.controller, b.controller] { - case [HUMAN(i), HUMAN(j)]: i - j; - case _: 0; - }); - return humanControls.map(function(control:PlayerControl):PlayerState { - return players.get(control.playerId); - }); - } + public function get_humans():Array { + var humanControls = controls.filter(function(control:PlayerControl):Bool { + return switch control.controller { + case HUMAN(_): true; + case _: false; + } + }); + humanControls.sort(function(a, b) return switch [a.controller, b.controller] { + case [HUMAN(i), HUMAN(j)]: i - j; + case _: 0; + }); + return humanControls.map(function(control:PlayerControl):PlayerState { + return players.get(control.playerId); + }); + } - private function get_preset():GamePreset { - var config = configBundle.get(type); - var preset = config.getPreset(presetId); - return preset; - } + private function get_preset():GamePreset { + var config = configBundle.get(type); + var preset = config.getPreset(presetId); + return preset; + } - private function get_config():Config { - return configBundle.get(type); - } + private function get_config():Config { + return configBundle.get(type); + } - public function getTeamLife(id:TeamId):Int { - if (teams.exists(id)) { - return teams[id].life + Lambda.fold(teams[id].players, function(p, c) return c + p.life, 0); - } - return 0; + public function getTeamLife(id:TeamId):Int { + if (teams.exists(id)) { + return teams[id].life + Lambda.fold(teams[id].players, function(p, c) return c + p.life, 0); } + return 0; + } - public function getTeamScore(id:TeamId):Int { - if (teams.exists(id)) { - return Lambda.fold(teams[id].players, function(p, c) return c + p.score, 0); - } - return 0; + public function getTeamScore(id:TeamId):Int { + if (teams.exists(id)) { + return Lambda.fold(teams[id].players, function(p, c) return c + p.score, 0); } + return 0; + } - public function getPlayerLife(id:PlayerId):Int { - if (players.exists(id)) { - return players[id].life; - } - return 0; + public function getPlayerLife(id:PlayerId):Int { + if (players.exists(id)) { + return players[id].life; } + return 0; + } - public function getPlayerScore(id:PlayerId):Int { - if (players.exists(id)) { - return players[id].score; - } - return 0; + public function getPlayerScore(id:PlayerId):Int { + if (players.exists(id)) { + return players[id].score; } + return 0; + } - public function getPlayerColor(id:PlayerId):Color { - var playerState = players[id]; - return (playerState == null || playerState.color.zero) ? config.getColor(id) : playerState.color; - } + public function getPlayerColor(id:PlayerId):Color { + var playerState = players[id]; + return (playerState == null || playerState.color.zero) ? config.getColor(id) : playerState.color; + } - public function clean():Void { - for (p in players) { - p.frags = []; - var playerConfig = config.getPlayer(p.id); - if (!playerConfig.saveState) { - p.tank = null; - p.life = playerConfig.life; - } - } + public function clean():Void { + for (p in players) { + p.frags = []; + var playerConfig = config.getPlayer(p.id); + if (!playerConfig.saveState) { + p.tank = null; + p.life = playerConfig.life; + } } + } } diff --git a/src/common/haxe/ru/m/tankz/game/GameTracer.hx b/src/common/haxe/ru/m/tankz/game/GameTracer.hx index e2d8380..8c35659 100644 --- a/src/common/haxe/ru/m/tankz/game/GameTracer.hx +++ b/src/common/haxe/ru/m/tankz/game/GameTracer.hx @@ -3,11 +3,9 @@ package ru.m.tankz.game; import ru.m.tankz.game.IGame; class GameTracer implements GameListener { + public function new() {} - public function new() { - } - - public function onGameEvent(event:GameEvent):Void { - L.d("Game", Std.string(event)); - } + public function onGameEvent(event:GameEvent):Void { + L.d("Game", Std.string(event)); + } } diff --git a/src/common/haxe/ru/m/tankz/game/GameUtil.hx b/src/common/haxe/ru/m/tankz/game/GameUtil.hx index 2e98917..e32e744 100644 --- a/src/common/haxe/ru/m/tankz/game/GameUtil.hx +++ b/src/common/haxe/ru/m/tankz/game/GameUtil.hx @@ -10,100 +10,99 @@ import ru.m.tankz.Type; using ru.m.tankz.game.GameUtil; class GameUtil { + private static inline function teamTank(team:TeamId):Tank->Bool { + return function(tank:Tank):Bool return team == tank.playerId.team; + } - private static inline function teamTank(team:TeamId):Tank->Bool { - return function(tank:Tank):Bool return team == tank.playerId.team; + public static inline function alienTank(team:TeamId):Tank->Bool { + return function(tank:Tank):Bool return team != tank.playerId.team; + } + + public static inline function emitTankMove(game:IGame, tank:Tank, move:Bool = true):Void { + game.gameEventSignal.emit(MOVE(TANK(tank.id, {x: tank.rect.x, y: tank.rect.y, direction: tank.rect.direction}))); + if (!move) { + game.gameEventSignal.emit(STOP(TANK(tank.id))); } + } - public static inline function alienTank(team:TeamId):Tank->Bool { - return function(tank:Tank):Bool return team != tank.playerId.team; + public static inline function emitTankChange(game:IGame, tank:Tank):Void { + game.gameEventSignal.emit(CHANGE(TANK(tank.id, tank.config.type, tank.hits, tank.bonus, tank.boat))); + } + + public static function protectTank(game:IGame, tank:Tank, duration:Float):Void { + tank.protect = true; + game.gameEventSignal.emit(CHANGE(TANK_PROTECT(tank.id, tank.protect))); + game.ticker.emit(function() { + tank.protect = false; + game.gameEventSignal.emit(CHANGE(TANK_PROTECT(tank.id, tank.protect))); + }, Std.int(duration * 1000), 'protect.tank.${tank.id}'); + } + + public static function protectEagle(game:IGame, eagle:Eagle, duration:Float):Void { + eagle.protect = true; + game.gameEventSignal.emit(CHANGE(EAGLE_PROTECT(eagle.id, eagle.protect))); + game.ticker.emit(function() { + eagle.protect = false; + game.gameEventSignal.emit(CHANGE(EAGLE_PROTECT(eagle.id, eagle.protect))); + }, Std.int(duration * 1000), 'protect.eagle.${eagle.id}'); + } + + public static function freezeTank(game:IGame, tank:Tank, duration:Float):Void { + tank.freezing = true; + tank.stop(); + game.gameEventSignal.emit(STOP(TANK(tank.id))); + game.gameEventSignal.emit(CHANGE(TANK_FREEZE(tank.id, tank.freezing))); + game.ticker.emit(function() { + tank.freezing = false; + game.gameEventSignal.emit(CHANGE(TANK_FREEZE(tank.id, tank.freezing))); + }, Std.int(duration * 1000), 'freeze.tank.${tank.id}'); + } + + public static function freezeTeam(game:IGame, engine:IEngine, teamId:TeamId, duration:Float):Void { + game.getTeam(teamId).freezing = true; + for (tank in engine.getTanks(teamId.teamTank())) { + tank.freezing = true; + tank.stop(); + game.gameEventSignal.emit(STOP(TANK(tank.id))); + game.gameEventSignal.emit(CHANGE(TANK_FREEZE(tank.id, tank.freezing))); } - - public static inline function emitTankMove(game:IGame, tank:Tank, move:Bool = true):Void { - game.gameEventSignal.emit(MOVE(TANK(tank.id, {x:tank.rect.x, y:tank.rect.y, direction:tank.rect.direction}))); - if (!move) { - game.gameEventSignal.emit(STOP(TANK(tank.id))); - } - } - - public static inline function emitTankChange(game:IGame, tank:Tank):Void { - game.gameEventSignal.emit(CHANGE(TANK(tank.id, tank.config.type, tank.hits, tank.bonus, tank.boat))); - } - - public static function protectTank(game:IGame, tank:Tank, duration:Float):Void { - tank.protect = true; - game.gameEventSignal.emit(CHANGE(TANK_PROTECT(tank.id, tank.protect))); - game.ticker.emit(function() { - tank.protect = false; - game.gameEventSignal.emit(CHANGE(TANK_PROTECT(tank.id, tank.protect))); - }, Std.int(duration * 1000), 'protect.tank.${tank.id}'); - } - - public static function protectEagle(game:IGame, eagle:Eagle, duration:Float):Void { - eagle.protect = true; - game.gameEventSignal.emit(CHANGE(EAGLE_PROTECT(eagle.id, eagle.protect))); - game.ticker.emit(function() { - eagle.protect = false; - game.gameEventSignal.emit(CHANGE(EAGLE_PROTECT(eagle.id, eagle.protect))); - }, Std.int(duration * 1000), 'protect.eagle.${eagle.id}'); - } - - public static function freezeTank(game:IGame, tank:Tank, duration:Float):Void { - tank.freezing = true; - tank.stop(); - game.gameEventSignal.emit(STOP(TANK(tank.id))); + game.ticker.emit(function() { + game.getTeam(teamId).freezing = false; + for (tank in engine.getTanks(teamId.teamTank())) { + tank.freezing = false; game.gameEventSignal.emit(CHANGE(TANK_FREEZE(tank.id, tank.freezing))); - game.ticker.emit(function() { - tank.freezing = false; - game.gameEventSignal.emit(CHANGE(TANK_FREEZE(tank.id, tank.freezing))); - }, Std.int(duration * 1000), 'freeze.tank.${tank.id}'); - } + } + }, Std.int(duration * 1000), 'freeze.team.${teamId}'); + } - public static function freezeTeam(game:IGame, engine:IEngine, teamId:TeamId, duration:Float):Void { - game.getTeam(teamId).freezing = true; - for (tank in engine.getTanks(teamId.teamTank())) { - tank.freezing = true; - tank.stop(); - game.gameEventSignal.emit(STOP(TANK(tank.id))); - game.gameEventSignal.emit(CHANGE(TANK_FREEZE(tank.id, tank.freezing))); - } - game.ticker.emit(function() { - game.getTeam(teamId).freezing = false; - for (tank in engine.getTanks(teamId.teamTank())) { - tank.freezing = false; - game.gameEventSignal.emit(CHANGE(TANK_FREEZE(tank.id, tank.freezing))); - } - }, Std.int(duration * 1000), 'freeze.team.${teamId}'); - } + public static function changeLife(game:IGame, playerId:PlayerId, life:Int):Void { + var player = game.getPlayer(playerId); + player.state.life += life; + game.gameEventSignal.emit(CHANGE(PLAYER_LIFE(playerId, player.state.life))); + } - public static function changeLife(game:IGame, playerId:PlayerId, life:Int):Void { - var player = game.getPlayer(playerId); - player.state.life += life; - game.gameEventSignal.emit(CHANGE(PLAYER_LIFE(playerId, player.state.life))); - } + public static function changeTeamLife(game:IGame, teamId:TeamId, life:Int):Void { + var team = game.getTeam(teamId); + team.state.life += life; + game.gameEventSignal.emit(CHANGE(TEAM_LIFE(teamId, team.state.life))); + } - public static function changeTeamLife(game:IGame, teamId:TeamId, life:Int):Void { - var team = game.getTeam(teamId); - team.state.life += life; - game.gameEventSignal.emit(CHANGE(TEAM_LIFE(teamId, team.state.life))); - } + public static function changeScore(game:IGame, playerId:PlayerId, score:Int):Void { + var player = game.getPlayer(playerId); + var team = game.getTeam(playerId.team); + player.state.score += score; + game.gameEventSignal.emit(CHANGE(PLAYER_SCORE(playerId, player.state.score))); + game.gameEventSignal.emit(CHANGE(TEAM_SCORE(playerId.team, game.state.getTeamScore(team.id)))); + } - public static function changeScore(game:IGame, playerId:PlayerId, score:Int):Void { - var player = game.getPlayer(playerId); - var team = game.getTeam(playerId.team); - player.state.score += score; - game.gameEventSignal.emit(CHANGE(PLAYER_SCORE(playerId, player.state.score))); - game.gameEventSignal.emit(CHANGE(TEAM_SCORE(playerId.team, game.state.getTeamScore(team.id)))); - } - - public static function upgradeTank(game:IGame, tank:Tank, level:Int = 1):Void { - if (tank.config.upgrade != null) { - while (level-- > 0 && tank.config.upgrade != null) { - tank.config = game.config.getTank(tank.config.upgrade); - } - } else { - tank.hits++; - } - game.emitTankChange(tank); + public static function upgradeTank(game:IGame, tank:Tank, level:Int = 1):Void { + if (tank.config.upgrade != null) { + while (level-- > 0 && tank.config.upgrade != null) { + tank.config = game.config.getTank(tank.config.upgrade); + } + } else { + tank.hits++; } + game.emitTankChange(tank); + } } diff --git a/src/common/haxe/ru/m/tankz/game/IGame.hx b/src/common/haxe/ru/m/tankz/game/IGame.hx index 49387af..d5e6243 100644 --- a/src/common/haxe/ru/m/tankz/game/IGame.hx +++ b/src/common/haxe/ru/m/tankz/game/IGame.hx @@ -8,34 +8,34 @@ import ru.m.tankz.control.IControlFactory; import ru.m.tankz.Type; interface IGame extends GameListener { - public var type(default, null):GameType; - public var teams(default, null):Map; - public var config(default, null):Config; - public var winner(default, null):Null; - public var state(default, null):GameState; - public var level(default, null):LevelConfig; - public var controlFactory(default, null):IControlFactory; - public var pause(default, set):Bool; - public var controls(default, null):Map; - public var ticker(default, null):ITicker; + public var type(default, null):GameType; + public var teams(default, null):Map; + public var config(default, null):Config; + public var winner(default, null):Null; + public var state(default, null):GameState; + public var level(default, null):LevelConfig; + public var controlFactory(default, null):IControlFactory; + public var pause(default, set):Bool; + public var controls(default, null):Map; + public var ticker(default, null):ITicker; - public var gameEventSignal(default, null):Signal; + public var gameEventSignal(default, null):Signal; - public function connect(listener:GameListener):Void; + public function connect(listener:GameListener):Void; - public function disconnect(listener:GameListener):Void; + public function disconnect(listener:GameListener):Void; - public function dispose():Void; + public function dispose():Void; - public function getTeam(teamId:TeamId):Team; + public function getTeam(teamId:TeamId):Team; - public function getPlayer(playerId:PlayerId):Player; + public function getPlayer(playerId:PlayerId):Player; - public function start():Void; + public function start():Void; - public function update():Void; + public function update():Void; } interface GameListener { - public function onGameEvent(event:GameEvent):Void; + public function onGameEvent(event:GameEvent):Void; } diff --git a/src/common/haxe/ru/m/tankz/game/PackProgress.hx b/src/common/haxe/ru/m/tankz/game/PackProgress.hx index 10a3167..4636a7d 100644 --- a/src/common/haxe/ru/m/tankz/game/PackProgress.hx +++ b/src/common/haxe/ru/m/tankz/game/PackProgress.hx @@ -2,61 +2,59 @@ package ru.m.tankz.game; import ru.m.tankz.Type; -typedef LevelResult = { - -} +typedef LevelResult = {} typedef LevelProgress = { - var id:LevelId; - var presets:Map; + var id:LevelId; + var presets:Map; } class PackProgress { + public var id(default, null):PackId; - public var id(default, null):PackId; + private var completed(default, null):Map; - private var completed(default, null):Map; + public var progress(get, null):Int; - public var progress(get, null):Int; - - private function get_progress():Int { - var result = -1; - for (i in completed.keys()) { - if (i > result) { - result = i; - } - } - return result + 1; + private function get_progress():Int { + var result = -1; + for (i in completed.keys()) { + if (i > result) { + result = i; + } } + return result + 1; + } - public function new(id:PackId) { - this.id = id; - this.completed = new Map(); - } + public function new(id:PackId) { + this.id = id; + this.completed = new Map(); + } - public function isLevelAvailable(levelId:LevelId):Bool { - return levelId == 0 || completed.exists(levelId - 1); - } + public function isLevelAvailable(levelId:LevelId):Bool { + return levelId == 0 || completed.exists(levelId - 1); + } - public function isPresetAvailable(levelId:LevelId, presetId:PresetId):Bool { - return isLevelAvailable(levelId) && (presetId == 0 || (completed.exists(levelId) && completed.get(levelId).presets.get(presetId - 1) != null)); - } + public function isPresetAvailable(levelId:LevelId, presetId:PresetId):Bool { + return isLevelAvailable(levelId) + && (presetId == 0 || (completed.exists(levelId) && completed.get(levelId).presets.get(presetId - 1) != null)); + } - public function isPresetCompleted(levelId:LevelId, presetId:PresetId):Bool { - return completed.exists(levelId) && completed.get(levelId).presets.get(presetId) != null; - } + public function isPresetCompleted(levelId:LevelId, presetId:PresetId):Bool { + return completed.exists(levelId) && completed.get(levelId).presets.get(presetId) != null; + } - public function completeLevel(levelId:LevelId, presetId:PresetId, result:LevelResult):Void { - if (!completed.exists(levelId)) { - completed[levelId] = { - id: levelId, - presets: new Map(), - } - } - completed[levelId].presets[presetId] = result; + public function completeLevel(levelId:LevelId, presetId:PresetId, result:LevelResult):Void { + if (!completed.exists(levelId)) { + completed[levelId] = { + id: levelId, + presets: new Map(), + } } + completed[levelId].presets[presetId] = result; + } - public function toString():String { - return 'PackProgress(id=${id}, completed=${completed}})'; - } + public function toString():String { + return 'PackProgress(id=${id}, completed=${completed}})'; + } } diff --git a/src/common/haxe/ru/m/tankz/game/Player.hx b/src/common/haxe/ru/m/tankz/game/Player.hx index 3bfb8b5..cdc628b 100644 --- a/src/common/haxe/ru/m/tankz/game/Player.hx +++ b/src/common/haxe/ru/m/tankz/game/Player.hx @@ -5,25 +5,25 @@ import ru.m.tankz.game.GameState; import ru.m.tankz.Type; class Player { - public var config(default, null):PlayerConfig; - public var id(default, null):PlayerId; - public var tankId(default, set):Int; - public var isAlive(get, null):Bool; - public var state(default, default):PlayerState; + public var config(default, null):PlayerConfig; + public var id(default, null):PlayerId; + public var tankId(default, set):Int; + public var isAlive(get, null):Bool; + public var state(default, default):PlayerState; - public function new(teamId:TeamId, config:PlayerConfig, state:PlayerState = null) { - this.config = config; - this.id = new PlayerId(teamId, config.index); - this.state = state == null ? new PlayerState(id) : state; - this.tankId = -1; - } + public function new(teamId:TeamId, config:PlayerConfig, state:PlayerState = null) { + this.config = config; + this.id = new PlayerId(teamId, config.index); + this.state = state == null ? new PlayerState(id) : state; + this.tankId = -1; + } - private function set_tankId(value:Int):Int { - tankId = value; - return tankId; - } + private function set_tankId(value:Int):Int { + tankId = value; + return tankId; + } - private function get_isAlive():Bool { - return tankId > -1 || state.life > 0; - } + private function get_isAlive():Bool { + return tankId > -1 || state.life > 0; + } } diff --git a/src/common/haxe/ru/m/tankz/game/Spawner.hx b/src/common/haxe/ru/m/tankz/game/Spawner.hx index cb41128..f27b3e7 100644 --- a/src/common/haxe/ru/m/tankz/game/Spawner.hx +++ b/src/common/haxe/ru/m/tankz/game/Spawner.hx @@ -5,77 +5,77 @@ import ru.m.tankz.engine.ITicker; import ru.m.tankz.Type; typedef SpawnTask = { - var point:SpawnPoint; - var playerId:PlayerId; - var tank:TankInfo; + var point:SpawnPoint; + var playerId:PlayerId; + var tank:TankInfo; } class Spawner { + public var active(get, never):Bool; + public var runner(default, default):SpawnTask->Void; - public var active(get, never):Bool; - public var runner(default, default):SpawnTask -> Void; + private var config:TeamConfig; + private var points:Array; + private var queue:Array; - private var config:TeamConfig; - private var points:Array; - private var queue:Array; + private var indexedPoints:Map; + private var anyPoints:Array; + private var index:Int; - private var indexedPoints:Map; - private var anyPoints:Array; - private var index:Int; - - public function new(config:TeamConfig, points:Array) { - this.config = config; - this.points = points; - this.runner = null; - this.index = 0; - queue = []; - indexedPoints = new Map(); - anyPoints = []; - for (point in points) { - if (point.type == 'tank') { - if (point.index > -1) { - indexedPoints.set(point.index, point); - } else { - anyPoints.push(point); - } - } - } - } - - public function getPoint(type:String, index:Int=-1):Null { - for (point in points) { - if (point.type == type && point.index == index) { - return point; - } - } - return null; - } - - public function push(ticker:ITicker, playerId:PlayerId, tank:TankInfo):Void { - var point:SpawnPoint = null; - if (indexedPoints.exists(playerId.index)) { - point = indexedPoints.get(playerId.index); + public function new(config:TeamConfig, points:Array) { + this.config = config; + this.points = points; + this.runner = null; + this.index = 0; + queue = []; + indexedPoints = new Map(); + anyPoints = []; + for (point in points) { + if (point.type == 'tank') { + if (point.index > -1) { + indexedPoints.set(point.index, point); } else { - point = anyPoints[index++]; - if (index >= anyPoints.length) index = 0; - } - if (point != null) { - queue.push({playerId:playerId, point:point, tank:tank}); - if (config.spawnInterval == null) { - ticker.emit(spawn, 500); - } else { - ticker.emit(spawn, 500 + config.spawnInterval * queue.length); - } + anyPoints.push(point); } + } } + } - private function spawn():Void { - if (queue.length > 0) { - runner(queue.shift()); - } + public function getPoint(type:String, index:Int = -1):Null { + for (point in points) { + if (point.type == type && point.index == index) { + return point; + } } + return null; + } - private function get_active():Bool { - return queue.length > 0; + public function push(ticker:ITicker, playerId:PlayerId, tank:TankInfo):Void { + var point:SpawnPoint = null; + if (indexedPoints.exists(playerId.index)) { + point = indexedPoints.get(playerId.index); + } else { + point = anyPoints[index++]; + if (index >= anyPoints.length) + index = 0; } + if (point != null) { + queue.push({playerId: playerId, point: point, tank: tank}); + if (config.spawnInterval == null) { + ticker.emit(spawn, 500); + } else { + ticker.emit(spawn, 500 + config.spawnInterval * queue.length); + } + } + } + + private function spawn():Void { + if (queue.length > 0) { + runner(queue.shift()); + } + } + + private function get_active():Bool { + return queue.length > 0; + } } diff --git a/src/common/haxe/ru/m/tankz/game/Team.hx b/src/common/haxe/ru/m/tankz/game/Team.hx index 7897f11..25a52f9 100644 --- a/src/common/haxe/ru/m/tankz/game/Team.hx +++ b/src/common/haxe/ru/m/tankz/game/Team.hx @@ -5,62 +5,63 @@ import ru.m.tankz.game.GameState; import ru.m.tankz.Type; class Team { + public var id(default, null):TeamId; + public var config(default, null):TeamConfig; + public var spawner(default, null):Spawner; + public var players(default, null):Map; + public var isAlive(get, null):Bool; + public var score(get, null):Int; + public var eagleId(default, default):Int; - public var id(default, null):TeamId; - public var config(default, null):TeamConfig; - public var spawner(default, null):Spawner; - public var players(default, null):Map; - public var isAlive(get, null):Bool; - public var score(get, null):Int; - public var eagleId(default, default):Int; - private var active(default, default):Int; - public var state(default, default):TeamState; - public var freezing(default, default):Bool; + private var active(default, default):Int; - public function new(config:TeamConfig, points:Array, state:TeamState = null) { - this.id = config.id; - this.config = config; - this.active = 0; - this.eagleId = -1; - this.players = new Map(); - for (playerConfig in config.players) { - var playerState = state == null ? null : state.players[playerConfig.index]; - var player:Player = new Player(id, playerConfig, playerState); - this.players[playerConfig.index] = player; - } - this.spawner = new Spawner(config, points); - this.state = state == null ? new TeamState(id) : state; - this.state.life = config.life; + public var state(default, default):TeamState; + public var freezing(default, default):Bool; + + public function new(config:TeamConfig, points:Array, state:TeamState = null) { + this.id = config.id; + this.config = config; + this.active = 0; + this.eagleId = -1; + this.players = new Map(); + for (playerConfig in config.players) { + var playerState = state == null ? null : state.players[playerConfig.index]; + var player:Player = new Player(id, playerConfig, playerState); + this.players[playerConfig.index] = player; } + this.spawner = new Spawner(config, points); + this.state = state == null ? new TeamState(id) : state; + this.state.life = config.life; + } - public function tryRespawn(playerId:PlayerId):Bool { - var player:Player = players[playerId.index]; - var result = player.state.life > 0 || state.life > active; - active++; - return result; - } + public function tryRespawn(playerId:PlayerId):Bool { + var player:Player = players[playerId.index]; + var result = player.state.life > 0 || state.life > active; + active++; + return result; + } - public function onDestroy(playerId:PlayerId):Void { - active--; - } + public function onDestroy(playerId:PlayerId):Void { + active--; + } - // ToDo: eagle state? - private function get_isAlive():Bool { - if (state.life > 0) { - return true; - } - if (spawner.active) { - return true; - } - for (player in players) { - if (player.isAlive) { - return true; - } - } - return false; + // ToDo: eagle state? + private function get_isAlive():Bool { + if (state.life > 0) { + return true; } + if (spawner.active) { + return true; + } + for (player in players) { + if (player.isAlive) { + return true; + } + } + return false; + } - private function get_score():Int { - return Lambda.fold(players, function(p:Player, s:Int) return s + p.state.score, 0); - } + private function get_score():Int { + return Lambda.fold(players, function(p:Player, s:Int) return s + p.state.score, 0); + } } diff --git a/src/common/haxe/ru/m/tankz/game/record/GamePlayer.hx b/src/common/haxe/ru/m/tankz/game/record/GamePlayer.hx index 1c9336b..e896208 100644 --- a/src/common/haxe/ru/m/tankz/game/record/GamePlayer.hx +++ b/src/common/haxe/ru/m/tankz/game/record/GamePlayer.hx @@ -6,47 +6,46 @@ import ru.m.tankz.engine.Ticker; import ru.m.tankz.game.record.GameRecord; class GamePlayer extends Game { + private var record:GameRecord; + private var data:Array; - private var record:GameRecord; - private var data:Array; + public function new(record:GameRecord) { + super(record.state.type); + this.record = record; + this.data = null; + this.ticker = new Ticker(); + } - public function new(record:GameRecord) { - super(record.state.type); - this.record = record; - this.data = null; - this.ticker = new Ticker(); - } + override public function start():Void { + super.start(); + ticker.start(); + data = record.events.slice(0); + Lib.current.stage.addEventListener(Event.ENTER_FRAME, onEnterFrame); + } - override public function start():Void { - super.start(); - ticker.start(); - data = record.events.slice(0); - Lib.current.stage.addEventListener(Event.ENTER_FRAME, onEnterFrame); - } + public function stop():Void { + ticker.stop(); + Lib.current.stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame); + } - public function stop():Void { - ticker.stop(); - Lib.current.stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame); - } - - private function onEnterFrame(event:Event):Void { - ticker.tick(); - var events = 0; - for (event in data) { - if (event.time <= ticker.time) { - events++; - gameEventSignal.emit(event.event); - switch event.event { - case GameEvent.COMPLETE(_): - stop(); - case _: - } - } else { - break; - } - } - if (events > 0) { - data = data.slice(events); + private function onEnterFrame(event:Event):Void { + ticker.tick(); + var events = 0; + for (event in data) { + if (event.time <= ticker.time) { + events++; + gameEventSignal.emit(event.event); + switch event.event { + case GameEvent.COMPLETE(_): + stop(); + case _: } + } else { + break; + } } + if (events > 0) { + data = data.slice(events); + } + } } diff --git a/src/common/haxe/ru/m/tankz/game/record/GameRecord.hx b/src/common/haxe/ru/m/tankz/game/record/GameRecord.hx index ee4440a..4c9e5b4 100644 --- a/src/common/haxe/ru/m/tankz/game/record/GameRecord.hx +++ b/src/common/haxe/ru/m/tankz/game/record/GameRecord.hx @@ -5,37 +5,38 @@ import com.hurlant.crypto.extra.UUID; import com.hurlant.crypto.prng.Random; typedef EventItem = { - var time:Int; - var event:GameEvent; + var time:Int; + var event:GameEvent; } class GameRecordInfo { - public var id(default, default):String; - public var date(default, default):Date; - public var type(default, default):GameType; - public var presetId(default, default):PresetId; - public var levelId(default, default):LevelId; + public var id(default, default):String; + public var date(default, default):Date; + public var type(default, default):GameType; + public var presetId(default, default):PresetId; + public var levelId(default, default):LevelId; - public function new() {} + public function new() {} } class GameRecord { - public var info(default, null):GameRecordInfo; - public var events(default, default):Array; + public var info(default, null):GameRecordInfo; + public var events(default, default):Array; - public var state(get, null):GameState; + public var state(get, null):GameState; - public function new() { - this.info = new GameRecordInfo(); - this.info.id = UUID.generateRandom(new Random()).toString(); - this.events = []; - } + public function new() { + this.info = new GameRecordInfo(); + this.info.id = UUID.generateRandom(new Random()).toString(); + this.events = []; + } - private inline function get_state():GameState { - return new GameState(info.type, info.presetId); - } + private inline function get_state():GameState { + return new GameState(info.type, info.presetId); + } - public function toString():String { - return 'GameRecord{id=${info.id},date=${info.date},type=${info.type},preset=${info.presetId},level=${info.levelId},events=${events.length}}'; - } + public function toString():String { + return + 'GameRecord{id=${info.id},date=${info.date},type=${info.type},preset=${info.presetId},level=${info.levelId},events=${events.length}}'; + } } diff --git a/src/common/haxe/ru/m/tankz/game/record/GameRecorder.hx b/src/common/haxe/ru/m/tankz/game/record/GameRecorder.hx index 10cbf43..1db6327 100644 --- a/src/common/haxe/ru/m/tankz/game/record/GameRecorder.hx +++ b/src/common/haxe/ru/m/tankz/game/record/GameRecorder.hx @@ -5,29 +5,28 @@ import ru.m.tankz.engine.Ticker; import ru.m.tankz.game.IGame; class GameRecorder implements GameListener { + public var record(default, null):GameRecord; - public var record(default, null):GameRecord; + private var ticker:ITicker; - private var ticker:ITicker; + public function new() { + ticker = new Ticker(); + record = new GameRecord(); + } - public function new() { - ticker = new Ticker(); - record = new GameRecord(); - } - - public function onGameEvent(event:GameEvent):Void { - switch event { - case GameEvent.START(state, level): - ticker.start(); - record.info.type = state.type; - record.info.presetId = state.presetId; - record.info.levelId = level.id; - record.info.date = Date.now(); - case GameEvent.COMPLETE(_, _): - ticker.stop(); - case _: - } - ticker.tick(); - record.events.push({time: ticker.time, event: event}); + public function onGameEvent(event:GameEvent):Void { + switch event { + case GameEvent.START(state, level): + ticker.start(); + record.info.type = state.type; + record.info.presetId = state.presetId; + record.info.levelId = level.id; + record.info.date = Date.now(); + case GameEvent.COMPLETE(_, _): + ticker.stop(); + case _: } + ticker.tick(); + record.events.push({time: ticker.time, event: event}); + } } diff --git a/src/common/haxe/ru/m/tankz/map/Brick.hx b/src/common/haxe/ru/m/tankz/map/Brick.hx index e9679b2..56e315b 100644 --- a/src/common/haxe/ru/m/tankz/map/Brick.hx +++ b/src/common/haxe/ru/m/tankz/map/Brick.hx @@ -5,80 +5,76 @@ import ru.m.tankz.config.Config; import ru.m.tankz.map.Grid.GridCell; class Brick { - public var id(get, null):Int; + public var id(get, null):Int; - public var cellX(default, null):Int; - public var cellY(default, null):Int; + public var cellX(default, null):Int; + public var cellY(default, null):Int; - public var mapConfig(default, null):MapConfig; - public var config(default, set):BrickConfig; + public var mapConfig(default, null):MapConfig; + public var config(default, set):BrickConfig; - public var rect(default, null):Rectangle; - public var cells(default, null):Map; - public var broken(get, null):Int; - public var destroyed(get, set):Bool; + public var rect(default, null):Rectangle; + public var cells(default, null):Map; + public var broken(get, null):Int; + public var destroyed(get, set):Bool; - public function new(mapConfig:MapConfig, config:BrickConfig, cellX:Int, cellY:Int, cells:Map) { - this.cellX = cellX; - this.cellY = cellY; - this.cells = cells; - this.mapConfig = mapConfig; - this.config = config; - this.rect = new Rectangle( - cellX * mapConfig.cell.width, - cellY * mapConfig.cell.height, - mapConfig.cell.width, - mapConfig.cell.height - ); + public function new(mapConfig:MapConfig, config:BrickConfig, cellX:Int, cellY:Int, cells:Map) { + this.cellX = cellX; + this.cellY = cellY; + this.cells = cells; + this.mapConfig = mapConfig; + this.config = config; + this.rect = new Rectangle(cellX * mapConfig.cell.width, cellY * mapConfig.cell.height, mapConfig.cell.width, + mapConfig.cell.height); + } + + private function set_config(value:BrickConfig):BrickConfig { + config = value; + for (cell in cells) { + cell.layer = config.layer; + cell.armor = config.armor; + cell.destroyed = false; } + return config; + } - private function set_config(value:BrickConfig):BrickConfig { - config = value; - for (cell in cells) { - cell.layer = config.layer; - cell.armor = config.armor; - cell.destroyed = false; - } - return config; + private function get_broken():Int { + var i:Int = 0; + for (c in cells.iterator()) { + if (c.destroyed) { + i++; + } } + return i; + } - private function get_broken():Int { - var i:Int = 0; - for (c in cells.iterator()) { - if (c.destroyed) { - i++; - } - } - return i; + private function get_destroyed():Bool { + var i = 0; + var result:Bool = false; + for (c in cells.iterator()) { + if (!c.destroyed) { + return false; + } else { + result = true; + } } + return result; + } - private function get_destroyed():Bool { - var i = 0; - var result:Bool = false; - for (c in cells.iterator()) { - if (!c.destroyed) { - return false; - } else { - result = true; - } - } - return result; + private function set_destroyed(value:Bool):Bool { + if (value) { + for (c in cells.iterator()) { + c.destroyed = true; + } } + return value; + } - private function set_destroyed(value:Bool):Bool { - if (value) { - for (c in cells.iterator()) { - c.destroyed = true; - } - } - return value; - } + private function get_id():Int { + return -((cellX * 1000) + cellY); + } - private function get_id():Int { - return -((cellX * 1000) + cellY); - } - - public function toString() { - return 'Brick(${config.type},$cellX:$cellY)'; - } + public function toString() { + return 'Brick(${config.type},$cellX:$cellY)'; + } } diff --git a/src/common/haxe/ru/m/tankz/map/Grid.hx b/src/common/haxe/ru/m/tankz/map/Grid.hx index 928bf1e..355c7f7 100644 --- a/src/common/haxe/ru/m/tankz/map/Grid.hx +++ b/src/common/haxe/ru/m/tankz/map/Grid.hx @@ -5,77 +5,78 @@ import ru.m.geom.Line; import ru.m.geom.Rectangle; class GridCell { - public var cellX(default, null):Int; - public var cellY(default, null):Int; + public var cellX(default, null):Int; + public var cellY(default, null):Int; - public var position(default, null):GridPoint; - public var rect(default, null):Rectangle; - public var layer:Int; - public var armor:Float; - public var destroyed(default, set):Bool; + public var position(default, null):GridPoint; + public var rect(default, null):Rectangle; + public var layer:Int; + public var armor:Float; + public var destroyed(default, set):Bool; - public function new(cellX:Int, cellY:Int, width:Int, height:Int, layer:Int, armor:Float) { - this.cellX = cellX; - this.cellY = cellY; - this.position = new GridPoint(cellX, cellY); - this.rect = new Rectangle(cellX * width, cellY * height, width, height); - this.layer = layer; - this.armor = armor; - this.destroyed = false; + public function new(cellX:Int, cellY:Int, width:Int, height:Int, layer:Int, armor:Float) { + this.cellX = cellX; + this.cellY = cellY; + this.position = new GridPoint(cellX, cellY); + this.rect = new Rectangle(cellX * width, cellY * height, width, height); + this.layer = layer; + this.armor = armor; + this.destroyed = false; + } + + private function set_destroyed(value:Bool):Bool { + destroyed = value; + if (destroyed) { + this.layer = 0; + this.armor = 0; } + return destroyed; + } - private function set_destroyed(value:Bool):Bool { - destroyed = value; - if (destroyed) { - this.layer = 0; - this.armor = 0; - } - return destroyed; - } - - public inline function getCollision(layer:Int):Bool { - return this.layer == -1 || (this.layer >= layer && this.layer < 3); - } + public inline function getCollision(layer:Int):Bool { + return this.layer == -1 || (this.layer >= layer && this.layer < 3); + } } class Grid { - public var cellWidth(default, null):Int; - public var cellHeight(default, null):Int; - public var width(default, null):Int; - public var height(default, null):Int; + public var cellWidth(default, null):Int; + public var cellHeight(default, null):Int; + public var width(default, null):Int; + public var height(default, null):Int; - private var border:Rectangle; + private var border:Rectangle; - public var cells(default, null):Map; + public var cells(default, null):Map; - public function new(cellWidth:Int, cellHeight:Int, width:Int, height:Int) { - this.cellWidth = cellWidth; - this.cellHeight = cellHeight; - this.width = width; - this.height = height; - border = new Rectangle(0, 0, Math.floor(width / cellWidth) - 1, Math.floor(height / cellHeight) - 1); - cells = new Map(); - } + public function new(cellWidth:Int, cellHeight:Int, width:Int, height:Int) { + this.cellWidth = cellWidth; + this.cellHeight = cellHeight; + this.width = width; + this.height = height; + border = new Rectangle(0, 0, Math.floor(width / cellWidth) - 1, Math.floor(height / cellHeight) - 1); + cells = new Map(); + } - private function buildBorderCell(cellX:Int, cellY:Int):GridCell { - return new GridCell(cellX, cellY, cellWidth, cellHeight, -1, -1); - } + private function buildBorderCell(cellX:Int, cellY:Int):GridCell { + return new GridCell(cellX, cellY, cellWidth, cellHeight, -1, -1); + } - public function getCells(line:Line):Array { - var result:Array = []; - for (x in Math.floor(line.point1.x / cellWidth)...Math.ceil(line.point2.x / cellWidth)) { - for (y in Math.floor(line.point1.y / cellHeight)...Math.ceil(line.point2.y / cellHeight)) { - var point = new GridPoint(x, y); - if (!border.contain(point)) { - var cell = buildBorderCell(Std.int(point.x), Std.int(point.y)); - cells.set(point, cell); - result.push(cell); - } else { - var cell = cells.get(point); - if (cell != null) result.push(cell); - } - } + public function getCells(line:Line):Array { + var result:Array = []; + for (x in Math.floor(line.point1.x / cellWidth)...Math.ceil(line.point2.x / cellWidth)) { + for (y in Math.floor(line.point1.y / cellHeight)...Math.ceil(line.point2.y / cellHeight)) { + var point = new GridPoint(x, y); + if (!border.contain(point)) { + var cell = buildBorderCell(Std.int(point.x), Std.int(point.y)); + cells.set(point, cell); + result.push(cell); + } else { + var cell = cells.get(point); + if (cell != null) + result.push(cell); } - return result; + } } + return result; + } } diff --git a/src/common/haxe/ru/m/tankz/map/LevelMap.hx b/src/common/haxe/ru/m/tankz/map/LevelMap.hx index 80f10d2..6c9e297 100755 --- a/src/common/haxe/ru/m/tankz/map/LevelMap.hx +++ b/src/common/haxe/ru/m/tankz/map/LevelMap.hx @@ -6,83 +6,80 @@ import ru.m.tankz.config.Config; import ru.m.tankz.map.Grid; class LevelMap { + public var config(default, null):MapConfig; - public var config(default, null):MapConfig; + public var cellWidth(default, null):Float; + public var cellHeight(default, null):Float; + public var gridWidth(default, null):Int; + public var gridHeight(default, null):Int; - public var cellWidth(default, null):Float; - public var cellHeight(default, null):Float; - public var gridWidth(default, null):Int; - public var gridHeight(default, null):Int; + public var width(get, null):Float; + public var height(get, null):Float; - public var width(get, null):Float; - public var height(get, null):Float; + public var bricks(default, null):Array; + public var bricksById(default, null):Map; - public var bricks(default, null):Array; - public var bricksById(default, null):Map; + public var grid(default, null):Grid; - public var grid(default, null):Grid; + private var bricksMap(default, null):Map; - private var bricksMap(default, null):Map; + public function new(config:MapConfig, size:GridSize = null) { + this.config = config; + cellWidth = config.cell.width; + cellHeight = config.cell.width; + gridWidth = size != null ? size.width : config.grid.width; + gridHeight = size != null ? size.height : config.grid.height; + bricksMap = new Map(); + bricks = []; + bricksById = new Map(); + grid = new Grid(Std.int(cellWidth / 2), Std.int(cellHeight / 2), Std.int(cellWidth * gridWidth), + Std.int(cellHeight * gridHeight)); + } - public function new(config:MapConfig, size:GridSize = null) { - this.config = config; - cellWidth = config.cell.width; - cellHeight = config.cell.width; - gridWidth = size != null ? size.width : config.grid.width; - gridHeight = size != null ? size.height : config.grid.height; - bricksMap = new Map(); - bricks = []; - bricksById = new Map(); - grid = new Grid( - Std.int(cellWidth / 2), - Std.int(cellHeight / 2), - Std.int(cellWidth * gridWidth), - Std.int(cellHeight * gridHeight) - ); - } + public function setData(data:Array):Void { + bricksMap = new Map(); + bricks = Lambda.array(Lambda.mapi(data, function(i:Int, brickConfig:BrickConfig):Brick { + var cellX = Std.int(i % gridWidth); + var cellY = Std.int(Math.floor(i / gridWidth)); + var cells:Map = new Map(); + var point:Point = new Point(cellX * 2, cellY * 2); + if (brickConfig.layer > 0 || brickConfig.armor > 0) { + for (x in 0...2) + for (y in 0...2) { + var cell:GridCell = new GridCell(Std.int(point.x + x), Std.int(point.y + y), Std.int(cellWidth / 2), + Std.int(cellHeight / 2), brickConfig.layer, brickConfig.armor); + grid.cells.set(cell.position, cell); + cells.set(new GridPoint(x, y), cell); + } + } + var brick = new Brick(config, brickConfig, cellX, cellY, cells); + for (cell in brick.cells.iterator()) { + bricksMap.set(cell.position, brick); + } + bricksById.set(brick.id, brick); + return brick; + })); + } - public function setData(data:Array):Void { - bricksMap = new Map(); - bricks = Lambda.array(Lambda.mapi(data, function(i:Int, brickConfig:BrickConfig):Brick { - var cellX = Std.int(i % gridWidth); - var cellY = Std.int(Math.floor(i / gridWidth)); - var cells:Map = new Map(); - var point:Point = new Point(cellX * 2, cellY * 2); - if (brickConfig.layer > 0 || brickConfig.armor > 0) { - for (x in 0...2) for (y in 0...2) { - var cell:GridCell = new GridCell(Std.int(point.x + x), Std.int(point.y + y), Std.int(cellWidth / 2), Std.int(cellHeight / 2), brickConfig.layer, brickConfig.armor); - grid.cells.set(cell.position, cell); - cells.set(new GridPoint(x, y), cell); - } - } - var brick = new Brick(config, brickConfig, cellX, cellY, cells); - for (cell in brick.cells.iterator()) { - bricksMap.set(cell.position, brick); - } - bricksById.set(brick.id, brick); - return brick; - })); - } + public function getBrick(position:Point):Brick { + return bricks[Std.int(position.x + position.y * gridWidth)]; + } - public function getBrick(position:Point):Brick { - return bricks[Std.int(position.x + position.y * gridWidth)]; - } + public function getCellBrick(position:GridPoint):Brick { + return bricksMap.get(position); + } - public function getCellBrick(position:GridPoint):Brick { - return bricksMap.get(position); - } + public function getPointBrick(point:Point):Brick { + var cellX:Int = Math.floor(point.x / cellWidth); + var cellY:Int = Math.floor(point.y / cellHeight); + return bricks[cellX + cellY * gridWidth]; + } - public function getPointBrick(point:Point):Brick { - var cellX:Int = Math.floor(point.x / cellWidth); - var cellY:Int = Math.floor(point.y / cellHeight); - return bricks[cellX + cellY * gridWidth]; - } + private inline function get_width():Float { + return cellWidth * gridWidth; + } - private inline function get_width():Float { - return cellWidth * gridWidth; - } - - private inline function get_height():Float { - return cellHeight * gridHeight; - } + private inline function get_height():Float { + return cellHeight * gridHeight; + } } diff --git a/src/common/haxe/ru/m/tankz/util/LevelUtil.hx b/src/common/haxe/ru/m/tankz/util/LevelUtil.hx index e176e30..10e56e2 100644 --- a/src/common/haxe/ru/m/tankz/util/LevelUtil.hx +++ b/src/common/haxe/ru/m/tankz/util/LevelUtil.hx @@ -13,96 +13,97 @@ import yaml.Renderer; import yaml.Yaml; typedef LevelSource = { - var data:String; - @:optional var name:String; - @:optional var points:Array; - @:optional var size:GridSize; + var data:String; + @:optional var name:String; + @:optional var points:Array; + @:optional var size:GridSize; } class LevelUtil { + private static function yamlParse(data:String):Dynamic { + return Yaml.parse(data, Parser.options().useObjects()); + } - private static function yamlParse(data:String):Dynamic { - return Yaml.parse(data, Parser.options().useObjects()); + private static function yamlRender(data:Dynamic):String { + return new SortingRenderer().render(data, Renderer.options().setFlowLevel(1)); + } + + public static function formatLevel(level:Int):String { + var result = Std.string(level); + while (result.length < 3) + result = '0${result}'; + return result; + } + + public static function loads(data:String):LevelConfig { + var obj:LevelSource = yamlParse(data); + return { + data: obj.data.split('').map(function(c) return Std.parseInt(c)), + points: obj.points, + name: obj.name, + size: obj.size, } + } - private static function yamlRender(data:Dynamic):String { - return new SortingRenderer().render(data, Renderer.options().setFlowLevel(1)); + public static function dumps(level:LevelConfig):String { + var bricksStr = level.data.join(''); + return yamlRender({ + data: bricksStr, + points: level.points, + name: level.name, + size: level.size, + }); + } + + public static function empty(size:GridSize, filler:BrickIndex):LevelConfig { + return { + data: [for (i in 0...size.width * size.height) filler], + size: size, } + } - public static function formatLevel(level:Int):String { - var result = Std.string(level); - while (result.length < 3) result = '0${result}'; - return result; + public static function getMeta(bytes:Bytes):LevelPackMeta { + var files = haxe.zip.Reader.readZip(new BytesInput(bytes)); + for (entry in files) { + if (entry.fileName == "meta.yml") { + var content = ZipUtil.extractEntry(entry); + return yamlParse(content); + } } + return null; + } - public static function loads(data:String):LevelConfig { - var obj:LevelSource = yamlParse(data); - return { - data: obj.data.split('').map(function(c) return Std.parseInt(c)), - points: obj.points, - name: obj.name, - size: obj.size, + public static function unpack(bytes:Bytes):LevelPack { + var files = haxe.zip.Reader.readZip(new BytesInput(bytes)); + var meta = null; + var data:Array = []; + for (entry in files) { + var content = ZipUtil.extractEntry(entry); + if (entry.fileName == "meta.yml") { + meta = yamlParse(content); + } else { + var level:LevelConfig = LevelUtil.loads(content); + level.packId = meta.id; + if (level.id == null) { + level.id = Std.parseInt(entry.fileName.split("level").pop()); } + data.push(level); + } } + return { + id: meta.id, + meta: meta, + data: data, + } + } - public static function dumps(level:LevelConfig):String { - var bricksStr = level.data.join(''); - return yamlRender({ - data: bricksStr, - points: level.points, - name: level.name, - size: level.size, - }); - } - - public static function empty(size:GridSize, filler:BrickIndex):LevelConfig { - return { - data: [for (i in 0...size.width * size.height) filler], - size: size, - } - } - - public static function getMeta(bytes:Bytes):LevelPackMeta { - var files = haxe.zip.Reader.readZip(new BytesInput(bytes)); - for (entry in files) { - if (entry.fileName == "meta.yml") { - var content = ZipUtil.extractEntry(entry); - return yamlParse(content); - } - } - return null; - } - - public static function unpack(bytes:Bytes):LevelPack { - var files = haxe.zip.Reader.readZip(new BytesInput(bytes)); - var meta = null; - var data:Array = []; - for (entry in files) { - var content = ZipUtil.extractEntry(entry); - if (entry.fileName == "meta.yml") { - meta = yamlParse(content); - } else { - var level:LevelConfig = LevelUtil.loads(content); - level.packId = meta.id; - if (level.id == null) { - level.id = Std.parseInt(entry.fileName.split("level").pop()); - } - data.push(level); - } - } - return { - id: meta.id, - meta: meta, - data: data, - } - } - - public static function pack(pack:LevelPack):Bytes { - var output = new BytesOutput(); - var writer = new Writer(output); - var metaEntry:Entry = ZipUtil.createEntry("meta.yml", yamlRender(pack.meta)); - var levelEntries:Array = pack.data.map(function(level) return ZipUtil.createEntry('${formatLevel(level.id)}.yml', dumps(level))); - writer.write(Lambda.list([metaEntry].concat(levelEntries))); - return output.getBytes(); - } + public static function pack(pack:LevelPack):Bytes { + var output = new BytesOutput(); + var writer = new Writer(output); + var metaEntry:Entry = ZipUtil.createEntry("meta.yml", yamlRender(pack.meta)); + var levelEntries:Array = pack.data.map(function(level) return + ZipUtil.createEntry('${formatLevel(level.id)}.yml', dumps(level))); + writer.write(Lambda.list([metaEntry].concat(levelEntries))); + return output.getBytes(); + } } diff --git a/src/common/haxe/ru/m/tankz/util/ZipUtil.hx b/src/common/haxe/ru/m/tankz/util/ZipUtil.hx index abaa6b9..3e80b27 100644 --- a/src/common/haxe/ru/m/tankz/util/ZipUtil.hx +++ b/src/common/haxe/ru/m/tankz/util/ZipUtil.hx @@ -5,32 +5,31 @@ import haxe.zip.Entry; import haxe.zip.Tools; class ZipUtil { - - public static function extractEntry(entry:Entry):String { - var bytes:Bytes = entry.data; - if (entry.compressed) { - #if ((flash || html5) && lime) - bytes = cast(bytes, lime.utils.Bytes).decompress(lime.utils.CompressionAlgorithm.DEFLATE); - #else - bytes = haxe.zip.Reader.unzip(entry); - #end - } - return bytes.toString(); + public static function extractEntry(entry:Entry):String { + var bytes:Bytes = entry.data; + if (entry.compressed) { + #if ((flash || html5) && lime) + bytes = cast(bytes, lime.utils.Bytes).decompress(lime.utils.CompressionAlgorithm.DEFLATE); + #else + bytes = haxe.zip.Reader.unzip(entry); + #end } + return bytes.toString(); + } - public static function createEntry(name:String, content:String):Entry { - var bytes = Bytes.ofString(content); - var crc = haxe.crypto.Crc32.make(bytes); - var result:Entry = { - fileName: name, - fileSize: bytes.length, - fileTime: Date.now(), - compressed: false, - dataSize: bytes.length, - data: bytes, - crc32: crc, - }; - Tools.compress(result, 9); - return result; - } + public static function createEntry(name:String, content:String):Entry { + var bytes = Bytes.ofString(content); + var crc = haxe.crypto.Crc32.make(bytes); + var result:Entry = { + fileName: name, + fileSize: bytes.length, + fileTime: Date.now(), + compressed: false, + dataSize: bytes.length, + data: bytes, + crc32: crc, + }; + Tools.compress(result, 9); + return result; + } } diff --git a/src/common/haxe/ru/m/tankz2/config/Config.hx b/src/common/haxe/ru/m/tankz2/config/Config.hx index 3b9b1b0..02bbabe 100644 --- a/src/common/haxe/ru/m/tankz2/config/Config.hx +++ b/src/common/haxe/ru/m/tankz2/config/Config.hx @@ -1,27 +1,25 @@ package ru.m.tankz2.config; typedef MapConfig = { - var grid:{ - width:Int, - height:Int, - }; + var grid:{ + width:Int, + height:Int, + }; } typedef TankConfig = { - var width:Float; - var height:Float; - var speed:Float; + var width:Float; + var height:Float; + var speed:Float; } -typedef PlayerConfig = { - -} +typedef PlayerConfig = {} typedef TeamConfig = { - var players:Array; + var players:Array; } typedef Config = { - var map:MapConfig; - var teams:Array; + var map:MapConfig; + var teams:Array; } diff --git a/src/common/haxe/ru/m/tankz2/game/Game.hx b/src/common/haxe/ru/m/tankz2/game/Game.hx index c5e9585..4691e74 100644 --- a/src/common/haxe/ru/m/tankz2/game/Game.hx +++ b/src/common/haxe/ru/m/tankz2/game/Game.hx @@ -3,9 +3,9 @@ package ru.m.tankz2.game; import ru.m.tankz2.state.State; class Game { - public var state(default, null):State; + public var state(default, null):State; - public function new(state:State) { - this.state = state; - } + public function new(state:State) { + this.state = state; + } } diff --git a/src/common/haxe/ru/m/tankz2/game/Team.hx b/src/common/haxe/ru/m/tankz2/game/Team.hx index 70c610f..13c3dd7 100644 --- a/src/common/haxe/ru/m/tankz2/game/Team.hx +++ b/src/common/haxe/ru/m/tankz2/game/Team.hx @@ -5,13 +5,13 @@ import ru.m.tankz2.Id; import ru.m.tankz2.state.State; class Team { - public var id(default, default):TeamId; - public var config(default, default):TeamConfig; - public var state(default, default):TeamState; + public var id(default, default):TeamId; + public var config(default, default):TeamConfig; + public var state(default, default):TeamState; - public function new(id:TeamId, config:TeamConfig, state:TeamState) { - this.id = id; - this.config = config; - this.state = state; - } + public function new(id:TeamId, config:TeamConfig, state:TeamState) { + this.id = id; + this.config = config; + this.state = state; + } } diff --git a/src/common/haxe/ru/m/tankz2/state/State.hx b/src/common/haxe/ru/m/tankz2/state/State.hx index 61044ac..04fbd07 100644 --- a/src/common/haxe/ru/m/tankz2/state/State.hx +++ b/src/common/haxe/ru/m/tankz2/state/State.hx @@ -3,11 +3,11 @@ package ru.m.tankz2.state; import ru.m.tankz2.config.Config; typedef TeamState = { - var alive:Bool; - var life:Null; + var alive:Bool; + var life:Null; } typedef State = { - var config:Config; - var teams:Array; + var config:Config; + var teams:Array; } diff --git a/src/common/haxe/ru/m/yaml/SortingRenderer.hx b/src/common/haxe/ru/m/yaml/SortingRenderer.hx index 2788eec..60bf10a 100644 --- a/src/common/haxe/ru/m/yaml/SortingRenderer.hx +++ b/src/common/haxe/ru/m/yaml/SortingRenderer.hx @@ -3,69 +3,64 @@ package ru.m.yaml; import yaml.Renderer; class SortingRenderer extends Renderer { + private static function fields(object:Dynamic):Array { + var result = Reflect.fields(object); + result.sort(function(a, b) return a > b ? 1 : -1); + return result; + } - private static function fields(object:Dynamic):Array { - var result = Reflect.fields(object); - result.sort(function(a, b) return a > b ? 1 : -1); - return result; + override function writeObjectFlowMapping(level:Int, object:Dynamic) { + var _result = ''; + var _tag = tag; + var index = 0; + var objectKey; + + for (objectKey in fields(object)) { + if (0 != index++) + _result += ', '; + + var objectValue = Reflect.field(object, objectKey); + + writeNode(level, objectKey, false, false); + + if (result.length > 1024) + _result += '? '; + + _result += result + ': '; + writeNode(level, objectValue, false, false); + _result += result; } - override function writeObjectFlowMapping(level:Int, object:Dynamic) - { - var _result = ''; - var _tag = tag; - var index = 0; - var objectKey; + tag = _tag; + result = '{' + _result + '}'; + } - for (objectKey in fields(object)) - { - if (0 != index++) - _result += ', '; + override function writeObjectBlockMapping(level:Int, object:Dynamic, compact:Bool) { + var _result = ''; + var _tag = tag; + var index = 0; - var objectValue = Reflect.field(object, objectKey); + for (objectKey in fields(object)) { + if (!compact || 0 != index++) + _result += generateNextLine(level); - writeNode(level, objectKey, false, false); + var objectValue = Reflect.field(object, objectKey); + writeNode(level + 1, objectKey, true, true); + var explicitPair = (null != tag && '?' != tag && result.length <= 1024); - if (result.length > 1024) - _result += '? '; + if (explicitPair) + _result += '? '; - _result += result + ': '; - writeNode(level, objectValue, false, false); - _result += result; - } + _result += result; - tag = _tag; - result = '{' + _result + '}'; + if (explicitPair) + _result += generateNextLine(level); + + writeNode(level + 1, objectValue, true, explicitPair); + _result += ': ' + result; } - override function writeObjectBlockMapping(level:Int, object:Dynamic, compact:Bool) - { - var _result = ''; - var _tag = tag; - var index = 0; - - for (objectKey in fields(object)) - { - if (!compact || 0 != index++) - _result += generateNextLine(level); - - var objectValue = Reflect.field(object, objectKey); - writeNode(level + 1, objectKey, true, true); - var explicitPair = (null != tag && '?' != tag && result.length <= 1024); - - if (explicitPair) - _result += '? '; - - _result += result; - - if (explicitPair) - _result += generateNextLine(level); - - writeNode(level + 1, objectValue, true, explicitPair); - _result += ': ' + result; - } - - tag = _tag; - result = _result; - } + tag = _tag; + result = _result; + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/ColorView.hx b/src/editor/haxe/ru/m/tankz/editor/ColorView.hx index cfcc9fd..9b99be9 100644 --- a/src/editor/haxe/ru/m/tankz/editor/ColorView.hx +++ b/src/editor/haxe/ru/m/tankz/editor/ColorView.hx @@ -7,30 +7,29 @@ import hw.signal.Signal; import openfl.Assets; class ColorView extends ImageView { + public var onSelect(default, null):Signal = new Signal(); - public var onSelect(default, null):Signal = new Signal(); + public function new() { + super(Assets.getBitmapData("resources/image/colors.png")); + content.cacheAsBitmap = true; + content.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); + } - public function new() { - super(Assets.getBitmapData("resources/image/colors.png")); - content.cacheAsBitmap = true; - content.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); + private function onMouseDown(event:MouseEvent):Void { + content.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); + content.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); + onMouseMove(event); + } + + private function onMouseMove(event:MouseEvent):Void { + if (event.localX >= width || event.localY >= height) { + return; } + onSelect.emit(image.getPixel32(Std.int(event.localX), Std.int(event.localY))); + } - private function onMouseDown(event:MouseEvent):Void { - content.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); - content.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); - onMouseMove(event); - } - - private function onMouseMove(event:MouseEvent):Void { - if (event.localX >= width || event.localY >= height) { - return; - } - onSelect.emit(image.getPixel32(Std.int(event.localX), Std.int(event.localY))); - } - - private function onMouseUp(event:MouseEvent):Void { - content.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); - content.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); - } + private function onMouseUp(event:MouseEvent):Void { + content.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); + content.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/Editor.hx b/src/editor/haxe/ru/m/tankz/editor/Editor.hx index 03301ae..4735969 100644 --- a/src/editor/haxe/ru/m/tankz/editor/Editor.hx +++ b/src/editor/haxe/ru/m/tankz/editor/Editor.hx @@ -17,41 +17,41 @@ import ru.m.tankz.editor.view.PackListFrame; import ru.m.tankz.storage.GameStorage; class Editor { - private static inline var TAG = "Editor"; + private static inline var TAG = "Editor"; - @:provide static var resources:IResources; - @:provide static var theme:ITheme; - @:provide static var switcher:FrameSwitcher; - @:provide static var configBundle:IConfigBundle; - @:provide static var levelBundle:ILevelBundle; + @:provide static var resources:IResources; + @:provide static var theme:ITheme; + @:provide static var switcher:FrameSwitcher; + @:provide static var configBundle:IConfigBundle; + @:provide static var levelBundle:ILevelBundle; - public static function main() { - L.push(new hw.log.TraceLogger()); - #if flash - L.push(new hw.log.JSLogger()); - #end - #if debug - //L.push(new hw.log.SocketLogger()); - #end - // ToDo: fix @:provide macro - PopupManager; - LoaderManager; - GameStorage; - AnimateManager; - // - Const.init(); - L.d(TAG, 'Debug: ${Const.DEBUG}'); - L.i(TAG, 'Version: ${Const.VERSION}'); - L.i(TAG, 'Build: ${Const.BUILD}'); - resources.text.put("version", '${Const.VERSION}'); + public static function main() { + L.push(new hw.log.TraceLogger()); + #if flash + L.push(new hw.log.JSLogger()); + #end + #if debug + // L.push(new hw.log.SocketLogger()); + #end + // ToDo: fix @:provide macro + PopupManager; + LoaderManager; + GameStorage; + AnimateManager; + // + Const.init(); + L.d(TAG, 'Debug: ${Const.DEBUG}'); + L.i(TAG, 'Version: ${Const.VERSION}'); + L.i(TAG, 'Build: ${Const.BUILD}'); + resources.text.put("version", '${Const.VERSION}'); - theme = new EditorTheme(); - configBundle = new ConfigBundle(); - levelBundle = new CachedLevelBundle(new ClientLevelSource()); + theme = new EditorTheme(); + configBundle = new ConfigBundle(); + levelBundle = new CachedLevelBundle(new ClientLevelSource()); - var view = new EditorView(); - Root.bind(view); - switcher = view.switcher; - switcher.change(PackListFrame.ID); - } + var view = new EditorView(); + Root.bind(view); + switcher = view.switcher; + switcher.change(PackListFrame.ID); + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/EditorStorage.hx b/src/editor/haxe/ru/m/tankz/editor/EditorStorage.hx index 9924b0c..dd56117 100644 --- a/src/editor/haxe/ru/m/tankz/editor/EditorStorage.hx +++ b/src/editor/haxe/ru/m/tankz/editor/EditorStorage.hx @@ -5,18 +5,18 @@ import hw.storage.SharedObjectStorage; import ru.m.tankz.config.Config; @:provide class EditorStorage extends SharedObjectStorage { - private static inline var VERSION = 2; + private static inline var VERSION = 2; - public function new() { - super('editor_${VERSION}'); - } + public function new() { + super('editor_${VERSION}'); + } - public function packList():Array { - var result = []; - var data:DynamicAccess = so.data; - for (id in data.keys()) { - result.push(read(id)); - } - return result; + public function packList():Array { + var result = []; + var data:DynamicAccess = so.data; + for (id in data.keys()) { + result.push(read(id)); } + return result; + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/FileUtil.hx b/src/editor/haxe/ru/m/tankz/editor/FileUtil.hx index ee49ea5..6a0467d 100644 --- a/src/editor/haxe/ru/m/tankz/editor/FileUtil.hx +++ b/src/editor/haxe/ru/m/tankz/editor/FileUtil.hx @@ -9,37 +9,36 @@ import promhx.Deferred; import promhx.Promise; typedef FileContent = { - var name:String; - var content:Bytes; + var name:String; + var content:Bytes; } class FileUtil { + public static function browse():Promise { + var d = new Deferred(); + var file = new FileReference(); + file.addEventListener(Event.SELECT, function(event:Event) { + cast(event.target, FileReference).load(); + }); + file.addEventListener(IOErrorEvent.IO_ERROR, function(event:IOErrorEvent) { + d.throwError(event); + }); + file.addEventListener(ProgressEvent.PROGRESS, function(event:ProgressEvent) { + // trace('progress', '${event}'); + }); + file.addEventListener(Event.COMPLETE, function(event:Event) { + var f:FileReference = cast event.target; + d.resolve({ + name: f.name, + content: Bytes.ofData(f.data), + }); + }); + file.browse(); + return d.promise(); + } - public static function browse():Promise { - var d = new Deferred(); - var file = new FileReference(); - file.addEventListener(Event.SELECT, function(event:Event) { - cast(event.target, FileReference).load(); - }); - file.addEventListener(IOErrorEvent.IO_ERROR, function(event:IOErrorEvent) { - d.throwError(event); - }); - file.addEventListener(ProgressEvent.PROGRESS, function(event:ProgressEvent) { - //trace('progress', '${event}'); - }); - file.addEventListener(Event.COMPLETE, function(event:Event) { - var f:FileReference = cast event.target; - d.resolve({ - name: f.name, - content: Bytes.ofData(f.data), - }); - }); - file.browse(); - return d.promise(); - } - - public static function save(content:FileContent):Void { - var file = new FileReference(); - file.save(content.content.getData(), content.name); - } + public static function save(content:FileContent):Void { + var file = new FileReference(); + file.save(content.content.getData(), content.name); + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/view/EditorView.hx b/src/editor/haxe/ru/m/tankz/editor/view/EditorView.hx index 46f4c53..b091bbd 100644 --- a/src/editor/haxe/ru/m/tankz/editor/view/EditorView.hx +++ b/src/editor/haxe/ru/m/tankz/editor/view/EditorView.hx @@ -4,6 +4,5 @@ import hw.view.frame.FrameSwitcher; import hw.view.group.VGroupView; @:template class EditorView extends VGroupView { - @:view public var switcher(default, null):FrameSwitcher; + @:view public var switcher(default, null):FrameSwitcher; } - diff --git a/src/editor/haxe/ru/m/tankz/editor/view/PackFrame.hx b/src/editor/haxe/ru/m/tankz/editor/view/PackFrame.hx index 09ef098..5052654 100644 --- a/src/editor/haxe/ru/m/tankz/editor/view/PackFrame.hx +++ b/src/editor/haxe/ru/m/tankz/editor/view/PackFrame.hx @@ -17,137 +17,138 @@ import ru.m.tankz.Type; using ru.m.tankz.view.ViewUtil; @:template class PackFrame extends FrameView { - public static inline var ID = "pack"; + public static inline var ID = "pack"; - public var type(default, set):GameType; - public var level(default, set):LevelConfig; + public var type(default, set):GameType; + public var level(default, set):LevelConfig; - private var fileName:String; - private var pack:LevelPack; + private var fileName:String; + private var pack:LevelPack; - @:view var levels:ListView; - @:view var levelName:InputView; - @:view var mapView:MapEditView; - @:view var spawnPointList:DataView; - @:view var brickList:DataView; - @:view("width") var widthInput:InputView; - @:view("height") var heightInput:InputView; + @:view var levels:ListView; + @:view var levelName:InputView; + @:view var mapView:MapEditView; + @:view var spawnPointList:DataView; + @:view var brickList:DataView; + @:view("width") var widthInput:InputView; + @:view("height") var heightInput:InputView; - @:provide var configBundle:IConfigBundle; - @:provide var config:Config; - @:provide static var switcher:FrameSwitcher; - @:provide static var storage:EditorStorage; + @:provide var configBundle:IConfigBundle; + @:provide var config:Config; - public function new() { - super(ID); + @:provide static var switcher:FrameSwitcher; + @:provide static var storage:EditorStorage; + + public function new() { + super(ID); + } + + override public function onShow(data:LevelPack):Void { + super.onShow(data); + pack = data; + type = pack.id.type; + levels.data = pack.data; + if (pack.data.length > 0) { + level = pack.data[0]; } + } - override public function onShow(data:LevelPack):Void { - super.onShow(data); - pack = data; - type = pack.id.type; - levels.data = pack.data; - if (pack.data.length > 0) { - level = pack.data[0]; - } + private function set_type(value:GameType):GameType { + if (type != value) { + type = value; + config = configBundle.get(type); + mapView.config = config; + brickList.data = config.bricks.filter(function(brick) return brick.index > -1); + spawnPointList.data = config.points; + selectBrick(brickList.data[0]); + resetSize(); } + return type; + } - private function set_type(value:GameType):GameType { - if (type != value) { - type = value; - config = configBundle.get(type); - mapView.config = config; - brickList.data = config.bricks.filter(function(brick) return brick.index > -1); - spawnPointList.data = config.points; - selectBrick(brickList.data[0]); - resetSize(); - } - return type; + private function set_level(value:LevelConfig):LevelConfig { + level = value; + mapView.gridSize = level.size; + mapView.data = level; + levelName.text = level.name; + if (level.size != null) { + widthInput.text = Std.string(level.size.width); + heightInput.text = Std.string(level.size.height); + } else { + widthInput.text = Std.string(config.map.grid.width); + heightInput.text = Std.string(config.map.grid.height); } + levels.selected = [value]; + return level; + } - private function set_level(value:LevelConfig):LevelConfig { - level = value; - mapView.gridSize = level.size; - mapView.data = level; - levelName.text = level.name; - if (level.size != null) { - widthInput.text = Std.string(level.size.width); - heightInput.text = Std.string(level.size.height); - } else { - widthInput.text = Std.string(config.map.grid.width); - heightInput.text = Std.string(config.map.grid.height); - } - levels.selected = [value]; - return level; - } + private function levelViewFactory():IListItemView { + var result = new LabelListItem(function(index:Int, value:LevelConfig) return '#${value.id}'); + result.geometry.height = 48; + return result; + } - private function levelViewFactory():IListItemView { - var result = new LabelListItem(function(index:Int, value:LevelConfig) return '#${value.id}'); - result.geometry.height = 48; - return result; - } + private function onLevelSelect(item:IListItemView):Void { + level = item.data; + } - private function onLevelSelect(item:IListItemView):Void { - level = item.data; + private function updateSelected(brick:BrickConfig = null, point:SpawnPoint = null) { + for (v in brickList.dataViews) { + v.selected = v.data == brick; } + for (v in spawnPointList.dataViews) { + v.selected = v.data == point; + } + } - private function updateSelected(brick:BrickConfig = null, point:SpawnPoint = null) { - for (v in brickList.dataViews) { - v.selected = v.data == brick; - } - for (v in spawnPointList.dataViews) { - v.selected = v.data == point; - } - } + private function selectBrick(brick:BrickConfig):Void { + mapView.brush = BRICK(brick); + updateSelected(brick); + } - private function selectBrick(brick:BrickConfig):Void { - mapView.brush = BRICK(brick); - updateSelected(brick); - } + private function selectSpawnPoint(point:SpawnPoint):Void { + mapView.brush = POINT(point); + updateSelected(null, point); + } - private function selectSpawnPoint(point:SpawnPoint):Void { - mapView.brush = POINT(point); - updateSelected(null, point); - } + private function save():Void { + var data = mapView.data; + data.id = level.id; + data.packId = pack.id; + data.name = levelName.text; + pack.data[data.id] = data; + levels.data = pack.data; + level = data; + pack.meta.date = Date.now(); + storage.write(pack.id, pack); + } - private function save():Void { - var data = mapView.data; - data.id = level.id; - data.packId = pack.id; - data.name = levelName.text; - pack.data[data.id] = data; - levels.data = pack.data; - level = data; - pack.meta.date = Date.now(); - storage.write(pack.id, pack); - } + private function applySize():Void { + mapView.gridSize = {width: Std.parseInt(widthInput.text), height: Std.parseInt(heightInput.text)}; + } - private function applySize():Void { - mapView.gridSize = {width: Std.parseInt(widthInput.text), height: Std.parseInt(heightInput.text)}; - } + private function resetSize():Void { + widthInput.text = Std.string(config.map.grid.width); + heightInput.text = Std.string(config.map.grid.height); + mapView.gridSize = null; + } - private function resetSize():Void { - widthInput.text = Std.string(config.map.grid.width); - heightInput.text = Std.string(config.map.grid.height); - mapView.gridSize = null; - } + private function addLevel():Void { + var level = LevelUtil.empty(config.map.grid, 0); + level.id = pack.data.length; + level.packId = pack.id; + pack.data.push(level); + levels.data = pack.data; + this.level = level; + } - private function addLevel():Void { - var level = LevelUtil.empty(config.map.grid, 0); - level.id = pack.data.length; - level.packId = pack.id; - pack.data.push(level); - levels.data = pack.data; - this.level = level; - } - - private function removeLevel():Void { - if (level != null) { - pack.data.remove(level); - levels.data = pack.data; - if (pack.data.length > 0) { - this.level = pack.data[0]; - } - } + private function removeLevel():Void { + if (level != null) { + pack.data.remove(level); + levels.data = pack.data; + if (pack.data.length > 0) { + this.level = pack.data[0]; + } } + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/view/PackListFrame.hx b/src/editor/haxe/ru/m/tankz/editor/view/PackListFrame.hx index 87c2ddd..3bf8979 100644 --- a/src/editor/haxe/ru/m/tankz/editor/view/PackListFrame.hx +++ b/src/editor/haxe/ru/m/tankz/editor/view/PackListFrame.hx @@ -12,59 +12,59 @@ import ru.m.tankz.Type; import ru.m.tankz.util.LevelUtil; @:template class PackListFrame extends FrameView { - public static inline var ID = "pack_list"; + public static inline var ID = "pack_list"; - @:view("packs") var packView:ActionDataView; + @:view("packs") var packView:ActionDataView; - @:provide static var levelBundle:ILevelBundle; - @:provide static var switcher:FrameSwitcher; - @:provide static var storage:EditorStorage; + @:provide static var levelBundle:ILevelBundle; + @:provide static var switcher:FrameSwitcher; + @:provide static var storage:EditorStorage; - public function new() { - super(ID); - } + public function new() { + super(ID); + } - override public function onShow(data:Dynamic):Void { - super.onShow(data); + override public function onShow(data:Dynamic):Void { + super.onShow(data); + packView.data = storage.packList(); + } + + private function onPackAction(value:LevelPack, action:PackAction):Void { + switch action { + case EXPORT: + FileUtil.save({ + name: '${value.id}.zip', + content: LevelUtil.pack(value), + }); + storage.write(value.id, value); + packView.data = storage.packList(); + case EDIT: + switcher.change(PackFrame.ID, value); + case DELETE: + storage.delete(value.id); packView.data = storage.packList(); } + } - private function onPackAction(value:LevelPack, action:PackAction):Void { - switch action { - case EXPORT: - FileUtil.save({ - name: '${value.id}.zip', - content: LevelUtil.pack(value), - }); - storage.write(value.id, value); - packView.data = storage.packList(); - case EDIT: - switcher.change(PackFrame.ID, value); - case DELETE: - storage.delete(value.id); - packView.data = storage.packList(); + private function create():Void { + PackPopup.instance.show().then(function(packId:PackId) { + if (packId != null) { + var pack:LevelPack = { + id: packId, + meta: {id: packId, author: "default", date: null}, + data: [], } - } + storage.write(pack.id, pack); + packView.data = storage.packList(); + } + }); + } - private function create():Void { - PackPopup.instance.show().then(function(packId:PackId) { - if (packId != null) { - var pack:LevelPack = { - id: packId, - meta: {id: packId, author: "default", date: null}, - data: [], - } - storage.write(pack.id, pack); - packView.data = storage.packList(); - } - }); - } - - private function open():Void { - FileUtil.browse().then(function(file:FileContent) { - var pack:LevelPack = LevelUtil.unpack(file.content); - storage.write(pack.id, pack); - packView.data = storage.packList(); - }); - } + private function open():Void { + FileUtil.browse().then(function(file:FileContent) { + var pack:LevelPack = LevelUtil.unpack(file.content); + storage.write(pack.id, pack); + packView.data = storage.packList(); + }); + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/view/PackView.hx b/src/editor/haxe/ru/m/tankz/editor/view/PackView.hx index ae2bb55..ff8ee4f 100644 --- a/src/editor/haxe/ru/m/tankz/editor/view/PackView.hx +++ b/src/editor/haxe/ru/m/tankz/editor/view/PackView.hx @@ -10,47 +10,46 @@ import ru.m.tankz.config.Config; using ru.m.tankz.view.ViewUtil; enum PackAction { - EXPORT; - EDIT; - DELETE; + EXPORT; + EDIT; + DELETE; } @:template class PackView extends HGroupView implements IListItemView { + public var item_index(default, default):Int; + public var data(default, set):LevelPack; - public var item_index(default, default):Int; - public var data(default, set):LevelPack; + private var actionSignal(get, null):Signal2; - private var actionSignal(get, null):Signal2; + @:view var label:ButtonView; - @:view var label:ButtonView; + private function set_data(value:LevelPack):LevelPack { + data = value; + label.text = data.id.toPackLabel() + " | " + data.meta.date; + return data; + } - private function set_data(value:LevelPack):LevelPack { - data = value; - label.text = data.id.toPackLabel() + " | " + data.meta.date; - return data; - } + private function get_actionSignal():Signal2 { + var dataView:ActionDataView = cast parent; + return dataView.onDataAction; + } - private function get_actionSignal():Signal2 { - var dataView:ActionDataView = cast parent; - return dataView.onDataAction; - } + private function export():Void { + actionSignal.emit(data, EXPORT); + } - private function export():Void { - actionSignal.emit(data, EXPORT); - } + private function edit():Void { + actionSignal.emit(data, EDIT); + } - private function edit():Void { - actionSignal.emit(data, EDIT); - } + private function delete():Void { + actionSignal.emit(data, DELETE); + } - private function delete():Void { - actionSignal.emit(data, DELETE); - } - - public static function factory(index:Int, value:LevelPack):PackView { - var result = new PackView(); - result.item_index = index; - result.data = value; - return result; - } + public static function factory(index:Int, value:LevelPack):PackView { + var result = new PackView(); + result.item_index = index; + result.data = value; + return result; + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/view/TankFrame.hx b/src/editor/haxe/ru/m/tankz/editor/view/TankFrame.hx index c2dc5e6..608a950 100644 --- a/src/editor/haxe/ru/m/tankz/editor/view/TankFrame.hx +++ b/src/editor/haxe/ru/m/tankz/editor/view/TankFrame.hx @@ -7,23 +7,23 @@ import hw.view.group.IGroupView; import ru.m.tankz.editor.view.tank.TankView; @:template class TankFrame extends FrameView { - public static inline var ID = 'tank'; + public static inline var ID = 'tank'; - @:view var tanks(default, null):IGroupView; - @:view("color") var colorLabel(default, null):InputView; - private var color(default, set):Color; + @:view var tanks(default, null):IGroupView; + @:view("color") var colorLabel(default, null):InputView; + private var color(default, set):Color; - public function new() { - super(ID); - color = 0x00ff00; - } - - private function set_color(value:Color):Color { - color = value; - colorLabel.text = value.toString(); - for (view in tanks.views) { - cast(view, TankView).color = color; - } - return color; + public function new() { + super(ID); + color = 0x00ff00; + } + + private function set_color(value:Color):Color { + color = value; + colorLabel.text = value.toString(); + for (view in tanks.views) { + cast(view, TankView).color = color; } + return color; + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/view/map/BrickView.hx b/src/editor/haxe/ru/m/tankz/editor/view/map/BrickView.hx index da59897..756a2e2 100644 --- a/src/editor/haxe/ru/m/tankz/editor/view/map/BrickView.hx +++ b/src/editor/haxe/ru/m/tankz/editor/view/map/BrickView.hx @@ -5,23 +5,22 @@ import flash.display.BitmapData; import openfl.utils.Assets; import ru.m.tankz.config.Config; -class BrickView extends BrushView { +class BrickView extends BrushView { + override private function resolveImage(value:BrickConfig):BitmapData { + var image = Assets.getBitmapData('resources/image/map/${value.type}.png'); + var result = new BitmapData(image.width * 2, image.height * 2, true, 0x00000000); + var m = new Matrix(); + result.draw(image, m); + m.translate(image.width, 0); + result.draw(image, m); + m.translate(0, image.height); + result.draw(image, m); + m.translate(-image.width, 0); + result.draw(image, m); + return result; + } - override private function resolveImage(value:BrickConfig):BitmapData { - var image = Assets.getBitmapData('resources/image/map/${value.type}.png'); - var result = new BitmapData(image.width * 2, image.height * 2, true, 0x00000000); - var m = new Matrix(); - result.draw(image, m); - m.translate(image.width, 0); - result.draw(image, m); - m.translate(0, image.height); - result.draw(image, m); - m.translate(-image.width, 0); - result.draw(image, m); - return result; - } - - public static inline function factory(index:Int, value:BrickConfig) { - return new BrickView(value); - } + public static inline function factory(index:Int, value:BrickConfig) { + return new BrickView(value); + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/view/map/BrushView.hx b/src/editor/haxe/ru/m/tankz/editor/view/map/BrushView.hx index e223466..5437eba 100644 --- a/src/editor/haxe/ru/m/tankz/editor/view/map/BrushView.hx +++ b/src/editor/haxe/ru/m/tankz/editor/view/map/BrushView.hx @@ -7,51 +7,50 @@ import hw.color.Color; import hw.view.ImageView; class BrushView extends ImageView { + public var data(default, set):D; + public var selected(default, set):Bool; - public var data(default, set):D; - public var selected(default, set):Bool; + private var selectView:Shape; - private var selectView:Shape; - - public function new(data:D = null) { - super(); - selectView = new Shape(); - selectView.visible = false; - content.addChild(selectView); - if (data != null) { - this.data = data; - } - style = "brush"; - // TODO: fillType in style - fillType = FillType.CONTAIN; + public function new(data:D = null) { + super(); + selectView = new Shape(); + selectView.visible = false; + content.addChild(selectView); + if (data != null) { + this.data = data; } + style = "brush"; + // TODO: fillType in style + fillType = FillType.CONTAIN; + } - override public function update():Void { - super.update(); - selectView.graphics.clear(); - selectView.graphics.lineStyle(4, theme.colors.active); - selectView.graphics.drawRect(0, 0, width, height); - selectView.graphics.lineStyle(); - } + override public function update():Void { + super.update(); + selectView.graphics.clear(); + selectView.graphics.lineStyle(4, theme.colors.active); + selectView.graphics.drawRect(0, 0, width, height); + selectView.graphics.lineStyle(); + } - private function resolveImage(value:D):BitmapData { - return null; - } + private function resolveImage(value:D):BitmapData { + return null; + } - private function resolveColor(value:D):Color { - return 0; - } + private function resolveColor(value:D):Color { + return 0; + } - private function set_data(value:D):D { - data = value; - image = resolveImage(value); - color = resolveColor(value); - return data; - } + private function set_data(value:D):D { + data = value; + image = resolveImage(value); + color = resolveColor(value); + return data; + } - private function set_selected(value:Bool):Bool { - selected = value; - selectView.visible = value; - return selected; - } + private function set_selected(value:Bool):Bool { + selected = value; + selectView.visible = value; + return selected; + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/view/map/MapEditView.hx b/src/editor/haxe/ru/m/tankz/editor/view/map/MapEditView.hx index 91000c8..7539ae5 100644 --- a/src/editor/haxe/ru/m/tankz/editor/view/map/MapEditView.hx +++ b/src/editor/haxe/ru/m/tankz/editor/view/map/MapEditView.hx @@ -16,145 +16,144 @@ import ru.m.tankz.Type; import ru.m.tankz.util.LevelUtil; enum Brush { - POINT(point:SpawnPoint); - BRICK(brick:BrickConfig); + POINT(point:SpawnPoint); + BRICK(brick:BrickConfig); } @:dispatcher(GameListener) class MapEditView extends Render { + public var data(get, set):LevelConfig; + public var map(default, null):LevelMap; + public var brush(default, default):Brush; - public var data(get, set):LevelConfig; - public var map(default, null):LevelMap; - public var brush(default, default):Brush; + private var builder:EntityBuilder; + private var entityId:Int; + private var pointEntities:Map; - private var builder:EntityBuilder; - private var entityId:Int; - private var pointEntities:Map; + public function new() { + super(); + content.mouseChildren = false; + map = null; + pointEntities = null; + content.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); + connect(this); + reset(); + } - public function new() { - super(); - content.mouseChildren = false; - map = null; - pointEntities = null; - content.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); - connect(this); - reset(); + override private function set_config(value:Config):Config { + var result = super.set_config(value); + builder = new EntityBuilder(value); + data = LevelUtil.empty(gridSize != null ? gridSize : config.map.grid, config.bricks[1].index); + return result; + } + + override private function set_gridSize(value:GridSize):GridSize { + var result = super.set_gridSize(value); + data = LevelUtil.empty(gridSize != null ? gridSize : config.map.grid, config.bricks[1].index); + return result; + } + + override private function drawBackground():Void { + super.drawBackground(); + var g:Graphics = backgroundLayer.graphics; + g.lineStyle(1, 0x007700); + var gridWidth = gridSize != null ? gridSize.width : config.map.grid.width; + var gridHeight = gridSize != null ? gridSize.height : config.map.grid.height; + for (x in 0...gridWidth) { + g.moveTo(x * config.map.cell.width, 0); + g.lineTo(x * config.map.cell.height, mapHeight); } - - override private function set_config(value:Config):Config { - var result = super.set_config(value); - builder = new EntityBuilder(value); - data = LevelUtil.empty(gridSize != null ? gridSize : config.map.grid, config.bricks[1].index); - return result; + for (y in 0...gridHeight) { + g.moveTo(0, y * config.map.cell.height); + g.lineTo(mapWidth, y * config.map.cell.height); } + } - override private function set_gridSize(value:GridSize):GridSize { - var result = super.set_gridSize(value); - data = LevelUtil.empty(gridSize != null ? gridSize : config.map.grid, config.bricks[1].index); - return result; - } + private function onMouseDown(event:MouseEvent):Void { + content.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); + content.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); + onMouseMove(event); + } - override private function drawBackground():Void { - super.drawBackground(); - var g:Graphics = backgroundLayer.graphics; - g.lineStyle(1, 0x007700); - var gridWidth = gridSize != null ? gridSize.width : config.map.grid.width; - var gridHeight = gridSize != null ? gridSize.height : config.map.grid.height; - for (x in 0...gridWidth) { - g.moveTo(x * config.map.cell.width, 0); - g.lineTo(x * config.map.cell.height, mapHeight); - } - for (y in 0...gridHeight) { - g.moveTo(0, y * config.map.cell.height); - g.lineTo(mapWidth, y * config.map.cell.height); - } - } + private function onMouseUp(event:MouseEvent):Void { + content.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); + content.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); + } - private function onMouseDown(event:MouseEvent):Void { - content.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); - content.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); - onMouseMove(event); + private function onMouseMove(event:MouseEvent):Void { + var p = new Point(event.localX, event.localY); + p.x -= container.x; + p.y -= container.y; + p.x *= (1 / container.scaleX); + p.y *= (1 / container.scaleY); + var b = map.getPointBrick(p); + if (b != null) { + switch (brush) { + case Brush.POINT(point): + var entity = pointEntities[pointKey(point)]; + point.x = b.cellX; + point.y = b.cellY; + var rect = builder.buildRect(point, entity.rect.width, entity.rect.height); + entity.rect.position = rect.position; + gameEventSignal.emit(EventUtil.buildMove(entity)); + case Brush.BRICK(brickConfig): + b.config = config.getBrick(brickConfig.type); + gameEventSignal.emit(GameEvent.CHANGE(BRICK(b.id, brickConfig.type))); + } } + } - private function onMouseUp(event:MouseEvent):Void { - content.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); - content.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); - } + private static function pointKey(point:SpawnPoint):String { + return '${point.type}:${point.team}:${point.index}'; + } - private function onMouseMove(event:MouseEvent):Void { - var p = new Point(event.localX, event.localY); - p.x -= container.x; - p.y -= container.y; - p.x *= (1 / container.scaleX); - p.y *= (1 / container.scaleY); - var b = map.getPointBrick(p); - if (b != null) { - switch (brush) { - case Brush.POINT(point): - var entity = pointEntities[pointKey(point)]; - point.x = b.cellX; - point.y = b.cellY; - var rect = builder.buildRect(point, entity.rect.width, entity.rect.height); - entity.rect.position = rect.position; - gameEventSignal.emit(EventUtil.buildMove(entity)); - case Brush.BRICK(brickConfig): - b.config = config.getBrick(brickConfig.type); - gameEventSignal.emit(GameEvent.CHANGE(BRICK(b.id, brickConfig.type))); - } - } + private function get_data():LevelConfig { + return { + data: map.bricks.map(function(brick:Brick) return brick.config.index), + points: config.points, + size: gridSize, } + } - private static function pointKey(point:SpawnPoint):String { - return '${point.type}:${point.team}:${point.index}'; + private function set_data(value:LevelConfig):LevelConfig { + reset(); + pointEntities = new Map(); + map = new LevelMap(config.map, gridSize); + map.setData(value.data.map(function(index) return config.getBrickByIndex(index))); + gameEventSignal.emit(EventUtil.buildBricksSpawn(map)); + for (point in config.points) { + switch point.type { + case "eagle": + var eagle = builder.buildEagle(point, point.team); + pointEntities[pointKey(point)] = eagle; + gameEventSignal.emit(EventUtil.buildEagleSpawn(eagle)); + case "tank": + var playerId = new PlayerId(point.team, point.index < 0 ? 0 : point.index); + var player = config.getPlayer(playerId); + var tankSpawn = player.tanks[0]; + var tankInfo:TankInfo = { + type: tankSpawn.type, + skin: config.getTank(tankSpawn.type).skin, + hits: 0, + bonus: false, + boat: false, + color: config.getColor(playerId), + name: playerId.format(), + } + var tank = builder.buildTank(point, playerId, tankInfo); + pointEntities[pointKey(point)] = tank; + gameEventSignal.emit(EventUtil.buildTankSpawn(tank)); + } } - - private function get_data():LevelConfig { - return { - data: map.bricks.map(function(brick:Brick) return brick.config.index), - points: config.points, - size: gridSize, - } - } - - private function set_data(value:LevelConfig):LevelConfig { - reset(); - pointEntities = new Map(); - map = new LevelMap(config.map, gridSize); - map.setData(value.data.map(function(index) return config.getBrickByIndex(index))); - gameEventSignal.emit(EventUtil.buildBricksSpawn(map)); - for (point in config.points) { - switch point.type { - case "eagle": - var eagle = builder.buildEagle(point, point.team); - pointEntities[pointKey(point)] = eagle; - gameEventSignal.emit(EventUtil.buildEagleSpawn(eagle)); - case "tank": - var playerId = new PlayerId(point.team, point.index < 0 ? 0 : point.index); - var player = config.getPlayer(playerId); - var tankSpawn = player.tanks[0]; - var tankInfo:TankInfo = { - type: tankSpawn.type, - skin: config.getTank(tankSpawn.type).skin, - hits: 0, - bonus: false, - boat: false, - color: config.getColor(playerId), - name: playerId.format(), - } - var tank = builder.buildTank(point, playerId, tankInfo); - pointEntities[pointKey(point)] = tank; - gameEventSignal.emit(EventUtil.buildTankSpawn(tank)); - } - } - if (value.points != null) { - for (point in value.points) { - var entity = pointEntities[pointKey(point)]; - var rect = builder.buildRect(point, entity.rect.width, entity.rect.height); - entity.rect.position = rect.position; - gameEventSignal.emit(EventUtil.buildMove(entity)); - } - } - draw(); - toUpdate(); - return value; + if (value.points != null) { + for (point in value.points) { + var entity = pointEntities[pointKey(point)]; + var rect = builder.buildRect(point, entity.rect.width, entity.rect.height); + entity.rect.position = rect.position; + gameEventSignal.emit(EventUtil.buildMove(entity)); + } } + draw(); + toUpdate(); + return value; + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/view/map/SpawnPointView.hx b/src/editor/haxe/ru/m/tankz/editor/view/map/SpawnPointView.hx index d777b09..7f4508e 100644 --- a/src/editor/haxe/ru/m/tankz/editor/view/map/SpawnPointView.hx +++ b/src/editor/haxe/ru/m/tankz/editor/view/map/SpawnPointView.hx @@ -6,31 +6,29 @@ import ru.m.tankz.config.Config; import ru.m.tankz.render.RenderUtil; import ru.m.tankz.Type.PlayerId; -class SpawnPointView extends BrushView { +class SpawnPointView extends BrushView { + @:provide var config:Config; - @:provide var config:Config; + override private function resolveColor(value:SpawnPoint):Color { + return config.getColor(new PlayerId(value.team, value.index)); + } - override private function resolveColor(value:SpawnPoint):Color { - return config.getColor(new PlayerId(value.team, value.index)); + override private function resolveImage(value:SpawnPoint):BitmapData { + var preset:GamePreset = config.presets[config.presets.length - 1]; + var tankConfig:TankConfig = null; + if (value.type == 'tank') { + var player = config.getPlayer(new PlayerId(value.team, value.index < 0 ? 0 : value.index)); + var tankType = player.tanks[0]; + tankConfig = config.getTank(tankType.type); } - - override private function resolveImage(value:SpawnPoint):BitmapData { - var preset:GamePreset = config.presets[config.presets.length - 1]; - var tankConfig:TankConfig = null; - if (value.type == 'tank') { - var player = config.getPlayer(new PlayerId(value.team, value.index < 0 ? 0 : value.index)); - var tankType = player.tanks[0]; - tankConfig = config.getTank(tankType.type); - } - return switch value.type { - case "eagle": RenderUtil.eagleImage(); - case "tank": RenderUtil.tankImage(tankConfig.skin); - case _: RenderUtil.eagleImage(true); - } + return switch value.type { + case "eagle": RenderUtil.eagleImage(); + case "tank": RenderUtil.tankImage(tankConfig.skin); + case _: RenderUtil.eagleImage(true); } + } - public static inline function factory(index:Int, value:SpawnPoint) { - return new SpawnPointView(value); - } + public static inline function factory(index:Int, value:SpawnPoint) { + return new SpawnPointView(value); + } } - diff --git a/src/editor/haxe/ru/m/tankz/editor/view/popup/PackPopup.hx b/src/editor/haxe/ru/m/tankz/editor/view/popup/PackPopup.hx index 187d3df..a0d611c 100644 --- a/src/editor/haxe/ru/m/tankz/editor/view/popup/PackPopup.hx +++ b/src/editor/haxe/ru/m/tankz/editor/view/popup/PackPopup.hx @@ -6,24 +6,23 @@ import hw.view.popup.PopupView; import ru.m.tankz.Type; @:template class PackPopup extends PopupView { + public static var instance(get, null):PackPopup; - public static var instance(get, null):PackPopup; - - private static function get_instance():PackPopup { - if (instance == null) { - instance = new PackPopup(); - } - return instance; + private static function get_instance():PackPopup { + if (instance == null) { + instance = new PackPopup(); } + return instance; + } - @:view("type") var typeSelect:SelectView; - @:view("name") var nameInput:InputView; + @:view("type") var typeSelect:SelectView; + @:view("name") var nameInput:InputView; - override private function onShow():Void { - super.onShow(); - } + override private function onShow():Void { + super.onShow(); + } - private function submit():Void { - close(new PackId(typeSelect.selected, nameInput.text)); - } + private function submit():Void { + close(new PackId(typeSelect.selected, nameInput.text)); + } } diff --git a/src/editor/haxe/ru/m/tankz/editor/view/tank/TankView.hx b/src/editor/haxe/ru/m/tankz/editor/view/tank/TankView.hx index bb032ae..f5a459b 100644 --- a/src/editor/haxe/ru/m/tankz/editor/view/tank/TankView.hx +++ b/src/editor/haxe/ru/m/tankz/editor/view/tank/TankView.hx @@ -7,30 +7,29 @@ import hw.view.utils.BitmapUtil; import hw.view.View; class TankView extends View { + public var image(default, set):BitmapData; + public var color(default, set):Color; - public var image(default, set):BitmapData; - public var color(default, set):Color; + public function new() { + super(new Bitmap()); + } - public function new() { - super(new Bitmap()); - } - - inline private function get_image():BitmapData { - return content.bitmapData; - } - - inline private function set_image(value:BitmapData):BitmapData { - image = value; - content.bitmapData = BitmapUtil.colorize(image, color); - setSize(image.width, image.height); - return image; - } - - inline private function set_color(value:Color):Color { - color = value; - if (image != null) { - content.bitmapData = BitmapUtil.colorize(image, color); - } - return color; + inline private function get_image():BitmapData { + return content.bitmapData; + } + + inline private function set_image(value:BitmapData):BitmapData { + image = value; + content.bitmapData = BitmapUtil.colorize(image, color); + setSize(image.width, image.height); + return image; + } + + inline private function set_color(value:Color):Color { + color = value; + if (image != null) { + content.bitmapData = BitmapUtil.colorize(image, color); } + return color; + } } diff --git a/src/server/haxe/ru/m/tankz/server/Server.hx b/src/server/haxe/ru/m/tankz/server/Server.hx index af93bb6..cec5927 100755 --- a/src/server/haxe/ru/m/tankz/server/Server.hx +++ b/src/server/haxe/ru/m/tankz/server/Server.hx @@ -14,48 +14,47 @@ import ru.m.tankz.server.session.GameSession; import sys.net.Socket; class Server extends ThreadServer { + private static inline var TAG = 'Server'; - private static inline var TAG = 'Server'; + override public function clientConnected(socket:Socket):GameSession { + var session = new GameSession(socket); + L.d(TAG, 'Client connected'); + return session; + } - override public function clientConnected(socket:Socket):GameSession { - var session = new GameSession(socket); - L.d(TAG, 'Client connected'); - return session; - } + override public function clientDisconnected(session:GameSession) { + L.d(TAG, 'Client disconnected'); + session.disconnect(); + } - override public function clientDisconnected(session:GameSession) { - L.d(TAG, 'Client disconnected'); - session.disconnect(); - } + override public function readClientMessage(session:GameSession, buf:Bytes, pos:Int, len:Int) { + // L.d(TAG, 'Client message: ${buf}'); + return {msg: buf.sub(pos, len), bytes: len}; + } - override public function readClientMessage(session:GameSession, buf:Bytes, pos:Int, len:Int) { - //L.d(TAG, 'Client message: ${buf}'); - return {msg: buf.sub(pos, len), bytes: len}; - } + override public function clientMessage(session:GameSession, bytes:Bytes) { + session.pushData(bytes); + } - override public function clientMessage(session:GameSession, bytes:Bytes) { - session.pushData(bytes); - } + @:provide static var gameManager:IGameManager; + @:provide static var configBundle:IConfigBundle; + @:provide static var levelBundle:ILevelBundle; - @:provide static var gameManager:IGameManager; - @:provide static var configBundle:IConfigBundle; - @:provide static var levelBundle:ILevelBundle; - - public static function main() { - L.push(new TraceLogger()); - #if debug - L.push(new hw.log.SocketLogger()); - #end - L.d(TAG, 'Running'); - L.i(TAG, 'Build: ${CompilationOption.get("build")}'); - configBundle = new AssetConfigBundle(); - levelBundle = new CachedLevelBundle(new AssetLevelSource()); - levelBundle.load(); - gameManager = new GameManager(); - var host:String = Sys.args().length > 0 ? Sys.args()[0] : "0.0.0.0"; - var port:Int = Sys.args().length > 1 ? Std.parseInt(Sys.args()[1]) : 5000; - var wserver = new Server(); - L.i(TAG, 'Start on ${host}:${port}'); - wserver.run(host, port); - } + public static function main() { + L.push(new TraceLogger()); + #if debug + L.push(new hw.log.SocketLogger()); + #end + L.d(TAG, 'Running'); + L.i(TAG, 'Build: ${CompilationOption.get("build")}'); + configBundle = new AssetConfigBundle(); + levelBundle = new CachedLevelBundle(new AssetLevelSource()); + levelBundle.load(); + gameManager = new GameManager(); + var host:String = Sys.args().length > 0 ? Sys.args()[0] : "0.0.0.0"; + var port:Int = Sys.args().length > 1 ? Std.parseInt(Sys.args()[1]) : 5000; + var wserver = new Server(); + L.i(TAG, 'Start on ${host}:${port}'); + wserver.run(host, port); + } } diff --git a/src/server/haxe/ru/m/tankz/server/bundle/AssetConfigBundle.hx b/src/server/haxe/ru/m/tankz/server/bundle/AssetConfigBundle.hx index 1bd6640..239c386 100644 --- a/src/server/haxe/ru/m/tankz/server/bundle/AssetConfigBundle.hx +++ b/src/server/haxe/ru/m/tankz/server/bundle/AssetConfigBundle.hx @@ -8,16 +8,15 @@ import yaml.Parser; import yaml.Yaml; class AssetConfigBundle implements IConfigBundle { + private var _cache:Map = new Map(); - private var _cache:Map = new Map(); + public function new() {} - public function new() {} - - public function get(type:GameType):Config { - if (!_cache.exists(type)) { - var source:ConfigSource = Yaml.parse(Assets.getText('config/${type}.yaml'), Parser.options().useObjects()); - _cache.set(type, Config.fromSource(type, source)); - } - return _cache.get(type); + public function get(type:GameType):Config { + if (!_cache.exists(type)) { + var source:ConfigSource = Yaml.parse(Assets.getText('config/${type}.yaml'), Parser.options().useObjects()); + _cache.set(type, Config.fromSource(type, source)); } + return _cache.get(type); + } } diff --git a/src/server/haxe/ru/m/tankz/server/bundle/AssetLevelSource.hx b/src/server/haxe/ru/m/tankz/server/bundle/AssetLevelSource.hx index d594e72..4185194 100644 --- a/src/server/haxe/ru/m/tankz/server/bundle/AssetLevelSource.hx +++ b/src/server/haxe/ru/m/tankz/server/bundle/AssetLevelSource.hx @@ -8,26 +8,25 @@ import ru.m.tankz.Type; import ru.m.tankz.util.LevelUtil; class AssetLevelSource implements ILevelSource { + public function new() {} - public function new() {} + public function resolveMeta(id:PackId):LevelPackMeta { + var bytes = Assets.getBytes('level/${id}.zip'); + return LevelUtil.getMeta(bytes); + } - public function resolveMeta(id:PackId):LevelPackMeta { - var bytes = Assets.getBytes('level/${id}.zip'); - return LevelUtil.getMeta(bytes); - } - - public function resolve(id:PackId):LevelPack { - var bytes = Assets.getBytes('level/${id}.zip'); - return LevelUtil.unpack(bytes); - } - - public function list():Array { - var result = []; - for (path in Assets.list(AssetType.BINARY)) { - if (StringTools.startsWith(path, "level")) { - result.push(PackId.fromString(path.split("/").pop().split(".").shift())); - } - } - return result; + public function resolve(id:PackId):LevelPack { + var bytes = Assets.getBytes('level/${id}.zip'); + return LevelUtil.unpack(bytes); + } + + public function list():Array { + var result = []; + for (path in Assets.list(AssetType.BINARY)) { + if (StringTools.startsWith(path, "level")) { + result.push(PackId.fromString(path.split("/").pop().split(".").shift())); + } } + return result; + } } diff --git a/src/server/haxe/ru/m/tankz/server/bundle/ServerConfigBundle.hx b/src/server/haxe/ru/m/tankz/server/bundle/ServerConfigBundle.hx index f015e5c..27210ef 100644 --- a/src/server/haxe/ru/m/tankz/server/bundle/ServerConfigBundle.hx +++ b/src/server/haxe/ru/m/tankz/server/bundle/ServerConfigBundle.hx @@ -9,13 +9,12 @@ import yaml.Parser; import yaml.Yaml; class ServerConfigBundle implements IConfigBundle { + public function new() {} - public function new() {} - - public function get(type:GameType):Config { - var path:String = FileSystem.absolutePath('./config/${type}.yaml'); - var data:String = File.getContent(path); - var source:ConfigSource = Yaml.parse(data, Parser.options().useObjects()); - return Config.fromSource(type, source); - } + public function get(type:GameType):Config { + var path:String = FileSystem.absolutePath('./config/${type}.yaml'); + var data:String = File.getContent(path); + var source:ConfigSource = Yaml.parse(data, Parser.options().useObjects()); + return Config.fromSource(type, source); + } } diff --git a/src/server/haxe/ru/m/tankz/server/bundle/ServerLevelSource.hx b/src/server/haxe/ru/m/tankz/server/bundle/ServerLevelSource.hx index a6b3358..db4f2b4 100644 --- a/src/server/haxe/ru/m/tankz/server/bundle/ServerLevelSource.hx +++ b/src/server/haxe/ru/m/tankz/server/bundle/ServerLevelSource.hx @@ -8,28 +8,27 @@ import sys.FileSystem; import sys.io.File; class ServerLevelSource implements ILevelSource { + private static inline var PATH = "./level"; - private static inline var PATH = "./level"; + public function new() {} - public function new() {} + public function resolveMeta(id:PackId):LevelPackMeta { + var path = FileSystem.absolutePath('${PATH}/${id}.zip'); + var bytes = File.getBytes(path); + return LevelUtil.getMeta(bytes); + } - public function resolveMeta(id:PackId):LevelPackMeta { - var path = FileSystem.absolutePath('${PATH}/${id}.zip'); - var bytes = File.getBytes(path); - return LevelUtil.getMeta(bytes); - } - - public function resolve(id:PackId):LevelPack { - var path = FileSystem.absolutePath('${PATH}/${id}.zip'); - var bytes = File.getBytes(path); - return LevelUtil.unpack(bytes); - } - - public function list():Array { - var result = []; - for (path in FileSystem.readDirectory(PATH)) { - result.push(PackId.fromString(path.split("/").pop().split(".").shift())); - } - return result; + public function resolve(id:PackId):LevelPack { + var path = FileSystem.absolutePath('${PATH}/${id}.zip'); + var bytes = File.getBytes(path); + return LevelUtil.unpack(bytes); + } + + public function list():Array { + var result = []; + for (path in FileSystem.readDirectory(PATH)) { + result.push(PackId.fromString(path.split("/").pop().split(".").shift())); } + return result; + } } diff --git a/src/server/haxe/ru/m/tankz/server/control/ServerControlFactory.hx b/src/server/haxe/ru/m/tankz/server/control/ServerControlFactory.hx index ec842cc..f880ca3 100644 --- a/src/server/haxe/ru/m/tankz/server/control/ServerControlFactory.hx +++ b/src/server/haxe/ru/m/tankz/server/control/ServerControlFactory.hx @@ -7,8 +7,7 @@ import ru.m.tankz.control.BaseControlFactory; class ClientControl extends Control {} class ServerControlFactory extends BaseControlFactory { - - override private function buildHuman(id:PlayerId, index:Int):Control { - return new ClientControl(id); - } + override private function buildHuman(id:PlayerId, index:Int):Control { + return new ClientControl(id); + } } diff --git a/src/server/haxe/ru/m/tankz/server/game/GameManager.hx b/src/server/haxe/ru/m/tankz/server/game/GameManager.hx index 14e933e..ad4cef0 100644 --- a/src/server/haxe/ru/m/tankz/server/game/GameManager.hx +++ b/src/server/haxe/ru/m/tankz/server/game/GameManager.hx @@ -11,124 +11,118 @@ import ru.m.tankz.proto.room.SlotProto; import ru.m.tankz.server.game.IGameManager; class _GameListener implements GameListener { - private var game:ServerGame; - private var dispatcher:IGameManager; + private var game:ServerGame; + private var dispatcher:IGameManager; - public function new(game:ServerGame, dispatcher:IGameManager) { - this.game = game; - this.dispatcher = dispatcher; - } + public function new(game:ServerGame, dispatcher:IGameManager) { + this.game = game; + this.dispatcher = dispatcher; + } - public function onGameEvent(event:GameEvent):Void { - dispatcher.dispatchEvent(game, event); - switch event { - case COMPLETE(_): - dispatcher.delete(game.id); - dispose(); - case _: - } + public function onGameEvent(event:GameEvent):Void { + dispatcher.dispatchEvent(game, event); + switch event { + case COMPLETE(_): + dispatcher.delete(game.id); + dispose(); + case _: } + } - public function dispose():Void { - game.disconnect(this); - game = null; - dispatcher = null; - } + public function dispose():Void { + game.disconnect(this); + game = null; + dispatcher = null; + } } @:dispatcher(GameManagerListener) class GameManager implements IGameManager { - public var games(default, null):Array; - public var gamesById(default, null):Map; - public var gamesByCreator(default, null):Map; - public var gamesByUser(default, null):Map; + public var games(default, null):Array; + public var gamesById(default, null):Map; + public var gamesByCreator(default, null):Map; + public var gamesByUser(default, null):Map; - private var counter:Int; + private var counter:Int; - public function new() { - counter = 0; - games = []; - gamesById = new Map(); - gamesByCreator = new Map(); - gamesByUser = new Map(); + public function new() { + counter = 0; + games = []; + gamesById = new Map(); + gamesByCreator = new Map(); + gamesByUser = new Map(); + } + + public function create(user:UserProto, type:String, level:Int):ServerGame { + if (gamesByCreator.exists(user.uuid)) { + delete(gamesByCreator[user.uuid].id); } - - public function create(user:UserProto, type:String, level:Int):ServerGame { - if (gamesByCreator.exists(user.uuid)) { - delete(gamesByCreator[user.uuid].id); - } - var room = new RoomProto() - .setGame( - new GameProto() - .setId(++counter) - .setType(type) - .setLevel(level) - ) - .setCreator(user); - var game = new ServerGame(room); - var slots:Array = []; - for (team in game.state.teams) { - for (player in team.players) { - slots.push(new RoomSlotProto().setSlot(new SlotProto().setTeam(player.id.team).setIndex(player.id.index))); - } - } - game.room.setSlots(slots); - games.push(game); - gamesById[game.id] = game; - gamesByCreator[game.room.creator.uuid] = game; - createSignal.emit(game); - join(game.id, user); - return game; + var room = new RoomProto().setGame(new GameProto().setId(++counter).setType(type).setLevel(level)).setCreator(user); + var game = new ServerGame(room); + var slots:Array = []; + for (team in game.state.teams) { + for (player in team.players) { + slots.push(new RoomSlotProto().setSlot(new SlotProto().setTeam(player.id.team).setIndex(player.id.index))); + } } + game.room.setSlots(slots); + games.push(game); + gamesById[game.id] = game; + gamesByCreator[game.room.creator.uuid] = game; + createSignal.emit(game); + join(game.id, user); + return game; + } - public function join(gameId:Int, user:UserProto):Void { - if (gamesById.exists(gameId)) { - var game = gamesById[gameId]; - game.join(user); - gamesByUser[user.uuid] = game; - changeSignal.emit(game, JOIN(user)); - } + public function join(gameId:Int, user:UserProto):Void { + if (gamesById.exists(gameId)) { + var game = gamesById[gameId]; + game.join(user); + gamesByUser[user.uuid] = game; + changeSignal.emit(game, JOIN(user)); } + } - public function delete(gameId:Int):Void { - if (gamesById.exists(gameId)) { - var game = gamesById[gameId]; - games.remove(game); - gamesById.remove(game.id); - gamesByCreator.remove(game.room.creator.uuid); - deleteSignal.emit(game); - } + public function delete(gameId:Int):Void { + if (gamesById.exists(gameId)) { + var game = gamesById[gameId]; + games.remove(game); + gamesById.remove(game.id); + gamesByCreator.remove(game.room.creator.uuid); + deleteSignal.emit(game); } + } - public function leave(user:UserProto):Void { - /*if (gamesByCreator.exists(user.uuid)) { - delete(gamesByCreator[user.uuid].proto.id); - } else*/ if (gamesByUser.exists(user.uuid)) { - var game = gamesByUser[user.uuid]; - gamesByUser.remove(user.uuid); - game.leave(user); - changeSignal.emit(game, LEAVE(user)); - } + public function leave(user:UserProto):Void { + /*if (gamesByCreator.exists(user.uuid)) { + delete(gamesByCreator[user.uuid].proto.id); + } else*/ + if (gamesByUser.exists(user.uuid)) { + var game = gamesByUser[user.uuid]; + gamesByUser.remove(user.uuid); + game.leave(user); + changeSignal.emit(game, LEAVE(user)); } + } - public function slot(user:UserProto, slot:SlotProto):Void { - if (gamesByUser.exists(user.uuid)) { - var game = gamesByUser[user.uuid]; - game.slot(user, slot); - changeSignal.emit(game, SLOT(user, slot)); - } + public function slot(user:UserProto, slot:SlotProto):Void { + if (gamesByUser.exists(user.uuid)) { + var game = gamesByUser[user.uuid]; + game.slot(user, slot); + changeSignal.emit(game, SLOT(user, slot)); } + } - public function start(gameId:Int):Void { - if (gamesById.exists(gameId)) { - var game:ServerGame = gamesById[gameId]; - game.room.game.setStarted(true); - changeSignal.emit(game, START); - game.connect(new _GameListener(game, this)); - game.start(); - } + public function start(gameId:Int):Void { + if (gamesById.exists(gameId)) { + var game:ServerGame = gamesById[gameId]; + game.room.game.setStarted(true); + changeSignal.emit(game, START); + game.connect(new _GameListener(game, this)); + game.start(); } + } - public function dispatchEvent(game:ServerGame, event:GameEvent):Void { - eventSignal.emit(game, event); - } + public function dispatchEvent(game:ServerGame, event:GameEvent):Void { + eventSignal.emit(game, event); + } } diff --git a/src/server/haxe/ru/m/tankz/server/game/IGameManager.hx b/src/server/haxe/ru/m/tankz/server/game/IGameManager.hx index 5919ca7..982cbdb 100644 --- a/src/server/haxe/ru/m/tankz/server/game/IGameManager.hx +++ b/src/server/haxe/ru/m/tankz/server/game/IGameManager.hx @@ -6,39 +6,39 @@ import ru.m.tankz.proto.core.UserProto; import ru.m.tankz.proto.room.SlotProto; enum GameChange { - JOIN(user:UserProto); - LEAVE(user:UserProto); - SLOT(user:UserProto, slot:SlotProto); - START(); + JOIN(user:UserProto); + LEAVE(user:UserProto); + SLOT(user:UserProto, slot:SlotProto); + START(); } interface GameManagerListener { - public function onCreate(game:ServerGame):Void; - public function onChange(game:ServerGame, change:GameChange):Void; - public function onDelete(game:ServerGame):Void; - public function onEvent(game:ServerGame, event:GameEvent):Void; + public function onCreate(game:ServerGame):Void; + public function onChange(game:ServerGame, change:GameChange):Void; + public function onDelete(game:ServerGame):Void; + public function onEvent(game:ServerGame, event:GameEvent):Void; } interface IGameManager { - public var games(default, null):Array; - public var gamesById(default, null):Map; - public var gamesByCreator(default, null):Map; - public var gamesByUser(default, null):Map; + public var games(default, null):Array; + public var gamesById(default, null):Map; + public var gamesByCreator(default, null):Map; + public var gamesByUser(default, null):Map; - private var createSignal(default, null):Signal; - private var changeSignal(default, null):Signal2; - private var deleteSignal(default, null):Signal; - private var eventSignal(default, null):Signal2; + private var createSignal(default, null):Signal; + private var changeSignal(default, null):Signal2; + private var deleteSignal(default, null):Signal; + private var eventSignal(default, null):Signal2; - public function dispatchEvent(game:ServerGame, event:GameEvent):Void; + public function dispatchEvent(game:ServerGame, event:GameEvent):Void; - public function connect(listener:GameManagerListener):Void; - public function disconnect(listener:GameManagerListener):Void; + public function connect(listener:GameManagerListener):Void; + public function disconnect(listener:GameManagerListener):Void; - public function create(user:UserProto, type:String, level:Int):ServerGame; - public function delete(gameId:Int):Void; - public function join(gameId:Int, user:UserProto):Void; - public function slot(user:UserProto, slot:SlotProto):Void; - public function leave(user:UserProto):Void; - public function start(gameId:Int):Void; + public function create(user:UserProto, type:String, level:Int):ServerGame; + public function delete(gameId:Int):Void; + public function join(gameId:Int, user:UserProto):Void; + public function slot(user:UserProto, slot:SlotProto):Void; + public function leave(user:UserProto):Void; + public function start(gameId:Int):Void; } diff --git a/src/server/haxe/ru/m/tankz/server/game/ServerGame.hx b/src/server/haxe/ru/m/tankz/server/game/ServerGame.hx index a145fb9..405180d 100644 --- a/src/server/haxe/ru/m/tankz/server/game/ServerGame.hx +++ b/src/server/haxe/ru/m/tankz/server/game/ServerGame.hx @@ -16,94 +16,96 @@ import ru.m.tankz.server.control.ServerControlFactory; import ru.m.tankz.Type; class ServerGame extends GameRunner { + public var runner(default, null):GameRunner; + public var room(default, null):RoomProto; + public var id(get, null):Int; - public var runner(default, null):GameRunner; - public var room(default, null):RoomProto; - public var id(get, null):Int; + private var timer:Timer; - private var timer:Timer; + @:provide static var levelBundle:ILevelBundle; - @:provide static var levelBundle:ILevelBundle; + public function new(room:RoomProto) { + super({ + state: new GameState(room.game.type, 0), + level: levelBundle.get(new PackId(room.game.type)).data[room.game.level], + }); + this.controlFactory = new ServerControlFactory(); + this.room = room; + } - public function new(room:RoomProto) { - super({ - state: new GameState(room.game.type, 0), - level: levelBundle.get(new PackId(room.game.type)).data[room.game.level], - }); - this.controlFactory = new ServerControlFactory(); - this.room = room; + private inline function get_id():Int { + return room.game.id; + } + + public function contains(user:UserProto):Bool { + for (slot in room.slots) { + if (slot.hasUser() && slot.user.uuid == user.uuid) { + return true; + } } + return false; + } - private inline function get_id():Int { - return room.game.id; + public function join(user:UserProto):Void { + if (!contains(user)) { + room.users.push(user); } + } - public function contains(user:UserProto):Bool { - for (slot in room.slots) { - if (slot.hasUser() && slot.user.uuid == user.uuid) { - return true; - } - } - return false; + public function slot(user:UserProto, slot:SlotProto):Void { + join(user); + for (s in room.slots) { + if (s.hasUser() && s.user.uuid == user.uuid) { + s.clearUser(); + break; + } } + for (s in room.slots) { + if (s.slot.team == slot.team && s.slot.index == slot.index) { + s.setUser(user); + break; + } + } + } - public function join(user:UserProto):Void { - if (!contains(user)) { - room.users.push(user); - } + public function leave(user:UserProto):Void { + for (slot in room.slots) { + if (slot.user != null && slot.user.uuid == user.uuid) { + slot.clearUser(); + break; + } } + room.setUsers(room.users.filter(function(u:UserProto) return u.uuid != user.uuid)); + } - public function slot(user:UserProto, slot:SlotProto):Void { - join(user); - for (s in room.slots) { - if (s.hasUser() && s.user.uuid == user.uuid) { - s.clearUser(); - break; - } - } - for (s in room.slots) { - if (s.slot.team == slot.team && s.slot.index == slot.index) { - s.setUser(user); - break; - } - } - } + override public function start():Void { + state.controls = room.slots.filter(function(slot:RoomSlotProto) return slot.hasUser()) + .map(function(slot:RoomSlotProto):PlayerControl return { + playerId: [slot.slot.team, slot.slot.index], + controller: HUMAN(0), + name: slot.user.name, + }); + super.start(); + } - public function leave(user:UserProto):Void { - for (slot in room.slots) { - if (slot.user != null && slot.user.uuid == user.uuid) { - slot.clearUser(); - break; - } - } - room.setUsers(room.users.filter(function(u:UserProto) return u.uuid != user.uuid)); - } - - override public function start():Void { - state.controls = room.slots - .filter(function(slot:RoomSlotProto) return slot.hasUser()) - .map(function(slot:RoomSlotProto):PlayerControl return { - playerId: [slot.slot.team, slot.slot.index], - controller: HUMAN(0), - name: slot.user.name, - }); - super.start(); - } - - public function restore():Array { - var result = []; - result.push(EventUtil.buildBricksSpawn(engine.map)); - result = result.concat(EventUtil.buildCellsDestroyed(engine.map)); - result.push(START({state: state, level: level})); - for (entity in engine.entities) { - switch EntityTypeResolver.of(entity) { - case EAGLE(eagle): result.push(EventUtil.buildEagleSpawn(eagle)); - case TANK(tank): result.push(EventUtil.buildTankSpawn(tank)); - case BONUS(bonus): result.push(EventUtil.buildBonusSpawn(bonus)); - case BULLET(bullet): result.push(EventUtil.buildBulletSpawn(bullet)); - case CELL(_): - } - } - return result; + public function restore():Array { + var result = []; + result.push(EventUtil.buildBricksSpawn(engine.map)); + result = result.concat(EventUtil.buildCellsDestroyed(engine.map)); + result.push(START({state: state, level: level})); + for (entity in engine.entities) { + switch EntityTypeResolver.of(entity) { + case EAGLE(eagle): + result.push(EventUtil.buildEagleSpawn(eagle)); + case TANK(tank): + result.push(EventUtil.buildTankSpawn(tank)); + case BONUS(bonus): + result.push(EventUtil.buildBonusSpawn(bonus)); + case BULLET(bullet): + result.push(EventUtil.buildBulletSpawn(bullet)); + case CELL(_): + } } + return result; + } } diff --git a/src/server/haxe/ru/m/tankz/server/session/GameSession.hx b/src/server/haxe/ru/m/tankz/server/session/GameSession.hx index ce29bee..83fafac 100644 --- a/src/server/haxe/ru/m/tankz/server/session/GameSession.hx +++ b/src/server/haxe/ru/m/tankz/server/session/GameSession.hx @@ -21,159 +21,162 @@ import ru.m.tankz.server.game.ServerGame; import sys.net.Socket; class GameSession extends ProtoSession implements GameManagerListener { - private static inline var TAG = "Session"; + private static inline var TAG = "Session"; - @:provide static var gameManager:IGameManager; + @:provide static var gameManager:IGameManager; - public var user(default, null):UserProto; - public var gameId(default, null):Int; + public var user(default, null):UserProto; + public var gameId(default, null):Int; - private var subscribed:Bool; - private var tag(get, never):String; + private var subscribed:Bool; + private var tag(get, never):String; - private function get_tag():String { - return '[${id}|${user == null ? '-' : user.name}|${gameId == -1 ? '-' : Std.string(gameId)}]'; + private function get_tag():String { + return '[${id}|${user == null ? '-' : user.name}|${gameId == -1 ? '-' : Std.string(gameId)}]'; + } + + public function new(socket:Socket) { + super(socket, Request); + gameId = -1; + } + + private function sendError(code:Int, message:String):Void { + send(new Response().setError(new ErrorResponse().setCode(code).setMessage(message))); + } + + private function listGame():RoomListResponse { + var games = gameManager.games; + return new RoomListResponse().setRooms([for (game in games) game.room]); + } + + override public function send(packet:Response):Void { + #if proto_debug L.d(TAG, '$tag send: ${packet}'); #end + try { + super.send(packet); + } catch (error:Dynamic) { + L.e(TAG, '$tag send ', error); } + } - public function new(socket:Socket) { - super(socket, Request); - gameId = -1; + private function logout(leave:Bool = true):Void { + gameId = -1; + gameManager.disconnect(this); + if (user != null && leave) { + gameManager.leave(user); + user = null; } + } - private function sendError(code:Int, message:String):Void { - send(new Response().setError(new ErrorResponse().setCode(code).setMessage(message))); + private function join(gameId:Int, restore:Bool):Void { + this.gameId = gameId; + gameManager.join(gameId, user); + var game = gameManager.gamesById[gameId]; + if (restore && game.room.game.started) { + for (event in game.restore()) { + send(new Response().setGameEvent(new GameEventResponse().setEvent(new GameEventProto().setTime(0) + .setEvent(Serializer.run(event))))); + } } + } - private function listGame():RoomListResponse { - var games = gameManager.games; - return new RoomListResponse().setRooms([for (game in games) game.room]); - } - - override public function send(packet:Response):Void { - #if proto_debug L.d(TAG, '$tag send: ${packet}'); #end - try { - super.send(packet); - } catch (error:Dynamic) { - L.e(TAG, '$tag send ', error); + override private function onRequest(request:Request):Void { + #if proto_debug L.d(TAG, '$tag onRequest: ${request}'); #end + try { + if (!request.hasLogin() && user == null) { + throw "Not Authorized"; + } + // login + if (request.hasLogin()) { + user = new UserProto() + .setUuid(request.login.uuid != null ? request.login.uuid : UUID.generateRandom(new Random()) + .toString()) + .setName(request.login.name); + gameManager.connect(this); + send(new Response().setLogin(new LoginResponse().setUser(user))); + if (gameManager.gamesByUser.exists(user.uuid)) { + join(gameManager.gamesByUser[user.uuid].id, false); } - } - - private function logout(leave:Bool = true):Void { - gameId = -1; - gameManager.disconnect(this); - if (user != null && leave) { - gameManager.leave(user); - user = null; + // logout + } else if (request.hasLogout()) { + logout(); + send(new Response().setLogout(new LogoutResponse())); + // room + } else if (request.hasRoom()) { + if (request.room.hasCreate()) { + var game = gameManager.create(user, request.room.create.type, request.room.create.level); + gameId = game.id; + send(new Response().setRoom(new RoomResponse().setRoom(game.room))); + } else if (request.room.hasJoin()) { + join(request.room.join.gameId, request.room.join.restore); + } else if (request.room.hasLeave()) { + gameManager.leave(user); + } else if (request.room.hasSlot()) { + gameManager.slot(user, request.room.slot.slot); + } else if (request.room.hasStart()) { + gameManager.start(gameId); } - } - - private function join(gameId:Int, restore:Bool):Void { - this.gameId = gameId; - gameManager.join(gameId, user); - var game = gameManager.gamesById[gameId]; - if (restore && game.room.game.started) { - for (event in game.restore()) { - send(new Response().setGameEvent(new GameEventResponse().setEvent(new GameEventProto().setTime(0).setEvent(Serializer.run(event))))); - } - } - } - - override private function onRequest(request:Request):Void { - #if proto_debug L.d(TAG, '$tag onRequest: ${request}'); #end - try { - if (!request.hasLogin() && user == null) { - throw "Not Authorized"; - } - // login - if (request.hasLogin()) { - user = new UserProto() - .setUuid(request.login.uuid != null ? request.login.uuid : UUID.generateRandom(new Random()).toString()) - .setName(request.login.name); - gameManager.connect(this); - send(new Response().setLogin(new LoginResponse().setUser(user))); - if (gameManager.gamesByUser.exists(user.uuid)) { - join(gameManager.gamesByUser[user.uuid].id, false); - } - // logout - } else if (request.hasLogout()) { - logout(); - send(new Response().setLogout(new LogoutResponse())); - // room - } else if (request.hasRoom()) { - if (request.room.hasCreate()) { - var game = gameManager.create(user, request.room.create.type, request.room.create.level); - gameId = game.id; - send(new Response().setRoom(new RoomResponse().setRoom(game.room))); - } else if (request.room.hasJoin()) { - join(request.room.join.gameId, request.room.join.restore); - } else if (request.room.hasLeave()) { - gameManager.leave(user); - } else if (request.room.hasSlot()) { - gameManager.slot(user, request.room.slot.slot); - } else if (request.room.hasStart()) { - gameManager.start(gameId); - } - // room list - } else if (request.hasRoomList()) { - subscribed = request.roomList.subscribe; - if (subscribed) { - send(new Response().setRoomList(listGame())); - } - } else if (request.hasGameEvent()) { - if (gameManager.gamesById.exists(gameId)) { - var event:GameEvent = Unserializer.run(request.gameEvent.event.event); - gameManager.gamesById[gameId].gameEventSignal.emit(event); - } - } - } catch (error:Dynamic) { - L.e(TAG, '$tag onRequest ', error); - sendError(500, LoggerUtil.printError(error)); - } - } - - override public function disconnect():Void { - L.d(TAG, '$tag disconnect'); - logout(false); - super.disconnect(); - } - - public function onCreate(game:ServerGame):Void { + // room list + } else if (request.hasRoomList()) { + subscribed = request.roomList.subscribe; if (subscribed) { - send(new Response().setRoomList(listGame())); + send(new Response().setRoomList(listGame())); } + } else if (request.hasGameEvent()) { + if (gameManager.gamesById.exists(gameId)) { + var event:GameEvent = Unserializer.run(request.gameEvent.event.event); + gameManager.gamesById[gameId].gameEventSignal.emit(event); + } + } + } catch (error:Dynamic) { + L.e(TAG, '$tag onRequest ', error); + sendError(500, LoggerUtil.printError(error)); } + } - public function onChange(game:ServerGame, change:GameChange):Void { - if (gameId == game.id) { - switch change { - case LEAVE(user): - if (user.uuid == this.user.uuid) { - gameId = -1; - send(new Response().setRoom(new RoomResponse())); - return; - } - case _: - } - send(new Response().setRoom(new RoomResponse().setRoom(game.room))); - } - if (subscribed) { - send(new Response().setRoomList(listGame())); - } + override public function disconnect():Void { + L.d(TAG, '$tag disconnect'); + logout(false); + super.disconnect(); + } + + public function onCreate(game:ServerGame):Void { + if (subscribed) { + send(new Response().setRoomList(listGame())); } + } - public function onDelete(game:ServerGame):Void { - if (gameId == game.id) { + public function onChange(game:ServerGame, change:GameChange):Void { + if (gameId == game.id) { + switch change { + case LEAVE(user): + if (user.uuid == this.user.uuid) { gameId = -1; send(new Response().setRoom(new RoomResponse())); - } - if (subscribed) { - send(new Response().setRoomList(listGame())); - } + return; + } + case _: + } + send(new Response().setRoom(new RoomResponse().setRoom(game.room))); } + if (subscribed) { + send(new Response().setRoomList(listGame())); + } + } - public function onEvent(game:ServerGame, event:GameEvent):Void { - if (gameId == game.id) { - send(new Response().setGameEvent(new GameEventResponse().setEvent(new GameEventProto().setTime(0).setEvent(Serializer.run(event))))); - } + public function onDelete(game:ServerGame):Void { + if (gameId == game.id) { + gameId = -1; + send(new Response().setRoom(new RoomResponse())); } + if (subscribed) { + send(new Response().setRoomList(listGame())); + } + } + + public function onEvent(game:ServerGame, event:GameEvent):Void { + if (gameId == game.id) { + send(new Response().setGameEvent(new GameEventResponse().setEvent(new GameEventProto().setTime(0) + .setEvent(Serializer.run(event))))); + } + } } diff --git a/src/server/haxe/ru/m/tankz/server/session/ISession.hx b/src/server/haxe/ru/m/tankz/server/session/ISession.hx index ae97bec..ec197d1 100644 --- a/src/server/haxe/ru/m/tankz/server/session/ISession.hx +++ b/src/server/haxe/ru/m/tankz/server/session/ISession.hx @@ -3,7 +3,7 @@ package ru.m.tankz.server.session; import haxe.io.Bytes; interface ISession { - public var id(default, null):Int; - public function pushData(bytes:Bytes):Void; - public function disconnect():Void; + public var id(default, null):Int; + public function pushData(bytes:Bytes):Void; + public function disconnect():Void; } diff --git a/src/server/haxe/ru/m/tankz/server/session/ProtoSession.hx b/src/server/haxe/ru/m/tankz/server/session/ProtoSession.hx index c86af2e..ef81d0d 100644 --- a/src/server/haxe/ru/m/tankz/server/session/ProtoSession.hx +++ b/src/server/haxe/ru/m/tankz/server/session/ProtoSession.hx @@ -8,65 +8,66 @@ import ru.m.connect.neko.NekoWSConnection; import sys.net.Socket; class ProtoSession implements ISession { - private static inline var TAG = "Session"; + private static inline var TAG = "Session"; - private static var POLICY_FILE:String = [ - "", - "", - "", - "", - "", - "" - ].join("\n"); + private static var POLICY_FILE:String = [ + "", + "", + "", + "", + "", + "" + ].join("\n"); - private static var idCounter:Int = 0; + private static var idCounter:Int = 0; - public var id(default, null):Int; - public var connection(default, null):IConnection; - private var socket:Socket; - private var request:Class; + public var id(default, null):Int; + public var connection(default, null):IConnection; - public function new(socket:Socket, request:Class) { - this.id = ++idCounter; - this.socket = socket; - this.request = request; + private var socket:Socket; + private var request:Class; + + public function new(socket:Socket, request:Class) { + this.id = ++idCounter; + this.socket = socket; + this.request = request; + } + + private function buildConnection(bytes:Bytes):IConnection { + var str:String = bytes.getString(0, bytes.length); + if (str == "" + String.fromCharCode(0)) { + L.d(TAG, "policy-file-request"); + socket.output.writeString(POLICY_FILE + String.fromCharCode(0)); + socket.output.flush(); + return null; } - - private function buildConnection(bytes:Bytes):IConnection { - var str:String = bytes.getString(0, bytes.length); - if (str == "" + String.fromCharCode(0)) { - L.d(TAG, "policy-file-request"); - socket.output.writeString(POLICY_FILE + String.fromCharCode(0)); - socket.output.flush(); - return null; - } - if (StringTools.startsWith(str, "GET")) { - connection = new NekoWSConnection(socket, request); - } else { - connection = new NekoConnection(socket, request); - } - connection.receiveHandler.connect(onRequest); - return connection; + if (StringTools.startsWith(str, "GET")) { + connection = new NekoWSConnection(socket, request); + } else { + connection = new NekoConnection(socket, request); } + connection.receiveHandler.connect(onRequest); + return connection; + } - public function send(packet:O):Void { - connection.send(packet); - } + public function send(packet:O):Void { + connection.send(packet); + } - public function pushData(bytes:Bytes):Void { - if (connection == null) { - connection = buildConnection(bytes); - } - if (connection != null) { - connection.pushData(bytes); - } + public function pushData(bytes:Bytes):Void { + if (connection == null) { + connection = buildConnection(bytes); } + if (connection != null) { + connection.pushData(bytes); + } + } - public function disconnect():Void { - connection.disconnect(); - } + public function disconnect():Void { + connection.disconnect(); + } - private function onRequest(request:I):Void { - L.d(TAG, 'onRequest: ${request}'); - } + private function onRequest(request:I):Void { + L.d(TAG, 'onRequest: ${request}'); + } } diff --git a/tankz.code-workspace b/tankz.code-workspace index 117b5ce..898bcc4 100644 --- a/tankz.code-workspace +++ b/tankz.code-workspace @@ -13,8 +13,8 @@ }, "haxe.configurations": [ [ - //"build/client/flash/haxe/debug.hxml", - "build/editor/flash/haxe/debug.hxml" + "build/client/flash/haxe/debug.hxml", + //"build/editor/flash/haxe/debug.hxml" ] ], "haxe.displayServer": {