[common] added PlayerState

This commit is contained in:
2018-02-20 17:23:53 +03:00
parent 5b04242aab
commit 2e856c1256
16 changed files with 135 additions and 126 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "tankz", "name": "tankz",
"version": "0.7.0", "version": "0.7.1",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"ansi-colors": "^1.0.1", "ansi-colors": "^1.0.1",

View File

@@ -69,7 +69,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand
} }
private function stateString(game:Game):String { private function stateString(game:Game):String {
if (game.state == null) { if (game == null) {
return ''; return '';
} }
var result:Array<String> = []; var result:Array<String> = [];
@@ -77,12 +77,12 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand
for (team in game.teams) { for (team in game.teams) {
if (game.state.loser == team.id) { if (game.state.loser == team.id) {
result.push('${team.id}: LOSE'); result.push('${team.id}: LOSE');
} else if (team.life > -1) { } else if (team.life > 0) {
result.push('${team.id}: ${team.life}'); result.push('${team.id}: ${team.life}');
} else { } else {
for (player in team.players) { for (player in team.players) {
if (player.life > -1) { if (player.state.life > 0) {
result.push('${player.id.team}${player.id.index}: ${player.life}'); result.push('${player.id.team}${player.id.index}: ${player.state.life}');
} }
} }
} }

View File

@@ -96,6 +96,7 @@ class Render extends SpriteView implements EngineListener {
clearLayer(entryLayer); clearLayer(entryLayer);
clearLayer(groundLayer); clearLayer(groundLayer);
clearLayer(upLayer); clearLayer(upLayer);
clearLayer(upperLayer);
} }
public function onSpawn(entity:EntityType):Void { public function onSpawn(entity:EntityType):Void {

View File

@@ -21,25 +21,26 @@ player:
human: &human human: &human
control: human control: human
life: 3 life: 3
protect: 5
tanks: tanks:
- {type: human0, rate: 1, protect: 5} - {type: human0, rate: 1}
bot: &bot bot: &bot
control: bot control: bot
color: 0xFFFFFF color: 0xFFFFFF
life: -1 bonus: 0.25
tanks: tanks:
- {type: bot0, rate: 0.25, bonus: 0.25} - {type: bot0, rate: 0.25}
- {type: bot1, rate: 0.25, bonus: 0.25} - {type: bot1, rate: 0.25}
- {type: bot2, rate: 0.25, bonus: 0.25} - {type: bot2, rate: 0.25}
- {type: bot3, rate: 0.25, bonus: 0.25} - {type: bot3, rate: 0.25}
presets: presets:
# player1
- id: player1 - id: player1
teams: teams:
- id: human - id: human
life: -1
players: players:
- {<<: *human, index: 0, color: 0xF5C040, life: 3} - {<<: *human, index: 0, color: 0xFFFF00}
- id: bot - id: bot
spawnInterval: 3000 spawnInterval: 3000
life: 20 life: 20
@@ -48,14 +49,13 @@ presets:
- {<<: *bot, index: 1} - {<<: *bot, index: 1}
- {<<: *bot, index: 2} - {<<: *bot, index: 2}
- {<<: *bot, index: 3} - {<<: *bot, index: 3}
# player2
- id: player2 - id: player2
teams: teams:
- id: human - id: human
life: -1
players: players:
- {<<: *human, index: 0, color: 0xF5C040, life: 3} - {<<: *human, index: 0, color: 0xFFFF00}
- {<<: *human, index: 1, color: 0x15C040, life: 3} - {<<: *human, index: 1, color: 0x15C040}
- id: bot - id: bot
spawnInterval: 3000 spawnInterval: 3000
life: 20 life: 20
@@ -117,6 +117,7 @@ tanks:
- type: human3 - type: human3
upgrade: human3 upgrade: human3
downgrade: human2
width: 42 width: 42
height: 38 height: 38
speed: 2.9 speed: 2.9
@@ -125,7 +126,6 @@ tanks:
speed: 9.0 speed: 9.0
piercing: 3 piercing: 3
bullets: 2 bullets: 2
hits: 1
skin: pd skin: pd
- type: bot0 - type: bot0

View File

@@ -17,34 +17,42 @@ bricks:
- {type: armor, index: 4, layer: 2, armor: 2} - {type: armor, index: 4, layer: 2, armor: 2}
- {type: brick, index: 5, layer: 2, armor: 1} - {type: brick, index: 5, layer: 2, armor: 1}
team: player:
radiant: &radiant base: &player
id: radiant
color: 0xff4422
life: 20
dire: &dire
id: dire
color: 0x2244ff
life: 20
player: &player
life: -1
control: bot control: bot
protect: 3
tanks: tanks:
- {type: slow, rate: 0.5, protect: 3, bonus: 0} - {type: slow, rate: 0.5}
- {type: fast, rate: 0.5, protect: 3, bonus: 0} - {type: fast, rate: 0.5}
human1: &human1
human1: &human1
<<: *player <<: *player
control: human control: human
color: 0xf055a0 color: 0xf055a0
human2: &human2
human2: &human2
<<: *player <<: *player
control: human control: human
color: 0xa055f0 color: 0xa055f0
team:
base: &team
life: 20
players:
- {<<: *player, index: 0}
- {<<: *player, index: 1}
- {<<: *player, index: 2}
- {<<: *player, index: 3}
- {<<: *player, index: 4}
radiant: &radiant
id: radiant
color: 0xff4422
<<: *team
dire: &dire
id: dire
color: 0x2244ff
<<: *team
presets: presets:
# player1
- id: player1 - id: player1
teams: teams:
- <<: *radiant - <<: *radiant
@@ -55,12 +63,7 @@ presets:
- {<<: *player, index: 3} - {<<: *player, index: 3}
- {<<: *player, index: 4} - {<<: *player, index: 4}
- <<: *dire - <<: *dire
players: # player2_coop
- {<<: *player, index: 0}
- {<<: *player, index: 1}
- {<<: *player, index: 2}
- {<<: *player, index: 3}
- {<<: *player, index: 4}
- id: player2_coop - id: player2_coop
teams: teams:
- <<: *radiant - <<: *radiant
@@ -71,12 +74,7 @@ presets:
- {<<: *player, index: 3} - {<<: *player, index: 3}
- {<<: *player, index: 4} - {<<: *player, index: 4}
- <<: *dire - <<: *dire
players: # player2_vs
- {<<: *player, index: 0}
- {<<: *player, index: 1}
- {<<: *player, index: 2}
- {<<: *player, index: 3}
- {<<: *player, index: 4}
- id: player2_vs - id: player2_vs
teams: teams:
- <<: *radiant - <<: *radiant

View File

@@ -49,6 +49,7 @@ typedef TankConfig = {
var hits:Int; var hits:Int;
var skin:String; var skin:String;
@:optinal var upgrade:TankType; @:optinal var upgrade:TankType;
@:optinal var downgrade:TankType;
} }
typedef BonusConfig = { typedef BonusConfig = {
@@ -59,14 +60,14 @@ typedef BonusConfig = {
typedef TankSpawn = { typedef TankSpawn = {
var type:TankType; var type:TankType;
var rate:Float; var rate:Float;
@:optional var bonus:Float;
@:optional var protect:Float;
} }
typedef PlayerConfig = { typedef PlayerConfig = {
var index:Int; var index:Int;
var control:ControlType; var control:ControlType;
var tanks:Array<TankSpawn>; var tanks:Array<TankSpawn>;
@:optional var bonus:Float;
@:optional var protect:Float;
@:optional var life:Int; @:optional var life:Int;
@:optional var color:Color; @:optional var color:Color;
} }

View File

@@ -26,7 +26,6 @@ class Tank extends MobileEntity {
this.freezing = new Modificator(); this.freezing = new Modificator();
this.playerId = playerId; this.playerId = playerId;
this.config = config; this.config = config;
this.hits = config.hits;
this.layer = 1; this.layer = 1;
} }
@@ -36,6 +35,7 @@ class Tank extends MobileEntity {
rect.direction = d; rect.direction = d;
speed = value.speed; speed = value.speed;
config = value; config = value;
hits = config.hits;
return value; return value;
} }

View File

@@ -51,7 +51,9 @@ class CollisionProcessor implements EngineListener {
// Nothing // Nothing
} else { } else {
if (!tank.protect.active) { if (!tank.protect.active) {
if (tank.hits > 0) { if (tank.config.downgrade != null) {
tank.config = engine.config.getTank(tank.config.downgrade);
} else if (tank.hits > 0) {
tank.hits--; tank.hits--;
engine.change(tank, EntityChange.HIT); engine.change(tank, EntityChange.HIT);
} else { } else {

View File

@@ -55,17 +55,22 @@ class Game implements EngineListener {
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(task:SpawnTask):Tank {
var player = getPlayer(playerId); var player = getPlayer(task.playerId);
var tankType:TankType = if (task.tankType != null) {
task.tankType;
} else {
var spawns:Array<TankSpawn> = player.config.tanks; 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); spawn.type;
var tank = new Tank(playerId, tankConfig); }
tank.color = player.config.color.zero ? teams[playerId.team].config.color : player.config.color; var tankConfig:TankConfig = config.getTank(tankType);
tank.bonus = Math.random() < spawn.bonus; var tank = new Tank(task.playerId, tankConfig);
applyPoint(tank, point); tank.color = player.config.color.zero ? teams[task.playerId.team].config.color : player.config.color;
if (spawn.protect > 0) { tank.bonus = Math.random() < player.config.bonus;
tank.protect.on(spawn.protect); applyPoint(tank, task.point);
if (player.config.protect > 0) {
tank.protect.on(player.config.protect);
} }
return tank; return tank;
} }
@@ -86,19 +91,9 @@ class Game implements EngineListener {
var humanControlIndex = 0; var humanControlIndex = 0;
for (teamConfig in preset.teams) { for (teamConfig in preset.teams) {
var teamPoints = points.filter(function(p:SpawnPoint) return p.team == teamConfig.id); var teamPoints = points.filter(function(p:SpawnPoint) return p.team == teamConfig.id);
var team:Team = new Team(teamConfig, teamPoints); var team:Team = new Team(teamConfig, teamPoints, save);
teams[team.id] = team; teams[team.id] = team;
for (player in team.players.iterator()) { for (player in team.players.iterator()) {
var playerSave:PlayerSave = save.getPlayer(player.id);
if (playerSave != null) {
player.life = playerSave.life;
if (playerSave.tank != null) {
player.config.tanks = [{
type: playerSave.tank,
rate: 1,
}];
}
}
if (player.config.control != null) { if (player.config.control != null) {
var control = switch (player.config.control) { var control = switch (player.config.control) {
case Control.HUMAN: new HumanControl(player.id, humanControlIndex++); case Control.HUMAN: new HumanControl(player.id, humanControlIndex++);
@@ -119,7 +114,7 @@ class Game implements EngineListener {
for (team in teams.iterator()) { for (team in teams.iterator()) {
for (player in team.players.iterator()) { for (player in team.players.iterator()) {
if (team.trySpawn(player.id)) { if (team.trySpawn(player.id)) {
team.spawner.push(player.id); team.spawner.push(player.id, player.state.tank);
} }
} }
var eaglePoint = team.spawner.getPoint('eagle'); var eaglePoint = team.spawner.getPoint('eagle');
@@ -140,8 +135,9 @@ class Game implements EngineListener {
var player = getPlayer(task.playerId); var player = getPlayer(task.playerId);
player.tankId = 0; player.tankId = 0;
if (getTeam(task.playerId.team).trySpawn(task.playerId, true)) { if (getTeam(task.playerId.team).trySpawn(task.playerId, true)) {
var tank = buildTank(task.playerId, task.point); var tank = buildTank(task);
player.tankId = tank.id; player.tankId = tank.id;
player.state.tank = tank.config.type;
engine.spawn(tank); engine.spawn(tank);
} else if (!team.isAlive) { } else if (!team.isAlive) {
lose(team.id); lose(team.id);
@@ -257,7 +253,7 @@ class Game implements EngineListener {
private function applyBonus(tank:Tank, bonus:Bonus):Void { private function applyBonus(tank:Tank, bonus:Bonus):Void {
switch (bonus.config.type) { switch (bonus.config.type) {
case 'life': case 'life':
getPlayer(tank.playerId).life++; getPlayer(tank.playerId).state.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);
@@ -291,23 +287,14 @@ class Game implements EngineListener {
} }
public function save():GameSave { public function save():GameSave {
var players:Array<PlayerSave> = []; var save:GameSave = new GameSave(state);
for (team in teams) { for (team in teams) {
for (player in team.players) { for (player in team.players) {
if (player.config.control == Control.HUMAN) { if (player.config.control == Control.HUMAN) {
var tank:Tank = EntityTypeResolver.as(engine.entities[player.tankId], Tank); save.addPlayerState(player.id, player.state);
players.push({
id: player.id,
life: player.life + (player.tankId > 0 ? 1 : 0),
tank: tank != null ? tank.config.type : null
});
} }
} }
} }
return new GameSave({ return save;
type: state.type,
presetId: state.presetId,
level: state.level
}, players);
} }
} }

View File

@@ -1,42 +1,46 @@
package ru.m.tankz.game; package ru.m.tankz.game;
import ru.m.tankz.game.Player;
import ru.m.tankz.Type;
import yaml.Parser; import yaml.Parser;
import yaml.Renderer; import yaml.Renderer;
import yaml.Yaml; import yaml.Yaml;
import ru.m.tankz.Type;
typedef PlayerSave = { typedef PlayerSave = {
var id:PlayerId; var id:PlayerId;
var tank:TankType; var state:PlayerState;
var life:Int;
} }
class GameSave { class GameSave {
public var state:GameState; public var state:GameState;
public var players:Array<PlayerSave>; public var players:Array<PlayerSave>;
public function new(state:GameState, ?players:Array<PlayerSave>) { public function new(state:GameState, ?players:Array<PlayerSave>) {
this.state = state; this.state = {
type: state.type,
presetId: state.presetId,
level: state.level,
};
this.players = players != null ? players : []; this.players = players != null ? players : [];
} }
public function getPlayer(id:PlayerId):PlayerSave { public function addPlayerState(id:PlayerId, state:PlayerState):Void {
players.push({id: id, state: state});
}
public function getPlayerState(id:PlayerId):PlayerState {
for (player in players) { for (player in players) {
if (player.id.team == id.team && player.id.index == id.index) { if (player.id.team == id.team && player.id.index == id.index) {
return player; return player.state;
} }
} }
return null; return null;
} }
public function toYaml():String { public function toYaml():String {
return Yaml.render({ return Yaml.render({state: state, players: players}, Renderer.options().setFlowLevel(0));
state: state,
players: players,
}, Renderer.options().setFlowLevel(0));
} }
public static function fromYaml(value:String):GameSave { public static function fromYaml(value:String):GameSave {

View File

@@ -5,20 +5,29 @@ import ru.m.tankz.control.Control;
import ru.m.tankz.Type; import ru.m.tankz.Type;
class Player { typedef PlayerState = {
var tank:TankType;
var life:Int;
var score:Int;
}
class Player {
public var config(default, null):PlayerConfig; 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 var isAlive(get, null):Bool; 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) {
this.config = config; this.config = config;
this.id = {team:teamId, index:config.index}; this.id = {team:teamId, index:config.index};
this.control = null; this.control = null;
this.life = config.life; this.state = {
life: config.life,
tank: null,
score: 0,
}
} }
private function set_tankId(value:Int):Int { private function set_tankId(value:Int):Int {
@@ -39,6 +48,6 @@ class Player {
} }
private function get_isAlive():Bool { private function get_isAlive():Bool {
return tankId > 0 || life > 0; return tankId > 0 || state.life > 0;
} }
} }

View File

@@ -8,6 +8,7 @@ import ru.m.tankz.Type;
typedef SpawnTask = { typedef SpawnTask = {
var point:SpawnPoint; var point:SpawnPoint;
var playerId:PlayerId; var playerId:PlayerId;
var tankType:TankType;
} }
class Spawner { class Spawner {
@@ -51,7 +52,7 @@ class Spawner {
return null; return null;
} }
public function push(playerId:PlayerId):Void { public function push(playerId:PlayerId, ?tankType:TankType):Void {
var point:SpawnPoint = null; var point:SpawnPoint = null;
if (indexedPoints.exists(playerId.index)) { if (indexedPoints.exists(playerId.index)) {
point = indexedPoints.get(playerId.index); point = indexedPoints.get(playerId.index);
@@ -60,7 +61,7 @@ class Spawner {
if (index >= anyPoints.length) index = 0; if (index >= anyPoints.length) index = 0;
} }
if (point != null) { if (point != null) {
queue.push({playerId:playerId, point:point}); queue.push({playerId:playerId, point:point, tankType:tankType});
run(); run();
} }
} }

View File

@@ -14,12 +14,15 @@ class Team {
public var isAlive(get, null):Bool; public var isAlive(get, null):Bool;
public var eagleId(default, default):Int; public var eagleId(default, default):Int;
public function new(config:TeamConfig, points:Array<SpawnPoint>) { public function new(config:TeamConfig, points:Array<SpawnPoint>, ?save:GameSave) {
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) { for (playerConfig in config.players) {
this.players[playerConfig.index] = new Player(id, playerConfig); var player:Player = new Player(id, playerConfig);
var state = save.getPlayerState(player.id);
if (state != null) player.state = state;
this.players[playerConfig.index] = player;
} }
this.life = config.life; this.life = config.life;
this.spawner = new Spawner(config, points); this.spawner = new Spawner(config, points);
@@ -28,17 +31,13 @@ class Team {
public function trySpawn(playerId:PlayerId, spawn:Bool = false):Bool { public function trySpawn(playerId:PlayerId, spawn:Bool = false):Bool {
var player:Player = players[playerId.index]; var player:Player = players[playerId.index];
var result = false; var result = false;
if (player.life > -1) { if (player.state.life > 0) {
if (player.life > 0) { if (spawn) player.state.life--;
if (spawn) player.life--;
result = true; result = true;
} } else if (life > 0) {
} else if (life > -1) {
if (life > 0) {
if (spawn) life--; if (spawn) life--;
result = true; result = true;
} }
}
return result; return result;
} }

View File

@@ -1,5 +1,9 @@
package ru.m.tankz.editor; package ru.m.tankz.editor;
import ru.m.tankz.bundle.LevelBundle;
import ru.m.tankz.bundle.ILevelBundle;
import ru.m.tankz.bundle.ConfigBundle;
import ru.m.tankz.bundle.IConfigBundle;
import flash.text.Font; import flash.text.Font;
import haxework.gui.ButtonView; import haxework.gui.ButtonView;
import haxework.gui.frame.FrameSwitcher; import haxework.gui.frame.FrameSwitcher;
@@ -54,6 +58,9 @@ class Editor {
Root.bind(view); Root.bind(view);
view.content.stage.stageFocusRect = false; view.content.stage.stageFocusRect = false;
Provider.setFactory(IConfigBundle, ConfigBundle);
Provider.setFactory(ILevelBundle, LevelBundle);
view.switcher.change(LevelFrame.ID); view.switcher.change(LevelFrame.ID);
} }

View File

@@ -4,7 +4,7 @@ pWidth: 100
pHeight: 100 pHeight: 100
skin: skin:
$type: haxework.gui.skin.BitmapSkin $type: haxework.gui.skin.BitmapSkin
image: "@asset:image:resources/images/background.png" image: "@asset:image:resources/image/ui/background.png"
fillType: REPEAT fillType: REPEAT
views: views:
# Tabs # Tabs

View File

@@ -1,5 +1,7 @@
package ru.m.tankz.editor.frame; package ru.m.tankz.editor.frame;
import ru.m.tankz.util.LevelUtil;
import ru.m.tankz.bundle.IConfigBundle;
import haxework.gui.ButtonView; import haxework.gui.ButtonView;
import haxework.gui.LabelView; import haxework.gui.LabelView;
import haxework.gui.list.ListView; import haxework.gui.list.ListView;
@@ -8,8 +10,6 @@ import haxework.gui.VGroupView;
import haxework.gui.ViewBuilder; import haxework.gui.ViewBuilder;
import haxework.provider.Provider; import haxework.provider.Provider;
import ru.m.tankz.config.Config; import ru.m.tankz.config.Config;
import ru.m.tankz.config.ConfigBundle;
import ru.m.tankz.config.LevelBundle;
import ru.m.tankz.editor.FileUtil; import ru.m.tankz.editor.FileUtil;
import ru.m.tankz.editor.level.BrickView; import ru.m.tankz.editor.level.BrickView;
import ru.m.tankz.editor.level.MapEditView; import ru.m.tankz.editor.level.MapEditView;
@@ -73,11 +73,11 @@ class LevelFrame extends VGroupView implements ViewBuilder implements LevelFrame
} }
private function setGameType(type:GameType):Void { private function setGameType(type:GameType):Void {
config = ConfigBundle.get(type); config = Provider.get(IConfigBundle).get(type);
Provider.set(Config, config); Provider.set(Config, config);
mapView.config = config; mapView.config = config;
mapView.data = LevelBundle.empty(config); mapView.data = LevelUtil.empty(config);
brickList.data = config.bricks.filter(function(brick) return brick.index > -1); brickList.data = config.bricks.filter(function(brick) return brick.index > -1);
spawnPointList.data = config.points; spawnPointList.data = config.points;
@@ -96,13 +96,13 @@ class LevelFrame extends VGroupView implements ViewBuilder implements LevelFrame
L.d(TAG, 'OPEN'); L.d(TAG, 'OPEN');
FileUtil.browse().then(function(content:FileContent) { FileUtil.browse().then(function(content:FileContent) {
fileNameLabel.text = content.name; fileNameLabel.text = content.name;
mapView.data = LevelBundle.loads(config, content.content); mapView.data = LevelUtil.loads(config, content.content);
}); });
case 'saveButton': case 'saveButton':
L.d(TAG, 'SAVE'); L.d(TAG, 'SAVE');
FileUtil.save({ FileUtil.save({
name: fileNameLabel.text, name: fileNameLabel.text,
content: LevelBundle.dumps(config, mapView.data), content: LevelUtil.dumps(config, mapView.data),
}); });
case _: case _:
} }