[common] add GameStart

This commit is contained in:
2019-03-13 17:11:20 +03:00
parent d9915120d4
commit 85e5f9a553
25 changed files with 247 additions and 277 deletions

2
gen.sh
View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
haxelib run protohx generate protohx.json haxelib run protohx generate protohx.json
haxelib run orm mysql://shmyga:xkbp8jh9z2@localhost:3306/armageddon \ haxelib run orm mysql://shmyga:password@localhost:3306/armageddon \
-s src-gen/haxe \ -s src-gen/haxe \
-c ru.m.tankz.db \ -c ru.m.tankz.db \
-a ru.m.tankz.db -a ru.m.tankz.db

View File

@@ -7,7 +7,7 @@
"gulp": "^4.0.0", "gulp": "^4.0.0",
"gulp-add": "0.0.2", "gulp-add": "0.0.2",
"gulp-clean": "^0.4.0", "gulp-clean": "^0.4.0",
"gulp-haxetool": "^0.0.14" "gulp-haxetool": "^0.0.15"
}, },
"haxeDependencies": { "haxeDependencies": {
"haxework": "git@bitbucket.org:shmyga/haxework.git", "haxework": "git@bitbucket.org:shmyga/haxework.git",

View File

@@ -15,7 +15,6 @@ import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.proto.pack.Request; import ru.m.tankz.proto.pack.Request;
import ru.m.tankz.proto.pack.Response; import ru.m.tankz.proto.pack.Response;
import ru.m.tankz.sound.SoundManager; import ru.m.tankz.sound.SoundManager;
import ru.m.tankz.storage.SaveStorage;
import ru.m.tankz.storage.UserStorage; import ru.m.tankz.storage.UserStorage;
#if flash #if flash
import flash.Lib; import flash.Lib;
@@ -46,7 +45,6 @@ class Init {
Provider.setFactory(IResources, Resources); Provider.setFactory(IResources, Resources);
Provider.setFactory(ILevelBundle, LevelBundle); Provider.setFactory(ILevelBundle, LevelBundle);
Provider.setFactory(IConfigBundle, ConfigBundle); Provider.setFactory(IConfigBundle, ConfigBundle);
Provider.setFactory(SaveStorage, SaveStorage);
Provider.setFactory(UserStorage, UserStorage); Provider.setFactory(UserStorage, UserStorage);
Provider.setFactory(SettingsStorage, SettingsStorage); Provider.setFactory(SettingsStorage, SettingsStorage);
Provider.setFactory(SoundManager, SoundManager); Provider.setFactory(SoundManager, SoundManager);

View File

@@ -5,14 +5,12 @@ import ru.m.tankz.frame.dota.DotaLevelFrame;
import haxework.gui.ButtonView; import haxework.gui.ButtonView;
import haxework.gui.frame.FrameSwitcher; import haxework.gui.frame.FrameSwitcher;
import haxework.gui.VGroupView; import haxework.gui.VGroupView;
import ru.m.tankz.storage.SaveStorage;
@:template class StartFrame extends VGroupView { @:template class StartFrame extends VGroupView {
public static var ID(default, never):String = "start"; public static var ID(default, never):String = "start";
@:provide var frameSwitcher:FrameSwitcher; @:provide var frameSwitcher:FrameSwitcher;
@:provide var storage:SaveStorage;
public function onPress(view:ButtonView):Void { public function onPress(view:ButtonView):Void {
switch (view.id) { switch (view.id) {

View File

@@ -15,12 +15,15 @@ import ru.m.tankz.preset.ClassicGame;
public var game:Game; public var game:Game;
private function updateViews():Void { private function updateViews():Void {
bot.count.text = '${game.teams[ClassicGame.BOT].life}'; bot.live.text = '${game.teams[ClassicGame.BOT].life}';
player1.count.text = '${game.teams[ClassicGame.HUMAN].players[0].state.life}'; player1.live.text = '${game.teams[ClassicGame.HUMAN].players[0].state.life}';
player1.score.text = '${game.teams[ClassicGame.HUMAN].players[0].state.score}';
if (game.teams[ClassicGame.HUMAN].players[1] != null) { if (game.teams[ClassicGame.HUMAN].players[1] != null) {
player2.count.text = '${game.teams[ClassicGame.HUMAN].players[1].state.life}'; player2.live.text = '${game.teams[ClassicGame.HUMAN].players[1].state.life}';
player2.score.text = '${game.teams[ClassicGame.HUMAN].players[1].state.score}';
} else { } else {
player2.count.text = ""; player2.live.text = "";
player2.score.text = "";
} }
} }

View File

@@ -7,11 +7,10 @@ import haxework.gui.frame.FrameSwitcher;
import haxework.gui.GroupView; import haxework.gui.GroupView;
import ru.m.tankz.frame.common.IGamePanel; import ru.m.tankz.frame.common.IGamePanel;
import ru.m.tankz.game.Game; import ru.m.tankz.game.Game;
import ru.m.tankz.game.GameState; import ru.m.tankz.game.GameStart;
import ru.m.tankz.network.NetworkManager; import ru.m.tankz.network.NetworkManager;
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;
class GameFrame extends GroupView { class GameFrame extends GroupView {
@@ -22,8 +21,7 @@ class GameFrame extends GroupView {
@:provide var network:NetworkManager; @:provide var network:NetworkManager;
@:provide var sound:SoundManager; @:provide var sound:SoundManager;
@:provide var state:GameState; @:provide var gameStart:GameStart;
@:provide var storage:SaveStorage;
@:provide var switcher:FrameSwitcher; @:provide var switcher:FrameSwitcher;
private var game:Game; private var game:Game;
@@ -38,14 +36,14 @@ class GameFrame extends GroupView {
} }
public function onShow():Void { public function onShow():Void {
start(state); start(gameStart);
} }
private function start(state:GameState):Void { private function start(start:GameStart):Void {
game = new Game(state.type); game = new Game(start.type);
game.engine.connect(render); game.engine.connect(render);
game.engine.connect(sound); game.engine.connect(sound);
game.start(state).then(onGameStateChange).endThen(onGameComplete); game.start(start).then(onGameStateChange).endThen(onGameComplete);
timer = new Timer(10); timer = new Timer(10);
timer.run = updateEngine; timer.run = updateEngine;
panel.game = game; panel.game = game;
@@ -67,24 +65,15 @@ class GameFrame extends GroupView {
render.reset(); render.reset();
} }
private function onGameStateChange(s:GameState):GameState { private function onGameStateChange(_):Void {
panel.toUpdate(); panel.toUpdate();
return s;
} }
private function onGameComplete(result:Option<GameState>):Void { private function onGameComplete(_):Void {
switch (result) {
case Option.Some(s):
panel.toUpdate();
case Option.None:
}
switch (game.next()) { switch (game.next()) {
case Option.Some(s): case Option.Some(s):
var state = game.save();
this.state = state;
storage.write(state);
stop(); stop();
start(state); start(s);
case Option.None: case Option.None:
switcher.change(StartFrame.ID); switcher.change(StartFrame.ID);
} }

View File

@@ -6,8 +6,7 @@ import haxework.resources.IResources;
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.control.Control;
import ru.m.tankz.game.GameState; import ru.m.tankz.game.GameStart;
import ru.m.tankz.storage.SaveStorage;
import ru.m.tankz.Type; import ru.m.tankz.Type;
class LevelFrame extends GroupView { class LevelFrame extends GroupView {
@@ -18,12 +17,11 @@ class LevelFrame extends GroupView {
private var config(default, null):Config; private var config(default, null):Config;
@:provide var configBundle:IConfigBundle; @:provide var configBundle:IConfigBundle;
@:provide var state:GameState; @:provide var start:GameStart;
@:provide var storage:SaveStorage;
@:provide var resources:IResources; @:provide var resources:IResources;
private function set_gameType(value:GameType):GameType { private function set_gameType(value:GameType):GameType {
if (gameType != value) { if (gameType != value || true) { // ToDo:
gameType = value; gameType = value;
config = configBundle.get(gameType); config = configBundle.get(gameType);
preset = config.presets[0]; preset = config.presets[0];
@@ -32,13 +30,13 @@ class LevelFrame extends GroupView {
} }
private function set_preset(value:GamePreset):GamePreset { private function set_preset(value:GamePreset):GamePreset {
if (preset != value) { if (preset != value || true) { // ToDo:
preset = value; preset = value;
state = new GameState(gameType, preset.id); start = new GameStart(gameType, preset.id);
for (team in value.teams) { for (team in value.teams) {
for (player in team.players) { for (player in team.players) {
var playerId = new PlayerId(team.id, player.index); var playerId = new PlayerId(team.id, player.index);
state.control.set(playerId, player.control != null ? player.control : Control.BOT); start.players.push({playerId: playerId, control: player.control != null ? player.control : Control.BOT});
} }
} }
} }
@@ -46,8 +44,8 @@ class LevelFrame extends GroupView {
} }
private function set_level(value:Int):Int { private function set_level(value:Int):Int {
state.level = value; start.level = value;
return state.level; return start.level;
} }
private function levelViewFactory(index:Int, level:Int):ButtonView { private function levelViewFactory(index:Int, level:Int):ButtonView {

View File

@@ -6,5 +6,6 @@ import haxework.gui.HGroupView;
@:template class LifeView extends HGroupView { @:template class LifeView extends HGroupView {
@:view public var image:ImageView; @:view public var image:ImageView;
@:view public var count:LabelView; @:view public var live:LabelView;
@:view public var score:LabelView;
} }

View File

@@ -3,7 +3,11 @@ layout.margin: 5
views: views:
- id: image - id: image
$type: haxework.gui.ImageView $type: haxework.gui.ImageView
- id: count - id: live
$type: haxework.gui.LabelView $type: haxework.gui.LabelView
skinId: text.box skinId: text.box
geometry.size.fixed: [50, 38] geometry.size.fixed: [50, 38]
- id: score
$type: haxework.gui.LabelView
skinId: text.box
geometry.size.fixed: [100, 38]

View File

@@ -1,65 +1,93 @@
package ru.m.tankz.frame.common; package ru.m.tankz.frame.common;
import haxework.color.Color; import haxework.gui.DataView;
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; import haxework.gui.skin.ISkin;
import haxework.gui.skin.Skin; import haxework.gui.ToggleButtonView;
import openfl.Assets; import ru.m.tankz.game.GameStart;
import ru.m.tankz.bundle.IConfigBundle; import ru.m.tankz.Type.PlayerId;
import ru.m.tankz.control.Control; import ru.m.tankz.Type.TeamId;
import ru.m.tankz.game.GameState;
import ru.m.tankz.Type;
@:template class PlayerView extends HGroupView implements IListItemView<PlayerId> { class TeamButton extends ToggleButtonView {
public var team(default, set):TeamId;
public var item_index(default, default):Int; private function set_team(value:TeamId):TeamId {
public var data(default, set):PlayerId; if (team != value) {
team = value;
@:view("index") var indexLabel(default, null):LabelView; text = team.substr(0, 1).toUpperCase() + team.substr(1);
@:view var control(default, null):ButtonView;
@:provide var state:GameState;
@:provide var configBundle:IConfigBundle;
private function set_data(value:PlayerId):PlayerId {
data = value;
indexLabel.text = '${value.team} ${Std.string(data.index + 1)}';
var color = 0xffffff;
var config = configBundle.get(state.type);
var preset = config.getPreset(state.presetId);
for (team in preset.teams) {
if (team.id == data.team) {
color = team.color;
for (player in team.players) {
if (player.index == data.index) {
if (!player.color.zero) {
color = player.color;
}
break;
}
}
preset.teams;
}
} }
indexLabel.fontColor = color; return team;
var controlType = state.control.get(value); }
var image = Assets.getBitmapData('resources/image/ui/control/${controlType}.png'); }
control.skin = [Skin.buttonBitmap(image)];
indexLabel.update(); class TeamSkin implements ISkin<TeamButton> {
public var color(default, default):Int;
public function new(color:Int) {
this.color = color;
}
public function draw(view:TeamButton):Void {
view.fontColor = view.on ? 0x000000 : 0xcccccc;
var graphics = view.content.graphics;
graphics.beginFill(view.on ? color : 0x333333);
graphics.lineStyle(1, view.on ? 0x333333 : color);
graphics.drawRect(0, 0, view.width, view.height);
graphics.endFill();
graphics.lineStyle();
}
}
@:template class PlayerView extends HGroupView {
private static inline var NONE:TeamId = "none";
public var item_index(default, set):Int;
public var data(default, set):PlayerStart;
@:view var label(default, null):LabelView;
@:view var teams(default, null):DataView<TeamId, ToggleButtonView>;
@:provide var start:GameStart;
private function teamViewFactory(index:Int, team:TeamId) {
var view = new TeamButton();
view.skin = [new TeamSkin(getTeamColor(team))];
view.geometry.padding = [10, 5];
view.team = team;
view.on = team == NONE;
return view;
}
private function set_data(value:PlayerStart):PlayerStart {
data = value;
teams.data = [NONE].concat([for (team in start.preset.teams) team.id]);
return data; return data;
} }
public function toggleControl():Void { private function getTeamColor(teamId:TeamId):Int {
if (data != null && data.index > -1) { var color = 0xcccccc;
var controlType = switch state.control.get(data) { for (team in start.preset.teams) {
case Control.BOT: Control.HUMAN; if (team.id == teamId) {
case Control.HUMAN: Control.BOT; if (!team.color.zero) color = team.color;
case _: Control.BOT; break;
} }
state.control.set(data, controlType); }
this.data = data; return color;
}
private function set_item_index(value:Int):Int {
item_index = value;
label.text = 'Player ${item_index}';
return item_index;
}
private function onTeamSelect(team:TeamId) {
data.playerId = new PlayerId(team, item_index);
for (view in teams.views) {
var button = cast(view, TeamButton);
button.on = team == button.team;
} }
} }
} }

View File

@@ -1,18 +1,15 @@
--- ---
geometry.size.width: 200
geometry.size.height: 44
geometry.margin: 5 geometry.margin: 5
layout.margin: 10 layout.margin: 10
layout.vAlign: middle
views: views:
- id: index - id: label
$type: haxework.gui.LabelView $type: haxework.gui.LabelView
geometry.size.stretch: true skinId: text
skin: - id: teams
- $type: haxework.gui.skin.ColorSkin $type: haxework.gui.DataView
color: 0x000000 factory: $this:teamViewFactory
alpha: 0.2 layout:
shadow: true $type: haxework.gui.layout.HorizontalLayout
shadowColor: 0x000000 margin: 3
- id: control +onDataSelect: $this:onTeamSelect
$type: haxework.gui.ButtonView
+onPress: $code:toggleControl()

View File

@@ -1,10 +1,10 @@
package ru.m.tankz.frame.dota; package ru.m.tankz.frame.dota;
import ru.m.tankz.preset.DotaGame;
import ru.m.tankz.frame.common.LifeView;
import ru.m.tankz.frame.common.IGamePanel;
import haxework.gui.HGroupView; import haxework.gui.HGroupView;
import ru.m.tankz.frame.common.IGamePanel;
import ru.m.tankz.frame.common.LifeView;
import ru.m.tankz.game.Game; import ru.m.tankz.game.Game;
import ru.m.tankz.preset.DotaGame;
@:template class DotaGamePanel extends HGroupView implements IGamePanel { @:template class DotaGamePanel extends HGroupView implements IGamePanel {
@@ -13,31 +13,11 @@ import ru.m.tankz.game.Game;
public var game:Game; public var game:Game;
private function stateString(game:Game):String {
if (game == null) {
return '';
}
var result:Array<String> = [];
result.push('Level: ${game.state.level}');
for (team in game.teams) {
if (game.loser == team.id) {
result.push('${team.id}: LOSE');
} else if (team.life > 0) {
result.push('${team.id}: ${team.life}');
} else {
for (player in team.players) {
if (player.state.life > 0) {
result.push('${player.id.team}${player.id.index}: ${player.state.life}');
}
}
}
}
return '[ ${result.join(' | ')} ]';
}
private function updateViews():Void { private function updateViews():Void {
radiant.count.text = '${game.teams[DotaGame.RADIANT].life}'; radiant.live.text = '${game.teams[DotaGame.RADIANT].life}';
dire.count.text = '${game.teams[DotaGame.DIRE].life}'; radiant.score.text = '0'; // ToDO
dire.live.text = '${game.teams[DotaGame.DIRE].life}';
dire.score.text = '0'; // ToDO
} }
override public function update():Void { override public function update():Void {

View File

@@ -3,16 +3,17 @@ package ru.m.tankz.frame.dota;
import haxework.gui.ButtonView; import haxework.gui.ButtonView;
import haxework.gui.DataView; import haxework.gui.DataView;
import haxework.gui.frame.FrameSwitcher; import haxework.gui.frame.FrameSwitcher;
import ru.m.tankz.control.Control;
import ru.m.tankz.frame.common.LevelFrame; import ru.m.tankz.frame.common.LevelFrame;
import ru.m.tankz.frame.common.PlayerView; import ru.m.tankz.frame.common.PlayerView;
import ru.m.tankz.game.GameStart.PlayerStart;
import ru.m.tankz.preset.DotaGame; import ru.m.tankz.preset.DotaGame;
import ru.m.tankz.Type;
@:template class DotaLevelFrame extends LevelFrame { @:template class DotaLevelFrame extends LevelFrame {
public static inline var ID = "dota.level"; public static inline var ID = "dota.level";
@:view var levels(default, null):DataView<Int, ButtonView>; @:view var levels(default, null):DataView<Int, ButtonView>;
@:view var players(default, null):DataView<PlayerId, PlayerView>; @:view var players(default, null):DataView<PlayerStart, PlayerView>;
@:provide var frames:FrameSwitcher; @:provide var frames:FrameSwitcher;
@@ -20,15 +21,17 @@ import ru.m.tankz.Type;
gameType = DotaGame.TYPE; gameType = DotaGame.TYPE;
levels.data = [for (i in 0...config.game.levels) i]; levels.data = [for (i in 0...config.game.levels) i];
var data = []; var data = [];
for (team in preset.teams) { for (i in 0...2) {
for (p in team.players) { data.push({
data.push(new PlayerId(team.id, p.index)); playerId: null,
} control: Control.HUMAN,
});
} }
start.players = data;
players.data = data; players.data = data;
} }
private function playerViewFactory(index:Int, player:PlayerId):PlayerView { private function playerViewFactory(index:Int, player:PlayerStart):PlayerView {
var view = new PlayerView(); var view = new PlayerView();
view.item_index = index; view.item_index = index;
view.data = player; view.data = player;

View File

@@ -6,21 +6,19 @@ views:
- $type: haxework.gui.LabelView - $type: haxework.gui.LabelView
skinId: text.header skinId: text.header
text: DotA text: DotA
- $type: haxework.gui.HGroupView - id: players
views: $type: haxework.gui.DataView
- id: players layout:
$type: haxework.gui.DataView $type: haxework.gui.layout.VerticalLayout
layout: hAlign: center
$type: haxework.gui.layout.VerticalLayout factory: $this:playerViewFactory
hAlign: center geometry.padding: 10
factory: $this:playerViewFactory - id: levels
geometry.padding: 10 $type: haxework.gui.DataView
- id: levels layout:
$type: haxework.gui.DataView $type: haxework.gui.layout.TailLayout
layout: rowSize: 5
$type: haxework.gui.layout.TailLayout margin: 5
rowSize: 5 factory: $this:levelViewFactory
margin: 5 +onDataSelect: $code:function(value) level = value
factory: $this:levelViewFactory geometry.padding: 10
+onDataSelect: $code:function(value) level = value
geometry.padding: 10

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1,8 +1,5 @@
package ru.m.tankz; package ru.m.tankz;
import haxe.io.Bytes;
import haxe.crypto.Crc32;
typedef Type = Dynamic; typedef Type = Dynamic;
typedef GameType = String; typedef GameType = String;
@@ -17,20 +14,20 @@ typedef TankType = String;
typedef BonusType = String; typedef BonusType = String;
class PlayerId { abstract PlayerId(Array<Dynamic>) {
public var team(default, null):TeamId; public var team(get, never):TeamId;
public var index(default, null):Int; public var index(get, never):Int;
private var _hashCode(default, null):Int;
public function new(team:TeamId, index:Int) { public function new(team:TeamId, index:Int) {
this.team = team; this = [team, index];
this.index = index;
this._hashCode = Crc32.make(Bytes.ofString('${team}-${index}'));
} }
public function hashCode():Int { private inline function get_team():TeamId return this[0];
return _hashCode;
private inline function get_index():Int return this[1];
@:to public inline function toString():String {
return '${team}:${index}';
} }
} }

View File

@@ -5,7 +5,6 @@ import haxe.Timer;
import haxework.provider.Provider; import haxework.provider.Provider;
import promhx.Deferred; import promhx.Deferred;
import promhx.Stream; import promhx.Stream;
import ru.m.geom.Direction;
import ru.m.geom.Point; import ru.m.geom.Point;
import ru.m.tankz.bundle.IConfigBundle; import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.bundle.ILevelBundle; import ru.m.tankz.bundle.ILevelBundle;
@@ -18,17 +17,17 @@ import ru.m.tankz.core.Entity;
import ru.m.tankz.core.EntityType; import ru.m.tankz.core.EntityType;
import ru.m.tankz.core.Tank; import ru.m.tankz.core.Tank;
import ru.m.tankz.engine.Engine; import ru.m.tankz.engine.Engine;
import ru.m.tankz.game.GameState; import ru.m.tankz.game.GameStart;
import ru.m.tankz.game.Spawner; import ru.m.tankz.game.Spawner;
import ru.m.tankz.Type; import ru.m.tankz.Type;
class Game { class Game {
private static var TAG(default, never):String = 'Game'; private static var TAG(default, never):String = 'Game';
public var type(default, null):GameType; public var type(default, null):GameType;
public var state(default, null):GameState; public var level(default, null):Int;
public var players(default, null):Array<PlayerStart>;
public var preset(default, null):GamePreset; 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;
@@ -36,10 +35,11 @@ class Game {
public var loser(default, null):Null<TeamId>; 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<Dynamic>;
private var stream:Stream<GameState>; private var stream:Stream<Dynamic>;
@:provide var configBundle:IConfigBundle; @:provide var configBundle:IConfigBundle;
@:provide var levelBundle:ILevelBundle;
public function new(type:GameType) { public function new(type:GameType) {
this.type = type; this.type = type;
@@ -81,29 +81,34 @@ class Game {
entity.rect.direction = point.direction; entity.rect.direction = point.direction;
} }
public function start(state:GameState):Stream<GameState> { public function start(start:GameStart):Stream<Dynamic> {
this.state = state; this.players = start.players;
var players = players.slice(0);
this.loser = null; this.loser = null;
this.preset = config.getPreset(state.presetId); this.preset = config.getPreset(start.presetId);
this.level = start.level;
this.deferred = new Deferred(); this.deferred = new Deferred();
var level:LevelConfig = Provider.get(ILevelBundle).get(type, config, state.level); var level:LevelConfig = levelBundle.get(type, config, start.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>();
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, state); var team:Team = new Team(teamConfig, teamPoints);
teams[team.id] = team; teams[team.id] = team;
for (player in team.players.iterator()) { for (player in team.players.iterator()) {
var controlType: ControlType = state.control.get(player.id); var controlType:ControlType = Control.BOT;
if (controlType != null) { var nextPlayer = Lambda.find(players, function(p) return p.playerId != null && p.playerId.team == team.id);
var control = controlFactory.build(player.id, controlType); if (nextPlayer != null) {
L.d(TAG, 'control(${player.id} - ${control})'); players.remove(nextPlayer);
if (control != null) { controlType = nextPlayer.control;
player.control = control; }
player.control.bind(engine); var control = controlFactory.build(player.id, controlType);
} L.d(TAG, 'control(${player.id} - ${control})');
if (control != null) {
player.control = control;
player.control.bind(engine);
} }
} }
team.spawner.runner = spawn; team.spawner.runner = spawn;
@@ -140,7 +145,7 @@ class Game {
} else if (!team.isAlive) { } else if (!team.isAlive) {
lose(team.id); lose(team.id);
} }
deferred.resolve(state); deferred.resolve(null);
} }
private function complete():Void { private function complete():Void {
@@ -151,7 +156,7 @@ class Game {
} }
} }
Timer.delay(function() { Timer.delay(function() {
deferred.resolve(state); deferred.resolve(null);
stream.end(); stream.end();
}, 5000); }, 5000);
} }
@@ -160,6 +165,8 @@ class Game {
switch (entity) { switch (entity) {
case EntityType.TANK(tank): case EntityType.TANK(tank):
getPlayer(tank.playerId).control.start(); getPlayer(tank.playerId).control.start();
case EntityType.BULLET(bullet):
getPlayer(bullet.playerId).state.shots++;
case _: case _:
} }
} }
@@ -169,7 +176,7 @@ class Game {
case [EntityType.EAGLE(eagle), EntityChange.DEATH]: case [EntityType.EAGLE(eagle), EntityChange.DEATH]:
if (eagle.death) { if (eagle.death) {
lose(eagle.team); lose(eagle.team);
deferred.resolve(state); deferred.resolve(null);
} }
case [EntityType.TANK(tank), EntityChange.HIT]: case [EntityType.TANK(tank), EntityChange.HIT]:
if (tank.bonus) { if (tank.bonus) {
@@ -192,6 +199,8 @@ class Game {
switch [entity, with] { switch [entity, with] {
case [EntityType.TANK(tank), EntityType.BONUS(bonus)]: case [EntityType.TANK(tank), EntityType.BONUS(bonus)]:
applyBonus(tank, bonus); applyBonus(tank, bonus);
case [EntityType.BULLET(bullet), EntityType.TANK(tank)]:
getPlayer(bullet.playerId).state.hits++;
case _: case _:
} }
} }
@@ -214,14 +223,15 @@ class Game {
spawnBonus(); spawnBonus();
} }
if (tank.config.score > 0 && playerId != null) { if (tank.config.score > 0 && playerId != null) {
getPlayer(playerId).state.frags++;
getPlayer(playerId).state.score += tank.config.score; getPlayer(playerId).state.score += tank.config.score;
} }
deferred.resolve(state); deferred.resolve(null);
case EntityType.BONUS(bonus): case EntityType.BONUS(bonus):
if (bonus.config.score > 0 && playerId != null) { if (bonus.config.score > 0 && playerId != null) {
getPlayer(playerId).state.score += bonus.config.score; getPlayer(playerId).state.score += bonus.config.score;
} }
deferred.resolve(state); deferred.resolve(null);
case _: case _:
} }
} }
@@ -235,15 +245,15 @@ class Game {
engine.action(tankId, action); engine.action(tankId, action);
} }
public function next():Option<GameState> { public function next():Option<GameStart> {
for (rule in config.game.complete) { for (rule in config.game.complete) {
if (rule.team != null && rule.team == loser) { if (rule.team != null && rule.team == loser) {
return Option.None; return Option.None;
} }
} }
state.level++; var level = this.level + 1;
if (state.level >= config.game.levels) state.level = 0; if (level >= config.game.levels) level = 0;
return Option.Some(state); return Option.Some(new GameStart(type, preset.id, level, players));
} }
public function dispose():Void { public function dispose():Void {
@@ -298,8 +308,4 @@ class Game {
engine.destroy(tank); // :-D engine.destroy(tank); // :-D
} }
} }
public function save():GameState {
return state;
}
} }

View File

@@ -0,0 +1,34 @@
package ru.m.tankz.game;
import ru.m.tankz.config.Config;
import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.Type;
typedef PlayerStart = {
var playerId: PlayerId;
var control:ControlType;
}
class GameStart {
@:provide private var configBundle:IConfigBundle;
public var type(default, default):GameType;
public var presetId(default, default):PresetId;
public var level(default, default):Int;
public var players(default, default):Array<PlayerStart>;
public var preset(get, null):GamePreset;
public function new(type:GameType, presetId:PresetId, level:Int = 0, players:Array<PlayerStart> = null) {
this.type = type;
this.presetId = presetId;
this.level = level;
this.players = players == null ? [] : players;
}
private function get_preset():GamePreset {
var config = configBundle.get(type);
var preset = config.getPreset(presetId);
return preset;
}
}

View File

@@ -1,33 +0,0 @@
package ru.m.tankz.game;
import ru.m.tankz.game.Player.PlayerState;
import haxe.ds.HashMap;
import ru.m.tankz.Type;
class GameState {
public var type(default, null):GameType;
public var presetId(default, null):PresetId;
public var control(default, null):HashMap<PlayerId, ControlType>;
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

@@ -4,11 +4,13 @@ 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;
typedef PlayerState = { typedef PlayerState = {
var tank:TankType; var tank:TankType;
var life:Int; var life:Int;
var score:Int; var score:Int;
var shots:Int;
var hits:Int;
var frags:Int;
} }
class Player { class Player {
@@ -27,6 +29,9 @@ class Player {
life: config.life, life: config.life,
tank: null, tank: null,
score: 0, score: 0,
shots: 0,
hits: 0,
frags: 0,
} }
} }

View File

@@ -3,7 +3,6 @@ package ru.m.tankz.game;
import ru.m.tankz.Type; import ru.m.tankz.Type;
import ru.m.tankz.config.Config; import ru.m.tankz.config.Config;
class Team { class Team {
public var id(default, null):TeamId; public var id(default, null):TeamId;
@@ -14,14 +13,12 @@ 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>, ?state:GameState) { public function new(config:TeamConfig, points:Array<SpawnPoint>) {
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 = state.players.get(player.id);
if (state != null) player.state = state;
this.players[playerConfig.index] = player; this.players[playerConfig.index] = player;
} }
this.life = config.life; this.life = config.life;

View File

@@ -9,7 +9,7 @@ class DbProvider {
private var orm:Orm; private var orm:Orm;
public function new() { public function new() {
var db = new orm.Db("mysql://shmyga:xkbp8jh9z2@localhost:3306/armageddon"); var db = new orm.Db("mysql://shmyga:password@localhost:3306/armageddon");
orm = new Orm(db); orm = new Orm(db);
} }