diff --git a/.gitignore b/.gitignore index b697065..5e323f6 100755 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +build/ target/ src-gen/ out/ diff --git a/WORK.md b/WORK.md index 8bdeeb8..38a0fa6 100644 --- a/WORK.md +++ b/WORK.md @@ -1,8 +1,7 @@ * death game bonus * tanks and bullets speed balancing -* clean player state on restart in classic type +* clean player state on lose in classic type * network series -* map pack version (or hash) * bot upgrade * game config validate * mine z-order @@ -13,6 +12,10 @@ * display ammo count (screen gamepad) * bonus ammo * game panel rework -* pause * game state: config, map, entities, players * game menu pack progress +* balloons: change mute, network, pause +* render: animations pause +* settings: mute, pause, reset device actions +* game view: pause button +* game view: toggle panel on mobile diff --git a/package.json b/package.json index 8e28731..d83e6cd 100755 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "gulp": "^4.0.0", "gulp-add": "0.0.2", "gulp-clean": "^0.4.0", - "gulp-haxetool": "0.1.1", + "gulp-haxetool": "0.1.2", "yargs": "^13.2.4" }, "haxeDependencies": { diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index 61b1ad6..48ea9c9 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -38,6 +38,7 @@ class Render extends SpriteView implements IRender { private var upperLayer:Sprite; private var items:Map; + private var paused:Bool; public function new() { super(); @@ -92,7 +93,9 @@ class Render extends SpriteView implements IRender { } private function onEnterFrame(event:Event):Void { - draw(); + if (!paused) { + draw(); + } } private function clearLayer(layer:DisplayObjectContainer) { @@ -120,6 +123,8 @@ class Render extends SpriteView implements IRender { content.addEventListener(Event.ENTER_FRAME, onEnterFrame); case COMPLETE(_): content.removeEventListener(Event.ENTER_FRAME, onEnterFrame); + case PAUSE(paused): + this.paused = paused; case SPAWN(BRICK(bricks)): drawBackground(); for (brick in bricks) { diff --git a/src/client/haxe/ru/m/tankz/view/ClientView.hx b/src/client/haxe/ru/m/tankz/view/ClientView.hx index 1a803aa..a55fb7a 100644 --- a/src/client/haxe/ru/m/tankz/view/ClientView.hx +++ b/src/client/haxe/ru/m/tankz/view/ClientView.hx @@ -1,11 +1,12 @@ package ru.m.tankz.view; -import flash.events.KeyboardEvent; import flash.ui.Keyboard; import haxework.resources.IResources; import haxework.view.frame.FrameSwitcher; import haxework.view.group.VGroupView; -import ru.m.tankz.game.IGame; +import ru.m.control.DeviceAction; +import ru.m.control.DeviceType; +import ru.m.control.IControlBus; import ru.m.tankz.network.NetworkManager; import ru.m.tankz.sound.SoundManager; @@ -16,7 +17,7 @@ import ru.m.tankz.sound.SoundManager; @:provide var resources:IResources; @:provide var switcher:FrameSwitcher; @:provide var soundManager:SoundManager; - @:provide var game:IGame; + @:provide static var bus:IControlBus; public function init():Void { resources.text.put('version', '${Const.VERSION}'); @@ -26,18 +27,17 @@ import ru.m.tankz.sound.SoundManager; public function launch():Void { content.stage.stageFocusRect = false; - content.stage.addEventListener(KeyboardEvent.KEY_UP, function(event:KeyboardEvent):Void { - switch event.keyCode { - case Keyboard.ESCAPE: - switcher.change(MenuFrame.ID); - case Keyboard.M: - soundManager.mute = !soundManager.mute; - case Keyboard.P: - if (game != null) { - game.pause = !game.pause; - } - } - }); + 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 _: + } + } } diff --git a/src/client/haxe/ru/m/tankz/view/GameFrame.hx b/src/client/haxe/ru/m/tankz/view/GameFrame.hx index 6bbb1d8..7aa11d4 100644 --- a/src/client/haxe/ru/m/tankz/view/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/GameFrame.hx @@ -1,5 +1,7 @@ package ru.m.tankz.view; +import flash.ui.Keyboard; +import ru.m.control.DeviceAction; import haxework.view.frame.FrameSwitcher; import haxework.view.frame.FrameView; import haxework.view.group.GroupView; @@ -81,9 +83,19 @@ import ru.m.tankz.view.gamepad.GamepadView; } } } + 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; diff --git a/src/common/haxe/ru/m/tankz/game/GameEvent.hx b/src/common/haxe/ru/m/tankz/game/GameEvent.hx index b9ac393..cd3150f 100644 --- a/src/common/haxe/ru/m/tankz/game/GameEvent.hx +++ b/src/common/haxe/ru/m/tankz/game/GameEvent.hx @@ -86,4 +86,5 @@ enum GameEvent { 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 8344f5e..9557202 100644 --- a/src/common/haxe/ru/m/tankz/game/GameRunner.hx +++ b/src/common/haxe/ru/m/tankz/game/GameRunner.hx @@ -46,6 +46,7 @@ class GameRunner extends Game implements EngineListener { } else { engine.ticker.start(); } + gameEventSignal.emit(PAUSE(value)); } } diff --git a/src/common/haxe/ru/m/tankz/util/LevelUtil.hx b/src/common/haxe/ru/m/tankz/util/LevelUtil.hx index 5bcb5a9..e176e30 100644 --- a/src/common/haxe/ru/m/tankz/util/LevelUtil.hx +++ b/src/common/haxe/ru/m/tankz/util/LevelUtil.hx @@ -7,6 +7,7 @@ import haxe.zip.Entry; import haxe.zip.Writer; import ru.m.tankz.config.Config; import ru.m.tankz.Type; +import ru.m.yaml.SortingRenderer; import yaml.Parser; import yaml.Renderer; import yaml.Yaml; @@ -20,6 +21,14 @@ typedef LevelSource = { class LevelUtil { + 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}'; @@ -27,7 +36,7 @@ class LevelUtil { } public static function loads(data:String):LevelConfig { - var obj:LevelSource = Yaml.parse(data, Parser.options().useObjects()); + var obj:LevelSource = yamlParse(data); return { data: obj.data.split('').map(function(c) return Std.parseInt(c)), points: obj.points, @@ -38,12 +47,12 @@ class LevelUtil { public static function dumps(level:LevelConfig):String { var bricksStr = level.data.join(''); - return Yaml.render({ + return yamlRender({ data: bricksStr, points: level.points, name: level.name, size: level.size, - }, Renderer.options().setFlowLevel(1)); + }); } public static function empty(size:GridSize, filler:BrickIndex):LevelConfig { @@ -58,7 +67,7 @@ class LevelUtil { for (entry in files) { if (entry.fileName == "meta.yml") { var content = ZipUtil.extractEntry(entry); - return Yaml.parse(content, Parser.options().useObjects()); + return yamlParse(content); } } return null; @@ -71,7 +80,7 @@ class LevelUtil { for (entry in files) { var content = ZipUtil.extractEntry(entry); if (entry.fileName == "meta.yml") { - meta = Yaml.parse(content, Parser.options().useObjects()); + meta = yamlParse(content); } else { var level:LevelConfig = LevelUtil.loads(content); level.packId = meta.id; @@ -91,7 +100,7 @@ class LevelUtil { public static function pack(pack:LevelPack):Bytes { var output = new BytesOutput(); var writer = new Writer(output); - var metaEntry:Entry = ZipUtil.createEntry("meta.yml", Yaml.render(pack.meta, Renderer.options().setFlowLevel(1))); + 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/yaml/SortingRenderer.hx b/src/common/haxe/ru/m/yaml/SortingRenderer.hx new file mode 100644 index 0000000..2788eec --- /dev/null +++ b/src/common/haxe/ru/m/yaml/SortingRenderer.hx @@ -0,0 +1,71 @@ +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; + } + + 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; + } + + tag = _tag; + 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; + } +} diff --git a/src/common/resources/level/classic_modern.zip b/src/common/resources/level/classic_modern.zip index fca9f58..d61b8c7 100644 Binary files a/src/common/resources/level/classic_modern.zip and b/src/common/resources/level/classic_modern.zip differ