[common] game state refactored
This commit is contained in:
@@ -51,7 +51,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand
|
|||||||
render.draw(game.engine);
|
render.draw(game.engine);
|
||||||
timer = new Timer(10);
|
timer = new Timer(10);
|
||||||
timer.run = updateEngine;
|
timer.run = updateEngine;
|
||||||
state.text = stateString(s);
|
state.text = stateString(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function stop():Void {
|
private function stop():Void {
|
||||||
@@ -68,20 +68,18 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand
|
|||||||
render.reset();
|
render.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function stateString(state:GameState):String {
|
private function stateString(game:Game):String {
|
||||||
var result:Array<String> = [];
|
var result:Array<String> = [];
|
||||||
result.push('Level: ${state.level}');
|
result.push('Level: ${game.state.level}');
|
||||||
for (teamId in state.teams.keys()) {
|
for (team in game.teams) {
|
||||||
var ts:TeamState = state.teams[teamId];
|
if (game.state.loser == team.id) {
|
||||||
if (ts.lose) {
|
result.push('${team.id}: LOSE');
|
||||||
result.push('${teamId}: LOSE');
|
} else if (team.life > -1) {
|
||||||
} else if (ts.life > -1) {
|
result.push('${team.id}: ${team.life}');
|
||||||
result.push('${teamId}: ${ts.life}');
|
|
||||||
} else {
|
} else {
|
||||||
for (index in ts.players.keys()) {
|
for (player in team.players) {
|
||||||
var ps:PlayerState = ts.players[index];
|
if (player.life > -1) {
|
||||||
if (ps.life > -1) {
|
result.push('${player.id.team}${player.id.index}: ${player.life}');
|
||||||
result.push('${teamId}${index}: ${ps.life}');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,14 +88,14 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function onGameStateChange(s:GameState):GameState {
|
private function onGameStateChange(s:GameState):GameState {
|
||||||
state.text = stateString(s);
|
state.text = stateString(game);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onGameComplete(result:Option<GameState>):Void {
|
private function onGameComplete(result:Option<GameState>):Void {
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case Option.Some(s):
|
case Option.Some(s):
|
||||||
state.text = stateString(s);
|
state.text = stateString(game);
|
||||||
case Option.None:
|
case Option.None:
|
||||||
}
|
}
|
||||||
switch (game.next()) {
|
switch (game.next()) {
|
||||||
|
|||||||
@@ -47,14 +47,8 @@ class StartFrame extends VGroupView implements ViewBuilder implements StartFrame
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function startGame(type:GameType, mode:GameMode):Void {
|
private function startGame(type:GameType, presetId:PresetId):Void {
|
||||||
switch (type) {
|
Provider.set(GameState, new GameState(type, presetId));
|
||||||
case ClassicGame.TYPE:
|
Provider.get(IFrameSwitcher).change(LevelFrame.ID);
|
||||||
Provider.set(GameState, ClassicGame.buildState(0, mode));
|
|
||||||
Provider.get(IFrameSwitcher).change(LevelFrame.ID);
|
|
||||||
case DotaGame.TYPE:
|
|
||||||
Provider.set(GameState, DotaGame.buildState(0, mode));
|
|
||||||
Provider.get(IFrameSwitcher).change(LevelFrame.ID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,18 +17,55 @@ bricks:
|
|||||||
- {type: 4, layer: 2, armor: 2} # armor
|
- {type: 4, layer: 2, armor: 2} # armor
|
||||||
- {type: 5, layer: 2, armor: 1} # brick
|
- {type: 5, layer: 2, armor: 1} # brick
|
||||||
|
|
||||||
teams:
|
player:
|
||||||
- id: human
|
human: &human
|
||||||
|
control: human
|
||||||
|
life: 3
|
||||||
tanks:
|
tanks:
|
||||||
- {type: human0, rate: 1}
|
- {type: human0, rate: 1}
|
||||||
- id: bot
|
bot: &bot
|
||||||
spawnInterval: 3000
|
control: bot
|
||||||
|
life: -1
|
||||||
tanks:
|
tanks:
|
||||||
- {type: bot0, rate: 0.25, bonus: 0.25}
|
- {type: bot0, rate: 0.25, bonus: 0.25}
|
||||||
- {type: bot1, rate: 0.25, bonus: 0.25}
|
- {type: bot1, rate: 0.25, bonus: 0.25}
|
||||||
- {type: bot2, rate: 0.25, bonus: 0.25}
|
- {type: bot2, rate: 0.25, bonus: 0.25}
|
||||||
- {type: bot3, rate: 0.25, bonus: 0.25}
|
- {type: bot3, rate: 0.25, bonus: 0.25}
|
||||||
|
|
||||||
|
presets:
|
||||||
|
- id: player1
|
||||||
|
teams:
|
||||||
|
- id: human
|
||||||
|
life: -1
|
||||||
|
players:
|
||||||
|
- {<<: *human, index: 0, color: 0xFC9838, life: 3}
|
||||||
|
- id: bot
|
||||||
|
spawnInterval: 3000
|
||||||
|
life: 20
|
||||||
|
players:
|
||||||
|
- {<<: *bot, index: 0}
|
||||||
|
- {<<: *bot, index: 1}
|
||||||
|
- {<<: *bot, index: 2}
|
||||||
|
- {<<: *bot, index: 3}
|
||||||
|
|
||||||
|
- id: player2
|
||||||
|
teams:
|
||||||
|
- id: human
|
||||||
|
life: -1
|
||||||
|
players:
|
||||||
|
- {<<: *human, index: 0, color: 0xFC9838, life: 3}
|
||||||
|
- {<<: *human, index: 1, color: 0x159D49, life: 3}
|
||||||
|
- id: bot
|
||||||
|
spawnInterval: 3000
|
||||||
|
life: 20
|
||||||
|
players:
|
||||||
|
- {<<: *bot, index: 0}
|
||||||
|
- {<<: *bot, index: 1}
|
||||||
|
- {<<: *bot, index: 2}
|
||||||
|
- {<<: *bot, index: 3}
|
||||||
|
- {<<: *bot, index: 4}
|
||||||
|
- {<<: *bot, index: 5}
|
||||||
|
|
||||||
points:
|
points:
|
||||||
- {team: human, type: eagle, index: -1, direction: right, x: 12, y: 24}
|
- {team: human, type: eagle, index: -1, direction: right, x: 12, y: 24}
|
||||||
- {team: human, type: tank, index: 0, direction: top, x: 8, y: 24}
|
- {team: human, type: tank, index: 0, direction: top, x: 8, y: 24}
|
||||||
|
|||||||
@@ -17,18 +17,72 @@ bricks:
|
|||||||
- {type: 4, layer: 2, armor: 2} # armor
|
- {type: 4, layer: 2, armor: 2} # armor
|
||||||
- {type: 5, layer: 2, armor: 1} # brick
|
- {type: 5, layer: 2, armor: 1} # brick
|
||||||
|
|
||||||
team_tanks: &team_tanks
|
team:
|
||||||
|
radiant: &radiant
|
||||||
|
id: radiant
|
||||||
|
color: 0xff5555
|
||||||
|
life: 20
|
||||||
|
dire: &dire
|
||||||
|
id: dire
|
||||||
|
color: 0x5555ff
|
||||||
|
life: 20
|
||||||
|
|
||||||
|
player: &player
|
||||||
|
life: -1
|
||||||
|
control: bot
|
||||||
tanks:
|
tanks:
|
||||||
- {type: slow, rate: 0.5}
|
- {type: slow, rate: 0.5}
|
||||||
- {type: fast, rate: 0.5}
|
- {type: fast, rate: 0.5}
|
||||||
|
|
||||||
teams:
|
presets:
|
||||||
- <<: *team_tanks
|
- id: player1
|
||||||
id: radiant
|
teams:
|
||||||
color: 0xff5555
|
- <<: *radiant
|
||||||
- <<: *team_tanks
|
players:
|
||||||
id: dire
|
- {<<: *player, index: 0, control: human, color: 0xff7777}
|
||||||
color: 0x5555ff
|
- {<<: *player, index: 1}
|
||||||
|
- {<<: *player, index: 2}
|
||||||
|
- {<<: *player, index: 3}
|
||||||
|
- {<<: *player, index: 4}
|
||||||
|
- <<: *dire
|
||||||
|
players:
|
||||||
|
- {<<: *player, index: 0}
|
||||||
|
- {<<: *player, index: 1}
|
||||||
|
- {<<: *player, index: 2}
|
||||||
|
- {<<: *player, index: 3}
|
||||||
|
- {<<: *player, index: 4}
|
||||||
|
- id: player2_coop
|
||||||
|
teams:
|
||||||
|
- <<: *radiant
|
||||||
|
players:
|
||||||
|
- {<<: *player, index: 0, control: human, color: 0xff7777}
|
||||||
|
- {<<: *player, index: 1, control: human, color: 0xff7777}
|
||||||
|
- {<<: *player, index: 2}
|
||||||
|
- {<<: *player, index: 3}
|
||||||
|
- {<<: *player, index: 4}
|
||||||
|
- <<: *dire
|
||||||
|
players:
|
||||||
|
- {<<: *player, index: 0}
|
||||||
|
- {<<: *player, index: 1}
|
||||||
|
- {<<: *player, index: 2}
|
||||||
|
- {<<: *player, index: 3}
|
||||||
|
- {<<: *player, index: 4}
|
||||||
|
- id: player2_vs
|
||||||
|
teams:
|
||||||
|
- <<: *radiant
|
||||||
|
players:
|
||||||
|
- {<<: *player, index: 0, control: human, color: 0xff7777}
|
||||||
|
- {<<: *player, index: 1}
|
||||||
|
- {<<: *player, index: 2}
|
||||||
|
- {<<: *player, index: 3}
|
||||||
|
- {<<: *player, index: 4}
|
||||||
|
- <<: *dire
|
||||||
|
players:
|
||||||
|
- {<<: *player, index: 0, control: human, color: 0x7777ff}
|
||||||
|
- {<<: *player, index: 1}
|
||||||
|
- {<<: *player, index: 2}
|
||||||
|
- {<<: *player, index: 3}
|
||||||
|
- {<<: *player, index: 4}
|
||||||
|
|
||||||
points:
|
points:
|
||||||
- {team: radiant, type: eagle, index: -1, direction: right, x: 0, y: 28}
|
- {team: radiant, type: eagle, index: -1, direction: right, x: 0, y: 28}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package ru.m.tankz;
|
package ru.m.tankz;
|
||||||
|
|
||||||
import ru.m.draw.Color;
|
|
||||||
|
|
||||||
typedef Type = Dynamic;
|
typedef Type = Dynamic;
|
||||||
|
|
||||||
@@ -18,9 +17,7 @@ typedef BonusType = String;
|
|||||||
|
|
||||||
typedef PlayerId = {
|
typedef PlayerId = {
|
||||||
var team:TeamId;
|
var team:TeamId;
|
||||||
var type:ControlType;
|
|
||||||
var index:Int;
|
var index:Int;
|
||||||
@:optional var color:Color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef GameMode = Array<PlayerId>;
|
typedef PresetId = String;
|
||||||
|
|||||||
@@ -60,15 +60,26 @@ typedef TankSpawn = {
|
|||||||
@:optional var bonus:Float;
|
@:optional var bonus:Float;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef PlayerConfig = {
|
||||||
|
var index:Int;
|
||||||
|
var control:ControlType;
|
||||||
|
var tanks:Array<TankSpawn>;
|
||||||
|
@:optional var life:Int;
|
||||||
|
@:optional var color:Color;
|
||||||
|
}
|
||||||
|
|
||||||
typedef TeamConfig = {
|
typedef TeamConfig = {
|
||||||
var id:TeamId;
|
var id:TeamId;
|
||||||
var size:Int;
|
var players:Array<PlayerConfig>;
|
||||||
var tanks:Array<TankSpawn>;
|
@:optional var life:Int;
|
||||||
@:optional var spawnInterval:Int;
|
@:optional var spawnInterval:Int;
|
||||||
@:optional var color:Color;
|
@:optional var color:Color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef GamePreset = {
|
||||||
|
var id:PresetId;
|
||||||
|
var teams:Array<TeamConfig>;
|
||||||
|
}
|
||||||
|
|
||||||
typedef LevelConfig = {
|
typedef LevelConfig = {
|
||||||
var data:Array<BrickConfig>;
|
var data:Array<BrickConfig>;
|
||||||
@@ -82,13 +93,13 @@ class Config {
|
|||||||
public var map(default, null):MapConfig;
|
public var map(default, null):MapConfig;
|
||||||
public var bricks(default, null):Array<BrickConfig>;
|
public var bricks(default, null):Array<BrickConfig>;
|
||||||
public var tanks(default, null):Array<TankConfig>;
|
public var tanks(default, null):Array<TankConfig>;
|
||||||
public var teams(default, null):Array<TeamConfig>;
|
public var presets(default, null):Array<GamePreset>;
|
||||||
public var points(default, null):Array<SpawnPoint>;
|
public var points(default, null):Array<SpawnPoint>;
|
||||||
public var bonuses(default, null):Array<BonusConfig>;
|
public var bonuses(default, null):Array<BonusConfig>;
|
||||||
|
|
||||||
private var brickMap:Map<Int, BrickConfig>;
|
private var brickMap:Map<Int, BrickConfig>;
|
||||||
private var tankMap:Map<TankType, TankConfig>;
|
private var tankMap:Map<TankType, TankConfig>;
|
||||||
private var teamMap:Map<TeamId, TeamConfig>;
|
private var presetsMap:Map<PresetId, GamePreset>;
|
||||||
private var bonusMap:Map<BonusType, BonusConfig>;
|
private var bonusMap:Map<BonusType, BonusConfig>;
|
||||||
|
|
||||||
public function new(
|
public function new(
|
||||||
@@ -96,7 +107,7 @@ class Config {
|
|||||||
game:GameConfig,
|
game:GameConfig,
|
||||||
map:MapConfig,
|
map:MapConfig,
|
||||||
bricks:Array<BrickConfig>,
|
bricks:Array<BrickConfig>,
|
||||||
teams:Array<TeamConfig>,
|
presets:Array<GamePreset>,
|
||||||
points:Array<SpawnPoint>,
|
points:Array<SpawnPoint>,
|
||||||
tanks:Array<TankConfig>,
|
tanks:Array<TankConfig>,
|
||||||
bonuses:Array<BonusConfig>
|
bonuses:Array<BonusConfig>
|
||||||
@@ -105,7 +116,7 @@ class Config {
|
|||||||
this.game = game;
|
this.game = game;
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.bricks = bricks;
|
this.bricks = bricks;
|
||||||
this.teams = teams;
|
this.presets = presets;
|
||||||
this.points = points;
|
this.points = points;
|
||||||
this.tanks = tanks;
|
this.tanks = tanks;
|
||||||
this.bonuses = bonuses;
|
this.bonuses = bonuses;
|
||||||
@@ -117,9 +128,9 @@ class Config {
|
|||||||
for (item in bricks) {
|
for (item in bricks) {
|
||||||
brickMap.set(item.type, item);
|
brickMap.set(item.type, item);
|
||||||
}
|
}
|
||||||
teamMap = new Map();
|
presetsMap = new Map();
|
||||||
for (team in teams) {
|
for (preset in presets) {
|
||||||
teamMap.set(team.id, team);
|
presetsMap.set(preset.id, preset);
|
||||||
}
|
}
|
||||||
tankMap = new Map();
|
tankMap = new Map();
|
||||||
for (item in tanks) {
|
for (item in tanks) {
|
||||||
@@ -135,8 +146,8 @@ class Config {
|
|||||||
return brickMap.get(type);
|
return brickMap.get(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTeam(id:String):TeamConfig {
|
public function getPreset(id:PresetId):GamePreset {
|
||||||
return teamMap.get(id);
|
return presetsMap.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTank(type:TankType):TankConfig {
|
public function getTank(type:TankType):TankConfig {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ typedef ConfigSource = {
|
|||||||
var game:GameConfig;
|
var game:GameConfig;
|
||||||
var map: MapConfig;
|
var map: MapConfig;
|
||||||
var bricks: Array<BrickConfig>;
|
var bricks: Array<BrickConfig>;
|
||||||
var teams: Array<TeamConfig>;
|
var presets: Array<GamePreset>;
|
||||||
var points: Array<SpawnPoint>;
|
var points: Array<SpawnPoint>;
|
||||||
var tanks: Array<TankConfig>;
|
var tanks: Array<TankConfig>;
|
||||||
var bonuses: Array<BonusConfig>;
|
var bonuses: Array<BonusConfig>;
|
||||||
@@ -24,6 +24,6 @@ class ConfigBundle {
|
|||||||
|
|
||||||
public static function get(type:String):Config {
|
public static function get(type:String):Config {
|
||||||
var source = convert(Yaml.parse(Assets.getText('resources/${type}/config.yaml'), Parser.options().useObjects()));
|
var source = convert(Yaml.parse(Assets.getText('resources/${type}/config.yaml'), Parser.options().useObjects()));
|
||||||
return new Config(type, source.game, source.map, source.bricks, source.teams, source.points, source.tanks, source.bonuses);
|
return new Config(type, source.game, source.map, source.bricks, source.presets, source.points, source.tanks, source.bonuses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package ru.m.tankz.game;
|
package ru.m.tankz.game;
|
||||||
|
|
||||||
import haxe.ds.Option;
|
import haxe.ds.Option;
|
||||||
import ru.m.draw.Color;
|
|
||||||
import ru.m.tankz.control.Control;
|
|
||||||
import ru.m.tankz.game.Game;
|
import ru.m.tankz.game.Game;
|
||||||
import ru.m.tankz.game.GameState.PlayerState;
|
import ru.m.tankz.game.GameState;
|
||||||
import ru.m.tankz.Type;
|
import ru.m.tankz.Type;
|
||||||
|
|
||||||
|
|
||||||
@@ -15,57 +13,17 @@ class ClassicGame extends Game {
|
|||||||
public static var HUMAN(default, never):TeamId = 'human';
|
public static var HUMAN(default, never):TeamId = 'human';
|
||||||
public static var BOT(default, never):TeamId = 'bot';
|
public static var BOT(default, never):TeamId = 'bot';
|
||||||
|
|
||||||
private static var PLAYER1_COLOR:Color = 0xFC9838;
|
public static var PLAYER1(default, never):PresetId = 'player1';
|
||||||
private static var PLAYER2_COLOR:Color = 0x159D49;
|
public static var PLAYER2(default, never):PresetId = 'player2';
|
||||||
|
|
||||||
public static var PLAYER1(default, never):GameMode = [
|
|
||||||
{team:HUMAN, type:Control.HUMAN, color: PLAYER1_COLOR, index:0}
|
|
||||||
];
|
|
||||||
public static var PLAYER2(default, never):GameMode = [
|
|
||||||
{team:HUMAN, type:Control.HUMAN, color: PLAYER1_COLOR, index:0},
|
|
||||||
{team:HUMAN, type:Control.HUMAN, color: PLAYER2_COLOR, index:1}
|
|
||||||
];
|
|
||||||
|
|
||||||
private static var HUMAN_LIFE(default, never):Int = 3;
|
|
||||||
private static var BOT_LIFE(default, never):Int = 20;
|
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super(TYPE);
|
super(TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function buildState(level:Int, mode:GameMode):GameState {
|
|
||||||
var state = new GameState();
|
|
||||||
state.type = TYPE;
|
|
||||||
state.mode = mode;
|
|
||||||
state.level = level;
|
|
||||||
state.teams[HUMAN] = {life: -1, players: new Map(), lose: false};
|
|
||||||
state.teams[BOT] = {life: BOT_LIFE, players: new Map(), lose: false};
|
|
||||||
for (human in mode) {
|
|
||||||
state.teams[HUMAN].players[human.index] = {
|
|
||||||
id:human,
|
|
||||||
life:HUMAN_LIFE,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
for (i in 0...mode.length * 2 + 2) {
|
|
||||||
state.teams[BOT].players[i] = {
|
|
||||||
id:{team:BOT, index:i, type:Control.BOT},
|
|
||||||
life:-1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
override public function next():Option<GameState> {
|
override public function next():Option<GameState> {
|
||||||
if (!state.teams[HUMAN].lose) {
|
if (state.loser == HUMAN) {
|
||||||
state.level++;
|
return Option.None;
|
||||||
if (state.level >= config.game.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;
|
return super.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
package ru.m.tankz.game;
|
package ru.m.tankz.game;
|
||||||
|
|
||||||
import haxe.ds.Option;
|
|
||||||
import ru.m.draw.Color;
|
|
||||||
import ru.m.tankz.control.Control;
|
|
||||||
import ru.m.tankz.game.Game;
|
import ru.m.tankz.game.Game;
|
||||||
import ru.m.tankz.game.GameState;
|
|
||||||
import ru.m.tankz.Type;
|
import ru.m.tankz.Type;
|
||||||
|
|
||||||
|
|
||||||
@@ -15,57 +11,11 @@ class DotaGame extends Game {
|
|||||||
public static var RADIANT(default, never):TeamId = 'radiant';
|
public static var RADIANT(default, never):TeamId = 'radiant';
|
||||||
public static var DIRE(default, never):TeamId = 'dire';
|
public static var DIRE(default, never):TeamId = 'dire';
|
||||||
|
|
||||||
public static var PLAYER1(default, never):GameMode = [
|
public static var PLAYER1(default, never):PresetId = 'player1';
|
||||||
{team:RADIANT, type:Control.HUMAN, index:0}
|
public static var PLAYER2_COOP(default, never):PresetId = 'player2_coop';
|
||||||
];
|
public static var PLAYER2_VS(default, never):PresetId = 'player2_vs';
|
||||||
|
|
||||||
private static var PLAYER1_COLOR:Color = 0xff7777;
|
|
||||||
private static var PLAYER2_COLOR:Color = 0x7777ff;
|
|
||||||
|
|
||||||
public static var PLAYER2_COOP(default, never):GameMode = [
|
|
||||||
{team:RADIANT, type:Control.HUMAN, color: PLAYER1_COLOR, index:0},
|
|
||||||
{team:RADIANT, type:Control.HUMAN, color: PLAYER1_COLOR, index:1}
|
|
||||||
];
|
|
||||||
|
|
||||||
public static var PLAYER2_VS(default, never):GameMode = [
|
|
||||||
{team:RADIANT, type:Control.HUMAN, color: PLAYER1_COLOR, index:0},
|
|
||||||
{team:DIRE, type:Control.HUMAN, color: PLAYER2_COLOR, index:0}
|
|
||||||
];
|
|
||||||
|
|
||||||
private static var TEAM_SIZE(default, never):Int = 5;
|
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super(TYPE);
|
super(TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function buildState(level:Int, mode:GameMode):GameState {
|
|
||||||
var state = new GameState();
|
|
||||||
state.type = TYPE;
|
|
||||||
state.mode = mode;
|
|
||||||
state.level = level;
|
|
||||||
state.teams[RADIANT] = {life: 20, players: new Map(), lose: false};
|
|
||||||
state.teams[DIRE] = {life: 20, players: new Map(), lose: false};
|
|
||||||
for (i in 0...TEAM_SIZE) {
|
|
||||||
state.teams[RADIANT].players[i] = {
|
|
||||||
id: {team:RADIANT, index:i, type:Control.BOT},
|
|
||||||
life: -1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
for (i in 0...TEAM_SIZE) {
|
|
||||||
state.teams[DIRE].players[i] = {
|
|
||||||
id: {team:DIRE, index:i, type:Control.BOT},
|
|
||||||
life: -1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
for (human in mode) {
|
|
||||||
state.teams[human.team].players[human.index].id = human;
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
override public function next():Option<GameState> {
|
|
||||||
state.level++;
|
|
||||||
if (state.level >= config.game.levels) state.level = 0;
|
|
||||||
return Option.Some(buildState(state.level, state.mode));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package ru.m.tankz.game;
|
package ru.m.tankz.game;
|
||||||
|
|
||||||
import ru.m.tankz.core.Bonus;
|
|
||||||
import haxe.ds.Option;
|
import haxe.ds.Option;
|
||||||
import haxe.Timer;
|
import haxe.Timer;
|
||||||
import promhx.Deferred;
|
import promhx.Deferred;
|
||||||
@@ -13,6 +12,7 @@ import ru.m.tankz.config.ConfigBundle;
|
|||||||
import ru.m.tankz.config.LevelBundle;
|
import ru.m.tankz.config.LevelBundle;
|
||||||
import ru.m.tankz.control.Control;
|
import ru.m.tankz.control.Control;
|
||||||
import ru.m.tankz.control.HumanControl;
|
import ru.m.tankz.control.HumanControl;
|
||||||
|
import ru.m.tankz.core.Bonus;
|
||||||
import ru.m.tankz.core.Eagle;
|
import ru.m.tankz.core.Eagle;
|
||||||
import ru.m.tankz.core.Entity;
|
import ru.m.tankz.core.Entity;
|
||||||
import ru.m.tankz.core.EntityType;
|
import ru.m.tankz.core.EntityType;
|
||||||
@@ -29,12 +29,12 @@ class Game implements EngineListener {
|
|||||||
|
|
||||||
public var type(default, null):GameType;
|
public var type(default, null):GameType;
|
||||||
public var state(default, null):GameState;
|
public var state(default, null):GameState;
|
||||||
|
public var preset(default, null):GamePreset;
|
||||||
public var teams(default, null):Map<TeamId, Team>;
|
public var teams(default, null):Map<TeamId, Team>;
|
||||||
public var config(default, null):Config;
|
public var config(default, null):Config;
|
||||||
public var engine(default, null):Engine;
|
public var engine(default, null):Engine;
|
||||||
|
|
||||||
private var points:Array<SpawnPoint>;
|
private var points:Array<SpawnPoint>;
|
||||||
private var spawners:Map<TeamId, Spawner>;
|
|
||||||
private var deferred:Deferred<GameState>;
|
private var deferred:Deferred<GameState>;
|
||||||
private var stream:Stream<GameState>;
|
private var stream:Stream<GameState>;
|
||||||
|
|
||||||
@@ -45,16 +45,21 @@ class Game implements EngineListener {
|
|||||||
engine.listeners.push(this);
|
engine.listeners.push(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getTeam(teamId:TeamId):Team {
|
||||||
|
return teams[teamId];
|
||||||
|
}
|
||||||
|
|
||||||
public function getPlayer(playerId:PlayerId):Player {
|
public function getPlayer(playerId:PlayerId):Player {
|
||||||
return teams[playerId.team].players[playerId.index];
|
return teams[playerId.team].players[playerId.index];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildTank(playerId:PlayerId, point:SpawnPoint):Tank {
|
private function buildTank(playerId:PlayerId, point:SpawnPoint):Tank {
|
||||||
var spawns:Array<TankSpawn> = teams[playerId.team].config.tanks;
|
var player = getPlayer(playerId);
|
||||||
|
var spawns:Array<TankSpawn> = player.config.tanks;
|
||||||
var spawn:TankSpawn = spawns[Math.floor(Math.random() * spawns.length)];
|
var spawn:TankSpawn = spawns[Math.floor(Math.random() * spawns.length)];
|
||||||
var tankConfig:TankConfig = config.getTank(spawn.type);
|
var tankConfig:TankConfig = config.getTank(spawn.type);
|
||||||
var tank = new Tank(playerId, tankConfig);
|
var tank = new Tank(playerId, tankConfig);
|
||||||
tank.color = playerId.color.zero ? teams[playerId.team].config.color : playerId.color;
|
tank.color = player.config.color.zero ? teams[playerId.team].config.color : player.config.color;
|
||||||
tank.bonus = Math.random() < spawn.bonus;
|
tank.bonus = Math.random() < spawn.bonus;
|
||||||
applyPoint(tank, point);
|
applyPoint(tank, point);
|
||||||
return tank;
|
return tank;
|
||||||
@@ -66,26 +71,25 @@ class Game implements EngineListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function start(state:GameState):Stream<GameState> {
|
public function start(state:GameState):Stream<GameState> {
|
||||||
this.deferred = new Deferred();
|
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
this.preset = config.getPreset(state.presetId);
|
||||||
|
this.deferred = new Deferred();
|
||||||
var level = LevelBundle.get(type, config, state.level);
|
var level = LevelBundle.get(type, config, state.level);
|
||||||
points = level.points != null ? level.points : config.points;
|
points = level.points != null ? level.points : config.points;
|
||||||
engine.map.setData(level.data);
|
engine.map.setData(level.data);
|
||||||
teams = new Map<TeamId, Team>();
|
teams = new Map<TeamId, Team>();
|
||||||
spawners = new Map<TeamId, Spawner>();
|
|
||||||
var humanControlIndex = 0;
|
var humanControlIndex = 0;
|
||||||
for (teamConfig in config.teams) {
|
for (teamConfig in preset.teams) {
|
||||||
var team = new Team(teamConfig);
|
var teamPoints = points.filter(function(p:SpawnPoint) return p.team == teamConfig.id);
|
||||||
for (playerState in state.teams[team.id].players) {
|
var team:Team = new Team(teamConfig, teamPoints);
|
||||||
var player = new Player(playerState.id);
|
teams[team.id] = team;
|
||||||
team.players[player.id.index] = player;
|
for (player in team.players.iterator()) {
|
||||||
teams[team.id] = team;
|
if (player.config.control != null) {
|
||||||
if (player.id.type != null) {
|
var control = switch (player.config.control) {
|
||||||
var control = switch (player.id.type) {
|
|
||||||
case Control.HUMAN: new HumanControl(player.id, humanControlIndex++);
|
case Control.HUMAN: new HumanControl(player.id, humanControlIndex++);
|
||||||
case Control.BOT: new BotControl(player.id);
|
case Control.BOT: new BotControl(player.id);
|
||||||
case Control.NONE: null;
|
case Control.NONE: null;
|
||||||
case _: throw 'Unsupported control type: "${player.id.type}"';
|
case _: throw 'Unsupported control type: "${player.config.control}"';
|
||||||
}
|
}
|
||||||
L.d(TAG, 'control(${player.id} - ${control})');
|
L.d(TAG, 'control(${player.id} - ${control})');
|
||||||
if (control != null) {
|
if (control != null) {
|
||||||
@@ -94,17 +98,16 @@ class Game implements EngineListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var teamPoints = points.filter(function(p:SpawnPoint) return p.team == team.id);
|
team.spawner.runner = spawn;
|
||||||
spawners[team.id] = new Spawner(team.config, teamPoints, spawn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (team in teams) {
|
for (team in teams.iterator()) {
|
||||||
for (player in team.players) {
|
for (player in team.players.iterator()) {
|
||||||
if (trySpawn(player.id)) {
|
if (team.trySpawn(player.id)) {
|
||||||
spawners[team.id].push(player.id);
|
team.spawner.push(player.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var eaglePoint = spawners[team.id].getPoint('eagle');
|
var eaglePoint = team.spawner.getPoint('eagle');
|
||||||
if (eaglePoint != null) {
|
if (eaglePoint != null) {
|
||||||
var eagle = new Eagle(team.id);
|
var eagle = new Eagle(team.id);
|
||||||
applyPoint(eagle, eaglePoint);
|
applyPoint(eagle, eaglePoint);
|
||||||
@@ -117,15 +120,15 @@ class Game implements EngineListener {
|
|||||||
|
|
||||||
private function spawn(task:SpawnTask):Void {
|
private function spawn(task:SpawnTask):Void {
|
||||||
L.d(TAG, 'spawn(${task}');
|
L.d(TAG, 'spawn(${task}');
|
||||||
getPlayer(task.playerId).tankId = 0;
|
var team = getTeam(task.playerId.team);
|
||||||
if (trySpawn(task.playerId, true)) {
|
var player = getPlayer(task.playerId);
|
||||||
|
player.tankId = 0;
|
||||||
|
if (getTeam(task.playerId.team).trySpawn(task.playerId, true)) {
|
||||||
var tank = buildTank(task.playerId, task.point);
|
var tank = buildTank(task.playerId, task.point);
|
||||||
var player:Player = getPlayer(task.playerId);
|
|
||||||
player.tankId = tank.id;
|
player.tankId = tank.id;
|
||||||
Timer.delay(function() engine.spawn(tank), 1500);
|
Timer.delay(function() engine.spawn(tank), 1500);
|
||||||
} else if (!isTeamAlive(task.playerId.team)) {
|
} else if (!team.isAlive) {
|
||||||
state.teams[task.playerId.team].lose = true;
|
lose(team.id);
|
||||||
complete();
|
|
||||||
}
|
}
|
||||||
deferred.resolve(state);
|
deferred.resolve(state);
|
||||||
}
|
}
|
||||||
@@ -165,71 +168,43 @@ class Game implements EngineListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
public function onDestroy(entity:EntityType):Void {
|
||||||
switch (entity) {
|
switch (entity) {
|
||||||
case EntityType.TANK(tank):
|
case EntityType.TANK(tank):
|
||||||
getPlayer(tank.playerId).control.stop();
|
var team = getTeam(tank.playerId.team);
|
||||||
getPlayer(tank.playerId).tankId = 0; //ToDo: ?
|
var player = getPlayer(tank.playerId);
|
||||||
var respawn:Bool = trySpawn(tank.playerId);
|
player.control.stop();
|
||||||
|
player.tankId = 0; //ToDo: ?
|
||||||
|
var respawn:Bool = team.trySpawn(player.id);
|
||||||
if (respawn) {
|
if (respawn) {
|
||||||
spawners[tank.playerId.team].push(tank.playerId);
|
team.spawner.push(player.id);
|
||||||
}
|
}
|
||||||
if (!isTeamAlive(tank.playerId.team)) {
|
if (!team.isAlive) {
|
||||||
state.teams[tank.playerId.team].lose = true;
|
lose(team.id);
|
||||||
complete();
|
|
||||||
}
|
}
|
||||||
if (tank.bonus) spawnBonus();
|
if (tank.bonus) spawnBonus();
|
||||||
deferred.resolve(state);
|
deferred.resolve(state);
|
||||||
case EntityType.EAGLE(eagle):
|
case EntityType.EAGLE(eagle):
|
||||||
state.teams[eagle.team].lose = true;
|
lose(eagle.team);
|
||||||
complete();
|
|
||||||
deferred.resolve(state);
|
deferred.resolve(state);
|
||||||
case x:
|
case x:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function lose(teamId:TeamId):Void {
|
||||||
|
state.loser = teamId;
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
public function onAction(tankId:Int, action:TankAction):Void {
|
public function onAction(tankId:Int, action:TankAction):Void {
|
||||||
engine.action(tankId, action);
|
engine.action(tankId, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function next():Option<GameState> {
|
public function next():Option<GameState> {
|
||||||
return Option.None;
|
var level = state.level + 1;
|
||||||
|
state.level++;
|
||||||
|
if (level >= config.game.levels) level = 0;
|
||||||
|
return Option.Some(new GameState(state.type, preset.id, level));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function dispose():Void {
|
public function dispose():Void {
|
||||||
@@ -249,7 +224,7 @@ class Game implements EngineListener {
|
|||||||
private function applyBonus(tank:Tank, bonus:Bonus):Void {
|
private function applyBonus(tank:Tank, bonus:Bonus):Void {
|
||||||
switch (bonus.bonusType) {
|
switch (bonus.bonusType) {
|
||||||
case 'life':
|
case 'life':
|
||||||
state.teams[tank.playerId.team].players[tank.playerId.index].life++;
|
getPlayer(tank.playerId).life++;
|
||||||
case 'star':
|
case 'star':
|
||||||
if (tank.config.upgrade != null) {
|
if (tank.config.upgrade != null) {
|
||||||
tank.config = config.getTank(tank.config.upgrade);
|
tank.config = config.getTank(tank.config.upgrade);
|
||||||
|
|||||||
@@ -3,26 +3,16 @@ package ru.m.tankz.game;
|
|||||||
import ru.m.tankz.Type;
|
import ru.m.tankz.Type;
|
||||||
|
|
||||||
|
|
||||||
typedef PlayerState = {
|
|
||||||
var id:PlayerId;
|
|
||||||
var life:Int;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef TeamState = {
|
|
||||||
var players:Map<Int, PlayerState>;
|
|
||||||
var life:Int;
|
|
||||||
var lose:Bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
class GameState {
|
class GameState {
|
||||||
public var type:GameType;
|
public var type:GameType;
|
||||||
public var mode:GameMode;
|
|
||||||
public var level:Int;
|
public var level:Int;
|
||||||
public var teams:Map<TeamId, TeamState>;
|
public var presetId:PresetId;
|
||||||
|
public var loser:TeamId;
|
||||||
|
|
||||||
public function new() {
|
public function new(type:GameType, presetId:PresetId, level:Int = 0) {
|
||||||
type = null;
|
this.type = type;
|
||||||
level = -1;
|
this.presetId = presetId;
|
||||||
teams = new Map();
|
this.level = level;
|
||||||
|
this.loser = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,23 @@
|
|||||||
package ru.m.tankz.game;
|
package ru.m.tankz.game;
|
||||||
|
|
||||||
|
import ru.m.tankz.config.Config;
|
||||||
import ru.m.tankz.control.Control;
|
import ru.m.tankz.control.Control;
|
||||||
import ru.m.tankz.Type;
|
import ru.m.tankz.Type;
|
||||||
|
|
||||||
|
|
||||||
class Player {
|
class Player {
|
||||||
|
|
||||||
|
public var config(default, null):PlayerConfig;
|
||||||
public var id(default, null):PlayerId;
|
public var id(default, null):PlayerId;
|
||||||
public var tankId(default, set):Int;
|
public var tankId(default, set):Int;
|
||||||
public var control(default, set):Control;
|
public var control(default, set):Control;
|
||||||
|
public var life(default, default):Int;
|
||||||
|
|
||||||
public function new(id:PlayerId, control:Control=null) {
|
public function new(teamId:TeamId, config:PlayerConfig) {
|
||||||
this.id = id;
|
this.config = config;
|
||||||
this.control = control;
|
this.id = {team:teamId, index:config.index};
|
||||||
|
this.control = null;
|
||||||
|
this.life = config.life;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set_tankId(value:Int):Int {
|
public function set_tankId(value:Int):Int {
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ typedef SpawnTask = {
|
|||||||
class Spawner {
|
class Spawner {
|
||||||
|
|
||||||
public var active(get, never):Bool;
|
public var active(get, never):Bool;
|
||||||
|
public var runner(default, default):SpawnTask -> Void;
|
||||||
|
|
||||||
private var config:TeamConfig;
|
private var config:TeamConfig;
|
||||||
private var points:Array<SpawnPoint>;
|
private var points:Array<SpawnPoint>;
|
||||||
private var runner:SpawnTask -> Void;
|
|
||||||
private var queue:Array<SpawnTask>;
|
private var queue:Array<SpawnTask>;
|
||||||
private var timer:Timer;
|
private var timer:Timer;
|
||||||
|
|
||||||
@@ -24,10 +24,10 @@ class Spawner {
|
|||||||
private var anyPoints:Array<SpawnPoint>;
|
private var anyPoints:Array<SpawnPoint>;
|
||||||
private var index:Int;
|
private var index:Int;
|
||||||
|
|
||||||
public function new(config:TeamConfig, points:Array<SpawnPoint>, runner:SpawnTask -> Void) {
|
public function new(config:TeamConfig, points:Array<SpawnPoint>) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.points = points;
|
this.points = points;
|
||||||
this.runner = runner;
|
this.runner = null;
|
||||||
queue = [];
|
queue = [];
|
||||||
indexedPoints = new Map();
|
indexedPoints = new Map();
|
||||||
anyPoints = [];
|
anyPoints = [];
|
||||||
|
|||||||
@@ -1,21 +1,61 @@
|
|||||||
package ru.m.tankz.game;
|
package ru.m.tankz.game;
|
||||||
|
|
||||||
import ru.m.tankz.config.Config;
|
|
||||||
import ru.m.tankz.game.Player;
|
|
||||||
import ru.m.tankz.Type;
|
import ru.m.tankz.Type;
|
||||||
|
import ru.m.tankz.config.Config;
|
||||||
|
|
||||||
|
|
||||||
class Team {
|
class Team {
|
||||||
|
|
||||||
public var id(default, null):TeamId;
|
public var id(default, null):TeamId;
|
||||||
public var config(default, null):TeamConfig;
|
public var config(default, null):TeamConfig;
|
||||||
|
public var spawner(default, null):Spawner;
|
||||||
public var players(default, null):Map<Int, Player>;
|
public var players(default, null):Map<Int, Player>;
|
||||||
|
public var life(default, default):Int;
|
||||||
|
public var isAlive(get, null):Bool;
|
||||||
|
|
||||||
private static var i:Int = 0;
|
public function new(config:TeamConfig, points:Array<SpawnPoint>) {
|
||||||
|
|
||||||
public function new(config:TeamConfig) {
|
|
||||||
this.id = config.id;
|
this.id = config.id;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.players = new Map();
|
this.players = new Map();
|
||||||
|
for (playerConfig in config.players) {
|
||||||
|
this.players[playerConfig.index] = new Player(id, playerConfig);
|
||||||
|
}
|
||||||
|
this.life = config.life;
|
||||||
|
this.spawner = new Spawner(config, points);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function trySpawn(player:PlayerId, spawn:Bool = false):Bool {
|
||||||
|
var player:Player = players[player.index];
|
||||||
|
var result = false;
|
||||||
|
if (player.life > -1) {
|
||||||
|
if (player.life > 0) {
|
||||||
|
if (spawn) player.life--;
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
} else if (life > -1) {
|
||||||
|
if (life > 0) {
|
||||||
|
if (spawn) life--;
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToDo: eagle state?
|
||||||
|
private function get_isAlive():Bool {
|
||||||
|
var life:Int = Lambda.fold(players, function(p:Player, t:Int) return t + p.life, life);
|
||||||
|
if (life > 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
for (player in players) {
|
||||||
|
if (player.tankId > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (spawner.active) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user