diff --git a/gulpfile.js b/gulpfile.js index cf4444b..559ed4a 100755 --- a/gulpfile.js +++ b/gulpfile.js @@ -7,7 +7,8 @@ const dateformat = require('dateformat'); // ToDo: update default in gulp-haxetool -FlashPlayer.VERSION = '31'; +FlashPlayer.VERSION = '32'; +//Haxe.VERSION = '4.0.0-rc.2'; if (Config.SdkDir) { Sdk.dir = Config.SdkDir; } diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index e5e0bac..bd1787f 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -10,12 +10,12 @@ import promhx.Promise; import ru.m.animate.Animate; import ru.m.animate.OnceAnimate; import ru.m.geom.Point; -import ru.m.tankz.core.EntityType; import ru.m.tankz.engine.Engine; +import ru.m.tankz.game.Game.GameListener; +import ru.m.tankz.game.GameEvent; import ru.m.tankz.render.RenderItem; -import ru.m.tankz.Type; -class Render extends SpriteView implements EngineListener { +class Render extends SpriteView implements GameListener { private var backgroundLayer:Sprite; private var groundLayer:Sprite; @@ -99,69 +99,58 @@ class Render extends SpriteView implements EngineListener { clearLayer(upperLayer); } - public function onSpawn(entity:EntityType):Void { - switch entity { - case TANK(tank): + public function onGameEvent(event:GameEvent):Void { + switch event { + case SPAWN(TANK(tank)): var item = new TankItem(tank); items.set(tank.key, item); entryLayer.addChild(item.view); item.update(); playAnimate(tank.rect.center, AnimateBundle.tankSpawn()); - case BULLET(bullet): + case SPAWN(BULLET(bullet)): var item = new BulletItem(bullet); items.set(bullet.key, item); entryLayer.addChild(item.view); item.update(); - case EAGLE(eagle): + case SPAWN(EAGLE(eagle)): var item = new EagleItem(eagle); items.set(eagle.key, item); entryLayer.addChild(item.view); item.update(); - case BONUS(bonus): + case SPAWN(BONUS(bonus)): var item = new BonusItem(bonus); items.set(bonus.key, item); upperLayer.addChild(item.view); item.update(); - case _: - } - } - - public function onCollision(entity:EntityType, with:EntityType):Void { - switch [entity, with] { - case [BULLET(_), EAGLE(eagle)]: - if (eagle.death) { - playAnimate(eagle.rect.center, AnimateBundle.tankBoom()); - } - case _: - } - } - - public function onDestroy(entity:EntityType):Void { - switch entity { - case TANK(tank): + case DESTROY(TANK(tank, who, wherewith, score)): if (items.exists(tank.key)) { entryLayer.removeChild(items.get(tank.key).view); items.remove(tank.key); playAnimate(tank.rect.center, AnimateBundle.tankBoom()); - if (tank.config.score > 0) { - showScore(tank.rect.center, tank.config.score); + if (score != 0) { + showScore(tank.rect.center, score); } } - case BULLET(bullet): + case DESTROY(BULLET(bullet)): if (items.exists(bullet.key)) { entryLayer.removeChild(items.get(bullet.key).view); items.remove(bullet.key); var point = bullet.rect.center.add(new Point(bullet.rect.width * bullet.rect.direction.x, bullet.rect.height * bullet.rect.direction.y)); playAnimate(point, AnimateBundle.bulletBoom()); } - case BONUS(bonus): + case DESTROY(BONUS(bonus, who, score)): if (items.exists(bonus.key)) { upperLayer.removeChild(items.get(bonus.key).view); items.remove(bonus.key); - if (bonus.config.score > 0) { - showScore(bonus.rect.center, bonus.config.score); + if (score != 0) { + showScore(bonus.rect.center, score); } } + case DESTROY(EAGLE(eagle, who, wherewith, score)): + playAnimate(eagle.rect.center, AnimateBundle.tankBoom()); + if (score != 0) { + showScore(eagle.rect.center, score); + } case _: } } @@ -176,7 +165,6 @@ class Render extends SpriteView implements EngineListener { upperLayer.removeChild(animate); } animate.dispose(); - return null; }); } diff --git a/src/client/haxe/ru/m/tankz/sound/SoundManager.hx b/src/client/haxe/ru/m/tankz/sound/SoundManager.hx index c2d0744..f4aa115 100644 --- a/src/client/haxe/ru/m/tankz/sound/SoundManager.hx +++ b/src/client/haxe/ru/m/tankz/sound/SoundManager.hx @@ -5,10 +5,8 @@ import flash.media.Sound; import flash.media.SoundChannel; import flash.media.SoundTransform; import openfl.utils.Assets; -import ru.m.tankz.control.HumanControl; import ru.m.tankz.game.Game; import ru.m.tankz.game.GameEvent; -import ru.m.tankz.game.GameState; class SoundManager implements GameListener { private static var TAG(default, never):String = 'SoundManager'; @@ -76,44 +74,33 @@ class SoundManager implements GameListener { channels.remove(event.currentTarget); } - public function onGameStart(state:GameState):Void { - play('start'); - } - - public function onGameChange(state:GameState):Void { - } - - public function onGameComplete(state:GameState):Void { - } - public function onGameEvent(event:GameEvent):Void { - // ToDo: - /*switch event { - case SPAWN_BULLET(player): - // ToDo: - if (Std.is(player.control, HumanControl)) { + switch event { + case START(state): + play('start'); + case SPAWN(BULLET(bullet)): + if (false /* ToDo: human tank */) { play('shot'); } - case HIT_TANK(player, target): + case SPAWN(BONUS(bonus)): + play('bonus_add'); + case HIT(TANK(tank, who, wherewith)): play('bullet_hit'); - case DESTROY_TANK(player, target): - // ToDo: - if (Std.is(target.control, HumanControl)) { + case DESTROY(TANK(tank, who, wherewith, score)): + if (true /* ToDo: human tank */) { play('boom_player'); } else { play('boom_bot'); } - case DESTROY_EAGLE(player, eagleTeamId): + case DESTROY(EAGLE(eagle, who, wherewith, score)): play('boom_player'); - case SPAWN_BONUS(bonus): - play('bonus'); - case TAKE_BONUS(player, bonus): + case DESTROY(BONUS(bonus, who, score)): if (bonus.type == 'life') { play('live'); } else { play('bonus_get'); } case _: - }*/ + } } } 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 a7d1f1e..c6c08e1 100644 --- a/src/client/haxe/ru/m/tankz/view/classic/ClassicGamePanel.hx +++ b/src/client/haxe/ru/m/tankz/view/classic/ClassicGamePanel.hx @@ -1,8 +1,8 @@ package ru.m.tankz.view.classic; -import ru.m.tankz.game.GameEvent; import haxework.view.LabelView; import haxework.view.VGroupView; +import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.GameState; import ru.m.tankz.preset.ClassicGame; import ru.m.tankz.Type.PlayerId; @@ -19,15 +19,12 @@ import ru.m.tankz.view.common.LifeView; private var player1Id:PlayerId = new PlayerId(ClassicGame.HUMAN, 0); private var player2Id:PlayerId = new PlayerId(ClassicGame.HUMAN, 1); - public function onGameStart(state:GameState):Void { + public function refresh(state:GameState):Void { level.text = 'Level ${state.levelId}'; - } - - public function onGameChange(state:GameState):Void { bot.life = state.getTeamLife(ClassicGame.BOT); player1.life = state.getPlayerLife(player1Id); player1.score = state.getPlayerScore(player1Id); - if (true) { + if (state.getPlayerLife(player2Id) > 0) { player2.visible = true; player2.life = state.getPlayerLife(player2Id); player2.score = state.getPlayerScore(player2Id); @@ -36,11 +33,27 @@ import ru.m.tankz.view.common.LifeView; } } - public function onGameComplete(state:GameState):Void { - - } - public function onGameEvent(event:GameEvent):Void { - + switch event { + case START(state): + refresh(state); + case CHANGE(TEAM_LIFE(team, life)): + if (team.id == ClassicGame.BOT) { + bot.life = life; + } + case CHANGE(PLAYER_LIFE(player, life)): + if (player.id == player1Id) { + player1.life = life; + } else if (player.id == player2Id) { + player2.life = life; + } + case CHANGE(PLAYER_SCORE(player, score)): + if (player.id == player1Id) { + player1.score = score; + } else if (player.id == 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 b0e60b2..4df7343 100644 --- a/src/client/haxe/ru/m/tankz/view/common/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/common/GameFrame.hx @@ -45,7 +45,7 @@ class GameFrame extends GroupView implements GameListener { private function start(state:GameState):Void { game = new Game(state.type); - game.engine.connect(render); + game.connect(render); game.connect(soundManager); game.connect(this); if (panel != null) { @@ -71,26 +71,23 @@ class GameFrame extends GroupView implements GameListener { render.reset(); } - public function onGameStart(state:GameState):Void {} - - public function onGameChange(state:GameState):Void {} - - public function onGameComplete(state:GameState):Void { - result = state; - this.state = switch game.next() { - case Some(s): - // ToDo: - var progress = storage.get(game.type); - progress.completeLevel(result.levelId, result.presetId); - storage.set(progress); - s; - case None: null; - } - stop(); - switcher.change(ResultFrame.ID); - } - public function onGameEvent(event:GameEvent):Void { + switch event { + case GameEvent.COMPLETE(state, winner): + result = state; + this.state = switch game.next() { + case Some(s): + // ToDo: + var progress = storage.get(game.type); + progress.completeLevel(result.levelId, result.presetId); + storage.set(progress); + s; + case None: null; + } + stop(); + switcher.change(ResultFrame.ID); + case _: + } } public function onHide():Void { diff --git a/src/client/haxe/ru/m/tankz/view/common/LifeView.hx b/src/client/haxe/ru/m/tankz/view/common/LifeView.hx index f1a3b17..06c5c3d 100644 --- a/src/client/haxe/ru/m/tankz/view/common/LifeView.hx +++ b/src/client/haxe/ru/m/tankz/view/common/LifeView.hx @@ -4,7 +4,6 @@ import haxework.view.HGroupView; import haxework.view.ImageView; import haxework.view.LabelView; import openfl.Assets; -import ru.m.tankz.game.GameState.PlayerState; import ru.m.tankz.game.GameState; @:template class LifeView extends HGroupView { @@ -51,7 +50,7 @@ import ru.m.tankz.game.GameState; override public function update():Void { super.update(); - if (state != null) { + if (state != null && currentState != null) { var tankConfig = currentState.config.getTank(state.tank); tank = tankConfig == null ? 'ba' : tankConfig.skin; color = currentState.config.getColor(state.id); diff --git a/src/client/haxe/ru/m/tankz/view/death/DeathGamePanel.hx b/src/client/haxe/ru/m/tankz/view/death/DeathGamePanel.hx index 3340ee8..15a76a7 100644 --- a/src/client/haxe/ru/m/tankz/view/death/DeathGamePanel.hx +++ b/src/client/haxe/ru/m/tankz/view/death/DeathGamePanel.hx @@ -4,7 +4,6 @@ import haxework.view.DataView; import haxework.view.LabelView; import haxework.view.VGroupView; import ru.m.tankz.game.GameEvent; -import ru.m.tankz.game.GameState.PlayerState; import ru.m.tankz.game.GameState; import ru.m.tankz.view.common.IGamePanel; import ru.m.tankz.view.common.LifeView; @@ -14,22 +13,15 @@ import ru.m.tankz.view.common.LifeView; @:view var level:LabelView; @:view var players:DataView; - public function onGameStart(state:GameState):Void { - level.text = 'Level ${state.levelId}'; - players.data = Lambda.array(state.players); - } - - public function onGameChange(state:GameState):Void { - for (view in players.views) { - view.toUpdate(); + public function onGameEvent(event:GameEvent):Void { + switch event { + case START(state): + level.text = 'Level ${state.levelId}'; + players.data = Lambda.array(state.players); + case _: + for (view in players.views) { + view.toUpdate(); + } } } - - public function onGameComplete(state:GameState):Void { - - } - - public function onGameEvent(event:GameEvent):Void { - - } } 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 b9527e5..2b5e584 100644 --- a/src/client/haxe/ru/m/tankz/view/dota/DotaGamePanel.hx +++ b/src/client/haxe/ru/m/tankz/view/dota/DotaGamePanel.hx @@ -5,6 +5,7 @@ import haxework.view.LabelView; import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.GameState; import ru.m.tankz.preset.DotaGame; +import ru.m.tankz.Type.TeamId; import ru.m.tankz.view.common.IGamePanel; import ru.m.tankz.view.common.LifeView; @@ -14,22 +15,31 @@ import ru.m.tankz.view.common.LifeView; @:view var dire:LifeView; @:view var level:LabelView; - public function onGameStart(state:GameState):Void { + public function refresh(state:GameState):Void { level.text = 'Level ${state.levelId}'; - } - - public function onGameChange(state:GameState):Void { radiant.life = state.getTeamLife(DotaGame.RADIANT); radiant.score = state.getTeamScore(DotaGame.RADIANT); dire.life = state.getTeamLife(DotaGame.DIRE); dire.score = state.getTeamScore(DotaGame.DIRE); } - public function onGameComplete(state:GameState):Void { - + private inline function getLifeView(teamId:TeamId):LifeView { + return switch teamId { + case DotaGame.RADIANT: radiant; + case DotaGame.DIRE: dire; + case _: null; + } } public function onGameEvent(event:GameEvent):Void { - + 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 _: + } } } diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index dfa3334..2345f3a 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -12,9 +12,7 @@ import ru.m.tankz.map.Grid; import ru.m.tankz.map.LevelMap; interface EngineListener { - public function onSpawn(entity:EntityType):Void; public function onCollision(entity:EntityType, with:EntityType):Void; - public function onDestroy(entity:EntityType):Void; } @:yield @:dispatcher(EngineListener) class Engine { @@ -35,14 +33,10 @@ interface EngineListener { public function spawn(entity:Entity):Void { entities.set(entity.id, entity); - var type = EntityTypeResolver.of(entity); - spawnSignal.emit(type); } public function destroy(entity:Entity):Void { if (entities.exists(entity.id)) { - var type = EntityTypeResolver.of(entity); - destroySignal.emit(type); entities.remove(entity.id); } } diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index a5f1777..53a1b93 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 ru.m.tankz.game.GameEvent.ChangeEvent; import haxe.ds.Option; import haxe.Timer; import ru.m.geom.Point; @@ -19,13 +20,10 @@ import ru.m.tankz.game.Spawner; import ru.m.tankz.Type; interface GameListener { - public function onGameStart(state:GameState):Void; - public function onGameChange(state:GameState):Void; - public function onGameComplete(state:GameState):Void; public function onGameEvent(event:GameEvent):Void; } -@:dispatcher(GameListener) class Game implements IGame implements EngineListener { +@:dispatcher(GameListener) class Game implements IGame implements EngineListener implements GameListener { private static var TAG(default, never):String = "Game"; @@ -47,6 +45,7 @@ interface GameListener { this.config = configBundle.get(type); this.engine = new Engine(config); engine.connect(this); + connect(this); } public function action(tankId:Int, action:TankAction):Void { @@ -60,16 +59,16 @@ interface GameListener { case SHOT: var bullet = tank.shot(); if (bullet != null) { - engine.spawn(bullet); + gameEventSignal.emit(GameEvent.SPAWN(BULLET(bullet))); } } } - public function getTeam(teamId:TeamId):Team { + public inline function getTeam(teamId:TeamId):Team { return teams[teamId]; } - public function getPlayer(playerId:PlayerId):Player { + public inline function getPlayer(playerId:PlayerId):Player { return teams[playerId.team].players[playerId.index]; } @@ -132,11 +131,10 @@ interface GameListener { eagle.color = config.getColor(new PlayerId(eagle.team, -1)); team.eagleId = eagle.id; applyPoint(eagle, eaglePoint); - engine.spawn(eagle); + gameEventSignal.emit(GameEvent.SPAWN(EAGLE(eagle))); } } - gameStartSignal.emit(state); - gameChangeSignal.emit(state); + gameEventSignal.emit(GameEvent.START(state)); } private function spawn(task:SpawnTask):Void { @@ -147,11 +145,10 @@ interface GameListener { var tank = buildTank(task); player.tankId = tank.id; player.state.tank = tank.config.type; - engine.spawn(tank); - gameChangeSignal.emit(state); + gameEventSignal.emit(GameEvent.SPAWN(TANK(tank))); } - private function checkComplete() { + private function checkComplete():Void { var actives:Array = []; for (team in teams.iterator()) { if (team.isAlive) { @@ -180,22 +177,10 @@ interface GameListener { } } Timer.delay(function() { - //gameChangeSignal.emit(state); - gameCompleteSignal.emit(state); + gameEventSignal.emit(GameEvent.COMPLETE(state, getTeam(winner))); }, 5000); } - public function onSpawn(entity:EntityType):Void { - switch entity { - case TANK(tank): - getPlayer(tank.playerId).control.start(); - case BULLET(bullet): - getPlayer(bullet.playerId).state.shots++; - gameEventSignal.emit(GameEvent.SPAWN(BULLET(bullet))); - case _: - } - } - public function onCollision(entity:EntityType, with:EntityType):Void { switch entity { case EntityType.TANK(tank): @@ -209,14 +194,12 @@ interface GameListener { case [TANK(tank), EAGLE(eagle)]: tank.rect.lean(eagle.rect); case [BULLET(bullet), BULLET(other_bullet)]: - engine.destroy(bullet); - engine.destroy(other_bullet); + gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet))); + gameEventSignal.emit(GameEvent.DESTROY(BULLET(other_bullet))); case [BULLET(bullet), CELL(cell)]: - engine.destroy(bullet); gameEventSignal.emit(GameEvent.HIT(CELL(cell, bullet.tank, bullet))); + gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet))); case [TANK(tank), BONUS(bonus)]: - applyBonus(tank, bonus); - engine.destroy(bonus); gameEventSignal.emit(GameEvent.DESTROY(BONUS(bonus, tank, bonus.config.score))); case [BULLET(bullet), TANK(tank)]/* | [TANK(tank), BULLET(bullet)]*/: if (bullet.tankId == tank.id || (!engine.config.game.friendlyFire && tank.playerId.team == bullet.playerId.team)) { @@ -234,54 +217,20 @@ interface GameListener { tank.config = engine.config.getTank(tank.config.downgrade); gameEventSignal.emit(GameEvent.HIT(TANK(tank, bullet.tank, bullet))); } else { - engine.destroy(tank); - gameEventSignal.emit(GameEvent.DESTROY(TANK(tank, bullet.tank, bullet, tank.config.score))); + var score = tank.config.score; + if (tank.playerId.team == bullet.playerId.team) { + score = Math.round(score * -0.5); + } + gameEventSignal.emit(GameEvent.DESTROY(TANK(tank, bullet.tank, bullet, score))); } } - engine.destroy(bullet); + gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet))); } case [BULLET(bullet), EAGLE(eagle)]: - engine.destroy(bullet); if (!eagle.protect.active) { - eagle.death = true; - if (bullet.playerId.team != eagle.team) { - getPlayer(bullet.playerId).state.score += eagle.score; - } - checkComplete(); - gameChangeSignal.emit(state); - gameEventSignal.emit(GameEvent.DESTROY(EAGLE(eagle, bullet.tank, bullet, eagle.config.score))); + gameEventSignal.emit(GameEvent.DESTROY(EAGLE(eagle, bullet.tank, bullet, eagle.score))); } - case _: - } - } - - public function onDestroy(entity:EntityType):Void { - switch (entity) { - case BULLET(bullet): - var tank:Tank = bullet.tank; - if (tank != null) tank.onDestroyBullet(); - case TANK(tank): - var team = getTeam(tank.playerId.team); - var player = getPlayer(tank.playerId); - player.control.stop(); - player.tankId = 0; //ToDo: ? - team.onDestroy(player.id); - var respawn:Bool = team.tryRespawn(player.id); - if (respawn) { - team.spawner.push(player.id); - } - if (!team.isAlive) { - checkComplete(); - } - if (tank.bonus) { - spawnBonus(); - } - // ToDo: - /*if (playerId != null) { - getPlayer(playerId).state.frags++; - getPlayer(playerId).state.score += tank.config.score * (tank.playerId.team == playerId.team ? 0 : 1); - }*/ - gameChangeSignal.emit(state); + gameEventSignal.emit(GameEvent.DESTROY(BULLET(bullet))); case _: } } @@ -308,9 +257,6 @@ interface GameListener { public function dispose():Void { engine.dispose(); - gameStartSignal.dispose(); - gameChangeSignal.dispose(); - gameCompleteSignal.dispose(); gameEventSignal.dispose(); } @@ -319,23 +265,22 @@ interface GameListener { var bonus = new Bonus(bonusConfig); bonus.rect.x = Math.round(Math.random() * engine.map.width / engine.map.cellWidth) * engine.map.cellWidth; bonus.rect.y = Math.round(Math.random() * engine.map.height/ engine.map.cellHeight) * engine.map.cellHeight; - engine.spawn(bonus); gameEventSignal.emit(GameEvent.SPAWN(BONUS(bonus))); } - inline private function alienTank(team:TeamId):Tank->Bool { + private inline function alienTank(team:TeamId):Tank->Bool { return function(tank:Tank):Bool return team != tank.playerId.team; } private function applyBonus(tank:Tank, bonus:Bonus):Void { switch (bonus.config.type) { case "life": - getPlayer(tank.playerId).state.life++; + changeLife(tank.playerId, 1); case "star": upgradeTank(tank); case "grenade": for (t in engine.iterTanks(alienTank(tank.playerId.team))) { - engine.destroy(t); + gameEventSignal.emit(GameEvent.DESTROY(TANK(t, tank, null, 0))); } case "helmet": tank.protect.on(bonus.config.duration); @@ -353,15 +298,11 @@ interface GameListener { case "gun": upgradeTank(tank, 5); case _: - engine.destroy(tank); // :-D + gameEventSignal.emit(GameEvent.DESTROY(TANK(tank, null, null, 0))); // :-D } - if (bonus.config.score > 0) { - getPlayer(tank.playerId).state.score += bonus.config.score; - } - gameChangeSignal.emit(state); } - public function upgradeTank(tank:Tank, level:Int = 1):Void { + private function upgradeTank(tank:Tank, level:Int = 1):Void { if (tank.config.upgrade != null) { while (level-- > 0 && tank.config.upgrade != null) { tank.config = config.getTank(tank.config.upgrade); @@ -371,7 +312,83 @@ interface GameListener { } } - public function hitTank(tank:Tank):Void { + private function changeScore(playerId:PlayerId, score:Int):Void { + var player = getPlayer(playerId); + var team = getTeam(playerId.team); + player.state.score += score; + gameEventSignal.emit(GameEvent.CHANGE(PLAYER_SCORE(player, player.state.score))); + gameEventSignal.emit(GameEvent.CHANGE(TEAM_SCORE(team, state.getTeamScore(team.id)))); + } + private function changeLife(playerId:PlayerId, life:Int):Void { + var player = getPlayer(playerId); + player.state.life += life; + gameEventSignal.emit(GameEvent.CHANGE(PLAYER_LIFE(player, player.state.life))); + } + + private function changeTeamLife(teamId:TeamId, life:Int):Void { + var team = getTeam(teamId); + team.state.life += life; + gameEventSignal.emit(GameEvent.CHANGE(TEAM_LIFE(team, team.state.life))); + } + + public function onGameEvent(event:GameEvent):Void { + switch event { + case GameEvent.SPAWN(EAGLE(eagle)): + engine.spawn(eagle); + case GameEvent.SPAWN(TANK(tank)): + engine.spawn(tank); + getPlayer(tank.playerId).control.start(); + case GameEvent.SPAWN(BULLET(bullet)): + engine.spawn(bullet); + case GameEvent.SPAWN(BONUS(bonus)): + engine.spawn(bonus); + case GameEvent.DESTROY(EAGLE(eagle, who, wherewith, score)): + eagle.death = true; + if (score != 0) { + changeScore(who.playerId, score); + } + checkComplete(); + case GameEvent.DESTROY(TANK(tank, who, wherewith, score)): + engine.destroy(tank); + var team = getTeam(tank.playerId.team); + var player = getPlayer(tank.playerId); + player.control.stop(); + player.tankId = 0; //ToDo: ? + team.onDestroy(player.id); + if (player.state.life > 0) { + changeLife(player.id, -1); + } else if (team.state.life > 0) { + changeTeamLife(team.id, -1); + } + var respawn:Bool = team.tryRespawn(player.id); + if (respawn) { + team.spawner.push(player.id); + } + if (!team.isAlive) { + checkComplete(); + } + if (tank.bonus && wherewith != null) { + spawnBonus(); + } + if (score != 0) { + changeScore(who.playerId, score); + } + case GameEvent.DESTROY(CELL(cell, who, wherewith)): + + case GameEvent.DESTROY(BONUS(bonus, who, score)): + engine.destroy(bonus); + applyBonus(who, bonus); + if (score != 0) { + changeScore(who.playerId, score); + } + case GameEvent.DESTROY(BULLET(bullet)): + engine.destroy(bullet); + var tank:Tank = bullet.tank; + if (tank != null) { + tank.onDestroyBullet(); + } + case _: + } } } diff --git a/src/common/haxe/ru/m/tankz/game/GameEvent.hx b/src/common/haxe/ru/m/tankz/game/GameEvent.hx index 1949da1..b2752e4 100644 --- a/src/common/haxe/ru/m/tankz/game/GameEvent.hx +++ b/src/common/haxe/ru/m/tankz/game/GameEvent.hx @@ -23,17 +23,21 @@ enum DestroyEvent { TANK(tank:Tank, who:Tank, wherewith:Bullet, score:Int); CELL(cell:GridCell, who:Tank, wherewith:Bullet); BONUS(bonus:Bonus, who:Tank, score:Int); + BULLET(bullet:Bullet); } enum ChangeEvent { - SCORE(player:Player, value:Int); + PLAYER_SCORE(player:Player, value:Int); PLAYER_LIFE(player:Player, value:Int); + TEAM_SCORE(team:Team, value:Int); TEAM_LIFE(team:Team, value:Int); } enum GameEvent { + START(state:GameState); SPAWN(event:SpawnEvent); HIT(event:HitEvent); DESTROY(event:DestroyEvent); CHANGE(event:ChangeEvent); + COMPLETE(state:GameState, winner:Team); } diff --git a/src/common/haxe/ru/m/tankz/game/IGame.hx b/src/common/haxe/ru/m/tankz/game/IGame.hx index d07469f..0fb2934 100644 --- a/src/common/haxe/ru/m/tankz/game/IGame.hx +++ b/src/common/haxe/ru/m/tankz/game/IGame.hx @@ -1,9 +1,24 @@ package ru.m.tankz.game; +import haxework.signal.Signal; +import ru.m.tankz.control.Control; import ru.m.tankz.engine.Engine; -import ru.m.tankz.control.Control.TankAction; +import ru.m.tankz.game.Game; +import ru.m.tankz.Type; interface IGame { public var engine(default, null):Engine; + public var gameEventSignal(default, null):Signal; + + public function connect(listener:GameListener):Void; + + public function disconnect(listener:GameListener):Void; + + public function start(state:GameState):Void; + public function action(tankId:Int, action:TankAction):Void; + + public function getTeam(teamId:TeamId):Team; + + public function getPlayer(playerId:PlayerId):Player; } diff --git a/src/common/haxe/ru/m/tankz/game/Team.hx b/src/common/haxe/ru/m/tankz/game/Team.hx index b81e63b..e0b06b6 100644 --- a/src/common/haxe/ru/m/tankz/game/Team.hx +++ b/src/common/haxe/ru/m/tankz/game/Team.hx @@ -37,14 +37,8 @@ class Team { return result; } - public function onDestroy(playerId:PlayerId) { + public function onDestroy(playerId:PlayerId):Void { active--; - var player:Player = players[playerId.index]; - if (player.state.life > 0) { - player.state.life--; - } else { - state.life--; - } } // ToDo: eagle state?