feat(client): update game ui

This commit is contained in:
2024-05-30 18:54:19 +03:00
parent d6af58875d
commit 648d15fc88
14 changed files with 143 additions and 245 deletions

View File

@@ -89,7 +89,7 @@ const client = new Project(
],
meta: {
width: 1024,
height: 768,
height: 576,
},
flags: [
//'proto_debug',

View File

@@ -24,7 +24,7 @@ class AppTheme extends Theme {
}
public function new() {
super({embed: true}, COLORS, {base: "2.7h", big: "4h", veryBig: "4.5h"});
super({embed: true}, COLORS, {base: "3h", big: "4h", veryBig: "4.5h"});
}
override private function reload():Void {
@@ -93,7 +93,7 @@ class AppTheme extends Theme {
register(new Style("panel", [
"geometry.width" => SizeValue.fromString("100%"),
"geometry.padding" => Box.fromArray([10, 5]),
"geometry.padding" => Box.fromArray([20, 10]),
"layout.vAlign" => VAlign.MIDDLE,
], ["light"]));
@@ -113,9 +113,9 @@ class AppTheme extends Theme {
]));
register(new Style("icon.tank", [
"geometry.width" => SizeValue.fromString("8h"),
"geometry.height" => SizeValue.fromString("8h"),
"skin.fillType" => FillType.DEFAULT,
"geometry.width" => SizeValue.fromString("6h"),
"geometry.height" => SizeValue.fromString("6h"),
"skin.fillType" => FillType.CONTAIN,
]));
var green:Color = 0x00ff00;
@@ -162,17 +162,21 @@ class AppTheme extends Theme {
"skin.color" => colors.text,
"skin.activeColor" => colors.active,
]));
register(new Style("render", [
"skin.background.color" => colors.dark,
]));
}
private function registerButton(name:String, resource:String, solid:Bool = false):Void {
register(new Style('button.$name', [
"geometry.width" => SizeValue.fromString("8h"),
"geometry.height" => SizeValue.fromString("8h"),
"geometry.width" => SizeValue.fromString("10h"),
"geometry.height" => SizeValue.fromString("10h"),
"skin" => function() return new ButtonSVGSkin(Assets.getText('resources/image/icon/$resource'), colors.light, solid),
]));
register(new Style('button.$name.small', [
"geometry.width" => SizeValue.fromString("5h"),
"geometry.height" => SizeValue.fromString("5h"),
"geometry.width" => SizeValue.fromString("7h"),
"geometry.height" => SizeValue.fromString("7h"),
"skin" => function() return new ButtonSVGSkin(Assets.getText('resources/image/icon/$resource'), colors.light, solid),
]));
}

View File

@@ -1,5 +1,6 @@
package ru.m.tankz.render;
import hw.view.utils.DrawUtil;
import flash.display.DisplayObjectContainer;
import flash.display.Graphics;
import flash.display.Sprite;
@@ -73,12 +74,14 @@ class Render extends SpriteView implements IRender {
private function set_config(value:Config):Config {
config = value;
drawBackground();
toRedraw();
return config;
}
private function set_gridSize(value:GridSize):GridSize {
gridSize = value;
drawBackground();
toRedraw();
return gridSize;
}
@@ -86,13 +89,15 @@ class Render extends SpriteView implements IRender {
var g:Graphics = backgroundLayer.graphics;
g.clear();
g.beginFill(0x000000);
g.lineStyle(2, 0xcccccc);
g.drawRect(0, 0, mapWidth, mapHeight);
g.endFill();
}
override public function redraw():Void {
super.redraw();
var scale = Math.min(width / mapWidth, height / mapHeight);
container.scaleX = content.scaleY = scale;
container.scaleX = container.scaleY = scale;
container.x = (width - (mapWidth * scale)) / 2;
container.y = (height - (mapHeight * scale)) / 2;
}

View File

@@ -1,5 +1,6 @@
package ru.m.tankz.view;
import hw.view.text.TextView;
import ru.m.tankz.view.popup.PausePopup;
import flash.ui.Keyboard;
import ru.m.control.DeviceAction;
@@ -7,11 +8,14 @@ import hw.view.frame.FrameSwitcher;
import hw.view.frame.FrameView;
import hw.view.group.GroupView;
import hw.view.layout.DefaultLayout;
import hw.view.data.DataView;
import hw.view.form.LabelView;
import ru.m.control.DeviceType;
import ru.m.control.IControlBus;
import ru.m.tankz.control.HumanControl;
import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameInit;
import ru.m.tankz.game.GameState.TeamState;
import ru.m.tankz.game.IGame;
import ru.m.tankz.game.record.GamePlayer;
import ru.m.tankz.game.record.GameRecord;
@@ -21,10 +25,12 @@ import ru.m.tankz.sound.SoundManager;
import ru.m.tankz.storage.GameStorage;
import ru.m.tankz.storage.SettingsStorage;
import ru.m.tankz.Type;
import ru.m.tankz.view.game.GameViewA;
import ru.m.tankz.view.game.GameViewB;
import ru.m.tankz.view.game.IGameView;
import ru.m.tankz.view.gamepad.GamepadView;
import ru.m.tankz.view.game.TeamView;
import ru.m.tankz.view.game.PlayerView;
import ru.m.tankz.render.IRender;
using ru.m.tankz.view.ViewUtil;
@:template class GameFrame extends FrameView<GameInit> implements GameListener {
public static inline var ID = "game";
@@ -37,13 +43,13 @@ import ru.m.tankz.view.gamepad.GamepadView;
@:provide static var settings:SettingsStorage;
@:provide static var bus:IControlBus;
@:view("game") private var gameViewContainer(default, null):GroupView;
@:view private var render:IRender;
@:view private var teams:DataView<TeamState, TeamView>;
@:view private var level:TextView;
@:view private var gamepad(default, null):GamepadView;
private var gamepadPlayerId:PlayerId;
private var gameView:IGameView;
private var game:IGame;
private var recorder:GameRecord;
@@ -59,19 +65,13 @@ import ru.m.tankz.view.gamepad.GamepadView;
case NETWORK(network): new NetworkGame(network);
case RECORD(record): new GamePlayer(record);
}
gameView = switch game.type {
case "dota": GameViewB.factory(game.config);
case _: GameViewA.factory(game.config);
};
gameViewContainer.addView(gameView);
soundManager.config = game.config;
gameView.render.config = game.config;
game.connect(gameView.render);
render.config = game.config;
game.connect(render);
game.connect(soundManager);
game.connect(gameView);
game.connect(this);
game.start();
// ToDo:
// TODO:
for (control in game.controls) {
if (Std.is(control, HumanControl)) {
if (cast(control, HumanControl).hasDevice(SCREEN)) {
@@ -98,13 +98,69 @@ import ru.m.tankz.view.gamepad.GamepadView;
game.dispose();
game = null;
}
if (gameView != null) {
gameView.render.reset();
render.reset();
}
private function findTeamView(id:TeamId):Null<TeamView> {
for (view in 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):
level.text = start.level.toLevelLabel();
teams.data = [for (team in start.state.teams) team];
// TODO: PlayerState default tank?
for (teamView in teams.dataViews) {
for (playerView in teamView.dataViews) {
var tank = game.config.getPlayerTank(playerView.playerId);
playerView.tank = {
type: tank.type,
skin: tank.skin,
hits: 0,
bonus: false,
boat: false,
color: game.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 SPAWN(TANK(id, rect, playerId, info)):
if (gamepadPlayerId != null && playerId == gamepadPlayerId) {
var tankConfig = game.config.getTank(info.type);
@@ -133,9 +189,5 @@ import ru.m.tankz.view.gamepad.GamepadView;
override public function onHide():Void {
stop();
soundManager.stopAll();
if (gameView != null) {
gameViewContainer.removeView(gameView);
gameView = null;
}
}
}

View File

@@ -2,8 +2,38 @@
style: container
views:
- id: game
$type: hw.view.group.GroupView
$type: hw.view.group.HGroupView
geometry.stretch: true
views:
- id: left
$type: hw.view.group.GroupView
layout.vAlign: middle
geometry.height: 100%
geometry.width: 15%
- id: render
$type: ru.m.tankz.render.Render
style: render
geometry.height: 100%
geometry.width: 70%
- id: right
$type: hw.view.group.VGroupView
geometry.height: 100%
geometry.width: 15%
geometry.padding: 5
layout.vAlign: top
layout.margin: 5
views:
- id: level
$type: hw.view.text.TextView
style: text.box
geometry.width: 100%
- $type: hw.view.SpriteView
geometry.height: 30%
- id: teams
$type: hw.view.data.DataView
layout.margin: 3
geometry.width: 100%
factory: ~TeamView.viewFactory
- id: gamepad
$type: ru.m.tankz.view.gamepad.GamepadView
geometry.position: absolute

View File

@@ -1,5 +1,6 @@
package ru.m.tankz.view.common;
import hw.view.utils.DrawUtil.FillType;
import hw.view.ImageView;
import ru.m.tankz.render.RenderUtil;
import ru.m.tankz.Type.TankInfo;
@@ -11,6 +12,7 @@ class TankView extends ImageView {
public function new() {
super();
style = "icon.tank";
fillType = FillType.CONTAIN;
}
private function set_tank(value:TankInfo):TankInfo {

View File

@@ -1,27 +0,0 @@
package ru.m.tankz.view.game;
import hw.view.data.DataView;
import hw.view.form.LabelView;
import hw.view.group.HGroupView;
import ru.m.tankz.config.Config;
import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameState;
import ru.m.tankz.render.IRender;
@:template class GameViewA extends HGroupView implements IGameView {
@:view public var render:IRender;
@:view public var teams:DataView<TeamState, TeamView>;
@:view public var level:LabelView;
private var helper:GameViewHelper;
public function onGameEvent(event:GameEvent):Void {
helper.onGameEvent(event);
}
public static function factory(config:Config):GameViewA {
var result = new GameViewA();
result.helper = new GameViewHelper(result, config);
return result;
}
}

View File

@@ -1,30 +0,0 @@
---
geometry.stretch: true
views:
- id: left
$type: hw.view.group.GroupView
layout.vAlign: middle
geometry.height: 100%
geometry.width: 25%
- id: render
$type: ru.m.tankz.render.Render
geometry.height: 100%
geometry.width: 50%
- id: right
$type: hw.view.group.VGroupView
geometry.height: 100%
geometry.width: 25%
geometry.padding: 5
layout.vAlign: top
layout.margin: 5
views:
- id: level
$type: hw.view.form.LabelView
style: text.box
geometry.width: 100%
- $type: hw.view.SpriteView
geometry.height: 30%
- id: teams
$type: hw.view.data.DataView
layout.margin: 3
factory: ~TeamView.viewFactory

View File

@@ -1,27 +0,0 @@
package ru.m.tankz.view.game;
import hw.view.data.DataView;
import hw.view.form.LabelView;
import hw.view.group.VGroupView;
import ru.m.tankz.config.Config;
import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameState;
import ru.m.tankz.render.IRender;
@:template class GameViewB extends VGroupView implements IGameView {
@:view public var render:IRender;
@:view public var teams:DataView<TeamState, TeamView>;
@:view public var level:LabelView;
private var helper:GameViewHelper;
public function onGameEvent(event:GameEvent):Void {
helper.onGameEvent(event);
}
public static function factory(config:Config):GameViewB {
var result = new GameViewB();
result.helper = new GameViewHelper(result, config, true);
return result;
}
}

View File

@@ -1,22 +0,0 @@
---
geometry.stretch: true
views:
- id: top
$type: hw.view.group.HGroupView
layout.vAlign: middle
geometry.width: 100%
views:
- id: level
$type: hw.view.form.LabelView
style: text.box
- $type: hw.view.SpriteView
geometry.width: 100%
- id: teams
$type: hw.view.data.DataView
layout:
$type: hw.view.layout.HorizontalLayout
margin: 5
factory: ~TeamView.viewFactory
- id: render
$type: ru.m.tankz.render.Render
geometry.stretch: true

View File

@@ -1,84 +0,0 @@
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 GameViewHelper {
private var view:IGameView;
private var config:Config;
private var onelinelevel:Bool;
public function new(view:IGameView, config:Config, onelinelevel:Bool = false) {
this.view = view;
this.config = config;
this.onelinelevel = onelinelevel;
}
private function findTeamView(id:TeamId):Null<TeamView> {
for (view in view.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):
view.level.text = start.level.toLevelLabel(onelinelevel);
view.teams.data = [for (team in start.state.teams) team];
// ToDo: PlayerState default tank?
for (teamView in view.teams.dataViews) {
for (playerView in teamView.dataViews) {
var tank = config.getPlayerTank(playerView.playerId);
playerView.tank = {
type: tank.type,
skin: tank.skin,
hits: 0,
bonus: false,
boat: false,
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

@@ -1,14 +0,0 @@
package ru.m.tankz.view.game;
import hw.view.data.DataView;
import hw.view.form.LabelView;
import hw.view.IView;
import ru.m.tankz.game.GameState;
import ru.m.tankz.game.IGame;
import ru.m.tankz.render.IRender;
interface IGameView extends IView<Dynamic> extends GameListener {
public var render(default, null):IRender;
public var teams(default, null):DataView<TeamState, TeamView>;
public var level(default, null):LabelView;
}

View File

@@ -1,9 +1,21 @@
---
geometry.width: 100%
views:
- $type: hw.view.group.HGroupView
geometry.width: 100%
views:
- id: title
$type: hw.view.form.LabelView
visible: false
geometry.width: 50%
layout.hAlign: left
font.size: 2h
- id: score
$type: hw.view.form.LabelView
geometry.width: 50%
layout.hAlign: right
font.size: 2h
- $type: hw.view.group.HGroupView
geometry.width: 100%
layout.margin: 5
layout.vAlign: middle
views:
@@ -12,8 +24,4 @@ views:
- id: life
$type: hw.view.form.LabelView
style: text.box
geometry.width: 55
- id: score
$type: hw.view.form.LabelView
style: text.box
geometry.width: 100
geometry.width: 100%

View File

@@ -13,6 +13,7 @@ class TeamView extends DataView<PlayerState, PlayerView> {
super();
factory = PlayerView.factory;
layout.margin = 5;
geometry.width = "100%";
}
private function set_state(value:TeamState):TeamState {