From 183c6c16f1fb48b3b6a8f2bc37df4c8a43103a5d Mon Sep 17 00:00:00 2001 From: shmyga Date: Tue, 7 May 2019 17:21:01 +0300 Subject: [PATCH] [client] add RecordFrame --- src/client/haxe/ru/m/tankz/Init.hx | 4 -- src/client/haxe/ru/m/tankz/render/Render.hx | 1 + .../haxe/ru/m/tankz/view/ClientView.yaml | 2 + .../haxe/ru/m/tankz/view/RecordFrame.hx | 43 +++++++++++++++++++ .../haxe/ru/m/tankz/view/RecordFrame.yaml | 20 +++++++++ src/client/haxe/ru/m/tankz/view/StartFrame.hx | 4 +- .../haxe/ru/m/tankz/view/StartFrame.yaml | 6 ++- .../m/tankz/view/classic/ClassicGamePanel.hx | 16 +++---- .../haxe/ru/m/tankz/view/common/GameFrame.hx | 30 +++++++++++-- .../ru/m/tankz/view/dota/DotaGamePanel.hx | 8 ++-- src/common/haxe/ru/m/tankz/engine/Engine.hx | 5 ++- src/common/haxe/ru/m/tankz/game/Game.hx | 16 ++++++- src/common/haxe/ru/m/tankz/game/GameEvent.hx | 8 ++-- src/common/haxe/ru/m/tankz/game/GameRunner.hx | 19 +++----- .../haxe/ru/m/tankz/game/record/GamePlayer.hx | 12 ++---- .../haxe/ru/m/tankz/game/record/GameRecord.hx | 14 ++++++ .../ru/m/tankz/game/record/GameRecorder.hx | 5 ++- .../haxe/ru/m/tankz/network/NetworkGame.hx | 10 +---- src/common/resources/classic/config.yaml | 2 +- 19 files changed, 162 insertions(+), 63 deletions(-) create mode 100644 src/client/haxe/ru/m/tankz/view/RecordFrame.hx create mode 100644 src/client/haxe/ru/m/tankz/view/RecordFrame.yaml diff --git a/src/client/haxe/ru/m/tankz/Init.hx b/src/client/haxe/ru/m/tankz/Init.hx index df61182..40e4ca2 100644 --- a/src/client/haxe/ru/m/tankz/Init.hx +++ b/src/client/haxe/ru/m/tankz/Init.hx @@ -69,10 +69,6 @@ class Init { controlFactory = new ClientControlFactory(); popupManager = new PopupManager(); - for (record in recordStorage) { - L.w("RECORD", '${record.id}. ${record.date}'); - } - popupManager.showAnimateFactory = function(v) return new UnFadeAnimate(v, 100); popupManager.closeAnimateFactory = function(v) return new FadeAnimate(v, 100); diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index 770024f..ce42ba4 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -115,6 +115,7 @@ class Render extends SpriteView implements GameListener implements EngineListene var item = new BulletItem(bullet); items.set(bullet.key, item); entryLayer.addChild(item.view); + item.update(); case BONUS(bonus): var item = new BonusItem(bonus); items.set(bonus.key, item); diff --git a/src/client/haxe/ru/m/tankz/view/ClientView.yaml b/src/client/haxe/ru/m/tankz/view/ClientView.yaml index 50531f2..823ef15 100755 --- a/src/client/haxe/ru/m/tankz/view/ClientView.yaml +++ b/src/client/haxe/ru/m/tankz/view/ClientView.yaml @@ -17,3 +17,5 @@ views: $type: ru.m.tankz.view.ResultFrame - id: settings $type: ru.m.tankz.view.SettingsFrame + - id: record + $type: ru.m.tankz.view.RecordFrame diff --git a/src/client/haxe/ru/m/tankz/view/RecordFrame.hx b/src/client/haxe/ru/m/tankz/view/RecordFrame.hx new file mode 100644 index 0000000..3aabb7e --- /dev/null +++ b/src/client/haxe/ru/m/tankz/view/RecordFrame.hx @@ -0,0 +1,43 @@ +package ru.m.tankz.view; + +import haxework.view.frame.FrameSwitcher; +import haxework.view.list.ListView.IListItemView; +import haxework.view.list.VListView; +import haxework.view.VGroupView; +import ru.m.tankz.game.record.GameRecord; +import ru.m.tankz.preset.ClassicGame; +import ru.m.tankz.preset.DeathGame; +import ru.m.tankz.preset.DotaGame; +import ru.m.tankz.storage.RecordStorage; +import ru.m.tankz.view.classic.ClassicGameFrame; +import ru.m.tankz.view.death.DeathGameFrame; +import ru.m.tankz.view.dota.DotaGameFrame; + +@:template class RecordFrame extends VGroupView { + public static var ID(default, never):String = "record"; + + @:view var data:VListView; + + @:provide var recordStorage:RecordStorage; + @:provide var switcher:FrameSwitcher; + @:provide var record:GameRecord; + + public function onShow():Void { + data.data = Lambda.array(recordStorage); + } + + private function onRecordSelect(item:IListItemView):Void { + record = item.data; + // ToDo: copy@paste from LevelFrame + switcher.change(switch record.type { + case ClassicGame.TYPE: ClassicGameFrame.ID; + case DotaGame.TYPE: DotaGameFrame.ID; + case DeathGame.TYPE: DeathGameFrame.ID; + case _: StartFrame.ID; + }); + } + + private function close() { + switcher.change(StartFrame.ID); + } +} diff --git a/src/client/haxe/ru/m/tankz/view/RecordFrame.yaml b/src/client/haxe/ru/m/tankz/view/RecordFrame.yaml new file mode 100644 index 0000000..418b7f6 --- /dev/null +++ b/src/client/haxe/ru/m/tankz/view/RecordFrame.yaml @@ -0,0 +1,20 @@ +--- +views: + - $type: haxework.view.VGroupView + skinId: container + views: + - $type: haxework.view.LabelView + skinId: text.header + text: Records + - id: data + $type: haxework.view.list.VListView + factory: $code:function() return new haxework.view.list.LabelListItem() + +onItemSelect: $this:onRecordSelect + geometry.margin.top: 20 + geometry.size.stretch: true + - $type: haxework.view.HGroupView + skinId: panel + views: + - $type: haxework.view.ButtonView + skinId: button.close + +onPress: $code:close() diff --git a/src/client/haxe/ru/m/tankz/view/StartFrame.hx b/src/client/haxe/ru/m/tankz/view/StartFrame.hx index a57ca26..ed80309 100644 --- a/src/client/haxe/ru/m/tankz/view/StartFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/StartFrame.hx @@ -11,13 +11,13 @@ import ru.m.tankz.view.popup.FontPopup; public static var ID(default, never):String = "start"; @:provide var state:GameState; - @:provide var swicther:FrameSwitcher; + @:provide var switcher:FrameSwitcher; private var fontPopup:FontPopup; private function startGame(type:GameType):Void { state = new GameState(type); - swicther.change(LevelFrame.ID); + switcher.change(LevelFrame.ID); } private function choiceFont():Void { diff --git a/src/client/haxe/ru/m/tankz/view/StartFrame.yaml b/src/client/haxe/ru/m/tankz/view/StartFrame.yaml index 4834b3b..96014ec 100644 --- a/src/client/haxe/ru/m/tankz/view/StartFrame.yaml +++ b/src/client/haxe/ru/m/tankz/view/StartFrame.yaml @@ -21,13 +21,17 @@ views: skinId: button +onPress: $code:startGame('death') text: DeathMatch + - $type: haxework.view.ButtonView + skinId: button + +onPress: $code:switcher.change('record') + text: Records - $type: haxework.view.HGroupView skinId: panel views: - id: settings $type: haxework.view.ButtonView skinId: button.settings - +onPress: $code:swicther.change('settings') + +onPress: $code:switcher.change('settings') - $type: haxework.view.SpriteView geometry.size.width: 100% - $type: haxework.view.LabelView diff --git a/src/client/haxe/ru/m/tankz/view/classic/ClassicGamePanel.hx b/src/client/haxe/ru/m/tankz/view/classic/ClassicGamePanel.hx index c6c08e1..9274cc7 100644 --- a/src/client/haxe/ru/m/tankz/view/classic/ClassicGamePanel.hx +++ b/src/client/haxe/ru/m/tankz/view/classic/ClassicGamePanel.hx @@ -37,20 +37,20 @@ import ru.m.tankz.view.common.LifeView; switch event { case START(state): refresh(state); - case CHANGE(TEAM_LIFE(team, life)): - if (team.id == ClassicGame.BOT) { + case CHANGE(TEAM_LIFE(teamId, life)): + if (teamId == ClassicGame.BOT) { bot.life = life; } - case CHANGE(PLAYER_LIFE(player, life)): - if (player.id == player1Id) { + case CHANGE(PLAYER_LIFE(playerId, life)): + if (playerId == player1Id) { player1.life = life; - } else if (player.id == player2Id) { + } else if (playerId == player2Id) { player2.life = life; } - case CHANGE(PLAYER_SCORE(player, score)): - if (player.id == player1Id) { + case CHANGE(PLAYER_SCORE(playerId, score)): + if (playerId == player1Id) { player1.score = score; - } else if (player.id == player2Id) { + } else if (playerId == player2Id) { player2.score = score; } case _: diff --git a/src/client/haxe/ru/m/tankz/view/common/GameFrame.hx b/src/client/haxe/ru/m/tankz/view/common/GameFrame.hx index 567ffea..2333522 100644 --- a/src/client/haxe/ru/m/tankz/view/common/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/common/GameFrame.hx @@ -9,6 +9,8 @@ import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.GameRunner; import ru.m.tankz.game.GameState; import ru.m.tankz.game.IGame; +import ru.m.tankz.game.record.GamePlayer; +import ru.m.tankz.game.record.GameRecord; import ru.m.tankz.game.record.GameRecorder; import ru.m.tankz.network.NetworkManager; import ru.m.tankz.render.Render; @@ -27,6 +29,7 @@ class GameFrame extends GroupView implements GameListener { @:provide var network:NetworkManager; @:provide var soundManager:SoundManager; @:provide var state:GameState; + @:provide var record:GameRecord; @:provide("result") var result:GameState; @:provide var switcher:FrameSwitcher; @:provide var gameStorage:GameStorage; @@ -35,6 +38,7 @@ class GameFrame extends GroupView implements GameListener { private var game:IGame; private var runner:GameRunner; private var recorder:GameRecorder; + private var player:GamePlayer; private function get_render():Render { throw "Not implemented"; @@ -45,11 +49,16 @@ class GameFrame extends GroupView implements GameListener { } public function onShow():Void { - start(state); + if (record != null) { + play(record); + record = null; + } else { + start(state); + } } private function start(state:GameState):Void { - game = new Game(state.type); + game = new Game(state); game.connect(render); game.engine.connect(render); game.connect(soundManager); @@ -66,6 +75,21 @@ class GameFrame extends GroupView implements GameListener { render.draw(game.engine); } + private function play(record:GameRecord):Void { + game = new Game(record.state); + game.connect(render); + game.engine.connect(render); + game.connect(soundManager); + //game.connect(this); + if (panel != null) { + game.connect(panel); + } + player = new GamePlayer(game, record); + player.start(); + content.addEventListener(Event.ENTER_FRAME, _redraw); + render.draw(game.engine); + } + private function stop():Void { content.removeEventListener(Event.ENTER_FRAME, _redraw); if (runner != null) { @@ -83,7 +107,7 @@ class GameFrame extends GroupView implements GameListener { switch event { case GameEvent.COMPLETE(state, winner): // ToDo: - //recordStorage.save(recorder.record); + recordStorage.save(recorder.record); result = state; this.state = switch runner.next() { case Some(s): diff --git a/src/client/haxe/ru/m/tankz/view/dota/DotaGamePanel.hx b/src/client/haxe/ru/m/tankz/view/dota/DotaGamePanel.hx index 2b5e584..eae8529 100644 --- a/src/client/haxe/ru/m/tankz/view/dota/DotaGamePanel.hx +++ b/src/client/haxe/ru/m/tankz/view/dota/DotaGamePanel.hx @@ -35,10 +35,10 @@ import ru.m.tankz.view.common.LifeView; switch event { case START(state): refresh(state); - case CHANGE(TEAM_LIFE(team, life)): - getLifeView(team.id).life = life; - case CHANGE(TEAM_SCORE(team, score)): - getLifeView(team.id).score = score; + case CHANGE(TEAM_LIFE(teamId, life)): + getLifeView(teamId).life = life; + case CHANGE(TEAM_SCORE(teamId, score)): + getLifeView(teamId).score = score; case _: } } diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 66d96cf..e6f6447 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -152,8 +152,9 @@ import ru.m.tankz.map.LevelMap; } public function dispose():Void { - entities = null; - map = null; + // ToDo: set to null + entities = new Map(); + //map = null; spawnSignal.dispose(); collisionSignal.dispose(); moveSignal.dispose(); diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 87cec4a..aea2f5c 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -29,13 +29,25 @@ import ru.m.tankz.Type; @:provide var configBundle:IConfigBundle; - public function new(type:GameType) { - this.type = type; + public function new(state:GameState) { + this.type = state.type; this.teams = new Map(); this.config = configBundle.get(type); this.engine = new Engine(config); this.builder = new EntityBuilder(config); connect(this); + prepare(state); + } + + private function prepare(state:GameState):Void { + var level:LevelConfig = state.level; + var points:Array = level.points != null ? level.points : config.points; + engine.map.setData(level.data); + 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; + } } private function applyPoint(entity:Entity, point:SpawnPoint):Void { diff --git a/src/common/haxe/ru/m/tankz/game/GameEvent.hx b/src/common/haxe/ru/m/tankz/game/GameEvent.hx index 9a7c26f..e5c8f6f 100644 --- a/src/common/haxe/ru/m/tankz/game/GameEvent.hx +++ b/src/common/haxe/ru/m/tankz/game/GameEvent.hx @@ -30,10 +30,10 @@ enum DestroyEvent { } enum ChangeEvent { - PLAYER_SCORE(player:Player, value:Int); - PLAYER_LIFE(player:Player, value:Int); - TEAM_SCORE(team:Team, value:Int); - TEAM_LIFE(team:Team, value:Int); + PLAYER_SCORE(playerId:PlayerId, value:Int); + PLAYER_LIFE(playerId:PlayerId, value:Int); + TEAM_SCORE(teamId:TeamId, value:Int); + TEAM_LIFE(teamId:TeamId, value:Int); } enum GameEvent { diff --git a/src/common/haxe/ru/m/tankz/game/GameRunner.hx b/src/common/haxe/ru/m/tankz/game/GameRunner.hx index 7278604..39da7e8 100644 --- a/src/common/haxe/ru/m/tankz/game/GameRunner.hx +++ b/src/common/haxe/ru/m/tankz/game/GameRunner.hx @@ -23,7 +23,6 @@ class GameRunner implements EngineListener implements GameListener { private var game(default, null):IGame; private var gameEventSignal(get, null):Signal; - private var points:Array; private var timer:Timer; @@ -52,13 +51,7 @@ class GameRunner implements EngineListener implements GameListener { } public function start(state:GameState):Void { - var level:LevelConfig = state.level; - points = level.points != null ? level.points : game.config.points; - game.engine.map.setData(level.data); - 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]); - game.teams[team.id] = team; + for (team in game.teams.iterator()) { for (player in team.players.iterator()) { var control = controlFactory.build(player.id, AController.fromString(player.config.control)); if (control != null) { @@ -67,8 +60,6 @@ class GameRunner implements EngineListener implements GameListener { } } team.spawner.runner = spawn; - } - for (team in game.teams.iterator()) { for (player in team.players.iterator()) { if (team.tryRespawn(player.id)) { team.spawner.push(player.id); @@ -250,20 +241,20 @@ class GameRunner implements EngineListener implements GameListener { var player = game.getPlayer(playerId); var team = game.getTeam(playerId.team); player.state.score += score; - gameEventSignal.emit(GameEvent.CHANGE(PLAYER_SCORE(player, player.state.score))); - gameEventSignal.emit(GameEvent.CHANGE(TEAM_SCORE(team, game.state.getTeamScore(team.id)))); + gameEventSignal.emit(GameEvent.CHANGE(PLAYER_SCORE(playerId, player.state.score))); + gameEventSignal.emit(GameEvent.CHANGE(TEAM_SCORE(playerId.team, game.state.getTeamScore(team.id)))); } private function changeLife(playerId:PlayerId, life:Int):Void { var player = game.getPlayer(playerId); player.state.life += life; - gameEventSignal.emit(GameEvent.CHANGE(PLAYER_LIFE(player, player.state.life))); + gameEventSignal.emit(GameEvent.CHANGE(PLAYER_LIFE(playerId, player.state.life))); } private function changeTeamLife(teamId:TeamId, life:Int):Void { var team = game.getTeam(teamId); team.state.life += life; - gameEventSignal.emit(GameEvent.CHANGE(TEAM_LIFE(team, team.state.life))); + gameEventSignal.emit(GameEvent.CHANGE(TEAM_LIFE(teamId, team.state.life))); } public function onGameEvent(event:GameEvent):Void { 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 c7531bb..1c43610 100644 --- a/src/common/haxe/ru/m/tankz/game/record/GamePlayer.hx +++ b/src/common/haxe/ru/m/tankz/game/record/GamePlayer.hx @@ -18,13 +18,6 @@ class GamePlayer { this.data = null; } - public function onGameEvent(event:GameEvent):Void { - switch event { - case GameEvent.COMPLETE(_, _): - stop(); - } - } - public function start():Void { frame = 0; data = record.events.slice(0); @@ -42,15 +35,16 @@ class GamePlayer { if (event.frame <= frame) { events++; game.gameEventSignal.emit(event.event); - switch event { + switch event.event { case GameEvent.COMPLETE(_, _): stop(); + case _: } } else { break; } } - if (event > 0) { + 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 c9edaca..bdfc6e3 100644 --- a/src/common/haxe/ru/m/tankz/game/record/GameRecord.hx +++ b/src/common/haxe/ru/m/tankz/game/record/GameRecord.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game.record; +import ru.m.tankz.Type; import com.hurlant.crypto.extra.UUID; import com.hurlant.crypto.prng.Random; @@ -11,11 +12,24 @@ typedef EventItem = { class GameRecord { 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 events(default, default):Array; + public var state(get, null):GameState; + public function new() { this.id = UUID.generateRandom(new Random()).toString(); this.date = null; this.events = []; } + + private inline function get_state():GameState { + return new GameState(type, presetId, levelId); + } + + public function toString():String { + return 'GameRecord{id=$id,date=$date,type=$type,preset=$presetId,level=$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 a71f267..0c47deb 100644 --- a/src/common/haxe/ru/m/tankz/game/record/GameRecorder.hx +++ b/src/common/haxe/ru/m/tankz/game/record/GameRecorder.hx @@ -16,7 +16,10 @@ class GameRecorder implements GameListener { public function onGameEvent(event:GameEvent):Void { switch event { - case GameEvent.START(_): + case GameEvent.START(state): + record.type = state.type; + record.presetId = state.presetId; + record.levelId = state.levelId; start(); case GameEvent.COMPLETE(_, _): stop(); diff --git a/src/common/haxe/ru/m/tankz/network/NetworkGame.hx b/src/common/haxe/ru/m/tankz/network/NetworkGame.hx index e1a1bc0..69c0a85 100644 --- a/src/common/haxe/ru/m/tankz/network/NetworkGame.hx +++ b/src/common/haxe/ru/m/tankz/network/NetworkGame.hx @@ -1,19 +1,13 @@ package ru.m.tankz.network; -import ru.m.tankz.proto.game.GameChangeProto; -import ru.m.tankz.proto.core.GameProto; -import ru.m.tankz.Type; import ru.m.tankz.game.Game; - +import ru.m.tankz.proto.core.GameProto; +import ru.m.tankz.proto.game.GameChangeProto; class NetworkGame extends Game { private static var TAG(default, never):String = 'NetworkGame'; - public function new(type:GameType) { - super(type); - } - public function load(proto:GameProto):Void { L.w(TAG, 'load: ${proto}'); // ToDo: diff --git a/src/common/resources/classic/config.yaml b/src/common/resources/classic/config.yaml index 17d93dc..14a65ec 100644 --- a/src/common/resources/classic/config.yaml +++ b/src/common/resources/classic/config.yaml @@ -163,7 +163,7 @@ presets: - {<<: *team_human} - id: bot spawnInterval: 3000 - life: 10 + life: 1 players: - {<<: *bot, index: 0, control: bot-stupid} - {<<: *bot, index: 1, control: bot-stupid}