[client] rework GamePanel

This commit is contained in:
2019-07-29 17:57:33 +03:00
parent 8a3ceec1ee
commit 7125cc1e9f
22 changed files with 247 additions and 248 deletions

View File

@@ -1,23 +1,23 @@
package ru.m.tankz.view;
import haxework.view.form.ButtonView;
import haxework.view.data.DataView;
import haxework.view.form.ButtonView;
import haxework.view.form.LabelView;
import haxework.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView;
import haxework.view.form.LabelView;
import ru.m.tankz.bundle.ILevelBundle;
import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameInit;
import ru.m.tankz.game.GameState;
import ru.m.tankz.storage.GameStorage;
import ru.m.tankz.view.common.LifeView;
import ru.m.tankz.view.game.PlayerView;
using ru.m.tankz.view.ViewUtil;
@:template class ResultFrame extends FrameView<Result> {
public static var ID(default, never):String = "result";
@:view("result") var resultView:DataView<PlayerState, LifeView>;
@:view("result") var resultView:DataView<PlayerState, PlayerView>;
@:view("level") var levelLabel:LabelView;
@:view("next") var nextButton:ButtonView;
@@ -31,12 +31,9 @@ using ru.m.tankz.view.ViewUtil;
super(ID);
}
private function playerViewFactory(index:Int, player:PlayerState):LifeView {
var view = new LifeView();
var playerConfig = result.state.config.getPlayer(player.id);
var tankType = playerConfig.tanks[0].type;
var tankConfig = result.state.config.getTank(tankType);
view.tank = tankConfig == null ? 'ba' : tankConfig.skin;
private function playerViewFactory(index:Int, player:PlayerState):PlayerView {
var view = new PlayerView();
view.tank = result.state.config.getPlayerTank(player.id).skin;
view.color = result.state.getPlayerColor(player.id);
view.life = player.frags;
view.score = player.score;

View File

@@ -13,10 +13,7 @@ views:
geometry.height: 100%
overflow.y: scroll
geometry.margin.top: 20
layout:
$type: haxework.view.layout.VerticalLayout
hAlign: right
margin: 10
layout.margin: 5
- $type: haxework.view.group.HGroupView
style: panel
layout.margin: 10

View File

@@ -1,13 +0,0 @@
---
layout.margin: 5
views:
- id: tank
$type: haxework.view.ImageView
- id: life
$type: haxework.view.form.LabelView
style: text.box
geometry.width: 50
- id: score
$type: haxework.view.form.LabelView
style: text.box
geometry.width: 100

View File

@@ -1,62 +0,0 @@
package ru.m.tankz.view.game;
import haxework.view.form.LabelView;
import haxework.view.group.VGroupView;
import ru.m.geom.Direction;
import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameState;
import ru.m.tankz.preset.ClassicGame;
import ru.m.tankz.Type.PlayerId;
import ru.m.tankz.view.common.LifeView;
using ru.m.tankz.view.ViewUtil;
@:template class ClassicGamePanel extends VGroupView implements IGamePanel {
public var position(default, null):Direction = Direction.RIGHT;
@:view var bot:LifeView;
@:view var player1:LifeView;
@:view var player2:LifeView;
@:view var level:LabelView;
private var player1Id:PlayerId = new PlayerId(ClassicGame.HUMAN, 0);
private var player2Id:PlayerId = new PlayerId(ClassicGame.HUMAN, 1);
public function refresh(state:GameState):Void {
bot.life = state.getTeamLife(ClassicGame.BOT);
player1.life = state.getPlayerLife(player1Id);
player1.score = state.getPlayerScore(player1Id);
if (state.getPlayerLife(player2Id) > 0) {
player2.visible = true;
player2.life = state.getPlayerLife(player2Id);
player2.score = state.getPlayerScore(player2Id);
} else {
player2.visible = false;
}
}
public function onGameEvent(event:GameEvent):Void {
switch event {
case START(start):
this.level.text = start.level.toLevelLabel();
refresh(start.state);
case CHANGE(TEAM_LIFE(teamId, life)):
if (teamId == ClassicGame.BOT) {
bot.life = life;
}
case CHANGE(PLAYER_LIFE(playerId, life)):
if (playerId == player1Id) {
player1.life = life;
} else if (playerId == player2Id) {
player2.life = life;
}
case CHANGE(PLAYER_SCORE(playerId, score)):
if (playerId == player1Id) {
player1.score = score;
} else if (playerId == player2Id) {
player2.score = score;
}
case _:
}
}
}

View File

@@ -1,24 +0,0 @@
---
geometry.padding: 5
geometry.height: 100%
layout.margin: 5
layout.hAlign: left
views:
- id: level
$type: haxework.view.form.LabelView
style: text.box
geometry.width: 100%
- $type: haxework.view.SpriteView
geometry.height: 50%
- id: bot
$type: ru.m.tankz.view.common.LifeView
tank: ba
scoreLabel.visible: false
- id: player1
$type: ru.m.tankz.view.common.LifeView
tank: pa
color: 0xFFFF00
- id: player2
$type: ru.m.tankz.view.common.LifeView
tank: pa
color: 0x15C040

View File

@@ -1,48 +0,0 @@
package ru.m.tankz.view.game;
import haxework.view.data.DataView;
import haxework.view.form.LabelView;
import haxework.view.group.VGroupView;
import ru.m.geom.Direction;
import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameState;
import ru.m.tankz.preset.DeathGame;
import ru.m.tankz.view.common.LifeView;
using ru.m.tankz.view.ViewUtil;
@:template class DeathGamePanel extends VGroupView implements IGamePanel {
public var position(default, null):Direction = Direction.RIGHT;
@:view var level:LabelView;
@:view var players:DataView<PlayerState, LifeView>;
@:provide var configBundle:IConfigBundle;
private function getView(playerId):LifeView {
for (view in players.dataViews) {
if (view.playerId == playerId) {
return view;
}
}
return null;
}
public function onGameEvent(event:GameEvent):Void {
switch event {
case START(start):
this.level.text = start.level.toLevelLabel();
players.data = Lambda.array(start.state.players);
case SPAWN(TANK(_, _, playerId, info)):
var skin = configBundle.get(DeathGame.TYPE).getTank(info.type).skin;
getView(playerId).tank = skin;
getView(playerId).color = info.color;
case CHANGE(PLAYER_LIFE(playerId, life)):
getView(playerId).life = life;
case CHANGE(PLAYER_SCORE(playerId, score)):
getView(playerId).score = score;
case _:
}
}
}

View File

@@ -1,48 +0,0 @@
package ru.m.tankz.view.game;
import haxework.view.group.HGroupView;
import haxework.view.form.LabelView;
import ru.m.geom.Direction;
import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameState;
import ru.m.tankz.preset.DotaGame;
import ru.m.tankz.Type.TeamId;
import ru.m.tankz.view.common.LifeView;
using ru.m.tankz.view.ViewUtil;
@:template class DotaGamePanel extends HGroupView implements IGamePanel {
public var position(default, null):Direction = Direction.TOP;
@:view var radiant:LifeView;
@:view var dire:LifeView;
@:view var level:LabelView;
public function refresh(state:GameState):Void {
radiant.life = state.getTeamLife(DotaGame.RADIANT);
radiant.score = state.getTeamScore(DotaGame.RADIANT);
dire.life = state.getTeamLife(DotaGame.DIRE);
dire.score = state.getTeamScore(DotaGame.DIRE);
}
private inline function getLifeView(teamId:TeamId):LifeView {
return switch teamId {
case DotaGame.RADIANT: radiant;
case DotaGame.DIRE: dire;
case _: null;
}
}
public function onGameEvent(event:GameEvent):Void {
switch event {
case START(start):
this.level.text = start.level.toLevelLabel(true);
refresh(start.state);
case CHANGE(TEAM_LIFE(teamId, life)):
getLifeView(teamId).life = life;
case CHANGE(TEAM_SCORE(teamId, score)):
getLifeView(teamId).score = score;
case _:
}
}
}

View File

@@ -1,19 +0,0 @@
---
geometry.width: 100%
layout.margin: 20
views:
- id: radiant
$type: ru.m.tankz.view.common.LifeView
tank: bc
color: 0xff4422
- $type: haxework.view.SpriteView
geometry.width: 50%
- id: level
$type: haxework.view.form.LabelView
style: text.box
- $type: haxework.view.SpriteView
geometry.width: 50%
- id: dire
$type: ru.m.tankz.view.common.LifeView
tank: bc
color: 0x3284ff

View File

@@ -0,0 +1,76 @@
package ru.m.tankz.view.game;
import ru.m.tankz.config.Config;
import ru.m.tankz.game.GameEvent;
import ru.m.tankz.Type;
using ru.m.tankz.view.ViewUtil;
class GamePanelHelper {
private var panel:IGamePanel;
private var config:Config;
private var onelinelevel:Bool;
public function new(panel:IGamePanel, config:Config, onelinelevel:Bool = false) {
this.panel = panel;
this.config = config;
this.onelinelevel = onelinelevel;
}
private function findTeamView(id:TeamId):Null<TeamView> {
for (view in panel.teams.dataViews) {
if (view.teamId == id) {
return view;
}
}
return null;
}
private function findPlayerView(id:PlayerId):Null<PlayerView> {
var teamView = findTeamView(id.team);
if (teamView != null) {
for (view in teamView.dataViews) {
if (view.playerId == id) {
return view;
}
}
}
return null;
}
public function onGameEvent(event:GameEvent):Void {
switch event {
case START(start):
panel.level.text = start.level.toLevelLabel(onelinelevel);
panel.teams.data = [for (team in start.state.teams) team];
for (teamView in panel.teams.dataViews) {
for (playerView in teamView.dataViews) {
playerView.tank = config.getPlayerTank(playerView.playerId).skin;
playerView.color = config.getColor(playerView.playerId);
}
}
case CHANGE(TEAM_LIFE(teamId, life)):
var view = findPlayerView([teamId, -1]);
if (view != null) {
view.life = life;
}
case CHANGE(TEAM_SCORE(teamId, score)):
var view = findPlayerView([teamId, -1]);
if (view != null) {
view.score = score;
}
case CHANGE(PLAYER_LIFE(playerId, life)):
var view = findPlayerView(playerId);
if (view != null) {
view.life = life;
}
case CHANGE(PLAYER_SCORE(playerId, score)):
var view = findPlayerView(playerId);
if (view != null) {
view.score = score;
}
case _:
}
}
}

View File

@@ -3,6 +3,7 @@ package ru.m.tankz.view.game;
import haxework.view.group.IGroupView;
import haxework.view.group.VGroupView;
import ru.m.geom.Direction;
import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.preset.ClassicGame;
import ru.m.tankz.preset.DeathGame;
import ru.m.tankz.preset.DotaGame;
@@ -11,6 +12,8 @@ import ru.m.tankz.Type;
@:template class GameView extends VGroupView {
@:provide static var configBundle:IConfigBundle;
@:view public var render(default, null):IRender;
public var panel(default, null):IGamePanel;
public var type(default, set):GameType;
@@ -34,10 +37,12 @@ import ru.m.tankz.Type;
private function buildPanel(type:GameType):IGamePanel {
return switch type {
case ClassicGame.TYPE: new ClassicGamePanel();
case DotaGame.TYPE: new DotaGamePanel();
case DeathGame.TYPE: new DeathGamePanel();
case _: throw 'Unsupported type: ${type}';
case ClassicGame.TYPE | DeathGame.TYPE:
SideGamePanel.factory(configBundle.get(type));
case DotaGame.TYPE:
TopGamePanel.factory(configBundle.get(type));
case _:
throw 'Unsupported type: ${type}';
}
}

View File

@@ -1,9 +1,14 @@
package ru.m.tankz.view.game;
import haxework.view.data.DataView;
import haxework.view.form.LabelView;
import haxework.view.IView;
import ru.m.geom.Direction;
import ru.m.tankz.game.GameState;
import ru.m.tankz.game.IGame;
interface IGamePanel extends IView<Dynamic> extends GameListener {
public var position(default, null):Direction;
public var teams(default, null):DataView<TeamState, TeamView>;
public var level(default, null):LabelView;
}

View File

@@ -1,15 +1,16 @@
package ru.m.tankz.view.common;
package ru.m.tankz.view.game;
import haxework.color.Color;
import haxework.view.group.HGroupView;
import haxework.view.ImageView;
import haxework.view.form.LabelView;
import haxework.view.group.VGroupView;
import haxework.view.ImageView;
import openfl.Assets;
import ru.m.tankz.game.GameState;
import ru.m.tankz.Type;
@:template class LifeView extends HGroupView {
@:template class PlayerView extends VGroupView {
@:view("title") public var titleView:LabelView;
@:view("tank") public var tankImage:ImageView;
@:view("life") public var lifeLabel:LabelView;
@:view("score") public var scoreLabel:LabelView;
@@ -23,6 +24,7 @@ import ru.m.tankz.Type;
private inline function set_state(value:PlayerState):PlayerState {
playerId = value.id;
titleView.text = value.name != null ? value.name : playerId.index > -1 ? '${playerId.team} #${playerId.index}' : playerId.team;
tank = value.tank;
color = value.color;
life = value.life;
@@ -53,8 +55,8 @@ import ru.m.tankz.Type;
return value;
}
public static inline function factory(index:Int, data:PlayerState):LifeView {
var result = new LifeView();
public static inline function factory(index:Int, data:PlayerState):PlayerView {
var result = new PlayerView();
result.state = data;
return result;
}

View File

@@ -0,0 +1,21 @@
---
views:
- id: title
$type: haxework.view.form.LabelView
visible: false
- $type: haxework.view.group.HGroupView
layout.margin: 5
layout.vAlign: middle
views:
- id: tank
$type: haxework.view.ImageView
geometry.width: 42
geometry.height: 42
- id: life
$type: haxework.view.form.LabelView
style: text.box
geometry.width: 55
- id: score
$type: haxework.view.form.LabelView
style: text.box
geometry.width: 100

View File

@@ -0,0 +1,28 @@
package ru.m.tankz.view.game;
import haxework.view.data.DataView;
import haxework.view.form.LabelView;
import haxework.view.group.VGroupView;
import ru.m.geom.Direction;
import ru.m.tankz.config.Config;
import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameState;
@:template class SideGamePanel extends VGroupView implements IGamePanel {
public var position(default, null):Direction = Direction.RIGHT;
@:view public var teams:DataView<TeamState, TeamView>;
@:view public var level:LabelView;
private var helper:GamePanelHelper;
public static function factory(config:Config):SideGamePanel {
var result = new SideGamePanel();
result.helper = new GamePanelHelper(result, config);
return result;
}
public function onGameEvent(event:GameEvent):Void {
helper.onGameEvent(event);
}
}

View File

@@ -2,7 +2,6 @@
geometry.padding: 5
geometry.height: 100%
layout.margin: 5
layout.hAlign: right
views:
- id: level
$type: haxework.view.form.LabelView
@@ -10,8 +9,7 @@ views:
geometry.width: 100%
- $type: haxework.view.SpriteView
geometry.height: 50%
- id: players
- id: teams
$type: haxework.view.data.DataView
layout:
$type: haxework.view.layout.VerticalLayout
factory: ~ru.m.tankz.view.common.LifeView.factory
layout.margin: 3
factory: ~TeamView.viewFactory

View File

@@ -0,0 +1,35 @@
package ru.m.tankz.view.game;
import haxework.view.data.DataView;
import ru.m.tankz.game.GameState;
import ru.m.tankz.Type;
class TeamView extends DataView<PlayerState, PlayerView> {
public var teamId(default, default):TeamId;
public var state(default, set):TeamState;
private function new():Void {
super();
factory = PlayerView.factory;
layout.margin = 5;
}
private function set_state(value:TeamState):TeamState {
teamId = value.id;
var players = [for (player in value.players) player].filter(function(player) return player.life > 0);
if (value.life > 0) {
var teamState = new PlayerState([value.id, -1]);
teamState.life = value.life;
players.unshift(teamState);
}
data = players;
return value;
}
public static inline function viewFactory(index:Int, data:TeamState):TeamView {
var result = new TeamView();
result.state = data;
return result;
}
}

View File

@@ -0,0 +1,28 @@
package ru.m.tankz.view.game;
import haxework.view.data.DataView;
import haxework.view.form.LabelView;
import haxework.view.group.HGroupView;
import ru.m.geom.Direction;
import ru.m.tankz.config.Config;
import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameState;
@:template class TopGamePanel extends HGroupView implements IGamePanel {
public var position(default, null):Direction = Direction.TOP;
@:view public var teams:DataView<TeamState, TeamView>;
@:view public var level:LabelView;
private var helper:GamePanelHelper;
public static function factory(config:Config):TopGamePanel {
var result = new TopGamePanel();
result.helper = new GamePanelHelper(result, config, true);
return result;
}
public function onGameEvent(event:GameEvent):Void {
helper.onGameEvent(event);
}
}

View File

@@ -0,0 +1,15 @@
---
geometry.width: 100%
layout.margin: 20
views:
- id: level
$type: haxework.view.form.LabelView
style: text.box
- $type: haxework.view.SpriteView
geometry.width: 100%
- id: teams
$type: haxework.view.data.DataView
layout:
$type: haxework.view.layout.HorizontalLayout
margin: 5
factory: ~TeamView.viewFactory

View File

@@ -34,7 +34,9 @@ import ru.m.tankz.proto.room.RoomProto;
network.joinGame(data.game.id, true);
}
public static function factory():RoomItemView {
return new RoomItemView();
public static function factory(index:Int, value:RoomProto):RoomItemView {
var result = new RoomItemView();
result.data = value;
return result;
}
}

View File

@@ -1,8 +1,8 @@
package ru.m.tankz.view.network;
import haxework.view.data.DataView;
import haxework.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView;
import haxework.view.list.VListView;
import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.proto.room.RoomProto;
import ru.m.tankz.view.popup.CreateGamePopup;
@@ -10,7 +10,7 @@ import ru.m.tankz.view.popup.CreateGamePopup;
@:template class RoomListFrame extends FrameView<Dynamic> {
public static inline var ID = "room_list";
@:view var games:VListView<RoomProto>;
@:view var games:DataView<RoomProto, RoomItemView>;
@:provide var switcher:FrameSwitcher;
@:provide var network:NetworkManager;

View File

@@ -16,7 +16,7 @@ views:
text: Create
+onPress: ~create()
- id: games
$type: haxework.view.list.VListView
$type: haxework.view.data.DataView
geometry.stretch: true
factory: ~ru.m.tankz.view.network.RoomItemView.factory
geometry.margin: 10