[client] add universal LevelFrame

This commit is contained in:
2019-04-03 17:23:15 +03:00
parent c58735ea43
commit 9dc0a4ce06
31 changed files with 268 additions and 366 deletions

View File

@@ -1,10 +1,8 @@
package ru.m.tankz;
import ru.m.tankz.storage.MultiplayerStorage;
import ru.m.tankz.storage.SettingsStorage;
import haxework.view.popup.PopupManager;
import haxework.resources.IResources;
import haxework.resources.Resources;
import haxework.view.popup.PopupManager;
import ru.m.connect.IConnection;
import ru.m.tankz.bundle.ConfigBundle;
import ru.m.tankz.bundle.IConfigBundle;
@@ -16,6 +14,9 @@ import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.proto.pack.Request;
import ru.m.tankz.proto.pack.Response;
import ru.m.tankz.sound.SoundManager;
import ru.m.tankz.storage.GameStorage;
import ru.m.tankz.storage.MultiplayerStorage;
import ru.m.tankz.storage.SettingsStorage;
#if flash
import flash.Lib;
#elseif html5
@@ -29,6 +30,7 @@ class Init {
@:provide static var configBundle:IConfigBundle;
@:provide static var settingsStorage:SettingsStorage;
@:provide static var multiplayerStorage:MultiplayerStorage;
@:provide static var gameStorage:GameStorage;
@:provide static var soundManager:SoundManager;
@:provide static var networkManager:NetworkManager;
@:provide static var controlFactory:IControlFactory;
@@ -57,6 +59,7 @@ class Init {
configBundle = new ConfigBundle();
settingsStorage = new SettingsStorage();
multiplayerStorage = new MultiplayerStorage();
gameStorage = new GameStorage();
soundManager = new SoundManager();
controlFactory = new ClientControlFactory();
popupManager = new PopupManager();

View File

@@ -125,5 +125,9 @@ class Style {
Skin.size(64, 64),
new ButtonSVGSkin(Assets.getText("resources/image/icon/arrow-alt-circle-right-solid.svg"), lightColor),
]);
resources.skin.put("button.start", [
Skin.size(64, 64),
new ButtonSVGSkin(Assets.getText("resources/image/icon/play-circle-solid.svg"), lightColor),
]);
}
}

View File

@@ -7,10 +7,17 @@ import ru.m.tankz.util.LevelUtil;
class LevelBundle implements ILevelBundle {
private var cache:Map<String, LevelConfig> = new Map();
public function new() {}
public function get(type:GameType, config:Config, level:Int):LevelConfig {
var data:String = Assets.getText('resources/${type}/levels/level${LevelUtil.formatLevel(level)}.txt');
return LevelUtil.loads(config, data);
var key = '${type}:${level}';
if (!cache.exists(key)) {
var data:String = Assets.getText('resources/${type}/levels/level${LevelUtil.formatLevel(level)}.txt');
cache[key] = LevelUtil.loads(config, data);
cache[key].index = level;
}
return cache[key];
}
}

View File

@@ -0,0 +1,20 @@
package ru.m.tankz.storage;
import ru.m.tankz.game.GameState;
import ru.m.tankz.Type.GameType;
import haxework.storage.SharedObjectStorage;
class GameStorage extends SharedObjectStorage {
public function new() {
super("game");
}
public function get(type:GameType, level:Int):GameState {
return read('${type}:${level}');
}
public function set(state:GameState):Void {
write('${state.type}:${state.level}', state);
}
}

View File

@@ -5,26 +5,15 @@ skinId: dark
views:
- id: start
$type: ru.m.tankz.view.StartFrame
# classic
- id: classic.level
$type: ru.m.tankz.view.classic.ClassicLevelFrame
- id: classic.game
- id: level
$type: ru.m.tankz.view.LevelFrame
- id: classic
$type: ru.m.tankz.view.classic.ClassicGameFrame
# dota
- id: dota.level
$type: ru.m.tankz.view.dota.DotaLevelFrame
- id: dota.game
- id: dota
$type: ru.m.tankz.view.dota.DotaGameFrame
# death
- id: death.level
$type: ru.m.tankz.view.death.DeathLevelFrame
- id: death.game
- id: death
$type: ru.m.tankz.view.death.DeathGameFrame
# result
- id: result
$type: ru.m.tankz.view.ResultFrame
# - id: network
# $type: ru.m.tankz.view.NetworkFrame
# settings
- id: settings
$type: ru.m.tankz.view.SettingsFrame

View File

@@ -0,0 +1,51 @@
package ru.m.tankz.view;
import haxework.resources.IResources;
import haxework.view.DataView;
import haxework.view.frame.FrameSwitcher;
import haxework.view.LabelView;
import haxework.view.VGroupView;
import ru.m.tankz.bundle.ILevelBundle;
import ru.m.tankz.config.Config;
import ru.m.tankz.game.GameState;
import ru.m.tankz.preset.ClassicGame;
import ru.m.tankz.preset.DeathGame;
import ru.m.tankz.preset.DotaGame;
import ru.m.tankz.view.classic.ClassicGameFrame;
import ru.m.tankz.view.common.LevelView;
import ru.m.tankz.view.death.DeathGameFrame;
import ru.m.tankz.view.dota.DotaGameFrame;
@:template class LevelFrame extends VGroupView {
public static inline var ID = "level";
@:view var header:LabelView;
@:view var levels:DataView<LevelConfig, LevelView>;
@:provide var state:GameState;
@:provide var resources:IResources;
@:provide var swicther:FrameSwitcher;
@:provide var levelBundle:ILevelBundle;
public function onShow():Void {
header.text = state.type;
levels.data = [for (i in 0...state.config.game.levels) levelBundle.get(state.type, state.config, i)];
for (view in levels.dataViews) view.onStart.connect(start);
}
private function start(level:LevelConfig):Void {
state.level = level.index;
swicther.change(switch state.type {
case ClassicGame.TYPE: ClassicGameFrame.ID;
case DotaGame.TYPE: DotaGameFrame.ID;
case DeathGame.TYPE: DeathGameFrame.ID;
case _: StartFrame.ID;
});
}
private function onLevelSelect(index:Int, level:LevelConfig, view:LevelView):Void {
for (v in levels.views) {
cast(v, LevelView).selected = v == view;
}
}
}

View File

@@ -0,0 +1,18 @@
---
skinId: container
layout:
$type: haxework.view.layout.VerticalLayout
views:
- id: header
$type: haxework.view.LabelView
skinId: text.header
- id: levels
$type: haxework.view.DataView
geometry.size.width: 100%
layout:
$type: haxework.view.layout.TailLayout
rowSize: 10
margin: 5
factory: $code:ru.m.tankz.view.common.LevelView.factory
+onItemSelect: $this:onLevelSelect
geometry.padding: 10

View File

@@ -1,34 +1,23 @@
package ru.m.tankz.view;
import haxework.view.ButtonView;
import haxework.view.frame.FrameSwitcher;
import haxework.view.VGroupView;
import ru.m.tankz.view.classic.ClassicLevelFrame;
import ru.m.tankz.view.death.DeathLevelFrame;
import ru.m.tankz.view.dota.DotaLevelFrame;
import ru.m.tankz.game.GameState;
import ru.m.tankz.Type.GameType;
import ru.m.tankz.view.popup.FontPopup;
@:template class StartFrame extends VGroupView {
public static var ID(default, never):String = "start";
@:provide var frameSwitcher:FrameSwitcher;
@:provide var state:GameState;
@:provide var swicther:FrameSwitcher;
private var fontPopup:FontPopup;
private function onPress(view:ButtonView):Void {
switch (view.id) {
case 'classic':
frameSwitcher.change(ClassicLevelFrame.ID);
case 'dota':
frameSwitcher.change(DotaLevelFrame.ID);
case 'death':
frameSwitcher.change(DeathLevelFrame.ID);
case 'network':
//frameSwitcher.change(NetworkFrame.ID);
case 'settings':
frameSwitcher.change(SettingsFrame.ID);
}
private function startGame(type:GameType):Void {
state = new GameState(type);
swicther.change(LevelFrame.ID);
}
private function choiceFont():Void {

View File

@@ -9,39 +9,25 @@ views:
skinId: font
fontSize: 100
geometry.margin.bottom: 30
- id: classic
$type: haxework.view.ButtonView
- $type: haxework.view.ButtonView
skinId: button
+onPress: $this:onPress
+onPress: $code:startGame('classic')
text: Classic
- id: dota
$type: haxework.view.ButtonView
- $type: haxework.view.ButtonView
skinId: button
+onPress: $this:onPress
+onPress: $code:startGame('dota')
text: DotA
- id: death
$type: haxework.view.ButtonView
- $type: haxework.view.ButtonView
skinId: button
+onPress: $this:onPress
+onPress: $code:startGame('death')
text: DeathMatch
# - id: font
# $type: haxework.view.ButtonView
# skinId: button
# +onPress: $code:choiceFont()
# text: Font
# - id: network
# $type: haxework.view.ButtonView
# skinId: button
# +onPress: $this:onPress
# text: Network (in developing)
# fontColor: 0xff0000
- $type: haxework.view.HGroupView
skinId: panel
views:
- id: settings
$type: haxework.view.ButtonView
skinId: button.settings
+onPress: $this:onPress
+onPress: $code:swicther.change('settings')
- $type: haxework.view.SpriteView
geometry.size.width: 100%
- $type: haxework.view.LabelView

View File

@@ -5,7 +5,7 @@ import ru.m.tankz.render.Render;
import ru.m.tankz.view.common.GameFrame;
@:template class ClassicGameFrame extends GameFrame {
public static inline var ID = "classic.game";
public static inline var ID = "classic";
@:view("render") private var renderView(default, null):Render;
@:view("panel") private var panelView(default, null):IGamePanel;

View File

@@ -1,52 +0,0 @@
package ru.m.tankz.view.classic;
import haxework.view.ButtonView;
import haxework.view.DataView;
import haxework.view.frame.FrameSwitcher;
import haxework.view.ToggleButtonView;
import ru.m.tankz.config.Config;
import ru.m.tankz.view.common.LevelFrame;
import ru.m.tankz.preset.ClassicGame;
@:template class ClassicLevelFrame extends LevelFrame {
public static inline var ID = "classic.level";
@:view var presets(default, null):DataView<GamePreset, ToggleButtonView>;
@:view var levels(default, null):DataView<Int, ButtonView>;
@:provide var frames:FrameSwitcher;
private function onShow():Void {
gameType = ClassicGame.TYPE;
levels.data = [for (i in 0...config.game.levels) i];
presets.data = config.presets;
setSelectedPreset(preset);
}
private function setSelectedPreset(preset:GamePreset) {
for (view in presets.views) {
cast(view, ToggleButtonView).on = view.id == preset.id;
}
}
private function presetViewFactory(index:Int, preset:GamePreset):ToggleButtonView {
var view = new ToggleButtonView();
view.id = preset.id;
view.text = '${preset.id}';
resources.skin.bind("button.simple", view, "skin");
return view;
}
override private function set_preset(value:GamePreset):GamePreset {
var result = super.set_preset(value);
setSelectedPreset(result);
return result;
}
override private function set_level(value:Int):Int {
var result = super.set_level(value);
frames.change(ClassicGameFrame.ID);
return result;
}
}

View File

@@ -1,26 +0,0 @@
---
skinId: container
layout:
$type: haxework.view.layout.VerticalLayout
views:
- $type: haxework.view.LabelView
skinId: text.header
text: Classic
- id: presets
$type: haxework.view.DataView
layout:
$type: haxework.view.layout.HorizontalLayout
hAlign: center
margin: 2
factory: $this:presetViewFactory
+onDataSelect: $code:function(value) preset = value
geometry.padding: 10
- id: levels
$type: haxework.view.DataView
layout:
$type: haxework.view.layout.TailLayout
rowSize: 10
margin: 5
factory: $this:levelViewFactory
+onDataSelect: $code:function(value) level = value
geometry.padding: 10

View File

@@ -1,50 +0,0 @@
package ru.m.tankz.view.common;
import haxework.resources.IResources;
import haxework.view.ButtonView;
import haxework.view.GroupView;
import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.config.Config;
import ru.m.tankz.game.GameState;
import ru.m.tankz.Type;
class LevelFrame extends GroupView {
public var gameType(default, set):GameType;
public var preset(default, set):GamePreset;
public var level(default, set):Int;
private var config(default, null):Config;
@:provide var configBundle:IConfigBundle;
@:provide var state:GameState;
@:provide var resources:IResources;
private function set_gameType(value:GameType):GameType {
if (gameType != value || true) { // ToDo:
gameType = value;
config = configBundle.get(gameType);
preset = config.presets[0];
}
return gameType;
}
private function set_preset(value:GamePreset):GamePreset {
if (preset != value || true) { // ToDo:
preset = value;
state = new GameState(gameType, preset.id);
}
return preset;
}
private function set_level(value:Int):Int {
state.level = value;
return state.level;
}
private function levelViewFactory(index:Int, level:Int):ButtonView {
var view = new ButtonView();
view.text = '${level}';
resources.skin.bind("button.level", view, "skin");
return view;
}
}

View File

@@ -0,0 +1,46 @@
package ru.m.tankz.view.common;
import haxework.signal.Signal;
import haxework.view.core.Geometry;
import haxework.view.GroupView;
import haxework.view.LabelView;
import haxework.view.VGroupView;
import ru.m.tankz.config.Config;
@:template class LevelView extends VGroupView {
public var level(default, set):LevelConfig;
public var selected(default, set):Bool = false;
public var onStart:Signal<LevelConfig> = new Signal();
@:view("index") var indexView:LabelView;
@:view("name") var nameView:LabelView;
@:view("info") var infoView:GroupView;
private function set_level(value:LevelConfig):LevelConfig {
if (level != value) {
level = value;
nameView.text = '${level.index}. ${level.name != null ? level.name : "#"}';
indexView.text = '${level.index}';
}
return level;
}
private function set_selected(value:Bool):Bool {
if (selected != value) {
selected = value;
infoView.visible = selected;
infoView.geometry.position = selected ? Position.LAYOUT : Position.ABSOLUTE;
indexView.visible = !selected;
indexView.geometry.position = selected ? Position.ABSOLUTE : Position.LAYOUT;
toUpdateParent();
}
return selected;
}
public static function factory(index:Int, level:LevelConfig):LevelView {
var view = new LevelView();
view.level = level;
return view;
}
}

View File

@@ -0,0 +1,22 @@
---
skinId: light
views:
- id: index
$type: haxework.view.LabelView
skinId: text
geometry.padding: [20, 15]
- id: info
geometry.padding: [20, 15]
geometry.position: absolute
layout.margin: 10
visible: false
$type: haxework.view.VGroupView
views:
- id: name
$type: haxework.view.LabelView
skinId: text
- $type: haxework.view.HGroupView
views:
- $type: haxework.view.ButtonView
skinId: button.start
+onPress: $code:onStart.emit(level)

View File

@@ -6,7 +6,7 @@ import ru.m.tankz.view.common.IGamePanel;
@:template class DeathGameFrame extends GameFrame {
public static inline var ID = "death.game";
public static inline var ID = "death";
@:view("render") private var renderView(default, null):Render;
@:view("panel") private var panelView(default, null):IGamePanel;

View File

@@ -1,38 +0,0 @@
package ru.m.tankz.view.death;
import Lambda;
import haxework.view.ButtonView;
import haxework.view.DataView;
import haxework.view.frame.FrameSwitcher;
import ru.m.tankz.game.GameState;
import ru.m.tankz.preset.DeathGame;
import ru.m.tankz.view.common.LevelFrame;
import ru.m.tankz.view.common.PlayerView;
@:template class DeathLevelFrame extends LevelFrame {
public static inline var ID = "death.level";
@:view var levels(default, null):DataView<Int, ButtonView>;
@:view var players(default, null):DataView<Array<PlayerState>, PlayerView>;
@:provide var frames:FrameSwitcher;
private function onShow():Void {
gameType = DeathGame.TYPE;
levels.data = [for (i in 0...config.game.levels) i];
players.data = [for (i in 0...2) Lambda.array(state.players)];
}
private function playerViewFactory(index:Int, data:Array<PlayerState>):PlayerView {
var view = new PlayerView();
view.item_index = index;
view.data = data;
return view;
}
override private function set_level(value:Int):Int {
var result = super.set_level(value);
frames.change(DeathGameFrame.ID);
return result;
}
}

View File

@@ -1,24 +0,0 @@
---
skinId: container
layout:
$type: haxework.view.layout.VerticalLayout
views:
- $type: haxework.view.LabelView
skinId: text.header
text: DeathMatch
- id: players
$type: haxework.view.DataView
layout:
$type: haxework.view.layout.VerticalLayout
hAlign: right
factory: $this:playerViewFactory
geometry.padding: 10
- id: levels
$type: haxework.view.DataView
layout:
$type: haxework.view.layout.TailLayout
rowSize: 10
margin: 5
factory: $this:levelViewFactory
+onDataSelect: $code:function(value) level = value
geometry.padding: 10

View File

@@ -6,7 +6,7 @@ import ru.m.tankz.render.Render;
@:template class DotaGameFrame extends GameFrame {
public static inline var ID = "dota.game";
public static inline var ID = "dota";
@:view("render") private var renderView(default, null):Render;
@:view("panel") private var panelView(default, null):IGamePanel;

View File

@@ -1,39 +0,0 @@
package ru.m.tankz.view.dota;
import Lambda;
import haxework.view.ButtonView;
import haxework.view.DataView;
import haxework.view.frame.FrameSwitcher;
import ru.m.tankz.view.common.LevelFrame;
import ru.m.tankz.view.common.PlayerView;
import ru.m.tankz.game.GameState;
import ru.m.tankz.preset.DotaGame;
@:template class DotaLevelFrame extends LevelFrame {
public static inline var ID = "dota.level";
@:view var levels(default, null):DataView<Int, ButtonView>;
@:view var players(default, null):DataView<Array<PlayerState>, PlayerView>;
@:provide var frames:FrameSwitcher;
private function onShow():Void {
gameType = DotaGame.TYPE;
levels.data = [for (i in 0...config.game.levels) i];
players.data = [for (i in 0...2) Lambda.array(state.players)];
}
private function playerViewFactory(index:Int, data:Array<PlayerState>):PlayerView {
var view = new PlayerView();
view.item_index = index;
view.data = data;
view.colorize = true;
return view;
}
override private function set_level(value:Int):Int {
var result = super.set_level(value);
frames.change(DotaGameFrame.ID);
return result;
}
}

View File

@@ -1,24 +0,0 @@
---
skinId: container
layout:
$type: haxework.view.layout.VerticalLayout
views:
- $type: haxework.view.LabelView
skinId: text.header
text: DotA
- id: players
$type: haxework.view.DataView
layout:
$type: haxework.view.layout.VerticalLayout
hAlign: right
factory: $this:playerViewFactory
geometry.padding: 10
- id: levels
$type: haxework.view.DataView
layout:
$type: haxework.view.layout.TailLayout
rowSize: 10
margin: 5
factory: $this:levelViewFactory
+onDataSelect: $code:function(value) level = value
geometry.padding: 10

View File

@@ -1,6 +1,5 @@
package ru.m.tankz.view.settings;
import haxework.view.ButtonView;
import haxework.view.DataView;
import haxework.view.LabelView;
import haxework.view.VGroupView;
@@ -14,9 +13,6 @@ import ru.m.tankz.storage.SettingsStorage;
@:view var label:LabelView;
@:view var list:DataView<ActionItem, ActionView>;
@:view var change:ButtonView;
@:view var clear:ButtonView;
@:view var reset:ButtonView;
@:provide var storage:SettingsStorage;
@@ -34,44 +30,35 @@ import ru.m.tankz.storage.SettingsStorage;
return view;
}
public function onPress(view:ButtonView):Void {
switch (view.id) {
case "change": _change();
case "clear": _clear();
case "reset": _reset();
case _:
}
}
private function onItemSelect(index:Int, value:ActionItem, view:ActionView):Void {
view.edit();
}
private function _change():Void {
private function change():Void {
var p: Promise<Int> = Promise.promise(0);
for (view in list.views) {
var v: ActionView = cast view;
p = p.pipe(function(_):Promise<Int> return v.edit());
}
p.then(function(_) _save());
p.then(function(_) save());
}
private function _clear():Void {
private function clear():Void {
for (item in list.data) {
item.key = -1;
}
list.data = list.data;
list.toUpdate();
_save();
save();
}
private function _reset():Void {
private function reset():Void {
list.data = SettingsStorage.getDefaultActionConfig(controlIndex).data;
list.toUpdate();
_save();
save();
}
private function _save():Void {
private function save():Void {
storage.setActionConffig(controlIndex, new ActionConfig(list.data));
}
}

View File

@@ -9,17 +9,17 @@ views:
views:
- id: change
$type: haxework.view.ButtonView
+onPress: $this:onPress
+onPress: $code:change()
skinId: button.simple
text: Change
- id: clear
$type: haxework.view.ButtonView
+onPress: $this:onPress
+onPress: $code:clear()
skinId: button.simple
text: Clear
- id: reset
$type: haxework.view.ButtonView
+onPress: $this:onPress
+onPress: $code:reset()
skinId: button.simple
text: Reset
- id: list