From 8ea862a1189797dfa5b43a75f531514fb53a2ac6 Mon Sep 17 00:00:00 2001 From: shmyga Date: Thu, 14 Mar 2019 12:58:00 +0300 Subject: [PATCH] [common] add GameState --- .../haxe/ru/m/tankz/frame/common/GameFrame.hx | 12 ++-- .../ru/m/tankz/frame/common/LevelFrame.hx | 13 ++-- .../ru/m/tankz/frame/common/PlayerView.hx | 14 ++--- .../ru/m/tankz/frame/dota/DotaGamePanel.hx | 4 +- .../ru/m/tankz/frame/dota/DotaLevelFrame.hx | 13 ++-- src/common/haxe/ru/m/tankz/game/Game.hx | 59 +++++++++---------- src/common/haxe/ru/m/tankz/game/GameStart.hx | 34 ----------- src/common/haxe/ru/m/tankz/game/GameState.hx | 52 ++++++++++++++++ src/common/haxe/ru/m/tankz/game/Player.hx | 21 +------ src/common/haxe/ru/m/tankz/game/Spawner.hx | 4 +- src/common/haxe/ru/m/tankz/game/Team.hx | 29 ++++++--- src/common/resources/dota/config.yaml | 2 + 12 files changed, 132 insertions(+), 125 deletions(-) delete mode 100644 src/common/haxe/ru/m/tankz/game/GameStart.hx create mode 100644 src/common/haxe/ru/m/tankz/game/GameState.hx diff --git a/src/client/haxe/ru/m/tankz/frame/common/GameFrame.hx b/src/client/haxe/ru/m/tankz/frame/common/GameFrame.hx index 154e3a5..b4f851e 100644 --- a/src/client/haxe/ru/m/tankz/frame/common/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/frame/common/GameFrame.hx @@ -1,5 +1,6 @@ package ru.m.tankz.frame.common; +import ru.m.tankz.game.GameState; import flash.events.Event; import haxe.ds.Option; import haxe.Timer; @@ -7,7 +8,6 @@ import haxework.gui.frame.FrameSwitcher; import haxework.gui.GroupView; import ru.m.tankz.frame.common.IGamePanel; import ru.m.tankz.game.Game; -import ru.m.tankz.game.GameStart; import ru.m.tankz.network.NetworkManager; import ru.m.tankz.render.Render; import ru.m.tankz.sound.SoundManager; @@ -21,7 +21,7 @@ class GameFrame extends GroupView { @:provide var network:NetworkManager; @:provide var sound:SoundManager; - @:provide var gameStart:GameStart; + @:provide var state:GameState; @:provide var switcher:FrameSwitcher; private var game:Game; @@ -36,14 +36,14 @@ class GameFrame extends GroupView { } public function onShow():Void { - start(gameStart); + start(state); } - private function start(start:GameStart):Void { - game = new Game(start.type); + private function start(state:GameState):Void { + game = new Game(state.type); game.engine.connect(render); game.engine.connect(sound); - game.start(start).then(onGameStateChange).endThen(onGameComplete); + game.start(state).then(onGameStateChange).endThen(onGameComplete); timer = new Timer(10); timer.run = updateEngine; panel.game = game; diff --git a/src/client/haxe/ru/m/tankz/frame/common/LevelFrame.hx b/src/client/haxe/ru/m/tankz/frame/common/LevelFrame.hx index c2a2428..044b18c 100644 --- a/src/client/haxe/ru/m/tankz/frame/common/LevelFrame.hx +++ b/src/client/haxe/ru/m/tankz/frame/common/LevelFrame.hx @@ -5,8 +5,7 @@ import haxework.gui.GroupView; import haxework.resources.IResources; import ru.m.tankz.bundle.IConfigBundle; import ru.m.tankz.config.Config; -import ru.m.tankz.control.Control; -import ru.m.tankz.game.GameStart; +import ru.m.tankz.game.GameState; import ru.m.tankz.Type; class LevelFrame extends GroupView { @@ -17,7 +16,7 @@ class LevelFrame extends GroupView { private var config(default, null):Config; @:provide var configBundle:IConfigBundle; - @:provide var start:GameStart; + @:provide var state:GameState; @:provide var resources:IResources; private function set_gameType(value:GameType):GameType { @@ -32,11 +31,11 @@ class LevelFrame extends GroupView { private function set_preset(value:GamePreset):GamePreset { if (preset != value || true) { // ToDo: preset = value; - start = new GameStart(gameType, preset.id); + state = new GameState(gameType, preset.id); for (team in value.teams) { for (player in team.players) { var playerId = new PlayerId(team.id, player.index); - start.players.push({playerId: playerId, control: player.control != null ? player.control : Control.BOT}); + state.players.push(new PlayerState(playerId, player.control, player.life)); } } } @@ -44,8 +43,8 @@ class LevelFrame extends GroupView { } private function set_level(value:Int):Int { - start.level = value; - return start.level; + state.level = value; + return state.level; } private function levelViewFactory(index:Int, level:Int):ButtonView { diff --git a/src/client/haxe/ru/m/tankz/frame/common/PlayerView.hx b/src/client/haxe/ru/m/tankz/frame/common/PlayerView.hx index cf7d338..6a3bc37 100644 --- a/src/client/haxe/ru/m/tankz/frame/common/PlayerView.hx +++ b/src/client/haxe/ru/m/tankz/frame/common/PlayerView.hx @@ -5,7 +5,7 @@ import haxework.gui.HGroupView; import haxework.gui.LabelView; import haxework.gui.skin.ISkin; import haxework.gui.ToggleButtonView; -import ru.m.tankz.game.GameStart; +import ru.m.tankz.game.GameState; import ru.m.tankz.Type.PlayerId; import ru.m.tankz.Type.TeamId; @@ -44,12 +44,12 @@ class TeamSkin implements ISkin { private static inline var NONE:TeamId = "none"; public var item_index(default, set):Int; - public var data(default, set):PlayerType; + public var data(default, set):PlayerState; @:view var label(default, null):LabelView; @:view var teams(default, null):DataView; - @:provide var start:GameStart; + @:provide var state:GameState; private function teamViewFactory(index:Int, team:TeamId) { var view = new TeamButton(); @@ -60,15 +60,15 @@ class TeamSkin implements ISkin { return view; } - private function set_data(value:PlayerType):PlayerType { + private function set_data(value:PlayerState):PlayerState { data = value; - teams.data = [NONE].concat([for (team in start.preset.teams) team.id]); + teams.data = [NONE].concat([for (team in state.preset.teams) team.id]); return data; } private function getTeamColor(teamId:TeamId):Int { var color = 0xcccccc; - for (team in start.preset.teams) { + for (team in state.preset.teams) { if (team.id == teamId) { if (!team.color.zero) color = team.color; break; @@ -84,7 +84,7 @@ class TeamSkin implements ISkin { } private function onTeamSelect(team:TeamId) { - data.playerId = new PlayerId(team, item_index); + data.id = new PlayerId(team, item_index); for (view in teams.views) { var button = cast(view, TeamButton); button.on = team == button.team; diff --git a/src/client/haxe/ru/m/tankz/frame/dota/DotaGamePanel.hx b/src/client/haxe/ru/m/tankz/frame/dota/DotaGamePanel.hx index 8f8d14c..713738b 100644 --- a/src/client/haxe/ru/m/tankz/frame/dota/DotaGamePanel.hx +++ b/src/client/haxe/ru/m/tankz/frame/dota/DotaGamePanel.hx @@ -15,9 +15,9 @@ import ru.m.tankz.preset.DotaGame; private function updateViews():Void { radiant.live.text = '${game.teams[DotaGame.RADIANT].life}'; - radiant.score.text = '0'; // ToDO + radiant.score.text = '${game.teams[DotaGame.RADIANT].score}'; dire.live.text = '${game.teams[DotaGame.DIRE].life}'; - dire.score.text = '0'; // ToDO + dire.score.text = '${game.teams[DotaGame.DIRE].score}'; } override public function update():Void { diff --git a/src/client/haxe/ru/m/tankz/frame/dota/DotaLevelFrame.hx b/src/client/haxe/ru/m/tankz/frame/dota/DotaLevelFrame.hx index 56fcf31..704e1da 100644 --- a/src/client/haxe/ru/m/tankz/frame/dota/DotaLevelFrame.hx +++ b/src/client/haxe/ru/m/tankz/frame/dota/DotaLevelFrame.hx @@ -6,14 +6,14 @@ import haxework.gui.frame.FrameSwitcher; import ru.m.tankz.control.Control; import ru.m.tankz.frame.common.LevelFrame; import ru.m.tankz.frame.common.PlayerView; -import ru.m.tankz.game.GameStart.PlayerType; +import ru.m.tankz.game.GameState; import ru.m.tankz.preset.DotaGame; @:template class DotaLevelFrame extends LevelFrame { public static inline var ID = "dota.level"; @:view var levels(default, null):DataView; - @:view var players(default, null):DataView; + @:view var players(default, null):DataView; @:provide var frames:FrameSwitcher; @@ -22,16 +22,13 @@ import ru.m.tankz.preset.DotaGame; levels.data = [for (i in 0...config.game.levels) i]; var data = []; for (i in 0...2) { - data.push({ - playerId: null, - control: Control.HUMAN, - }); + data.push(new PlayerState(null, Control.HUMAN)); } - start.players = data; + state.players = data; players.data = data; } - private function playerViewFactory(index:Int, player:PlayerType):PlayerView { + private function playerViewFactory(index:Int, player:PlayerState):PlayerView { var view = new PlayerView(); view.item_index = index; view.data = player; diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 611ad39..eb77dca 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -17,7 +17,7 @@ import ru.m.tankz.core.Entity; import ru.m.tankz.core.EntityType; import ru.m.tankz.core.Tank; import ru.m.tankz.engine.Engine; -import ru.m.tankz.game.GameStart; +import ru.m.tankz.game.GameState; import ru.m.tankz.game.Spawner; import ru.m.tankz.Type; @@ -26,17 +26,16 @@ class Game { private static var TAG(default, never):String = 'Game'; public var type(default, null):GameType; - public var level(default, null):Int; - public var players(default, null):Array; - public var preset(default, null):GamePreset; public var teams(default, null):Map; public var config(default, null):Config; public var engine(default, null):Engine; public var loser(default, null):Null; + public var state(default, null):GameState; + private var points:Array; - private var deferred:Deferred; - private var stream:Stream; + private var deferred:Deferred; + private var stream:Stream; @:provide var configBundle:IConfigBundle; @:provide var levelBundle:ILevelBundle; @@ -81,26 +80,25 @@ class Game { entity.rect.direction = point.direction; } - public function start(start:GameStart):Stream { - this.players = start.players; - var players = players.slice(0); + public function start(state:GameState):Stream { + this.state = state; this.loser = null; - this.preset = config.getPreset(start.presetId); - this.level = start.level; this.deferred = new Deferred(); - var level:LevelConfig = levelBundle.get(type, config, start.level); + var level:LevelConfig = levelBundle.get(type, config, state.level); points = level.points != null ? level.points : config.points; engine.map.setData(level.data); teams = new Map(); var controlFactory:IControlFactory = Provider.build(IControlFactory); - for (teamConfig in preset.teams) { + var players = state.players.slice(0); + 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); teams[team.id] = team; for (player in team.players.iterator()) { var controlType:ControlType = Control.BOT; - var nextPlayer = Lambda.find(players, function(p) return p.playerId != null && p.playerId.team == team.id); + var nextPlayer:PlayerState = Lambda.find(players, function(p) return p.id != null && p.id.team == team.id); if (nextPlayer != null) { + player.state = nextPlayer; players.remove(nextPlayer); controlType = nextPlayer.control; } @@ -116,7 +114,7 @@ class Game { for (team in teams.iterator()) { for (player in team.players.iterator()) { - if (team.trySpawn(player.id)) { + if (team.tryRespawn(player.id)) { team.spawner.push(player.id, player.state.tank); } } @@ -137,15 +135,11 @@ class Game { var team = getTeam(task.playerId.team); var player = getPlayer(task.playerId); player.tankId = 0; - if (getTeam(task.playerId.team).trySpawn(task.playerId, true)) { - var tank = buildTank(task); - player.tankId = tank.id; - player.state.tank = tank.config.type; - engine.spawn(tank); - } else if (!team.isAlive) { - lose(team.id); - } - deferred.resolve(null); + var tank = buildTank(task); + player.tankId = tank.id; + player.state.tank = tank.config.type; + engine.spawn(tank); + deferred.resolve(state); } private function complete():Void { @@ -156,7 +150,7 @@ class Game { } } Timer.delay(function() { - deferred.resolve(null); + deferred.resolve(state); stream.end(); }, 5000); } @@ -176,7 +170,7 @@ class Game { case [EntityType.EAGLE(eagle), EntityChange.DEATH]: if (eagle.death) { lose(eagle.team); - deferred.resolve(null); + deferred.resolve(state); } case [EntityType.TANK(tank), EntityChange.HIT]: if (tank.bonus) { @@ -212,7 +206,8 @@ class Game { var player = getPlayer(tank.playerId); player.control.stop(); player.tankId = 0; //ToDo: ? - var respawn:Bool = team.trySpawn(player.id); + team.onDestroy(player.id); + var respawn:Bool = team.tryRespawn(player.id); if (respawn) { team.spawner.push(player.id); } @@ -226,12 +221,12 @@ class Game { getPlayer(playerId).state.frags++; getPlayer(playerId).state.score += tank.config.score; } - deferred.resolve(null); + deferred.resolve(state); case EntityType.BONUS(bonus): if (bonus.config.score > 0 && playerId != null) { getPlayer(playerId).state.score += bonus.config.score; } - deferred.resolve(null); + deferred.resolve(state); case _: } } @@ -245,15 +240,15 @@ class Game { engine.action(tankId, action); } - public function next():Option { + public function next():Option { for (rule in config.game.complete) { if (rule.team != null && rule.team == loser) { return Option.None; } } - var level = this.level + 1; + var level = this.state.level + 1; if (level >= config.game.levels) level = 0; - return Option.Some(new GameStart(type, preset.id, level, players)); + return Option.Some(new GameState(type, state.presetId, level, state.players)); } public function dispose():Void { diff --git a/src/common/haxe/ru/m/tankz/game/GameStart.hx b/src/common/haxe/ru/m/tankz/game/GameStart.hx deleted file mode 100644 index 0a7f625..0000000 --- a/src/common/haxe/ru/m/tankz/game/GameStart.hx +++ /dev/null @@ -1,34 +0,0 @@ -package ru.m.tankz.game; - -import ru.m.tankz.config.Config; -import ru.m.tankz.bundle.IConfigBundle; -import ru.m.tankz.Type; - -typedef PlayerType = { - var playerId: PlayerId; - var control:ControlType; -} - -class GameStart { - @:provide private var configBundle:IConfigBundle; - - public var type(default, default):GameType; - public var presetId(default, default):PresetId; - public var level(default, default):Int; - public var players(default, default):Array; - - public var preset(get, null):GamePreset; - - public function new(type:GameType, presetId:PresetId, level:Int = 0, players:Array = null) { - this.type = type; - this.presetId = presetId; - this.level = level; - this.players = players == null ? [] : players; - } - - private function get_preset():GamePreset { - var config = configBundle.get(type); - var preset = config.getPreset(presetId); - return preset; - } -} diff --git a/src/common/haxe/ru/m/tankz/game/GameState.hx b/src/common/haxe/ru/m/tankz/game/GameState.hx new file mode 100644 index 0000000..0e660ef --- /dev/null +++ b/src/common/haxe/ru/m/tankz/game/GameState.hx @@ -0,0 +1,52 @@ +package ru.m.tankz.game; + +import ru.m.tankz.bundle.IConfigBundle; +import ru.m.tankz.config.Config; +import ru.m.tankz.control.Control; +import ru.m.tankz.Type; + +class PlayerState { + public var id:PlayerId; + public var tank:TankType; + public var control:ControlType; + public var life:Int; + public var score:Int; + public var frags:Int; + public var shots:Int; + public var hits:Int; + + public function new(id:PlayerId, control:ControlType = null, life:Int = 0) { + this.id = id; + this.tank = null; + this.control = control == null ? Control.BOT : control; + this.life = life; + this.score = 0; + this.frags = 0; + this.shots = 0; + this.hits = 0; + } +} + +class GameState { + + public var type:GameType; + public var presetId:PresetId; + public var level:Int; + public var players:Array; + public var preset(get, null):GamePreset; + + @:provide private var configBundle:IConfigBundle; + + public function new(type:GameType, presetId:PresetId, level:Int = 1, players:Array = null) { + this.type = type; + this.presetId = presetId; + this.level = level; + this.players = players == null ? [] : players; + } + + private function get_preset():GamePreset { + var config = configBundle.get(type); + var preset = config.getPreset(presetId); + return preset; + } +} diff --git a/src/common/haxe/ru/m/tankz/game/Player.hx b/src/common/haxe/ru/m/tankz/game/Player.hx index 1ff0499..71fef7e 100644 --- a/src/common/haxe/ru/m/tankz/game/Player.hx +++ b/src/common/haxe/ru/m/tankz/game/Player.hx @@ -1,18 +1,10 @@ package ru.m.tankz.game; +import ru.m.tankz.game.GameState; import ru.m.tankz.config.Config; import ru.m.tankz.control.Control; import ru.m.tankz.Type; -typedef PlayerState = { - var tank:TankType; - var life:Int; - var score:Int; - var shots:Int; - var hits:Int; - var frags:Int; -} - class Player { public var config(default, null):PlayerConfig; public var id(default, null):PlayerId; @@ -21,18 +13,11 @@ class Player { public var isAlive(get, null):Bool; public var state(default, default):PlayerState; - public function new(teamId:TeamId, config:PlayerConfig) { + public function new(teamId:TeamId, config:PlayerConfig, state:PlayerState = null) { this.config = config; this.id = new PlayerId(teamId, config.index); this.control = null; - this.state = { - life: config.life, - tank: null, - score: 0, - shots: 0, - hits: 0, - frags: 0, - } + this.state = state == null ? new PlayerState(id) : state; } private function set_tankId(value:Int):Int { diff --git a/src/common/haxe/ru/m/tankz/game/Spawner.hx b/src/common/haxe/ru/m/tankz/game/Spawner.hx index 6248464..118ad07 100644 --- a/src/common/haxe/ru/m/tankz/game/Spawner.hx +++ b/src/common/haxe/ru/m/tankz/game/Spawner.hx @@ -69,7 +69,7 @@ class Spawner { private function run():Void { if (timer == null) { - timer = new Timer(config.spawnInterval == null ? 1 : config.spawnInterval); + timer = new Timer(config.spawnInterval == null ? 500 : config.spawnInterval); timer.run = spawn; } } @@ -88,4 +88,4 @@ class Spawner { private function get_active():Bool { return queue.length > 0; } -} \ No newline at end of file +} diff --git a/src/common/haxe/ru/m/tankz/game/Team.hx b/src/common/haxe/ru/m/tankz/game/Team.hx index e63b4b6..0ef9213 100644 --- a/src/common/haxe/ru/m/tankz/game/Team.hx +++ b/src/common/haxe/ru/m/tankz/game/Team.hx @@ -11,8 +11,11 @@ class Team { public var players(default, null):Map; public var life(default, default):Int; 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 function new(config:TeamConfig, points:Array) { this.id = config.id; this.config = config; @@ -25,19 +28,23 @@ class Team { this.spawner = new Spawner(config, points); } - public function trySpawn(playerId:PlayerId, spawn:Bool = false):Bool { + public function tryRespawn(playerId:PlayerId):Bool { var player:Player = players[playerId.index]; - var result = false; - if (player.state.life > 0) { - if (spawn) player.state.life--; - result = true; - } else if (life > 0) { - if (spawn) life--; - result = true; - } + var result = player.state.life > 0 || life > active; + active++; return result; } + public function onDestroy(playerId:PlayerId) { + active--; + var player:Player = players[playerId.index]; + if (player.state.life > 0) { + player.state.life--; + } else { + life--; + } + } + // ToDo: eagle state? private function get_isAlive():Bool { if (life > 0) { @@ -53,4 +60,8 @@ class Team { } return false; } + + 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/resources/dota/config.yaml b/src/common/resources/dota/config.yaml index 9850b0d..6b3ed4d 100644 --- a/src/common/resources/dota/config.yaml +++ b/src/common/resources/dota/config.yaml @@ -83,6 +83,7 @@ tanks: <<: *bullet speed: 12.0 bullets: 1 + score: 100 skin: bc - type: fast @@ -93,6 +94,7 @@ tanks: <<: *bullet speed: 8.0 bullets: 1 + score: 100 skin: bb bonuses: