[common] diffilicity presets support
This commit is contained in:
@@ -28,6 +28,7 @@ class ButtonSVGSkin implements ISkin<ButtonView> {
|
||||
svgs.set(ButtonState.UP, buildSVG(color));
|
||||
svgs.set(ButtonState.DOWN, buildSVG(ColorUtil.diff(color, -24)));
|
||||
svgs.set(ButtonState.OVER, buildSVG(ColorUtil.diff(color, 24)));
|
||||
svgs.set(ButtonState.DISABLED, buildSVG(ColorUtil.grey(color)));
|
||||
}
|
||||
|
||||
public function draw(view:ButtonView):Void {
|
||||
|
||||
@@ -134,5 +134,38 @@ class Style {
|
||||
Skin.size(64, 64),
|
||||
new ButtonSVGSkin(Assets.getText("resources/image/icon/play-circle-solid.svg"), lightColor),
|
||||
]);
|
||||
|
||||
resources.skin.put("preset.easy", [
|
||||
Skin.size(64, 64),
|
||||
new ButtonSVGSkin(Assets.getText("resources/image/icon/smile-solid.svg"), lightColor),
|
||||
]);
|
||||
resources.skin.put("preset.normal", [
|
||||
Skin.size(64, 64),
|
||||
new ButtonSVGSkin(Assets.getText("resources/image/icon/frown-open-solid.svg"), lightColor),
|
||||
]);
|
||||
resources.skin.put("preset.hard", [
|
||||
Skin.size(64, 64),
|
||||
new ButtonSVGSkin(Assets.getText("resources/image/icon/sad-cry-solid.svg"), lightColor),
|
||||
]);
|
||||
resources.skin.put("preset.default", [
|
||||
Skin.size(64, 64),
|
||||
new ButtonSVGSkin(Assets.getText("resources/image/icon/play-circle-solid.svg"), lightColor),
|
||||
]);
|
||||
resources.skin.put("preset.easy.complete", [
|
||||
Skin.size(64, 64),
|
||||
new ButtonSVGSkin(Assets.getText("resources/image/icon/smile-solid.svg"), 0x337733),
|
||||
]);
|
||||
resources.skin.put("preset.normal.complete", [
|
||||
Skin.size(64, 64),
|
||||
new ButtonSVGSkin(Assets.getText("resources/image/icon/frown-open-solid.svg"), 0x337733),
|
||||
]);
|
||||
resources.skin.put("preset.hard.complete", [
|
||||
Skin.size(64, 64),
|
||||
new ButtonSVGSkin(Assets.getText("resources/image/icon/sad-cry-solid.svg"), 0x337733),
|
||||
]);
|
||||
resources.skin.put("preset.default.complete", [
|
||||
Skin.size(64, 64),
|
||||
new ButtonSVGSkin(Assets.getText("resources/image/icon/play-circle-solid.svg"), 0x337733),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,12 @@ class LevelBundle implements ILevelBundle {
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function get(type:GameType, config:Config, level:Int):LevelConfig {
|
||||
var key = '${type}:${level}';
|
||||
public function get(type:GameType, config:Config, levelId:LevelId):LevelConfig {
|
||||
var key = '${type}:${levelId}';
|
||||
if (!cache.exists(key)) {
|
||||
var data:String = Assets.getText('resources/${type}/levels/level${LevelUtil.formatLevel(level)}.txt');
|
||||
var data:String = Assets.getText('resources/${type}/levels/level${LevelUtil.formatLevel(levelId)}.txt');
|
||||
cache[key] = LevelUtil.loads(config, data);
|
||||
cache[key].index = level;
|
||||
cache[key].id = levelId;
|
||||
}
|
||||
return cache[key];
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package ru.m.tankz.control;
|
||||
|
||||
import ru.m.tankz.bot.StupidBotControl;
|
||||
import ru.m.tankz.bot.HardBotControl;
|
||||
import ru.m.tankz.control.Control.Controller;
|
||||
import ru.m.tankz.Type;
|
||||
|
||||
class ClientControlFactory implements IControlFactory {
|
||||
|
||||
@@ -6,8 +6,10 @@ import ru.m.tankz.Type.GameType;
|
||||
|
||||
class GameStorage extends SharedObjectStorage {
|
||||
|
||||
private static inline var VERSION = 1;
|
||||
|
||||
public function new() {
|
||||
super("game");
|
||||
super('game_${VERSION}');
|
||||
}
|
||||
|
||||
public function get(type:GameType):GameProgress {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ru.m.tankz.view;
|
||||
|
||||
import haxework.resources.IResources;
|
||||
import haxework.view.ButtonView;
|
||||
import haxework.view.DataView;
|
||||
import haxework.view.frame.FrameSwitcher;
|
||||
@@ -13,6 +12,7 @@ import ru.m.tankz.preset.ClassicGame;
|
||||
import ru.m.tankz.preset.DeathGame;
|
||||
import ru.m.tankz.preset.DotaGame;
|
||||
import ru.m.tankz.storage.GameStorage;
|
||||
import ru.m.tankz.Type;
|
||||
import ru.m.tankz.view.classic.ClassicGameFrame;
|
||||
import ru.m.tankz.view.death.DeathGameFrame;
|
||||
import ru.m.tankz.view.dota.DotaGameFrame;
|
||||
@@ -22,10 +22,9 @@ import ru.m.tankz.view.popup.LevelPopup;
|
||||
public static inline var ID = "level";
|
||||
|
||||
@:view var header:LabelView;
|
||||
@:view var levels:DataView<Int, ButtonView>;
|
||||
@:view var levels:DataView<LevelId, ButtonView>;
|
||||
|
||||
@:provide var state:GameState;
|
||||
@:provide var resources:IResources;
|
||||
@:provide var switcher:FrameSwitcher;
|
||||
@:provide var levelBundle:ILevelBundle;
|
||||
@:provide var storage:GameStorage;
|
||||
@@ -37,8 +36,9 @@ import ru.m.tankz.view.popup.LevelPopup;
|
||||
levels.data = [for (i in 0...state.config.game.levels) i];
|
||||
}
|
||||
|
||||
private function start(level:LevelConfig):Void {
|
||||
state.level = level.index;
|
||||
private function start(level:LevelConfig, preset:GamePreset):Void {
|
||||
state.levelId = level.id;
|
||||
state.presetId = preset.id;
|
||||
switcher.change(switch state.type {
|
||||
case ClassicGame.TYPE: ClassicGameFrame.ID;
|
||||
case DotaGame.TYPE: DotaGameFrame.ID;
|
||||
@@ -47,22 +47,29 @@ import ru.m.tankz.view.popup.LevelPopup;
|
||||
});
|
||||
}
|
||||
|
||||
private function levelViewFactory(index:Int, level:Int):ButtonView {
|
||||
private function levelViewFactory(index:Int, levelId:LevelId):ButtonView {
|
||||
var progress = storage.get(state.type);
|
||||
var result = new ButtonView();
|
||||
result.skinId = "button.level";
|
||||
result.text = '${level}';
|
||||
result.disabled = !storage.get(state.type).isLevelAvailable(level);
|
||||
var presetsLine = [for (p in state.config.presets) progress.isPresetCompleted(levelId, p.id) ? '*' : '_'].join('');
|
||||
result.text = '${levelId}\n${presetsLine}';
|
||||
result.disabled = !progress.isLevelAvailable(levelId);
|
||||
return result;
|
||||
}
|
||||
|
||||
private function onLevelSelect(index:Int, level:Int, view:ButtonView):Void {
|
||||
if (!storage.get(state.type).isLevelAvailable(level)) {
|
||||
private function onLevelSelect(index:Int, levelId:LevelId, view:ButtonView):Void {
|
||||
if (!storage.get(state.type).isLevelAvailable(levelId)) {
|
||||
return;
|
||||
}
|
||||
if (levelPopup == null) {
|
||||
levelPopup = new LevelPopup();
|
||||
}
|
||||
levelPopup.level = levelBundle.get(state.type, state.config, level);
|
||||
levelPopup.show().then(start).catchError(function(_) {});
|
||||
var level = levelBundle.get(state.type, state.config, levelId);
|
||||
levelPopup.setData(
|
||||
level,
|
||||
state.config.presets,
|
||||
storage.get(state.type)
|
||||
);
|
||||
levelPopup.show().then(function(preset) start(level, preset)).catchError(function(_) {});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package ru.m.tankz.view;
|
||||
|
||||
import haxework.view.LabelView;
|
||||
import haxework.view.ButtonView;
|
||||
import haxework.view.DataView;
|
||||
import haxework.view.frame.FrameSwitcher;
|
||||
import haxework.view.LabelView;
|
||||
import haxework.view.VGroupView;
|
||||
import ru.m.tankz.control.Control;
|
||||
import ru.m.tankz.view.classic.ClassicGameFrame;
|
||||
import ru.m.tankz.view.common.LifeView;
|
||||
import ru.m.tankz.view.dota.DotaGameFrame;
|
||||
import ru.m.tankz.game.GameState;
|
||||
import ru.m.tankz.preset.ClassicGame;
|
||||
import ru.m.tankz.preset.DotaGame;
|
||||
import ru.m.tankz.view.classic.ClassicGameFrame;
|
||||
import ru.m.tankz.view.common.LifeView;
|
||||
import ru.m.tankz.view.dota.DotaGameFrame;
|
||||
|
||||
@:template class ResultFrame extends VGroupView {
|
||||
public static var ID(default, never):String = "result";
|
||||
@@ -37,11 +36,8 @@ import ru.m.tankz.preset.DotaGame;
|
||||
}
|
||||
|
||||
public function onShow() {
|
||||
resultView.data = Lambda.array(Lambda.filter(resultState.players, function(player:PlayerState):Bool return switch player.controller {
|
||||
case HUMAN(_): true;
|
||||
case _: false;
|
||||
}));
|
||||
levelLabel.text = 'Level ${resultState.level}';
|
||||
resultView.data = Lambda.array(resultState.players);
|
||||
levelLabel.text = 'Level ${resultState.levelId}';
|
||||
nextButton.visible = state != null;
|
||||
}
|
||||
|
||||
@@ -54,6 +50,6 @@ import ru.m.tankz.preset.DotaGame;
|
||||
}
|
||||
|
||||
private function close() {
|
||||
frames.change(StartFrame.ID);
|
||||
frames.change(LevelFrame.ID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import ru.m.tankz.view.common.LifeView;
|
||||
private var player2Id:PlayerId = new PlayerId(ClassicGame.HUMAN, 1);
|
||||
|
||||
public function onGameStart(state:GameState):Void {
|
||||
level.text = 'Level ${state.level}';
|
||||
level.text = 'Level ${state.levelId}';
|
||||
}
|
||||
|
||||
public function onGameChange(state:GameState):Void {
|
||||
|
||||
@@ -81,7 +81,7 @@ class GameFrame extends GroupView {
|
||||
case Some(s):
|
||||
// ToDo:
|
||||
var progress = storage.get(game.type);
|
||||
progress.completeLevel(result.level);
|
||||
progress.completeLevel(result.levelId, result.presetId);
|
||||
storage.set(progress);
|
||||
s;
|
||||
case None: null;
|
||||
|
||||
@@ -14,7 +14,7 @@ import ru.m.tankz.view.common.LifeView;
|
||||
@:view var players:DataView<PlayerState, LifeView>;
|
||||
|
||||
public function onGameStart(state:GameState):Void {
|
||||
level.text = 'Level ${state.level}';
|
||||
level.text = 'Level ${state.levelId}';
|
||||
players.data = Lambda.array(state.players);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import ru.m.tankz.view.common.LifeView;
|
||||
@:view var level:LabelView;
|
||||
|
||||
public function onGameStart(state:GameState):Void {
|
||||
level.text = 'Level ${state.level}';
|
||||
level.text = 'Level ${state.levelId}';
|
||||
}
|
||||
|
||||
public function onGameChange(state:GameState):Void {
|
||||
|
||||
@@ -1,20 +1,37 @@
|
||||
package ru.m.tankz.view.popup;
|
||||
|
||||
import haxework.view.ButtonView;
|
||||
import haxework.view.DataView;
|
||||
import haxework.view.LabelView;
|
||||
import haxework.view.popup.PopupView;
|
||||
import ru.m.tankz.config.Config;
|
||||
import ru.m.tankz.game.GameProgress;
|
||||
|
||||
@:template class LevelPopup extends PopupView<LevelConfig> {
|
||||
@:template class LevelPopup extends PopupView<GamePreset> {
|
||||
|
||||
public var level(default, set):LevelConfig;
|
||||
private var level:LevelConfig;
|
||||
private var progress:GameProgress;
|
||||
|
||||
@:view var name:LabelView;
|
||||
@:view("presets") var presetsView:DataView<GamePreset, ButtonView>;
|
||||
|
||||
private function set_level(value:LevelConfig):LevelConfig {
|
||||
if (level != value) {
|
||||
level = value;
|
||||
name.text = '${level.index}. ${level.name != null ? level.name : "#"}';
|
||||
public function setData(level:LevelConfig, presets:Array<GamePreset>, progress:GameProgress):Void {
|
||||
this.level = level;
|
||||
this.progress = progress;
|
||||
name.text = '${level.id}. ${level.name != null ? level.name : "#"}';
|
||||
presetsView.data = presets;
|
||||
}
|
||||
|
||||
private function presetViewFactory(index:Int, value:GamePreset):ButtonView {
|
||||
var result = new ButtonView();
|
||||
result.skinId = 'preset.${value.name}${progress.isPresetCompleted(level.id, value.id) ? '.complete' : ''}';
|
||||
result.disabled = !progress.isPresetAvailable(level.id, value.id);
|
||||
return result;
|
||||
}
|
||||
|
||||
private function onPresetSelect(value:GamePreset):Void {
|
||||
if (progress.isPresetAvailable(level.id, value.id)) {
|
||||
close(value);
|
||||
}
|
||||
return level;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,12 @@ view:
|
||||
geometry.padding: [20, 15]
|
||||
- $type: haxework.view.SpriteView
|
||||
geometry.size.height: 100%
|
||||
- $type: haxework.view.HGroupView
|
||||
layout.hAlign: center
|
||||
- id: presets
|
||||
$type: haxework.view.DataView
|
||||
factory: $this:presetViewFactory
|
||||
+onDataSelect: $this:onPresetSelect
|
||||
layout:
|
||||
$type: haxework.view.layout.HorizontalLayout
|
||||
hAlign: center
|
||||
margin: 5
|
||||
skinId: panel
|
||||
views:
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: button.start
|
||||
+onPress: $code:close(level)
|
||||
|
||||
1
src/client/resources/image/icon/frown-open-solid.svg
Normal file
1
src/client/resources/image/icon/frown-open-solid.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="frown-open" class="svg-inline--fa fa-frown-open fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zM136 208c0-17.7 14.3-32 32-32s32 14.3 32 32-14.3 32-32 32-32-14.3-32-32zm187.3 183.3c-31.2-9.6-59.4-15.3-75.3-15.3s-44.1 5.7-75.3 15.3c-11.5 3.5-22.5-6.3-20.5-18.1 7-40 60.1-61.2 95.8-61.2s88.8 21.3 95.8 61.2c2 11.9-9.1 21.6-20.5 18.1zM328 240c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32z"></path></svg>
|
||||
|
After Width: | Height: | Size: 617 B |
1
src/client/resources/image/icon/sad-cry-solid.svg
Normal file
1
src/client/resources/image/icon/sad-cry-solid.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="sad-cry" class="svg-inline--fa fa-sad-cry fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256c0 90.1 48.2 168.7 120 212.1V288c0-8.8 7.2-16 16-16s16 7.2 16 16v196.7c29.5 12.4 62 19.3 96 19.3s66.5-6.9 96-19.3V288c0-8.8 7.2-16 16-16s16 7.2 16 16v180.1C447.8 424.7 496 346 496 256 496 119 385 8 248 8zm-65.5 216.5c-14.8-13.2-46.2-13.2-61 0L112 233c-3.8 3.3-9.3 4-13.7 1.6-4.4-2.4-6.9-7.4-6.1-12.4 4-25.2 34.2-42.1 59.9-42.1S208 197 212 222.2c.8 5-1.7 10-6.1 12.4-5.8 3.1-11.2.7-13.7-1.6l-9.7-8.5zM248 416c-26.5 0-48-28.7-48-64s21.5-64 48-64 48 28.7 48 64-21.5 64-48 64zm149.8-181.5c-5.8 3.1-11.2.7-13.7-1.6l-9.5-8.5c-14.8-13.2-46.2-13.2-61 0L304 233c-3.8 3.3-9.3 4-13.7 1.6-4.4-2.4-6.9-7.4-6.1-12.4 4-25.2 34.2-42.1 59.9-42.1S400 197 404 222.2c.6 4.9-1.8 9.9-6.2 12.3z"></path></svg>
|
||||
|
After Width: | Height: | Size: 929 B |
1
src/client/resources/image/icon/smile-solid.svg
Normal file
1
src/client/resources/image/icon/smile-solid.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="smile" class="svg-inline--fa fa-smile fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm80 168c17.7 0 32 14.3 32 32s-14.3 32-32 32-32-14.3-32-32 14.3-32 32-32zm-160 0c17.7 0 32 14.3 32 32s-14.3 32-32 32-32-14.3-32-32 14.3-32 32-32zm194.8 170.2C334.3 380.4 292.5 400 248 400s-86.3-19.6-114.8-53.8c-13.6-16.3 11-36.7 24.6-20.5 22.4 26.9 55.2 42.2 90.2 42.2s67.8-15.4 90.2-42.2c13.4-16.2 38.1 4.2 24.6 20.5z"></path></svg>
|
||||
|
After Width: | Height: | Size: 616 B |
@@ -37,4 +37,5 @@ abstract PlayerId(Array<Dynamic>) {
|
||||
}
|
||||
}
|
||||
|
||||
typedef PresetId = String;
|
||||
typedef LevelId = Int;
|
||||
typedef PresetId = Int;
|
||||
|
||||
@@ -3,7 +3,6 @@ package ru.m.tankz.bundle;
|
||||
import ru.m.tankz.config.Config;
|
||||
import ru.m.tankz.Type;
|
||||
|
||||
|
||||
interface ILevelBundle {
|
||||
public function get(type:GameType, config:Config, level:Int):LevelConfig;
|
||||
public function get(type:GameType, config:Config, levelId:LevelId):LevelConfig;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ typedef PlayerConfig = {
|
||||
@:optional var protect:Float;
|
||||
@:optional var life:Int;
|
||||
@:optional var color:Color;
|
||||
@:optional var human:Int;
|
||||
@:optional var control:String;
|
||||
}
|
||||
|
||||
typedef EagleConfig = {
|
||||
@@ -93,11 +93,12 @@ typedef TeamConfig = {
|
||||
|
||||
typedef GamePreset = {
|
||||
var id:PresetId;
|
||||
var name:String;
|
||||
var teams:Array<TeamConfig>;
|
||||
}
|
||||
|
||||
typedef LevelConfig = {
|
||||
@:optional var index:Int;
|
||||
@:optional var id:LevelId;
|
||||
var data:Array<BrickConfig>;
|
||||
@:optional var name:String;
|
||||
@:optional var points:Array<SpawnPoint>;
|
||||
|
||||
@@ -13,12 +13,6 @@ enum TankAction {
|
||||
SHOT;
|
||||
}
|
||||
|
||||
enum Controller {
|
||||
NONE;
|
||||
HUMAN(index:Int);
|
||||
BOT(type:String);
|
||||
}
|
||||
|
||||
class Control {
|
||||
public var playerId(default, null):PlayerId;
|
||||
public var tankId(default, default):Int;
|
||||
|
||||
26
src/common/haxe/ru/m/tankz/control/Controller.hx
Normal file
26
src/common/haxe/ru/m/tankz/control/Controller.hx
Normal file
@@ -0,0 +1,26 @@
|
||||
package ru.m.tankz.control;
|
||||
|
||||
enum Controller {
|
||||
NONE;
|
||||
HUMAN(index:Int);
|
||||
BOT(type:String);
|
||||
}
|
||||
|
||||
abstract AController(Controller) {
|
||||
|
||||
public inline function new(value:Controller) {
|
||||
this = value;
|
||||
}
|
||||
|
||||
@:from public static function fromString(value:String):AController {
|
||||
return new AController(switch value.split("-") {
|
||||
case ["human", index]: HUMAN(Std.parseInt(index));
|
||||
case ["bot", type]: BOT(type);
|
||||
case _: NONE;
|
||||
});
|
||||
}
|
||||
|
||||
@:to public inline function toController():Controller {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package ru.m.tankz.game;
|
||||
|
||||
import ru.m.tankz.control.Controller.AController;
|
||||
import haxe.ds.Option;
|
||||
import haxe.Timer;
|
||||
import haxework.signal.Signal;
|
||||
import ru.m.geom.Point;
|
||||
import ru.m.tankz.bundle.IConfigBundle;
|
||||
import ru.m.tankz.bundle.ILevelBundle;
|
||||
import ru.m.tankz.config.Config;
|
||||
import ru.m.tankz.control.Control;
|
||||
import ru.m.tankz.control.IControlFactory;
|
||||
@@ -62,7 +62,6 @@ class Game extends GameDispatcher {
|
||||
private var points:Array<SpawnPoint>;
|
||||
|
||||
@:provide var configBundle:IConfigBundle;
|
||||
@:provide var levelBundle:ILevelBundle;
|
||||
@:provide var controlFactory:IControlFactory;
|
||||
|
||||
public function new(type:GameType) {
|
||||
@@ -109,7 +108,7 @@ class Game extends GameDispatcher {
|
||||
public function start(state:GameState):Void {
|
||||
this.state = state;
|
||||
this.winner = null;
|
||||
var level:LevelConfig = levelBundle.get(type, config, state.level);
|
||||
var level:LevelConfig = state.level;
|
||||
points = level.points != null ? level.points : config.points;
|
||||
engine.map.setData(level.data);
|
||||
teams = new Map<TeamId, Team>();
|
||||
@@ -118,10 +117,7 @@ class Game extends GameDispatcher {
|
||||
var team:Team = new Team(teamConfig, teamPoints, state.teams[teamConfig.id]);
|
||||
teams[team.id] = team;
|
||||
for (player in team.players.iterator()) {
|
||||
if (player.state.controller == NONE) {
|
||||
player.state.controller = BOT("hard");
|
||||
}
|
||||
var control = controlFactory.build(player.id, player.state.controller);
|
||||
var control = controlFactory.build(player.id, AController.fromString(player.config.control));
|
||||
L.d(TAG, 'control(${player.id} - ${control})');
|
||||
if (control != null) {
|
||||
player.control = control;
|
||||
@@ -288,7 +284,7 @@ class Game extends GameDispatcher {
|
||||
return Option.None;
|
||||
}
|
||||
}
|
||||
var level = this.state.level + 1;
|
||||
var level = this.state.levelId + 1;
|
||||
if (level >= config.game.levels) level = 0;
|
||||
return Option.Some(new GameState(type, state.presetId, level, state));
|
||||
}
|
||||
|
||||
@@ -1,22 +1,45 @@
|
||||
package ru.m.tankz.game;
|
||||
|
||||
import ru.m.tankz.Type.GameType;
|
||||
import ru.m.tankz.Type;
|
||||
|
||||
typedef LevelResult = {
|
||||
|
||||
}
|
||||
|
||||
typedef LevelProgress = {
|
||||
var id:LevelId;
|
||||
var presets:Map<Int, LevelResult>;
|
||||
}
|
||||
|
||||
class GameProgress {
|
||||
|
||||
public var type(default, null):GameType;
|
||||
private var completed(default, null):Map<Int, Bool>;
|
||||
private var completed(default, null):Map<Int, LevelProgress>;
|
||||
|
||||
public function new(type:GameType) {
|
||||
this.type = type;
|
||||
this.completed = new Map();
|
||||
}
|
||||
|
||||
public function isLevelAvailable(level:Int):Bool {
|
||||
return level == 0 || completed.get(level - 1);
|
||||
public function isLevelAvailable(levelId:LevelId):Bool {
|
||||
return levelId == 0 || completed.exists(levelId - 1);
|
||||
}
|
||||
|
||||
public function completeLevel(level:Int):Void {
|
||||
completed.set(level, true);
|
||||
public function isPresetAvailable(levelId:LevelId, presetId:PresetId):Bool {
|
||||
return presetId == 0 || completed.exists(levelId) && completed.get(levelId).presets.get(presetId - 1) != null;
|
||||
}
|
||||
|
||||
public function isPresetCompleted(levelId:LevelId, presetId:PresetId):Bool {
|
||||
return completed.exists(levelId) && completed.get(levelId).presets.get(presetId) != null;
|
||||
}
|
||||
|
||||
public function completeLevel(levelId:LevelId, presetId:PresetId):Void {
|
||||
if (!completed.exists(levelId)) {
|
||||
completed[levelId] = {
|
||||
id: levelId,
|
||||
presets: new Map(),
|
||||
}
|
||||
}
|
||||
completed[levelId].presets[presetId] = {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package ru.m.tankz.game;
|
||||
|
||||
import haxework.color.Color;
|
||||
import ru.m.tankz.bundle.IConfigBundle;
|
||||
import ru.m.tankz.bundle.ILevelBundle;
|
||||
import ru.m.tankz.config.Config;
|
||||
import ru.m.tankz.control.Control;
|
||||
import ru.m.tankz.Type;
|
||||
|
||||
class State {
|
||||
@@ -34,16 +34,14 @@ class State {
|
||||
class PlayerState extends State {
|
||||
public var id:PlayerId;
|
||||
public var tank:TankType;
|
||||
public var controller:Controller;
|
||||
public var color:Color;
|
||||
public var life:Int;
|
||||
public var total:State;
|
||||
|
||||
public function new(id:PlayerId, controller:Controller = null) {
|
||||
public function new(id:PlayerId) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.tank = null;
|
||||
this.controller = controller == null ? Controller.NONE : controller;
|
||||
this.life = 0;
|
||||
this.total = new State();
|
||||
}
|
||||
@@ -70,18 +68,20 @@ class GameState {
|
||||
|
||||
public var type:GameType;
|
||||
public var presetId:PresetId;
|
||||
public var level:Int;
|
||||
public var levelId:LevelId;
|
||||
public var players:Map<String, PlayerState>;
|
||||
public var teams:Map<TeamId, TeamState>;
|
||||
public var preset(get, null):GamePreset;
|
||||
public var config(get, null):Config;
|
||||
public var level(get, null):LevelConfig;
|
||||
|
||||
@:provide private var configBundle:IConfigBundle;
|
||||
@:provide private var levelBundle:ILevelBundle;
|
||||
|
||||
public function new(type:GameType, presetId:PresetId = null, level:Int = 0, state:GameState = null) {
|
||||
public function new(type:GameType, presetId:PresetId = 0, levelId:Int = 0, state:GameState = null) {
|
||||
this.type = type;
|
||||
this.presetId = presetId != null ? presetId : config.presets[0].id;
|
||||
this.level = level;
|
||||
this.presetId = presetId;
|
||||
this.levelId = levelId;
|
||||
if (state == null) {
|
||||
this.teams = new Map();
|
||||
this.players = new Map();
|
||||
@@ -89,8 +89,7 @@ class GameState {
|
||||
var teamState = new TeamState(team.id);
|
||||
for (player in team.players) {
|
||||
var playerId = new PlayerId(team.id, player.index);
|
||||
var controller = player.human > 0 ? HUMAN(player.human - 1) : NONE;
|
||||
var playerState = new PlayerState(playerId, controller);
|
||||
var playerState = new PlayerState(playerId);
|
||||
players[playerId] = playerState;
|
||||
teamState.players[player.index] = playerState;
|
||||
}
|
||||
@@ -112,6 +111,10 @@ class GameState {
|
||||
return configBundle.get(type);
|
||||
}
|
||||
|
||||
private function get_level():LevelConfig {
|
||||
return levelBundle.get(type, config, levelId);
|
||||
}
|
||||
|
||||
public function getTeamLife(id:TeamId):Int {
|
||||
if (teams.exists(id)) {
|
||||
return teams[id].life + Lambda.fold(teams[id].players, function(p, c) return c + p.life, 0);
|
||||
|
||||
@@ -34,39 +34,6 @@ player:
|
||||
- {type: bot2, rate: 0.27}
|
||||
- {type: bot3, rate: 0.15}
|
||||
|
||||
presets:
|
||||
# player1
|
||||
- id: 1 Player
|
||||
teams:
|
||||
- id: human
|
||||
players:
|
||||
- {<<: *human, index: 0, color: 0xFFFF00, human: 1}
|
||||
- id: bot
|
||||
spawnInterval: 3000
|
||||
life: 20
|
||||
players:
|
||||
- {<<: *bot, index: 0}
|
||||
- {<<: *bot, index: 1}
|
||||
- {<<: *bot, index: 2}
|
||||
- {<<: *bot, index: 3}
|
||||
# player2
|
||||
- id: 2 Players
|
||||
teams:
|
||||
- id: human
|
||||
players:
|
||||
- {<<: *human, index: 0, color: 0xFFFF00, human: 1}
|
||||
- {<<: *human, index: 1, color: 0x15C040, human: 2}
|
||||
- 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:
|
||||
- {team: human, type: eagle, index: -1, direction: right, x: 12, y: 24}
|
||||
- {team: human, type: tank, index: 0, direction: top, x: 8, y: 24}
|
||||
@@ -116,7 +83,6 @@ tanks:
|
||||
skin: pc
|
||||
|
||||
- type: human3
|
||||
# upgrade: human3
|
||||
downgrade: human2
|
||||
width: 42
|
||||
height: 38
|
||||
@@ -181,3 +147,49 @@ bonuses:
|
||||
- {score: 500, type: shovel, duration: 10}
|
||||
- {score: 500, type: star}
|
||||
- {score: 500, type: gun}
|
||||
|
||||
presets:
|
||||
- id: 0
|
||||
name: easy
|
||||
teams:
|
||||
- id: human
|
||||
players:
|
||||
- {<<: *human, index: 0, color: 0xFFFF00, control: human-0}
|
||||
- id: bot
|
||||
spawnInterval: 3000
|
||||
life: 10
|
||||
players:
|
||||
- {<<: *bot, index: 0, control: bot-stupid}
|
||||
- {<<: *bot, index: 1, control: bot-stupid}
|
||||
|
||||
- id: 1
|
||||
name: normal
|
||||
teams:
|
||||
- id: human
|
||||
players:
|
||||
- {<<: *human, index: 0, color: 0xFFFF00, control: human-0}
|
||||
- id: bot
|
||||
spawnInterval: 3000
|
||||
life: 20
|
||||
players:
|
||||
- {<<: *bot, index: 0, control: bot-stupid}
|
||||
- {<<: *bot, index: 1, control: bot-stupid}
|
||||
- {<<: *bot, index: 2, control: bot-hard}
|
||||
- {<<: *bot, index: 3, control: bot-hard}
|
||||
|
||||
- id: 2
|
||||
name: hard
|
||||
teams:
|
||||
- id: human
|
||||
players:
|
||||
- {<<: *human, index: 0, color: 0xFFFF00, control: human-0}
|
||||
- id: bot
|
||||
spawnInterval: 1000
|
||||
life: 30
|
||||
players:
|
||||
- {<<: *bot, index: 0, control: bot-hard}
|
||||
- {<<: *bot, index: 1, control: bot-hard}
|
||||
- {<<: *bot, index: 2, control: bot-hard}
|
||||
- {<<: *bot, index: 3, control: bot-hard}
|
||||
- {<<: *bot, index: 4, control: bot-hard}
|
||||
- {<<: *bot, index: 5, control: bot-hard}
|
||||
|
||||
@@ -29,15 +29,16 @@ player:
|
||||
team:
|
||||
base: &team
|
||||
players:
|
||||
- {<<: *player, index: 0}
|
||||
- {<<: *player, index: 0, control: bot-hard}
|
||||
|
||||
presets:
|
||||
- id: default
|
||||
- id: 0
|
||||
name: default
|
||||
teams:
|
||||
- id: alpha
|
||||
color: 0xFF4422
|
||||
players:
|
||||
- {<<: *player, index: 0, human: 1}
|
||||
- {<<: *player, index: 0, control: human-0}
|
||||
<<: *team
|
||||
- id: beta
|
||||
color: 0xFFD000
|
||||
|
||||
@@ -41,24 +41,25 @@ team:
|
||||
id: radiant
|
||||
color: 0xff4422
|
||||
players:
|
||||
- {<<: *player-slow, index: 0, human: 1, color: 0xff8866}
|
||||
- {<<: *player-fast, index: 1}
|
||||
- {<<: *player-slow, index: 2}
|
||||
- {<<: *player-fast, index: 3}
|
||||
- {<<: *player-slow, index: 4}
|
||||
- {<<: *player-slow, index: 0, control: human-0, color: 0xff8866}
|
||||
- {<<: *player-fast, index: 1, control: bot-hard}
|
||||
- {<<: *player-slow, index: 2, control: bot-hard}
|
||||
- {<<: *player-fast, index: 3, control: bot-hard}
|
||||
- {<<: *player-slow, index: 4, control: bot-hard}
|
||||
dire: &dire
|
||||
<<: *team
|
||||
id: dire
|
||||
color: 0x3284ff
|
||||
players:
|
||||
- {<<: *player-slow, index: 0}
|
||||
- {<<: *player-fast, index: 1}
|
||||
- {<<: *player-slow, index: 2}
|
||||
- {<<: *player-fast, index: 3}
|
||||
- {<<: *player-slow, index: 4}
|
||||
- {<<: *player-slow, index: 0, control: bot-hard}
|
||||
- {<<: *player-fast, index: 1, control: bot-hard}
|
||||
- {<<: *player-slow, index: 2, control: bot-hard}
|
||||
- {<<: *player-fast, index: 3, control: bot-hard}
|
||||
- {<<: *player-slow, index: 4, control: bot-hard}
|
||||
|
||||
presets:
|
||||
- id: default
|
||||
- id: 0
|
||||
name: default
|
||||
teams:
|
||||
- <<: *radiant
|
||||
- <<: *dire
|
||||
|
||||
@@ -7,13 +7,12 @@ import ru.m.tankz.util.LevelUtil;
|
||||
import sys.FileSystem;
|
||||
import sys.io.File;
|
||||
|
||||
|
||||
class ServerLevelBundle implements ILevelBundle {
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function get(type:GameType, config:Config, level:Int):LevelConfig {
|
||||
var path:String = FileSystem.absolutePath('./resources/${type}/levels/level${LevelUtil.formatLevel(level)}.txt');
|
||||
public function get(type:GameType, config:Config, levelId:LevelId):LevelConfig {
|
||||
var path:String = FileSystem.absolutePath('./resources/${type}/levels/level${LevelUtil.formatLevel(levelId)}.txt');
|
||||
var data:String = File.getContent(path);
|
||||
return LevelUtil.loads(config, data);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user