diff --git a/src/client/haxe/ru/m/tankz/game/LocalGame.hx b/src/client/haxe/ru/m/tankz/game/LocalGame.hx index 355d703..07303be 100644 --- a/src/client/haxe/ru/m/tankz/game/LocalGame.hx +++ b/src/client/haxe/ru/m/tankz/game/LocalGame.hx @@ -21,6 +21,7 @@ class LocalGame extends GameRunner { switch event { case GameEvent.COMPLETE(_, _): disconnect(recorder); + recorder.onGameEvent(event); //ToDo: recordStorage.save(recorder.record); case _: } diff --git a/src/client/haxe/ru/m/tankz/game/NetworkGame.hx b/src/client/haxe/ru/m/tankz/game/NetworkGame.hx index 238448b..0ec7174 100644 --- a/src/client/haxe/ru/m/tankz/game/NetworkGame.hx +++ b/src/client/haxe/ru/m/tankz/game/NetworkGame.hx @@ -20,7 +20,7 @@ class NetworkGame extends Game { } private function onGameEventProto(game:GameEventResponse):Void { - var frame = game.frame; + var time = game.time; var eventStr = game.event; var event:GameEvent = Unserializer.run(eventStr); gameEventSignal.emit(event); diff --git a/src/client/haxe/ru/m/tankz/network/NetworkManager.hx b/src/client/haxe/ru/m/tankz/network/NetworkManager.hx index 2a7ef57..3c95b17 100644 --- a/src/client/haxe/ru/m/tankz/network/NetworkManager.hx +++ b/src/client/haxe/ru/m/tankz/network/NetworkManager.hx @@ -106,7 +106,7 @@ class NetworkManager { } public function action(tankId:Int, action:TankAction):Void { - connection.send(new Request().setGameEvent(new GameEventRequest().setFrame(0).setEvent( + connection.send(new Request().setGameEvent(new GameEventRequest().setTime(0).setEvent( Serializer.run(GameEvent.ACTION(tankId, action)) ))); } diff --git a/src/common/haxe/ru/m/tankz/bot/BotControl.hx b/src/common/haxe/ru/m/tankz/bot/BotControl.hx index 29874e5..6e4ac40 100644 --- a/src/common/haxe/ru/m/tankz/bot/BotControl.hx +++ b/src/common/haxe/ru/m/tankz/bot/BotControl.hx @@ -12,7 +12,7 @@ class BotControl extends Control { private var tank(get, null):Tank; private inline function get_tank():Tank { - return handler == null ? null : engine.getEntity(tankId); + return handler == null || tankId == -1 ? null : engine.getEntity(tankId); } override public function stop():Void { diff --git a/src/common/haxe/ru/m/tankz/control/Control.hx b/src/common/haxe/ru/m/tankz/control/Control.hx index b0c1e6a..f98f5aa 100644 --- a/src/common/haxe/ru/m/tankz/control/Control.hx +++ b/src/common/haxe/ru/m/tankz/control/Control.hx @@ -22,6 +22,7 @@ class Control { public function new(playerId:PlayerId) { this.playerId = playerId; + this.tankId = -1; } public function bind(handler:IGame, engine:IEngine):Void { @@ -30,7 +31,7 @@ class Control { } public function action(action:TankAction):Void { - if (tankId != 0 && handler != null) { + if (tankId > -1 && handler != null) { handler.gameEventSignal.emit(GameEvent.ACTION(tankId, action)); } } @@ -45,5 +46,6 @@ class Control { stop(); handler = null; engine = null; + tankId = -1; } } diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 30eca56..676480c 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -20,14 +20,14 @@ import ru.m.tankz.map.LevelMap; public var allEntities(default, null):Map; public var entities(default, null):Map; - private var time:Float; + private var ticker:Ticker; public function new(config:Config) { this.config = config; map = new LevelMap(config.map); allEntities = new Map(); entities = new Map(); - time = Date.now().getTime(); + ticker = new Ticker(); } public function getEntity(entityId:Int):T { @@ -67,9 +67,8 @@ import ru.m.tankz.map.LevelMap; } public function update():Void { - var newTime:Float = Timer.stamp() * 1000; - var d:Float = newTime - time; - time = newTime; + if (!ticker.running) ticker.start(); + var d:Float = ticker.passed; 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/Ticker.hx b/src/common/haxe/ru/m/tankz/engine/Ticker.hx new file mode 100644 index 0000000..637f6c2 --- /dev/null +++ b/src/common/haxe/ru/m/tankz/engine/Ticker.hx @@ -0,0 +1,42 @@ +package ru.m.tankz.engine; + +class Ticker { + 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 static var TIME = Timer.stamp(); + + private inline static function now():Int { + return Std.int((Timer.stamp() - TIME) * 1000); + } + + public function new() { + begin = 0; + last = 0; + running = false; + } + + public function start():Void { + last = begin = now(); + running = true; + } + + public function stop():Void { + running = false; + } + + private function get_time():Int { + return now() - begin; + } + + private function get_passed():Int { + var now = now(); + var result = now - last; + last = now; + return result; + } +} diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 094dc09..ec1a679 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -24,7 +24,6 @@ import ru.m.tankz.Type; public var config(default, null):Config; public var winner(default, null):Null; public var state(default, null):GameState; - public var frame(default, null):Int; public var engine(default, null):IEngine; public var controlFactory(default, null):IControlFactory; @@ -35,7 +34,6 @@ import ru.m.tankz.Type; this.state = state; this.teams = new Map(); this.config = configBundle.get(type); - this.frame = 0; this.controlFactory = new NoneControlFactory(); connect(this); } diff --git a/src/common/haxe/ru/m/tankz/game/GameRunner.hx b/src/common/haxe/ru/m/tankz/game/GameRunner.hx index 678dc7b..3ad6b05 100644 --- a/src/common/haxe/ru/m/tankz/game/GameRunner.hx +++ b/src/common/haxe/ru/m/tankz/game/GameRunner.hx @@ -27,7 +27,6 @@ class GameRunner extends Game implements EngineListener { } private function update():Void { - frame++; engine.update(); } @@ -87,7 +86,7 @@ class GameRunner extends Game implements EngineListener { var actives:Array = []; for (team in teams.iterator()) { if (team.isAlive) { - if (team.eagleId > 0) { + if (team.eagleId > -1) { if (!cast(engine.entities[team.eagleId], Eagle).death) { actives.push(team.id); } @@ -341,7 +340,7 @@ class GameRunner extends Game implements EngineListener { if (player.control != null) { player.control.stop(); } - player.tankId = 0; //ToDo: ? + player.tankId = -1; team.onDestroy(player.id); if (player.state.life > 0) { changeLife(player.id, -1); diff --git a/src/common/haxe/ru/m/tankz/game/IGame.hx b/src/common/haxe/ru/m/tankz/game/IGame.hx index 9c954f5..3de47a4 100644 --- a/src/common/haxe/ru/m/tankz/game/IGame.hx +++ b/src/common/haxe/ru/m/tankz/game/IGame.hx @@ -11,7 +11,6 @@ interface IGame extends GameListener { public var config(default, null):Config; public var winner(default, null):Null; public var state(default, null):GameState; - public var frame(default, null):Int; public var controlFactory(default, null):IControlFactory; public var gameEventSignal(default, null):Signal; diff --git a/src/common/haxe/ru/m/tankz/game/Player.hx b/src/common/haxe/ru/m/tankz/game/Player.hx index c9b65c9..3ace588 100644 --- a/src/common/haxe/ru/m/tankz/game/Player.hx +++ b/src/common/haxe/ru/m/tankz/game/Player.hx @@ -22,6 +22,7 @@ class Player { this.state.reset(); this.state.life = Math.isNaN(config.life) ? 0 : config.life; this.bullets = 0; + this.tankId = -1; } private function set_tankId(value:Int):Int { @@ -42,6 +43,6 @@ class Player { } private function get_isAlive():Bool { - return tankId > 0 || state.life > 0; + return tankId > -1 || state.life > 0; } } diff --git a/src/common/haxe/ru/m/tankz/game/Team.hx b/src/common/haxe/ru/m/tankz/game/Team.hx index 5f514a6..0ebbc33 100644 --- a/src/common/haxe/ru/m/tankz/game/Team.hx +++ b/src/common/haxe/ru/m/tankz/game/Team.hx @@ -20,6 +20,7 @@ class Team { 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]; 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 da9f88d..2a9a5d0 100644 --- a/src/common/haxe/ru/m/tankz/game/record/GamePlayer.hx +++ b/src/common/haxe/ru/m/tankz/game/record/GamePlayer.hx @@ -2,23 +2,25 @@ package ru.m.tankz.game.record; import flash.events.Event; import flash.Lib; +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 ticker:Ticker; public function new(record:GameRecord) { super(record.state); - frame = 0; this.record = record; this.data = null; + this.ticker = new Ticker(); } override public function start():Void { super.start(); - frame = 0; + ticker.start(); data = record.events.slice(0); Lib.current.stage.addEventListener(Event.ENTER_FRAME, onEnterFrame); } @@ -28,10 +30,9 @@ class GamePlayer extends Game { } private function onEnterFrame(event:Event):Void { - frame++; var events = 0; for (event in data) { - if (event.frame <= frame) { + if (event.time <= ticker.time) { events++; gameEventSignal.emit(event.event); switch event.event { 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 3b9f988..a965822 100644 --- a/src/common/haxe/ru/m/tankz/game/record/GameRecord.hx +++ b/src/common/haxe/ru/m/tankz/game/record/GameRecord.hx @@ -5,8 +5,8 @@ import com.hurlant.crypto.extra.UUID; import com.hurlant.crypto.prng.Random; typedef EventItem = { - frame:Int, - event:GameEvent + var time:Int; + var event:GameEvent; } class GameRecordInfo { 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 fb5f793..ae2c85d 100644 --- a/src/common/haxe/ru/m/tankz/game/record/GameRecorder.hx +++ b/src/common/haxe/ru/m/tankz/game/record/GameRecorder.hx @@ -1,44 +1,31 @@ package ru.m.tankz.game.record; -import flash.events.Event; -import flash.Lib; +import ru.m.tankz.engine.Ticker; import ru.m.tankz.game.IGame; class GameRecorder implements GameListener { - private var frame:Int; public var record(default, null):GameRecord; + private var ticker:Ticker; + public function new() { - frame = 0; + ticker = new Ticker(); record = new GameRecord(); } 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): record.info.type = state.type; record.info.presetId = state.presetId; record.info.levelId = state.levelId; - start(); + record.info.date = Date.now(); case GameEvent.COMPLETE(_, _): - stop(); + ticker.stop(); case _: } - record.events.push({frame: frame, event: event}); - } - - public function start():Void { - frame = 0; - record.info.date = Date.now(); - Lib.current.stage.addEventListener(Event.ENTER_FRAME, onEnterFrame); - } - - public function stop():Void { - Lib.current.stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame); - } - - private function onEnterFrame(event:Event):Void { - frame++; } } diff --git a/src/common/proto/pack.proto b/src/common/proto/pack.proto index f3232e0..dd4c86f 100644 --- a/src/common/proto/pack.proto +++ b/src/common/proto/pack.proto @@ -70,12 +70,12 @@ message StartGameResponse { // Game message GameEventRequest { - int32 frame = 1; + int32 time = 1; string event = 2; } message GameEventResponse { - int32 frame = 1; + int32 time = 1; string event = 2; } 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 25d9cab..09f5c99 100644 --- a/src/server/haxe/ru/m/tankz/server/session/GameSession.hx +++ b/src/server/haxe/ru/m/tankz/server/session/GameSession.hx @@ -160,7 +160,7 @@ class GameSession extends ProtoSession implements GameManager public function onEvent(game:ServerGame, event:GameEvent):Void { if (gameId == game.proto.id) { - send(new Response().setGameEvent(new GameEventResponse().setFrame(game.frame).setEvent(Serializer.run(event)))); + send(new Response().setGameEvent(new GameEventResponse().setTime(0).setEvent(Serializer.run(event)))); } } }