[common] remove GameSave; [client] update @:template macro use

This commit is contained in:
2018-08-09 12:17:41 +03:00
parent a24d610b05
commit 95148a9b0b
30 changed files with 202 additions and 254 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "tankz", "name": "tankz",
"version": "0.7.4", "version": "0.7.5",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"dateformat": "^3.0.3", "dateformat": "^3.0.3",

View File

@@ -13,7 +13,7 @@ import haxework.resources.IResources;
#if flash import haxework.log.JSLogger; #end #if flash import haxework.log.JSLogger; #end
#if debug import haxework.log.SocketLogger; #end #if debug import haxework.log.SocketLogger; #end
@:style("ru/m/tankz/Style.yaml")
class Client { class Client {
private static inline var TAG = 'Tankz'; private static inline var TAG = 'Tankz';
@@ -36,16 +36,16 @@ class Client {
} }
} }
@:template('ru/m/tankz/Client.yaml', 'ru/m/tankz/Style.yaml') @:template class ClientView extends VGroupView {
class ClientView extends VGroupView {
@:view private var switcher(default, null):IFrameSwitcher;
private static inline var TAG = 'Tankz'; private static inline var TAG = 'Tankz';
@:view private var switcher(default, null):IFrameSwitcher;
@:provide var resources:IResources;
public function init():Void { public function init():Void {
var font:Font = Font.enumerateFonts()[0]; var font:Font = Font.enumerateFonts()[0];
Provider.get(IResources).text.put('font', 'Bookman Old Style'); resources.text.put('font', 'Bookman Old Style');
Provider.get(IResources).text.put('version', 'v${Const.VERSION} b${Const.BUILD}'); resources.text.put('version', 'v${Const.VERSION} b${Const.BUILD}');
Provider.set(IFrameSwitcher, switcher); Provider.set(IFrameSwitcher, switcher);
} }

View File

@@ -1,6 +1,6 @@
package ru.m.tankz.control; package ru.m.tankz.control;
import ru.m.tankz.game.Player; import ru.m.tankz.Type;
import ru.m.tankz.bot.BotControl; import ru.m.tankz.bot.BotControl;
@@ -12,12 +12,12 @@ class ClientControlFactory implements IControlFactory {
humanControlIndex = 0; humanControlIndex = 0;
} }
public function build(player:Player):Control { public function build(id:PlayerId, type:ControlType):Control {
return switch (player.config.control) { return switch (type) {
case Control.HUMAN: new HumanControl(player.id, humanControlIndex++); case Control.HUMAN: new HumanControl(id, humanControlIndex++);
case Control.BOT: new BotControl(player.id); case Control.BOT: new BotControl(id);
case Control.NONE: null; case Control.NONE: null;
case _: throw 'Unsupported control type: "${player.config.control}"'; case _: throw 'Unsupported control type: "${type}"';
} }
} }
} }

View File

@@ -1,31 +1,26 @@
package ru.m.tankz.frame; package ru.m.tankz.frame;
import ru.m.tankz.frame.game.DotaGamePanel;
import ru.m.tankz.frame.game.IGamePanel;
import ru.m.tankz.frame.game.ClassicGamePanel;
import ru.m.tankz.preset.DotaGame;
import ru.m.tankz.preset.ClassicGame;
import ru.m.tankz.Type.GameType;
import haxework.gui.View;
import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.network.NetworkGame;
import flash.events.Event; import flash.events.Event;
import haxe.ds.Option; import haxe.ds.Option;
import haxe.Timer; import haxe.Timer;
import haxework.gui.frame.IFrameSwitcher; import haxework.gui.frame.IFrameSwitcher;
import haxework.gui.LabelView;
import haxework.gui.VGroupView; import haxework.gui.VGroupView;
import haxework.provider.Provider; import ru.m.tankz.frame.game.ClassicGamePanel;
import ru.m.tankz.frame.game.DotaGamePanel;
import ru.m.tankz.frame.game.IGamePanel;
import ru.m.tankz.game.Game; import ru.m.tankz.game.Game;
import ru.m.tankz.game.GameSave;
import ru.m.tankz.game.GameState; import ru.m.tankz.game.GameState;
import ru.m.tankz.network.NetworkGame;
import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.preset.ClassicGame;
import ru.m.tankz.preset.DotaGame;
import ru.m.tankz.render.Render; import ru.m.tankz.render.Render;
import ru.m.tankz.sound.SoundManager; import ru.m.tankz.sound.SoundManager;
import ru.m.tankz.storage.SaveStorage; import ru.m.tankz.storage.SaveStorage;
import ru.m.tankz.Type.GameType;
@:template("ru/m/tankz/frame/GameFrame.yaml", "ru/m/tankz/Style.yaml") @:template class GameFrame extends VGroupView {
class GameFrame extends VGroupView {
private static inline var TAG = "GameFrame"; private static inline var TAG = "GameFrame";
@@ -36,9 +31,13 @@ class GameFrame extends VGroupView {
@:view var dotaPanel(default, null):DotaGamePanel; @:view var dotaPanel(default, null):DotaGamePanel;
@:view var classicPanel(default, null):ClassicGamePanel; @:view var classicPanel(default, null):ClassicGamePanel;
var panels:Map<GameType, IGamePanel>; private var panels:Map<GameType, IGamePanel>;
@:provide var network:NetworkManager; @:provide var network:NetworkManager;
@:provide var sound:SoundManager;
@:provide var state:GameState;
@:provide var storage:SaveStorage;
@:provide var switcher:IFrameSwitcher;
private var game:Game; private var game:Game;
private var timer:Timer; private var timer:Timer;
@@ -50,35 +49,36 @@ class GameFrame extends VGroupView {
} }
public function onShow():Void { public function onShow():Void {
start(Provider.get(GameSave)); start(state);
} }
private function connectGame(game: Game) { private function connectGame(game: Game) {
game.engine.connect(render); game.engine.connect(render);
game.engine.connect(Provider.get(SoundManager)); game.engine.connect(sound);
} }
private function start(save:GameSave):Void { private function start(state:GameState):Void {
for (type in panels.keys()) { for (type in panels.keys()) {
panels.get(type).visible = type == save.state.type; panels.get(type).visible = type == state.type;
panels.get(type).inLayout = type == save.state.type; panels.get(type).inLayout = type == state.type;
} }
switch (save.server) { // ToDo: local / network game
case GameServer.LOCAL: switch (1) {
game = new Game(save.state.type); case 1:
game = new Game(state.type);
connectGame(game); connectGame(game);
game.start(save).then(onGameStateChange).endThen(onGameComplete); game.start(state).then(onGameStateChange).endThen(onGameComplete);
timer = new Timer(10); timer = new Timer(10);
timer.run = updateEngine; timer.run = updateEngine;
case GameServer.NETWORK: case 2:
game = new NetworkGame(save.state.type); game = new NetworkGame(state.type);
connectGame(game); connectGame(game);
network.game = cast game; network.game = cast game;
} }
panels.get(save.state.type).game = game; panels.get(state.type).game = game;
content.addEventListener(Event.ENTER_FRAME, redraw); content.addEventListener(Event.ENTER_FRAME, redraw);
render.draw(game.engine); render.draw(game.engine);
Provider.get(SoundManager).play('start'); sound.play('start');
} }
private function stop():Void { private function stop():Void {
@@ -107,12 +107,13 @@ class GameFrame extends VGroupView {
} }
switch (game.next()) { switch (game.next()) {
case Option.Some(s): case Option.Some(s):
var save = game.save(); var state = game.save();
Provider.get(SaveStorage).write(save); this.state = state;
storage.write(state);
stop(); stop();
start(save); start(state);
case Option.None: case Option.None:
Provider.get(IFrameSwitcher).change(StartFrame.ID); switcher.change(StartFrame.ID);
} }
} }

View File

@@ -8,7 +8,7 @@ import haxework.gui.LabelView;
import haxework.gui.list.ListView; import haxework.gui.list.ListView;
import haxework.gui.VGroupView; import haxework.gui.VGroupView;
import haxework.provider.Provider; import haxework.provider.Provider;
import ru.m.tankz.game.GameSave; import ru.m.tankz.game.GameState;
import ru.m.tankz.network.NetworkManager; import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.preset.ClassicGame; import ru.m.tankz.preset.ClassicGame;
import ru.m.tankz.proto.core.GameInfoProto; import ru.m.tankz.proto.core.GameInfoProto;
@@ -16,8 +16,7 @@ import ru.m.tankz.proto.core.GameStateProto;
import ru.m.tankz.proto.core.UserProto; import ru.m.tankz.proto.core.UserProto;
@:template("ru/m/tankz/frame/NetworkFrame.yaml", "ru/m/tankz/Style.yaml") @:template class NetworkFrame extends VGroupView {
class NetworkFrame extends VGroupView {
public static var ID(default, never):String = "network"; public static var ID(default, never):String = "network";
@:view var frameSwitcher(default, null):IFrameSwitcher; @:view var frameSwitcher(default, null):IFrameSwitcher;
@@ -80,7 +79,7 @@ class NetworkFrame extends VGroupView {
userList.data = game.players; userList.data = game.players;
frameSwitcher.change(gameFrame.id); frameSwitcher.change(gameFrame.id);
if (game.state == GameStateProto.STARTED) { if (game.state == GameStateProto.STARTED) {
Provider.set(GameSave, new GameSave({type: ClassicGame.TYPE, presetId: ClassicGame.PLAYER1}, null, GameServer.NETWORK)); Provider.set(GameState, new GameState(ClassicGame.TYPE, ClassicGame.PLAYER1));
mainFrameSwitcher.change(GameFrame.ID); mainFrameSwitcher.change(GameFrame.ID);
} }
} else { } else {

View File

@@ -5,8 +5,7 @@ import haxework.gui.ButtonView;
import haxework.gui.VGroupView; import haxework.gui.VGroupView;
@:template("ru/m/tankz/frame/SettingsFrame.yaml", "ru/m/tankz/Style.yaml") @:template class SettingsFrame extends VGroupView {
class SettingsFrame extends VGroupView {
public static var ID(default, never):String = "settings"; public static var ID(default, never):String = "settings";

View File

@@ -3,16 +3,13 @@ package ru.m.tankz.frame;
import haxework.gui.ButtonView; import haxework.gui.ButtonView;
import haxework.gui.frame.IFrameSwitcher; import haxework.gui.frame.IFrameSwitcher;
import haxework.gui.VGroupView; import haxework.gui.VGroupView;
import haxework.provider.Provider; import ru.m.tankz.game.GameState;
import ru.m.tankz.preset.ClassicGame; import ru.m.tankz.preset.ClassicGame;
import ru.m.tankz.preset.DotaGame; import ru.m.tankz.preset.DotaGame;
import ru.m.tankz.game.GameSave;
import ru.m.tankz.storage.SaveStorage; import ru.m.tankz.storage.SaveStorage;
import ru.m.tankz.Type; import ru.m.tankz.Type;
@:template class StartFrame extends VGroupView {
@:template("ru/m/tankz/frame/StartFrame.yaml", "ru/m/tankz/Style.yaml")
class StartFrame extends VGroupView {
public static var ID(default, never):String = "start"; public static var ID(default, never):String = "start";
@@ -22,6 +19,7 @@ class StartFrame extends VGroupView {
@:view var settings(default, null):ButtonView; @:view var settings(default, null):ButtonView;
@:provide var frameSwitcher:IFrameSwitcher; @:provide var frameSwitcher:IFrameSwitcher;
@:provide var state:GameState;
@:provide var storage:SaveStorage; @:provide var storage:SaveStorage;
public function init():Void { public function init():Void {
@@ -45,7 +43,7 @@ class StartFrame extends VGroupView {
} }
private function startGame(type:GameType, presetId:PresetId):Void { private function startGame(type:GameType, presetId:PresetId):Void {
Provider.set(GameSave, new GameSave({type: type, presetId: presetId})); state = new GameState(type, presetId);
frameSwitcher.change(StartGameFrame.ID); frameSwitcher.change(StartGameFrame.ID);
} }
} }

View File

@@ -1,26 +1,26 @@
package ru.m.tankz.frame; package ru.m.tankz.frame;
import ru.m.tankz.storage.SaveStorage;
import haxework.gui.frame.IFrameSwitcher; import haxework.gui.frame.IFrameSwitcher;
import haxework.gui.list.ListView; import haxework.gui.list.ListView;
import haxework.gui.VGroupView; import haxework.gui.VGroupView;
import haxework.provider.Provider; import haxework.provider.Provider;
import ru.m.tankz.bundle.IConfigBundle; import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.config.Config; import ru.m.tankz.config.Config;
import ru.m.tankz.control.Control;
import ru.m.tankz.frame.level.PresetsView; import ru.m.tankz.frame.level.PresetsView;
import ru.m.tankz.game.GameSave; import ru.m.tankz.game.GameState;
import ru.m.tankz.storage.SaveStorage;
import ru.m.tankz.Type; import ru.m.tankz.Type;
@:template("ru/m/tankz/frame/StartGameFrame.yaml", "ru/m/tankz/Style.yaml") @:template class StartGameFrame extends VGroupView {
class StartGameFrame extends VGroupView {
public static inline var ID = "level"; public static inline var ID = "level";
@:view var presets(default, null):PresetsView; @:view var presets(default, null):PresetsView;
@:view var players(default, null):ListView<PlayerConfig>; @:view var players(default, null):ListView<PlayerId>;
@:view var levels(default, null):ListView<Int>; @:view var levels(default, null):ListView<Int>;
@:provide var save:GameSave; @:provide var state:GameState;
@:provide var storage:SaveStorage; @:provide var storage:SaveStorage;
public var gameType(default, set):GameType; public var gameType(default, set):GameType;
@@ -43,7 +43,7 @@ class StartGameFrame extends VGroupView {
presetId = null; presetId = null;
presetId = config.presets[0].id; presetId = config.presets[0].id;
var save:GameSave = storage.read(gameType); var save:GameState = storage.read(gameType);
// ToDo: start save button // ToDo: start save button
} }
return gameType; return gameType;
@@ -53,13 +53,19 @@ class StartGameFrame extends VGroupView {
if (presetId != value) { if (presetId != value) {
presetId = value; presetId = value;
presets.selected = presetId; presets.selected = presetId;
save.state.presetId = presetId; state = new GameState(gameType, presetId);
if (presetId != null) { if (presetId != null) {
preset = config.getPreset(presetId); preset = config.getPreset(presetId);
var players:Array<PlayerConfig> = []; var players:Array<PlayerId> = [];
for (team in preset.teams) { for (team in preset.teams) {
players.push({index: -1, control: 'Team "${team.id}"', tanks: []}); var human = true;
players = players.concat(team.players); players.push(new PlayerId(team.id, -1));
for (player in team.players) {
var playerId = new PlayerId(team.id, player.index);
state.control.set(playerId, human ? Control.HUMAN : Control.BOT);
human = false;
players.push(playerId);
}
} }
this.players.data = players; this.players.data = players;
} else { } else {
@@ -70,14 +76,14 @@ class StartGameFrame extends VGroupView {
} }
public function onShow():Void { public function onShow():Void {
gameType = save.state.type; gameType = state.type;
if (save.state.presetId != null) { if (state.presetId != null) {
presetId = save.state.presetId; presetId = state.presetId;
} }
} }
public function onListItemClick(item:IListItemView<Int>):Void { public function onListItemClick(item:IListItemView<Int>):Void {
Provider.get(GameSave).state.level = item.data; state.level = item.data;
Provider.get(IFrameSwitcher).change(GameFrame.ID); Provider.get(IFrameSwitcher).change(GameFrame.ID);
} }
} }

View File

@@ -11,7 +11,7 @@ views:
pHeight: 100 pHeight: 100
views: views:
- id: players - id: players
$type: haxework.gui.list.VListView<ru.m.tankz.config.Config.PlayerConfig> $type: haxework.gui.list.VListView<PlayerId>
factory: "@class:ru.m.tankz.frame.level.PlayerView" factory: "@class:ru.m.tankz.frame.level.PlayerView"
pWidth: 50 pWidth: 50
pHeight: 100 pHeight: 100

View File

@@ -5,8 +5,7 @@ import haxework.gui.VGroupView;
import ru.m.tankz.game.Game; import ru.m.tankz.game.Game;
import ru.m.tankz.preset.ClassicGame; import ru.m.tankz.preset.ClassicGame;
@:template("ru/m/tankz/frame/game/ClassicGamePanel.yaml", "ru/m/tankz/Style.yaml") @:template class ClassicGamePanel extends VGroupView implements IGamePanel {
class ClassicGamePanel extends VGroupView implements IGamePanel {
@:view var botstate(default, null):LabelView; @:view var botstate(default, null):LabelView;
@:view var player1state(default, null):LabelView; @:view var player1state(default, null):LabelView;

View File

@@ -4,8 +4,7 @@ import haxework.gui.LabelView;
import haxework.gui.HGroupView; import haxework.gui.HGroupView;
import ru.m.tankz.game.Game; import ru.m.tankz.game.Game;
@:template("ru/m/tankz/frame/game/DotaGamePanel.yaml", "ru/m/tankz/Style.yaml") @:template class DotaGamePanel extends HGroupView implements IGamePanel {
class DotaGamePanel extends HGroupView implements IGamePanel {
@:view var state(default, null):LabelView; @:view var state(default, null):LabelView;
@@ -18,7 +17,7 @@ class DotaGamePanel extends HGroupView implements IGamePanel {
var result:Array<String> = []; var result:Array<String> = [];
result.push('Level: ${game.state.level}'); result.push('Level: ${game.state.level}');
for (team in game.teams) { for (team in game.teams) {
if (game.state.loser == team.id) { if (game.loser == team.id) {
result.push('${team.id}: LOSE'); result.push('${team.id}: LOSE');
} else if (team.life > 0) { } else if (team.life > 0) {
result.push('${team.id}: ${team.life}'); result.push('${team.id}: ${team.life}');

View File

@@ -5,8 +5,7 @@ import haxework.gui.LabelView;
import haxework.gui.list.ListView.IListItemView; import haxework.gui.list.ListView.IListItemView;
@:template("ru/m/tankz/frame/level/LevelView.yaml", "ru/m/tankz/Style.yaml") @:template class LevelView extends HGroupView implements IListItemView<Int> {
class LevelView extends HGroupView implements IListItemView<Int> {
public var item_index(default, default):Int; public var item_index(default, default):Int;
public var data(default, set):Int; public var data(default, set):Int;

View File

@@ -4,39 +4,52 @@ import haxework.gui.ButtonView;
import haxework.gui.HGroupView; import haxework.gui.HGroupView;
import haxework.gui.LabelView; import haxework.gui.LabelView;
import haxework.gui.list.ListView.IListItemView; import haxework.gui.list.ListView.IListItemView;
import ru.m.tankz.config.Config;
import ru.m.tankz.control.Control; import ru.m.tankz.control.Control;
import ru.m.tankz.game.GameState;
import ru.m.tankz.Type;
@:template("ru/m/tankz/frame/level/PlayerView.yaml", "ru/m/tankz/Style.yaml") @:template class PlayerView extends HGroupView implements IListItemView<PlayerId> {
class PlayerView extends HGroupView implements IListItemView<PlayerConfig> {
public var item_index(default, default):Int; public var item_index(default, default):Int;
public var data(default, set):PlayerConfig; public var data(default, set):PlayerId;
@:view("index") var indexLabel(default, null):LabelView; @:view("index") var indexLabel(default, null):LabelView;
@:view var control(default, null):ButtonView; @:view var control(default, null):ButtonView;
@:provide var state:GameState;
private function init():Void { private function init():Void {
control.onPress = this; control.onPress = this;
} }
private function set_data(value:PlayerConfig):PlayerConfig { private function set_data(value:PlayerId):PlayerId {
data = value; data = value;
indexLabel.text = data.index == -1 ? "" : Std.string(data.index); if (data.index == -1) {
control.text = data.control; indexLabel.text = "";
control.fontColor = data.index == -1 ? 0x00ff00 : 0xffffff; control.text = data.team;
control.fontColor = 0x00ff00;
} else {
indexLabel.text = Std.string(data.index);
var controlType = state.control.get(value);
control.text = controlType;
control.fontColor = switch controlType {
case Control.HUMAN: 0xffff00;
case _: 0xffffff;
};
}
return data; return data;
} }
public function onPress(view:ButtonView):Void { public function onPress(view:ButtonView):Void {
if (data != null && data.index > -1) { if (data != null && data.index > -1) {
data.control = switch (data.control) { var controlType = switch state.control.get(data) {
case Control.BOT: Control.HUMAN; case Control.BOT: Control.HUMAN;
case Control.HUMAN: Control.BOT; case Control.HUMAN: Control.BOT;
case _: Control.BOT; case _: Control.BOT;
} }
control.text = data.control; state.control.set(data, controlType);
this.data = data;
} }
} }
} }

View File

@@ -6,8 +6,7 @@ import haxework.gui.list.ListView;
import ru.m.tankz.proto.core.GameInfoProto; import ru.m.tankz.proto.core.GameInfoProto;
@:template("ru/m/tankz/frame/network/GameItemView.yaml", "ru/m/tankz/Style.yaml") @:template class GameItemView extends HGroupView implements IListItemView<GameInfoProto> {
class GameItemView extends HGroupView implements IListItemView<GameInfoProto> {
public var item_index(default, default):Int; public var item_index(default, default):Int;
public var data(default, set):GameInfoProto; public var data(default, set):GameInfoProto;

View File

@@ -6,8 +6,7 @@ import haxework.gui.list.ListView;
import ru.m.tankz.proto.core.UserProto; import ru.m.tankz.proto.core.UserProto;
@:template("ru/m/tankz/frame/network/UserItemView.yaml", "ru/m/tankz/Style.yaml") @:template class UserItemView extends HGroupView implements IListItemView<UserProto> {
class UserItemView extends HGroupView implements IListItemView<UserProto> {
public var item_index(default, default):Int; public var item_index(default, default):Int;
public var data(default, set):UserProto; public var data(default, set):UserProto;

View File

@@ -38,8 +38,7 @@ class KeyboardMap {
} }
@:template("ru/m/tankz/frame/settings/ActionView.yaml", "ru/m/tankz/Style.yaml") @:template class ActionView extends HGroupView implements IListItemView<ActionItem> {
class ActionView extends HGroupView implements IListItemView<ActionItem> {
public var item_index(default, default):Int; public var item_index(default, default):Int;
public var data(default, set):ActionItem; public var data(default, set):ActionItem;

View File

@@ -1,17 +1,16 @@
package ru.m.tankz.frame.settings; package ru.m.tankz.frame.settings;
import haxework.gui.LabelView;
import ru.m.tankz.control.ActionConfig;
import promhx.Promise;
import ru.m.tankz.storage.SettingsStorage;
import haxework.gui.ButtonView; import haxework.gui.ButtonView;
import ru.m.tankz.control.ActionConfig.ActionItem; import haxework.gui.LabelView;
import haxework.gui.list.ListView; import haxework.gui.list.ListView;
import haxework.gui.VGroupView; import haxework.gui.VGroupView;
import promhx.Promise;
import ru.m.tankz.control.ActionConfig.ActionItem;
import ru.m.tankz.control.ActionConfig;
import ru.m.tankz.storage.SettingsStorage;
@:template("ru/m/tankz/frame/settings/SettingsEditor.yaml", "ru/m/tankz/Style.yaml") @:template class SettingsEditor extends VGroupView {
class SettingsEditor extends VGroupView {
public var controlIndex(default, set): Int; public var controlIndex(default, set): Int;

View File

@@ -1,8 +1,8 @@
package ru.m.tankz.storage; package ru.m.tankz.storage;
import flash.net.SharedObject; import flash.net.SharedObject;
import ru.m.tankz.game.GameState;
import ru.m.tankz.Type; import ru.m.tankz.Type;
import ru.m.tankz.game.GameSave;
class SaveStorage { class SaveStorage {
@@ -15,19 +15,19 @@ class SaveStorage {
so = SharedObject.getLocal('tankz'); so = SharedObject.getLocal('tankz');
} }
public function read(type:GameType):Null<GameSave> { public function read(type:GameType):Null<GameState> {
var data:String = Reflect.getProperty(so.data, type); var data:String = Reflect.getProperty(so.data, type);
L.d(TAG, 'read: ${data}'); L.d(TAG, 'read: ${data}');
if (data != null) { if (data != null) {
return GameSave.fromYaml(data); return GameState.fromYaml(data);
} }
return null; return null;
} }
public function write(save:GameSave):Void { public function write(save:GameState):Void {
var data:String = save.toYaml(); var data:String = save.toYaml();
L.d(TAG, 'write: ${data}'); L.d(TAG, 'write: ${data}');
so.setProperty(save.state.type, data); so.setProperty(save.type, data);
so.flush(); so.flush();
} }
} }

View File

@@ -33,7 +33,7 @@ class SettingsStorage {
} }
public static function getDefault(index: Int): ActionConfig { public static function getDefault(index: Int): ActionConfig {
return defaults.get(index).clone(); return (defaults.exists(index) ? defaults.get(index) : empty).clone();
} }
private static var defaults: Map<Int, ActionConfig> = [ private static var defaults: Map<Int, ActionConfig> = [
@@ -52,4 +52,12 @@ class SettingsStorage {
{action:TankAction.SHOT, key:Keyboard.NUMPAD_0}, {action:TankAction.SHOT, key:Keyboard.NUMPAD_0},
]), ]),
]; ];
private static var empty: ActionConfig = new ActionConfig([
{action:TankAction.MOVE(Direction.TOP), key:-1},
{action:TankAction.MOVE(Direction.LEFT), key:-1},
{action:TankAction.MOVE(Direction.BOTTOM), key:-1},
{action:TankAction.MOVE(Direction.RIGHT), key:-1},
{action:TankAction.SHOT, key:-1},
]);
} }

View File

@@ -1,5 +1,7 @@
package ru.m.tankz; package ru.m.tankz;
import haxe.io.Bytes;
import haxe.crypto.Crc32;
typedef Type = Dynamic; typedef Type = Dynamic;
@@ -15,9 +17,21 @@ typedef TankType = String;
typedef BonusType = String; typedef BonusType = String;
typedef PlayerId = { class PlayerId {
var team:TeamId; public var team(default, null):TeamId;
var index:Int; public var index(default, null):Int;
private var _hashCode(default, null):Int;
public function new(team:TeamId, index:Int) {
this.team = team;
this.index = index;
this._hashCode = Crc32.make(Bytes.ofString('${team}-${index}'));
}
public function hashCode():Int {
return _hashCode;
}
} }
typedef PresetId = String; typedef PresetId = String;

View File

@@ -71,7 +71,6 @@ typedef TankSpawn = {
typedef PlayerConfig = { typedef PlayerConfig = {
var index:Int; var index:Int;
var control:ControlType;
var tanks:Array<TankSpawn>; var tanks:Array<TankSpawn>;
@:optional var bonus:Float; @:optional var bonus:Float;
@:optional var protect:Float; @:optional var protect:Float;

View File

@@ -1,8 +1,8 @@
package ru.m.tankz.control; package ru.m.tankz.control;
import ru.m.tankz.game.Player; import ru.m.tankz.Type;
interface IControlFactory { interface IControlFactory {
public function build(player:Player):Control; public function build(id:PlayerId, type:ControlType):Control;
} }

View File

@@ -33,6 +33,7 @@ class Game {
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;
public var loser(default, null):Null<TeamId>;
private var points:Array<SpawnPoint>; private var points:Array<SpawnPoint>;
private var deferred:Deferred<GameState>; private var deferred:Deferred<GameState>;
@@ -78,8 +79,9 @@ class Game {
entity.rect.direction = Direction.fromString(point.direction); entity.rect.direction = Direction.fromString(point.direction);
} }
public function start(save:GameSave):Stream<GameState> { public function start(state:GameState):Stream<GameState> {
this.state = save.state; this.state = state;
this.loser = null;
this.preset = config.getPreset(state.presetId); this.preset = config.getPreset(state.presetId);
this.deferred = new Deferred(); this.deferred = new Deferred();
var level:LevelConfig = Provider.get(ILevelBundle).get(type, config, state.level); var level:LevelConfig = Provider.get(ILevelBundle).get(type, config, state.level);
@@ -89,11 +91,12 @@ class Game {
var controlFactory:IControlFactory = Provider.build(IControlFactory); var controlFactory:IControlFactory = Provider.build(IControlFactory);
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, save); var team:Team = new Team(teamConfig, teamPoints, state);
teams[team.id] = team; teams[team.id] = team;
for (player in team.players.iterator()) { for (player in team.players.iterator()) {
if (player.config.control != null) { var controlType: ControlType = state.control.get(player.id);
var control = controlFactory.build(player); if (controlType != null) {
var control = controlFactory.build(player.id, controlType);
L.d(TAG, 'control(${player.id} - ${control})'); L.d(TAG, 'control(${player.id} - ${control})');
if (control != null) { if (control != null) {
player.control = control; player.control = control;
@@ -222,7 +225,7 @@ class Game {
} }
private function lose(teamId:TeamId):Void { private function lose(teamId:TeamId):Void {
state.loser = teamId; loser = teamId;
complete(); complete();
} }
@@ -232,13 +235,13 @@ class Game {
public function next():Option<GameState> { public function next():Option<GameState> {
for (rule in config.game.complete) { for (rule in config.game.complete) {
if (rule.team != null && rule.team == state.loser) { if (rule.team != null && rule.team == loser) {
return Option.None; return Option.None;
} }
} }
state.level++; state.level++;
if (state.level >= config.game.levels) state.level = 0; if (state.level >= config.game.levels) state.level = 0;
return Option.Some({type: state.type, presetId: preset.id, level: state.level}); return Option.Some(state);
} }
public function dispose():Void { public function dispose():Void {
@@ -294,16 +297,7 @@ class Game {
} }
} }
public function save():GameSave { public function save():GameState {
var save:GameSave = new GameSave(state); return state;
for (team in teams) {
for (player in team.players) {
if (player.config.control == Control.HUMAN) {
player.state.life++;
save.addPlayerState(player.id, player.state);
}
}
}
return save;
} }
} }

View File

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

View File

@@ -1,11 +1,33 @@
package ru.m.tankz.game; package ru.m.tankz.game;
import ru.m.tankz.game.Player.PlayerState;
import haxe.ds.HashMap;
import ru.m.tankz.Type; import ru.m.tankz.Type;
typedef GameState = { class GameState {
var type:GameType; public var type(default, null):GameType;
var presetId:PresetId; public var presetId(default, null):PresetId;
@:optional var level:Int; public var control(default, null):HashMap<PlayerId, ControlType>;
@:optional var loser:TeamId; public var players(default, null):HashMap<PlayerId, PlayerState>;
public var level(default, default):Int;
public function new(type:GameType, presetId:PresetId) {
this.type = type;
this.presetId = presetId;
this.control = new HashMap();
this.players = new HashMap();
this.level = 0;
}
public function toYaml():String {
//return Yaml.render(this, Renderer.options().setFlowLevel(0));
return "";
}
public static function fromYaml(value:String):GameState {
//var data:Dynamic = Yaml.parse(value, Parser.options().useObjects());
//return new GameState();
return null;
}
} }

View File

@@ -21,7 +21,7 @@ class Player {
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 = new PlayerId(teamId, config.index);
this.control = null; this.control = null;
this.state = { this.state = {
life: config.life, life: config.life,

View File

@@ -14,13 +14,13 @@ 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>, ?save:GameSave) { public function new(config:TeamConfig, points:Array<SpawnPoint>, ?state:GameState) {
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) {
var player:Player = new Player(id, playerConfig); var player:Player = new Player(id, playerConfig);
var state = save.getPlayerState(player.id); var state = state.players.get(player.id);
if (state != null) player.state = state; if (state != null) player.state = state;
this.players[playerConfig.index] = player; this.players[playerConfig.index] = player;
} }

View File

@@ -21,13 +21,11 @@ bricks:
player: player:
human: &human human: &human
control: human
life: 3 life: 3
protect: 5 protect: 5
tanks: tanks:
- {type: human0, rate: 1} - {type: human0, rate: 1}
bot: &bot bot: &bot
control: bot
color: 0xFFFFFF color: 0xFFFFFF
bonus: 0.25 bonus: 0.25
tanks: tanks:

View File

@@ -20,29 +20,25 @@ bricks:
player: player:
base: &player base: &player
control: bot
protect: 3 protect: 3
fast: &player-fast
<<: *player
tanks: tanks:
- {type: slow, rate: 0.5} - {type: fast, rate: 1}
- {type: fast, rate: 0.5} slow: &player-slow
human1: &human1
<<: *player <<: *player
control: human tanks:
color: 0xf055a0 - {type: slow, rate: 1}
human2: &human2
<<: *player
control: human
color: 0xa055f0
team: team:
base: &team base: &team
life: 20 life: 20
players: players:
- {<<: *player, index: 0} - {<<: *player-slow, index: 0}
- {<<: *player, index: 1} - {<<: *player-fast, index: 1}
- {<<: *player, index: 2} - {<<: *player-slow, index: 2}
- {<<: *player, index: 3} - {<<: *player-fast, index: 3}
- {<<: *player, index: 4} - {<<: *player-slow, index: 4}
radiant: &radiant radiant: &radiant
id: radiant id: radiant
color: 0xff4422 color: 0xff4422
@@ -53,45 +49,10 @@ team:
<<: *team <<: *team
presets: presets:
# player1 - id: default
- id: player1
teams: teams:
- <<: *radiant - <<: *radiant
players:
- {<<: *human1, index: 0}
- {<<: *player, index: 1}
- {<<: *player, index: 2}
- {<<: *player, index: 3}
- {<<: *player, index: 4}
- <<: *dire - <<: *dire
# player2_coop
- id: player2_coop
teams:
- <<: *radiant
players:
- {<<: *human1, index: 0}
- {<<: *human1, index: 1}
- {<<: *player, index: 2}
- {<<: *player, index: 3}
- {<<: *player, index: 4}
- <<: *dire
# player2_vs
- id: player2_vs
teams:
- <<: *radiant
players:
- {<<: *human1, index: 0}
- {<<: *player, index: 1}
- {<<: *player, index: 2}
- {<<: *player, index: 3}
- {<<: *player, index: 4}
- <<: *dire
players:
- {<<: *human2, index: 0}
- {<<: *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}