diff --git a/build/client.js b/build/client.js index 82763a8..ebb49f7 100755 --- a/build/client.js +++ b/build/client.js @@ -89,8 +89,15 @@ exports['client:flash'] = gulp.series(prepare(Haxe.ID), generate(), build('flash exports['client:html5'] = gulp.series(prepare(Haxe.ID), generate(), build('html5')); exports['client:linux'] = gulp.series(prepare(Haxe.ID), generate(), build('linux')); exports['client:webapp'] = webapp; -exports['client'] = gulp.series(prepare(Haxe.ID), generate(), gulp.parallel(build('flash'), build('html5')), exports['client:flash:html'], webapp); exports['client:deb'] = buildDeb; +exports['client'] = gulp.series( + prepare(Haxe.ID), + generate(), + gulp.parallel(build('flash'), build('html5'), build('linux')), + exports['client:flash:html'], + webapp, + buildDeb, +); diff --git a/package.json b/package.json index a01743f..acb1743 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tankz", - "version": "0.2.0", + "version": "0.2.1", "private": true, "devDependencies": { "ansi-colors": "^1.0.1", diff --git a/src/client/haxe/ru/m/tankz/Client.hx b/src/client/haxe/ru/m/tankz/Client.hx index 4cdb55b..a90df2d 100755 --- a/src/client/haxe/ru/m/tankz/Client.hx +++ b/src/client/haxe/ru/m/tankz/Client.hx @@ -63,10 +63,10 @@ class Client implements IConnectionHandler { #end //Provider.get(IConnection).handler.addListener(this); - view = new MainView(); Provider.set(IFrameSwitcher, view.switcher); Root.bind(view); + view.content.stage.stageFocusRect = false; //view.logout.onPress = this; view.switcher.change(StartFrame.ID); diff --git a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx index 10e89c6..dff3100 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -33,11 +33,13 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand private var game:Game; private var timer:Timer; - public function init():Void { - } + public function init():Void {} public function onShow():Void { - var s:GameState = Provider.get(GameState); + start(Provider.get(GameState)); + } + + private function start(s:GameState):Void { game = Provider.build(Game, s.type); if (game == null) { throw 'Unsupported game type "${s.type}"'; @@ -52,8 +54,23 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand state.text = stateString(s); } + private function stop():Void { + //Provider.get(IConnection).packetHandler.removeListener(this); + if (timer != null) { + timer.stop(); + timer = null; + } + content.removeEventListener(Event.ENTER_FRAME, redraw); + if (game != null) { + game.dispose(); + game = null; + } + render.reset(); + } + private function stateString(state:GameState):String { var result:Array = []; + result.push('Level: ${state.level}'); for (teamId in state.teams.keys()) { var ts:TeamState = state.teams[teamId]; if (ts.lose) { @@ -69,7 +86,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand } } } - return result.join(' '); + return '[ ${result.join(' | ')} ]'; } private function onGameStateChange(s:GameState):GameState { @@ -83,18 +100,17 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand state.text = stateString(s); case Option.None: } - Provider.get(IFrameSwitcher).change(StartFrame.ID); + switch (game.next()) { + case Option.Some(s): + stop(); + start(s); + case Option.None: + Provider.get(IFrameSwitcher).change(StartFrame.ID); + } } public function onHide():Void { - //Provider.get(IConnection).packetHandler.removeListener(this); - if (timer != null) { - timer.stop(); - timer = null; - } - content.removeEventListener(Event.ENTER_FRAME, redraw); - game.dispose(); - render.reset(); + stop(); } private function updateEngine():Void { diff --git a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx index f685c4c..976df36 100644 --- a/src/common/haxe/ru/m/tankz/game/ClassicGame.hx +++ b/src/common/haxe/ru/m/tankz/game/ClassicGame.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game; +import haxe.ds.Option; import ru.m.tankz.game.GameState.PlayerState; import ru.m.tankz.game.Game; @@ -11,6 +12,9 @@ class ClassicGame extends Game { public static var HUMAN(default, never):TeamId = 'human'; public static var BOT(default, never):TeamId = 'bot'; + private static var HUMAN_LIFE(default, never):Int = 3; + private static var BOT_LIFE(default, never):Int = 20; + public function new() { super(TYPE); } @@ -20,7 +24,7 @@ class ClassicGame extends Game { state.type = TYPE; state.level = level; state.teams[HUMAN] = {life: -1, players: new Map(), lose: false}; - state.teams[BOT] = {life: 20, players: new Map(), lose: false}; + state.teams[BOT] = {life: BOT_LIFE, players: new Map(), lose: false}; for (i in 0...humans) { state.teams[HUMAN].players[i] = { index:i, @@ -32,7 +36,7 @@ class ClassicGame extends Game { type: 'human', index: i }, - life:3, + life:HUMAN_LIFE, }; } for (i in 0...humans*2+2) { @@ -51,4 +55,18 @@ class ClassicGame extends Game { } return state; } + + override public function next():Option { + if (!state.teams[HUMAN].lose) { + state.level++; + if (state.level >= config.levels) state.level = 0; + state.teams[BOT].lose = false; + state.teams[BOT].life = BOT_LIFE; + for (ps in state.teams[HUMAN].players) { + if (ps.life > 0) ps.life++; + } + return Option.Some(state); + } + return Option.None; + } } diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 700101e..07c0684 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game; +import haxe.ds.Option; import haxe.Timer; import promhx.Deferred; import promhx.Stream; @@ -95,7 +96,9 @@ class Game implements EngineListener { for (team in teams) { for (player in team.players) { - spawners.get(team.id).push(player.id); + if (trySpawn(player.id)) { + spawners.get(team.id).push(player.id); + } } var eaglePoint = spawners.get(team.id).getPoint('eagle'); if (eaglePoint != null) { @@ -109,15 +112,23 @@ class Game implements EngineListener { } private function spawn(task:SpawnTask):Void { - var tank = buildTank(task.playerId, config.getTank(task.playerId.team, '0'), task.point); - var player:Player = teams.get(task.playerId.team).players[task.playerId.index]; - engine.spawn(tank); - player.tankId = tank.id; + getPlayer(task.playerId).tankId = 0; + if (trySpawn(task.playerId, true)) { + var tank = buildTank(task.playerId, config.getTank(task.playerId.team, '0'), task.point); + var player:Player = getPlayer(task.playerId); + engine.spawn(tank); + player.tankId = tank.id; + } else if (!isTeamAlive(task.playerId.team)) { + state.teams[task.playerId.team].lose = true; + complete(); + } + deferred.resolve(state); } private function complete():Void { for (team in teams.iterator()) { for (player in team.players) { + player.control.action(TankAction.STOP); player.control.dispose(); } } @@ -157,28 +168,51 @@ class Game implements EngineListener { } } - private function calcTeamLife(ts:TeamState):Int { - return Lambda.fold(ts.players, function(ps, t) return t + ps.life, ts.life); + private function isTeamAlive(team:TeamId):Bool { + var ts:TeamState = state.teams[team]; + var life:Int = Lambda.fold(ts.players, function(ps, t) return t + ps.life, ts.life); + if (life > 0) { + return true; + } else { + for (player in teams[team].players) { + if (player.tankId > 0) { + return true; + } + } + if (spawners[team].active) { + return true; + } + } + return false; + } + + private function trySpawn(player:PlayerId, spawn:Bool = false):Bool { + var ts:TeamState = state.teams[player.team]; + var ps:PlayerState = ts.players[player.index]; + var result = false; + if (ps.life > -1) { + if (ps.life > 0) { + if (spawn) ps.life--; + result = true; + } + } else if (ts.life > -1) { + if (ts.life > 0) { + if (spawn) ts.life--; + result = true; + } + } + return result; } public function onDestroy(entity:EntityType):Void { switch (entity) { case EntityType.TANK(tank): - var respawn:Bool = false; - var teamState:TeamState = state.teams[tank.playerId.team]; - if (teamState.life > 0) { - teamState.life--; - respawn = true; - } else { - var playerState:PlayerState = teamState.players[tank.playerId.index]; - if (playerState.life > 0) { - playerState.life--; - respawn = true; - } - } + getPlayer(tank.playerId).tankId = 0; + var respawn:Bool = trySpawn(tank.playerId); if (respawn) { spawners.get(tank.playerId.team).push(tank.playerId); - } else if (calcTeamLife(teamState) < 1) { + } + if (!isTeamAlive(tank.playerId.team)) { state.teams[tank.playerId.team].lose = true; complete(); } @@ -197,6 +231,11 @@ class Game implements EngineListener { } + public function next():Option { + return Option.None; + } + + public function dispose():Void { engine.dispose(); } diff --git a/src/common/haxe/ru/m/tankz/game/Spawner.hx b/src/common/haxe/ru/m/tankz/game/Spawner.hx index 7db2992..3d41b87 100644 --- a/src/common/haxe/ru/m/tankz/game/Spawner.hx +++ b/src/common/haxe/ru/m/tankz/game/Spawner.hx @@ -14,6 +14,8 @@ typedef SpawnTask = { class Spawner { + public var active(get, never):Bool; + private var config:TeamConfig; private var runner:SpawnTask -> Void; private var queue:Array; @@ -80,4 +82,8 @@ class Spawner { runner(queue.shift()); } } + + private function get_active():Bool { + return queue.length > 0; + } } \ No newline at end of file