diff --git a/src/client/haxe/ru/m/tankz/view/ClientView.hx b/src/client/haxe/ru/m/tankz/view/ClientView.hx index 541a33b..1dd9209 100644 --- a/src/client/haxe/ru/m/tankz/view/ClientView.hx +++ b/src/client/haxe/ru/m/tankz/view/ClientView.hx @@ -1,5 +1,6 @@ package ru.m.tankz.view; +import ru.m.tankz.game.IGame; import flash.events.KeyboardEvent; import flash.ui.Keyboard; import haxework.resources.IResources; @@ -21,6 +22,7 @@ import ru.m.tankz.view.popup.LoginPopup; @:provide var resources:IResources; @:provide var switcher:FrameSwitcher; @:provide var soundManager:SoundManager; + @:provide var game:IGame; public function init():Void { resources.text.put('version', '${Const.VERSION}'); @@ -37,6 +39,10 @@ import ru.m.tankz.view.popup.LoginPopup; switcher.change(StartFrame.ID); case Keyboard.M: soundManager.mute = !soundManager.mute; + case Keyboard.P: + if (game != null) { + game.pause = !game.pause; + } } }); switcher.change(StartFrame.ID); @@ -54,7 +60,8 @@ import ru.m.tankz.view.popup.LoginPopup; logoutButton.visible = false; loginButton.visible = true; case ERROR(error): - L.e("ClientView", 'onConnectionState: ERROR', error); + //L.e("ClientView", 'onConnectionState: ERROR', error); + L.w("ClientView", 'onConnectionState: ERROR'); case _: username.text = ""; logoutButton.visible = false; diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 676480c..951d166 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -16,11 +16,10 @@ import ru.m.tankz.map.LevelMap; public var config(default, default):Config; public var map(default, null):LevelMap; - - public var allEntities(default, null):Map; + public var ticker(default, null):ITicker; public var entities(default, null):Map; - private var ticker:Ticker; + public var allEntities(default, null):Map; public function new(config:Config) { this.config = config; @@ -67,8 +66,7 @@ import ru.m.tankz.map.LevelMap; } public function update():Void { - if (!ticker.running) ticker.start(); - var d:Float = ticker.passed; + var d:Float = ticker.tick(); for (ent in entities) if (Std.is(ent, MobileEntity)) { var entityType:EntityType = EntityTypeResolver.of(ent); diff --git a/src/common/haxe/ru/m/tankz/engine/IEngine.hx b/src/common/haxe/ru/m/tankz/engine/IEngine.hx index 52dc073..030706b 100644 --- a/src/common/haxe/ru/m/tankz/engine/IEngine.hx +++ b/src/common/haxe/ru/m/tankz/engine/IEngine.hx @@ -12,6 +12,7 @@ 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 spawnSignal(default, null):Signal1; public var collisionSignal(default, null):Signal2; diff --git a/src/common/haxe/ru/m/tankz/engine/ITicker.hx b/src/common/haxe/ru/m/tankz/engine/ITicker.hx new file mode 100644 index 0000000..2dcaf2c --- /dev/null +++ b/src/common/haxe/ru/m/tankz/engine/ITicker.hx @@ -0,0 +1,11 @@ +package ru.m.tankz.engine; + +interface ITicker { + 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):Void; +} diff --git a/src/common/haxe/ru/m/tankz/engine/Ticker.hx b/src/common/haxe/ru/m/tankz/engine/Ticker.hx index 637f6c2..1de03fb 100644 --- a/src/common/haxe/ru/m/tankz/engine/Ticker.hx +++ b/src/common/haxe/ru/m/tankz/engine/Ticker.hx @@ -1,12 +1,17 @@ package ru.m.tankz.engine; -class Ticker { +typedef Action = { + var time:Int; + var action:Void->Void; +} + +class Ticker implements ITicker { public var time(get, null):Int; - public var passed(get, null):Int; public var running(default, null):Bool; - private var begin:Int; - private var last:Int; + private var passed:Int; + private var last_tick:Int; + private var actions:Array; private static var TIME = Timer.stamp(); @@ -15,13 +20,18 @@ class Ticker { } public function new() { - begin = 0; - last = 0; + passed = 0; + last_tick = 0; running = false; + actions = []; + } + + private function get_time():Int { + return passed; } public function start():Void { - last = begin = now(); + last_tick = now(); running = true; } @@ -29,14 +39,38 @@ class Ticker { running = false; } - private function get_time():Int { - return now() - begin; - } - - private function get_passed():Int { + public function tick():Int { + if (!running) { + return 0; + } var now = now(); - var result = now - last; - last = now; + var result = now - last_tick; + last_tick = now; + passed += result; + if (actions.length > 0) { + runActions(); + } return result; } + + private function runActions():Void { + var it = actions.iterator(); + var action = it.next(); + var i = 0; + while (action != null && time >= action.time) { + L.d("Ticker", 'run action: $action(${action.time}) on $time'); + action.action(); + i++; + action = it.next(); + } + if (i > 0) { + actions = actions.slice(i); + } + } + + public function emit(action:Void->Void, delay:Int):Void { + L.d("Ticker", 'emit: $action on ${time+delay}'); + actions.push({action:action, time:time+delay}); + actions.sort(function(a, b) return a.time - b.time); + } } diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 4bf14f6..cc95aa9 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -26,6 +26,7 @@ import ru.m.tankz.Type; public var state(default, null):GameState; public var engine(default, null):IEngine; public var controlFactory(default, null):IControlFactory; + public var pause(default, set):Bool; @:provide var configBundle:IConfigBundle; @@ -35,9 +36,20 @@ import ru.m.tankz.Type; this.teams = new Map(); this.config = configBundle.get(type); this.controlFactory = new NoneControlFactory(); + this.pause = false; connect(this); } + private function set_pause(value:Bool):Bool { + if (pause != value) { + pause = value; + changePause(pause); + } + return pause; + } + + private function changePause(value:Bool):Void {} + private function applyPosition(entity:Entity, position:Position):Void { entity.rect.center = new Point(position.x, position.y); if (position.direction != null) { diff --git a/src/common/haxe/ru/m/tankz/game/GameRunner.hx b/src/common/haxe/ru/m/tankz/game/GameRunner.hx index 851d953..088c60b 100644 --- a/src/common/haxe/ru/m/tankz/game/GameRunner.hx +++ b/src/common/haxe/ru/m/tankz/game/GameRunner.hx @@ -1,6 +1,5 @@ package ru.m.tankz.game; -import haxework.color.Color; import ru.m.geom.Line; import ru.m.geom.Point; import ru.m.tankz.control.Control; @@ -27,6 +26,14 @@ class GameRunner extends Game implements EngineListener { this.engine.connect(this); } + override function changePause(value:Bool):Void { + if (value) { + engine.ticker.stop(); + } else { + engine.ticker.start(); + } + } + private function update():Void { engine.update(); } @@ -47,7 +54,7 @@ class GameRunner extends Game implements EngineListener { team.spawner.runner = spawn; for (player in team.players.iterator()) { if (team.tryRespawn(player.id)) { - team.spawner.push(player.id); + team.spawner.push(engine.ticker, player.id); } } if (team.config.eagle != null) { @@ -293,12 +300,20 @@ class GameRunner extends Game implements EngineListener { } 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(); timer = new Timer(30); timer.run = update; case COMPLETE(_, _): + engine.ticker.stop(); if (timer != null) { timer.stop(); timer = null; @@ -351,7 +366,7 @@ class GameRunner extends Game implements EngineListener { } var respawn:Bool = team.tryRespawn(player.id); if (respawn) { - team.spawner.push(player.id); + team.spawner.push(engine.ticker, player.id); } if (!team.isAlive) { checkComplete(); diff --git a/src/common/haxe/ru/m/tankz/game/IGame.hx b/src/common/haxe/ru/m/tankz/game/IGame.hx index 3de47a4..0c1a772 100644 --- a/src/common/haxe/ru/m/tankz/game/IGame.hx +++ b/src/common/haxe/ru/m/tankz/game/IGame.hx @@ -12,6 +12,7 @@ interface IGame extends GameListener { public var winner(default, null):Null; public var state(default, null):GameState; public var controlFactory(default, null):IControlFactory; + public var pause(default, set):Bool; public var gameEventSignal(default, null):Signal; diff --git a/src/common/haxe/ru/m/tankz/game/Spawner.hx b/src/common/haxe/ru/m/tankz/game/Spawner.hx index 5f6b5a8..6f02be8 100644 --- a/src/common/haxe/ru/m/tankz/game/Spawner.hx +++ b/src/common/haxe/ru/m/tankz/game/Spawner.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game; +import ru.m.tankz.engine.ITicker; import ru.m.tankz.config.Config; import ru.m.tankz.Type; import ru.m.Timer; @@ -18,7 +19,6 @@ class Spawner { private var config:TeamConfig; private var points:Array; private var queue:Array; - private var timer:Timer; private var indexedPoints:Map; private var anyPoints:Array; @@ -61,7 +61,7 @@ class Spawner { return null; } - public function push(playerId:PlayerId):Void { + public function push(ticker:ITicker, playerId:PlayerId):Void { var point:SpawnPoint = null; if (indexedPoints.exists(playerId.index)) { point = indexedPoints.get(playerId.index); @@ -71,24 +71,16 @@ class Spawner { } if (point != null) { queue.push({playerId:playerId, point:point, tankType:getPlayerTank(playerId)}); - run(); - } - } - - private function run():Void { - if (timer == null) { - timer = new Timer(config.spawnInterval == null ? 500 : config.spawnInterval); - timer.run = spawn; + 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) { - if (timer != null) { - timer.stop(); - timer = null; - } - } else { + if (queue.length > 0) { runner(queue.shift()); } } 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 ae2c85d..6b85075 100644 --- a/src/common/haxe/ru/m/tankz/game/record/GameRecorder.hx +++ b/src/common/haxe/ru/m/tankz/game/record/GameRecorder.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game.record; +import ru.m.tankz.engine.ITicker; import ru.m.tankz.engine.Ticker; import ru.m.tankz.game.IGame; @@ -7,7 +8,7 @@ class GameRecorder implements GameListener { public var record(default, null):GameRecord; - private var ticker:Ticker; + private var ticker:ITicker; public function new() { ticker = new Ticker(); @@ -15,10 +16,9 @@ class GameRecorder implements GameListener { } public function onGameEvent(event:GameEvent):Void { - if (!ticker.running) ticker.start(); - record.events.push({time: ticker.time, event: event}); switch event { case GameEvent.START(state): + ticker.start(); record.info.type = state.type; record.info.presetId = state.presetId; record.info.levelId = state.levelId; @@ -27,5 +27,6 @@ class GameRecorder implements GameListener { ticker.stop(); case _: } + record.events.push({time: ticker.time, event: event}); } }