41 Commits

Author SHA1 Message Date
03d6e1f822 feat(editor): update editor ui 2024-06-01 20:39:21 +03:00
648d15fc88 feat(client): update game ui 2024-05-30 18:54:19 +03:00
d6af58875d feat(client): update elements sizes 2024-05-30 16:14:03 +03:00
16a5adefad feat(client): add render scaling 2024-05-29 15:19:18 +03:00
682eaa677c refactor: update to haxework 2.1.0 2024-05-27 11:31:35 +03:00
4319d66c61 build: add any scripts 2024-05-27 11:09:02 +03:00
f6f729e8d4 build: update haxework version 2023-01-04 10:54:04 +03:00
a39b02bfe7 refactor(server): use cpp target instead of neko 2023-01-02 14:36:44 +03:00
1cfc98dd57 refactor: update dependencies 2023-01-01 13:33:34 +03:00
ee846f6219 [rework] add base game class 2019-12-26 13:58:02 +03:00
e353d97415 [level] add death levels 2019-12-05 22:37:10 +03:00
2b49fafa0b [client] PackView progress 2019-11-21 17:47:46 +03:00
b33b853747 [client] update to template macro 2019-11-19 21:54:43 +03:00
8e3e6bdb6c [editor] remove unused provides 2019-11-19 18:01:10 +03:00
d9d385b0ef [client] use class provide macro 2019-11-18 18:01:26 +03:00
8c16b5ba90 [client] add AnimationManager 2019-11-14 16:51:05 +03:00
1aaa69f2d7 [build] confiigure build dir 2019-11-10 17:14:36 +03:00
6240846f0c [client] icon button size for mobile devices 2019-10-31 17:58:58 +03:00
70e6565e1f [client] add PausePopup 2019-10-30 22:16:06 +03:00
fffb6a3214 update 2019-10-23 17:53:19 +03:00
04bea46b3b [common] add LevelPackMeta 2019-10-22 18:00:36 +03:00
4da06e52e5 [work] update worklist 2019-10-17 21:36:46 +03:00
8878a825b8 [client] update bullet images 2019-10-09 17:57:22 +03:00
7de1897b32 [build] android keystore 2019-10-08 17:52:16 +03:00
d670722674 [common] weapon delay param 2019-10-07 17:29:20 +03:00
e7d031db58 [client] update boat bonus image 2019-10-04 17:55:54 +03:00
71087286b2 [client] render: fixes 2019-10-03 17:25:52 +03:00
757bc87426 [editor] build fix 2019-10-01 22:28:51 +03:00
1b5eef810c [client] render: fix empty brick render 2019-10-01 22:09:22 +03:00
cfa1475cf6 [client] compare versions in updater 2019-09-30 21:42:33 +03:00
1e79fcfacb [common] add ICaller; [client] rework BrickRenderItem 2019-09-29 20:34:51 +03:00
b34cb41bff [common] update game rework 2019-09-29 12:23:58 +03:00
d2aff5f2ee [common] add CachedLevelBundle; [client] add NetworkStateView 2019-09-23 14:26:38 +03:00
beda5e6c5f [client] display fps setting 2019-09-22 20:29:25 +03:00
50c4aebc0f up version 2019-09-17 20:11:32 +03:00
30325f6d16 [common] add boat bonus
[client] add active style to gamepad buttons
2019-09-16 14:41:12 +03:00
bddb590d30 [common] update Point, add GridPoint 2019-09-12 17:43:08 +03:00
de831fcb26 up version 2019-09-11 21:05:15 +03:00
5645fb6d0f [client] add PackView 2019-09-11 17:52:09 +03:00
bab588e6fb [editor] update 2019-09-10 19:47:35 +03:00
2565b6017a [editor] update 2019-09-10 17:56:51 +03:00
275 changed files with 9769 additions and 11175 deletions

View File

@@ -4,7 +4,7 @@ root = true
[*] [*]
charset = utf-8 charset = utf-8
indent_style = space indent_style = space
indent_size = 4 indent_size = 2
insert_final_newline = true insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true

2
.gitignore vendored
View File

@@ -1,3 +1,4 @@
build/
target/ target/
src-gen/ src-gen/
out/ out/
@@ -12,3 +13,4 @@ config.json
/node_modules /node_modules
/log /log
/ansible/*.retry /ansible/*.retry
.npmrc

34
WORK.md
View File

@@ -1,22 +1,20 @@
* bonuses * death game bonus
* death game bonuses
* boat bonus
* tanks and bullets speed balancing * tanks and bullets speed balancing
* game series * clean player state on lose in classic type
* network series * network series
* map packs * bot upgrade
* create in editor
* import in game
* save imported in local storage
* database
* cache
* improve bots
* A star
* game config validate * game config validate
* additional weapon * mine z-order
* mine * mine spawn position
* display count * mine spawn on other mine
* double rocket
* display ammo count (panel)
* display ammo count (screen gamepad)
* bonus ammo * bonus ammo
* screen gamepad (button enabled, count label) * game panel rework
* ui: * game state: config, map, entities, players
* game frame layouts * game menu pack progress
* game save
* balloons: change mute, network, pause
* settings: mute, pause, reset device actions
* game view: toggle panel on mobile

View File

@@ -9,7 +9,7 @@ deploy_repo_version: develop
deploy_npm: yes deploy_npm: yes
service_name: "{{ project_name }}" service_name: "{{ project_name }}"
service_work_dir: "{{ deploy_current_dir }}/target/server/neko" service_work_dir: "{{ deploy_current_dir }}/target/server/cpp"
service_command: "/usr/bin/neko {{ service_work_dir }}/{{ project_name }}.n {{ service_host }}" service_command: "{{ service_work_dir }}/{{ project_name }} {{ service_host }}"
service_user: www-data service_user: www-data
service_control_user: "{{ project_user }}" service_control_user: "{{ project_user }}"

View File

@@ -1,4 +1,5 @@
all: all:
hosts: shmyga.ru hosts: shmyga.ru
vars: vars:
service_host: 172.31.1.100 service_host: 213.139.208.180
config_src: "/home/holop/tankz/config.json"

View File

@@ -0,0 +1,2 @@
config_src: "{{ deploy_release_dir }}/config.{{ inventory_hostname }}.json"
config_dest: "{{ deploy_release_dir }}/config.json"

View File

@@ -1,11 +1,11 @@
--- ---
- name: "Copy config" - name: "Copy config"
copy: copy:
src: "{{ deploy_release_dir }}/config.{{ inventory_hostname }}.json" src: "{{ config_src }}"
dest: "{{ deploy_release_dir }}/config.json" dest: "{{ config_dest }}"
remote_src: true remote_src: true
- name: "Gulp build" - name: "Gulp build"
command: "/usr/local/lib/npm/bin/gulp default --host shmyga.ru" command: "{{ deploy_release_dir }}/node_modules/.bin/gulp default --host shmyga.ru"
args: args:
chdir: "{{ deploy_release_dir }}" chdir: "{{ deploy_release_dir }}"

View File

@@ -1,9 +1,11 @@
{ {
"SdkDir": "C:\\sdk", "SdkDir": "C:\\sdk",
"BuildDir": null,
"PublishDir": "", "PublishDir": "",
"PublishUrl": "https://shmyga.ru/repo/tankz", "PublishUrl": "https://shmyga.ru/repo/tankz",
"SSH": { "Develop": false,
"PrivateKey": null, "Key": {
"Passphrase": null "store": "keystore.jks",
"pass": null
} }
} }

View File

@@ -1,9 +0,0 @@
{
"SdkDir": "/home/holop/sdk",
"PublishDir": "/opt/repo/tankz",
"PublishUrl": "https://shmyga.ru/repo/tankz",
"SSH": {
"PrivateKey": null,
"Passphrase": null
}
}

View File

@@ -7,10 +7,18 @@ const dateformat = require('dateformat');
const argv = require('yargs').argv; const argv = require('yargs').argv;
const publish = require('./tasks/gulp-publish'); const publish = require('./tasks/gulp-publish');
if (packageInfo.haxe) {
Haxe.VERSION = packageInfo.haxe;
}
if (Config.SdkDir) { if (Config.SdkDir) {
Sdk.dir = Config.SdkDir; Sdk.dir = Config.SdkDir;
} }
if (Config.BuildDir) {
Haxe.buildDir = Config.BuildDir;
}
exports.clean = function clean() { exports.clean = function clean() {
return gulp.src('target/*', {read: false}).pipe(gulpClean()); return gulp.src('target/*', {read: false}).pipe(gulpClean());
}; };
@@ -34,18 +42,19 @@ const config = new Project.Config({
pack: 'ru.m.tankz', pack: 'ru.m.tankz',
author: 'shmyga <shmyga.z@gmail.com>', author: 'shmyga <shmyga.z@gmail.com>',
company: 'MegaLoMania', company: 'MegaLoMania',
version: packageInfo.version, version: packageInfo.version + (Config.Develop ? '-SNAPSHOT' : ''),
}, },
key: Config.Key,
libs: packageInfo.haxeDependencies, libs: packageInfo.haxeDependencies,
sources: [ sources: [
'src/common/haxe', 'src/common/haxe',
'src-gen/haxe', 'src-gen/haxe',
], ],
assets: [ assets: [
'src/common/resources', 'src/common/resources/config',
], ],
flags: [ flags: [
//'proto_debug', 'proto_debug',
], ],
macros: [ macros: [
`CompilationOption.set('build','${dateformat(new Date(), 'yyyy-mm-dd HH:MM:ss')}')`, `CompilationOption.set('build','${dateformat(new Date(), 'yyyy-mm-dd HH:MM:ss')}')`,
@@ -70,17 +79,17 @@ const client = new Project(
config.branch({ config.branch({
name: 'client', name: 'client',
sources: [ sources: [
//'src/fixes/haxe',
'src/client/haxe', 'src/client/haxe',
], ],
main: 'ru.m.tankz.Client', main: 'ru.m.tankz.Client',
preloader: 'ru.m.tankz.Preloader', preloader: 'ru.m.tankz.Preloader',
assets: [ assets: [
'src/common/resources/level',
'src/client/resources', 'src/client/resources',
], ],
meta: { meta: {
width: 1024, width: 1024,
height: 768, height: 576,
}, },
flags: [ flags: [
//'proto_debug', //'proto_debug',
@@ -103,11 +112,11 @@ const editor = new Project(
[ [
Project.Platform.FLASH, Project.Platform.FLASH,
Project.Platform.HTML5, Project.Platform.HTML5,
Project.Platform.LINUX,
], ],
config.branch({ config.branch({
name: 'editor', name: 'editor',
sources: [ sources: [
//'src/fixes/haxe',
'src/client/haxe', 'src/client/haxe',
'src/editor/haxe', 'src/editor/haxe',
], ],
@@ -119,6 +128,7 @@ const editor = new Project(
], ],
meta: { meta: {
filename: 'editor', filename: 'editor',
pack: 'ru.m.tankz.editor',
width: 1024, width: 1024,
height: 768, height: 768,
}, },
@@ -133,11 +143,14 @@ const editor = new Project(
*/ */
const server = new Project( const server = new Project(
Project.BuildSystem.HAXE, Project.BuildSystem.HAXE,
Project.Platform.NEKO, Project.Platform.CPP,
config.branch({ config.branch({
name: 'server', name: 'server',
sources: ['src/server/haxe'], sources: ['src/server/haxe'],
main: 'ru.m.tankz.server.Server', main: 'ru.m.tankz.server.Server',
assets: [
'src/common/resources/level',
]
}), }),
).bind(module, gulp); ).bind(module, gulp);
@@ -160,7 +173,7 @@ const defaultSeries = [
module.exports['editor:flash:html'], module.exports['editor:flash:html'],
module.exports['editor:html5:build'], module.exports['editor:html5:build'],
module.exports['server:neko:build'], module.exports['server:cpp:build'],
]; ];
if (System.isLinux) { if (System.isLinux) {

5
hxformat.json Normal file
View File

@@ -0,0 +1,5 @@
{
"indentation": {
"character": " "
}
}

6779
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +1,25 @@
{ {
"name": "tankz", "name": "tankz",
"version": "0.17.0", "version": "0.18.0",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"dateformat": "^3.0.3", "dateformat": "^3.0.3",
"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.1.0", "gulp-haxetool": "^0.1.9",
"yargs": "^13.2.4" "yargs": "^13.2.4"
}, },
"haxeDependencies": { "haxeDependencies": {
"haxework": "git@bitbucket.org:shmyga/haxework.git", "haxework": "2.1.0",
"lime": "7.5.0", "lime": "8.0.0",
"openfl": "8.9.1", "openfl": "9.2.0",
"hxcpp": "4.0.52", "hxcpp": "4.2.1",
"promhx": "1.1.0",
"protohx": "0.4.6", "protohx": "0.4.6",
"yaml": "1.3.0",
"orm": "2.1.0", "orm": "2.1.0",
"haxe-crypto": "0.0.7", "haxe-crypto": "0.0.8",
"svg": "1.1.2" "svg": "1.1.3",
} "formatter": "1.16.0"
},
"haxe": "4.2.5"
} }

12
scripts/format Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -e
cd "$(dirname $(dirname "$0"))" || exit
source $NEKO_SDK/activate
source $HAXE_SDK/activate
haxelib install formatter
haxelib run formatter \
-s ./src/common/haxe \
-s ./src/client/haxe \
-s ./src/server/haxe \
-s ./src/editor/haxe

13
scripts/lint Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -e
cd "$(dirname $(dirname "$0"))" || exit
source $NEKO_SDK/activate
source $HAXE_SDK/activate
haxelib install formatter
haxelib run formatter \
--check \
-s ./src/common/haxe \
-s ./src/client/haxe \
-s ./src/server/haxe \
-s ./src/editor/haxe

5
scripts/setup Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -e
cd "$(dirname $(dirname "$0"))" || exit
npm ci

View File

@@ -36,7 +36,9 @@ class Device {
return true; return true;
} }
} }
#end
return false; return false;
#else
return false;
#end
} }
} }

View File

@@ -1,10 +1,8 @@
package ru.m.animate; package ru.m.animate;
import flash.display.PixelSnapping;
import haxe.Timer;
import flash.display.Bitmap; import flash.display.Bitmap;
import flash.display.BitmapData; import flash.display.BitmapData;
import flash.display.PixelSnapping;
typedef Frame = { typedef Frame = {
var image:BitmapData; var image:BitmapData;
@@ -13,35 +11,18 @@ typedef Frame = {
class Animate extends Bitmap { class Animate extends Bitmap {
private static var timer:Timer; public var playing(default, default):Bool;
private static var instances:Array<Animate> = [];
private static function init():Void {
if (timer == null) {
timer = new Timer(30);
timer.run = updateAll;
}
}
private static function updateAll():Void {
for (instance in instances) {
if (instance.playing) {
instance.update();
}
}
}
public var playing(default, set):Bool;
public var frames(default, set):Array<Frame>; public var frames(default, set):Array<Frame>;
private var sequence:Array<BitmapData>; private var sequence:Array<BitmapData>;
private var index:Int; private var index:Int;
@:provide private static var manager:AnimateManager;
public function new(?frames:Array<Frame>) { public function new(?frames:Array<Frame>) {
super(null, PixelSnapping.AUTO, true); super(null, PixelSnapping.AUTO, true);
this.frames = frames == null ? [] : frames; this.frames = frames == null ? [] : frames;
init(); manager.add(this);
instances.push(this);
} }
public function set_frames(value:Array<Frame>):Array<Frame> { public function set_frames(value:Array<Frame>):Array<Frame> {
@@ -59,14 +40,7 @@ class Animate extends Bitmap {
return frames; return frames;
} }
public function set_playing(value:Bool):Bool { public function update():Void {
if (playing != value) {
playing = value;
}
return playing;
}
private function update():Void {
if (++index >= sequence.length) { if (++index >= sequence.length) {
index = 0; index = 0;
} }
@@ -77,8 +51,6 @@ class Animate extends Bitmap {
} }
public function dispose():Void { public function dispose():Void {
if (instances.indexOf(this) > -1) { manager.remove(this);
instances.remove(this);
}
} }
} }

View File

@@ -0,0 +1,34 @@
package ru.m.animate;
@:provide class AnimateManager {
public var playing(default, default):Bool;
private var timer:Timer;
private var animations:Array<Animate>;
public function new() {
animations = [];
timer = new Timer(30);
timer.run = update;
}
public function update():Void {
if (playing) {
for (animation in animations) {
if (animation.playing) {
animation.update();
}
}
}
}
public function add(animate:Animate):Void {
animations.push(animate);
}
public function remove(animate:Animate):Void {
if (animations.indexOf(animate) > -1) {
animations.remove(animate);
}
}
}

View File

@@ -3,7 +3,6 @@ package ru.m.animate;
import promhx.Deferred; import promhx.Deferred;
import promhx.Promise; import promhx.Promise;
class OnceAnimate extends Animate { class OnceAnimate extends Animate {
private var deferred:Deferred<Animate>; private var deferred:Deferred<Animate>;
@@ -14,13 +13,14 @@ class OnceAnimate extends Animate {
return deferred.promise(); return deferred.promise();
} }
override private function update():Void { override public function update():Void {
super.update(); super.update();
if (index == 0) { if (index == 0) {
playing = false; playing = false;
if (deferred != null) { if (deferred != null) {
deferred.resolve(this); deferred.resolve(this);
} }
dispose();
} }
} }
} }

View File

@@ -1,6 +1,6 @@
package ru.m.control; package ru.m.control;
import haxework.signal.Signal; import hw.signal.Signal;
import ru.m.control.IControlBus; import ru.m.control.IControlBus;
class ControlBus implements IControlBus { class ControlBus implements IControlBus {

View File

@@ -1,6 +1,6 @@
package ru.m.control; package ru.m.control;
import haxework.signal.Signal; import hw.signal.Signal;
interface IControlBus { interface IControlBus {
public var devices(default, null):Array<IControlDevice>; public var devices(default, null):Array<IControlDevice>;

View File

@@ -1,6 +1,6 @@
package ru.m.control; package ru.m.control;
import haxework.signal.Signal; import hw.signal.Signal;
interface IControlDevice { interface IControlDevice {
public var type(default, null):DeviceType; public var type(default, null):DeviceType;

View File

@@ -1,6 +1,6 @@
package ru.m.control; package ru.m.control;
import haxework.signal.Signal; import hw.signal.Signal;
import lime.ui.Joystick; import lime.ui.Joystick;
import ru.m.control.DeviceAction; import ru.m.control.DeviceAction;
import ru.m.control.DeviceType; import ru.m.control.DeviceType;

View File

@@ -2,7 +2,7 @@ package ru.m.control;
import flash.display.Stage; import flash.display.Stage;
import flash.events.KeyboardEvent; import flash.events.KeyboardEvent;
import haxework.signal.Signal; import hw.signal.Signal;
import ru.m.control.DeviceAction; import ru.m.control.DeviceAction;
class KeyboardDevice implements IControlDevice { class KeyboardDevice implements IControlDevice {

View File

@@ -1,12 +1,12 @@
package ru.m.skin; package ru.m.skin;
import format.SVG; import format.SVG;
import haxework.color.Color; import hw.color.Color;
import haxework.view.form.ButtonView; import hw.view.form.ButtonView;
import haxework.view.skin.ISkin; import hw.view.skin.ISkin;
using StringTools; using StringTools;
using haxework.color.ColorUtil; using hw.color.ColorUtil;
@:style class ButtonSVGSkin implements ISkin<ButtonView> { @:style class ButtonSVGSkin implements ISkin<ButtonView> {

View File

@@ -1,18 +1,18 @@
package ru.m.tankz; package ru.m.tankz;
import flash.text.TextFormatAlign; import flash.text.TextFormatAlign;
import haxework.color.Color; import hw.color.Color;
import haxework.view.geometry.Box; import hw.view.geometry.Box;
import haxework.view.geometry.HAlign; import hw.view.geometry.HAlign;
import haxework.view.geometry.SizeValue; import hw.view.geometry.SizeValue;
import haxework.view.geometry.VAlign; import hw.view.geometry.VAlign;
import haxework.view.theme.ITheme; import hw.view.theme.ITheme;
import haxework.view.theme.Theme; import hw.view.theme.Theme;
import haxework.view.utils.DrawUtil; import hw.view.utils.DrawUtil;
import openfl.Assets; import openfl.Assets;
import ru.m.skin.ButtonSVGSkin; import ru.m.skin.ButtonSVGSkin;
using haxework.color.ColorUtil; using hw.color.ColorUtil;
class AppTheme extends Theme { class AppTheme extends Theme {
@@ -24,7 +24,7 @@ class AppTheme extends Theme {
} }
public function new() { public function new() {
super({embed: true}, COLORS); super({embed: true}, COLORS, {base: "3h", big: "4h", veryBig: "4.5h"});
} }
override private function reload():Void { override private function reload():Void {
@@ -58,6 +58,12 @@ class AppTheme extends Theme {
"geometry.height" => SizeValue.fromInt(50), "geometry.height" => SizeValue.fromInt(50),
], ["button"])); ], ["button"]));
register(new Style("button.small", [
"font.size" => SizeValue.fromString("3h"),
"geometry.padding" => Box.fromArray([8, 2]),
"skin.round" => 5,
], ["button"]));
register(new Style("text.box", [ register(new Style("text.box", [
"skin.background.color" => Color.fromInt(0x000000), "skin.background.color" => Color.fromInt(0x000000),
"skin.background.alpha" => 0.1, "skin.background.alpha" => 0.1,
@@ -72,9 +78,9 @@ class AppTheme extends Theme {
], ["text.box"])); ], ["text.box"]));
register(new Style("button.level", [ register(new Style("button.level", [
"font.size" => fontSize.veryBig, "font.size" => fontSize.big,
"geometry.width" => SizeValue.fromInt(64), "geometry.width" => SizeValue.fromString("12h"),
"geometry.height" => SizeValue.fromInt(64), "geometry.height" => SizeValue.fromString("12h"),
"geometry.padding" => Box.fromFloat(0), "geometry.padding" => Box.fromFloat(0),
], ["button"])); ], ["button"]));
@@ -87,10 +93,15 @@ class AppTheme extends Theme {
register(new Style("panel", [ register(new Style("panel", [
"geometry.width" => SizeValue.fromString("100%"), "geometry.width" => SizeValue.fromString("100%"),
"geometry.padding" => Box.fromArray([10, 5]), "geometry.padding" => Box.fromArray([20, 10]),
"layout.vAlign" => VAlign.MIDDLE, "layout.vAlign" => VAlign.MIDDLE,
], ["light"])); ], ["light"]));
register(new Style("panel_button", [
"font.size" => fontSize.big,
"geometry.height" => SizeValue.fromString("100%"),
], ["button"]));
register(new Style("window", [ register(new Style("window", [
"geometry.padding" => Box.fromFloat(2), "geometry.padding" => Box.fromFloat(2),
], ["dark", "border"])); ], ["dark", "border"]));
@@ -102,33 +113,54 @@ class AppTheme extends Theme {
register(new Style("window.close", [ register(new Style("window.close", [
"skin" => function() return new ButtonSVGSkin(Assets.getText("resources/image/icon/window-close-solid.svg"), colors.light), "skin" => function() return new ButtonSVGSkin(Assets.getText("resources/image/icon/window-close-solid.svg"), colors.light),
"geometry.width" => SizeValue.fromInt(36), "geometry.width" => SizeValue.fromString("8h"),
"geometry.height" => SizeValue.fromInt(36), "geometry.height" => SizeValue.fromString("8h"),
])); ]));
register(new Style("icon.tank", [ register(new Style("icon.tank", [
"geometry.width" => SizeValue.fromInt(42), "geometry.width" => SizeValue.fromString("6h"),
"geometry.height" => SizeValue.fromInt(42), "geometry.height" => SizeValue.fromString("6h"),
"skin.fillType" => FillType.DEFAULT, "skin.fillType" => FillType.CONTAIN,
])); ]));
var green:Color = 0x00ff00; var green:Color = 0x00ff00;
var red:Color = 0xff0000; var red:Color = 0xff0000;
register(new Style("result.winner", [ register(new Style("result.winner", [
"skin.border.color" => green, "skin.border.color" => green,
"skin.border.alpha" => 0.5,
"skin.border.thickness" => 5,
"skin.round" => 10,
], ["light"])); ], ["light"]));
register(new Style("result.loser", [ register(new Style("result.loser", [
"skin.border.color" => red, "skin.border.color" => red,
"skin.border.alpha" => 0.5,
"skin.border.thickness" => 5,
"skin.round" => 10,
], ["light"])); ], ["light"]));
register(new Style("player.winner", [ register(new Style("player.winner", [
"skin.background.alpha" => 0.1, "skin.background.alpha" => 0.2,
"skin.background.color" => green, "skin.background.color" => green,
])); ]));
register(new Style("player.loser", [ register(new Style("player.loser", [
"skin.background.alpha" => 0.1, "skin.background.alpha" => 0.2,
"skin.background.color" => red, "skin.background.color" => red,
])); ]));
register(new Style("button.pack", [
"geometry.width" => SizeValue.fromString("35h"),
"geometry.height" => SizeValue.fromString("20h"),
"geometry.padding" => Box.fromFloat(5),
"layout.hAlign" => HAlign.CENTER,
"layout.vAlign" => VAlign.MIDDLE,
"content.buttonMode" => true,
"content.mouseChildren" => false,
"skin.round" => 15,
], ["border", "light"]));
register(new Style("button.menu", [
"geometry.padding" => Box.fromArray([20, 10]),
]));
registerButton("settings", "cog-solid.svg"); registerButton("settings", "cog-solid.svg");
registerButton("close", "times-circle-solid.svg"); registerButton("close", "times-circle-solid.svg");
registerButton("next", "arrow-alt-circle-right-solid.svg"); registerButton("next", "arrow-alt-circle-right-solid.svg");
@@ -136,25 +168,31 @@ class AppTheme extends Theme {
registerButton("start", "play-circle-solid.svg"); registerButton("start", "play-circle-solid.svg");
registerButton("login", "sign-in-solid.svg"); registerButton("login", "sign-in-solid.svg");
registerButton("logout", "sign-out-solid.svg"); registerButton("logout", "sign-out-solid.svg");
registerButton("bars", "bars-solid.svg");
registerButton("keyboard", "keyboard-light.svg", true); registerButton("keyboard", "keyboard-light.svg", true);
registerButton("backspace", "backspace-light.svg", true); registerButton("backspace", "backspace-light.svg", true);
registerButton("tablet-android-alt", "tablet-android-alt-light.svg", true); registerButton("tablet-android-alt", "tablet-android-alt-light.svg", true);
register(new Style("gamepad", [ register(new Style("gamepad", [
"skin.color" => colors.active, "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 { private function registerButton(name:String, resource:String, solid:Bool = false):Void {
register(new Style('button.$name', [ register(new Style('button.$name', [
"geometry.width" => SizeValue.fromInt(42), "geometry.width" => SizeValue.fromString("10h"),
"geometry.height" => SizeValue.fromInt(42), "geometry.height" => SizeValue.fromString("10h"),
"skin" => function() return new ButtonSVGSkin(Assets.getText('resources/image/icon/$resource'), colors.light, solid), "skin" => function() return new ButtonSVGSkin(Assets.getText('resources/image/icon/$resource'), colors.light, solid),
])); ]));
register(new Style('button.$name.small', [ register(new Style('button.$name.small', [
"geometry.width" => SizeValue.fromInt(32), "geometry.width" => SizeValue.fromString("7h"),
"geometry.height" => SizeValue.fromInt(32), "geometry.height" => SizeValue.fromString("7h"),
"skin" => function() return new ButtonSVGSkin(Assets.getText('resources/image/icon/$resource'), colors.light, solid), "skin" => function() return new ButtonSVGSkin(Assets.getText('resources/image/icon/$resource'), colors.light, solid),
])); ]));
} }

View File

@@ -1,28 +1,43 @@
package ru.m.tankz; package ru.m.tankz;
import ru.m.animate.AnimateManager;
import flash.Lib; import flash.Lib;
import haxework.animate.Animate; import hw.animate.Animate;
import haxework.log.TraceLogger; import hw.log.TraceLogger;
import haxework.view.Root; import hw.net.manage.LoaderManager;
import hw.view.Root;
import hw.view.popup.PopupManager;
import ru.m.tankz.storage.GameStorage;
import ru.m.tankz.storage.SettingsStorage;
import ru.m.tankz.view.ClientView; import ru.m.tankz.view.ClientView;
class Client { class Client {
private static inline var TAG = "Tankz"; private static inline var TAG = "Tankz";
@:provide private static var settings:SettingsStorage;
public static function main() { public static function main() {
L.push(new TraceLogger()); L.push(new TraceLogger());
#if flash #if flash
L.push(new haxework.log.JSLogger()); L.push(new hw.log.JSLogger());
#end #end
#if debug #if debug
//L.push(new haxework.log.SocketLogger()); //L.push(new hw.log.SocketLogger());
#end #end
// ToDo: fix @:provide macro
PopupManager;
LoaderManager;
GameStorage;
AnimateManager;
//
Const.init(); Const.init();
Init.init(); Init.init();
Animate.bind(Lib.current.stage); // TODO:
// Animate.bind(Lib.current.stage);
L.d(TAG, 'Debug: ${Const.DEBUG}'); L.d(TAG, 'Debug: ${Const.DEBUG}');
L.i(TAG, 'Version: ${Const.VERSION}'); L.i(TAG, 'Version: ${Const.VERSION}');
L.i(TAG, 'Build: ${Const.BUILD}'); L.i(TAG, 'Build: ${Const.BUILD}');
L.i(TAG, 'Mobile: ${Device.isMobile()}');
#if linux #if linux
LinuxIcon.apply(); LinuxIcon.apply();
#end #end
@@ -30,9 +45,16 @@ class Client {
Root.bind(view); Root.bind(view);
view.launch(); view.launch();
#if debug
var fps = new openfl.display.FPS(0, 0, 0x00ff00); var fps = new openfl.display.FPS(0, 0, 0x00ff00);
fps.visible = settings.displayFPS;
Lib.current.addChild(fps); Lib.current.addChild(fps);
#end
settings.signal.connect(function(setting) {
switch setting {
case DISPLAY_FPS(value):
fps.visible = value;
case _:
}
});
} }
} }

View File

@@ -7,12 +7,14 @@ class Const {
public static var FPS:Int; public static var FPS:Int;
public static var BUILD:String; public static var BUILD:String;
public static var VERSION:String; public static var VERSION:String;
public static var NAME:String;
public static var DEBUG:Bool; public static var DEBUG:Bool;
public static function init():Void { public static function init():Void {
FPS = Std.parseInt(Lib.current.stage.application.meta.get("fps")); FPS = Std.parseInt(Lib.current.stage.application.meta.get("fps"));
BUILD = CompilationOption.get("build"); BUILD = CompilationOption.get("build");
VERSION = Lib.current.stage.application.meta.get("version"); VERSION = Lib.current.stage.application.meta.get("version");
NAME = Lib.current.stage.application.meta.get("name");
DEBUG = Capabilities.isDebugger; DEBUG = Capabilities.isDebugger;
} }
} }

View File

@@ -1,14 +1,11 @@
package ru.m.tankz; package ru.m.tankz;
import flash.Lib; import flash.Lib;
import haxework.animate.FadeAnimate; import hw.animate.FadeAnimate;
import haxework.animate.UnFadeAnimate; import hw.animate.UnFadeAnimate;
import haxework.net.manage.ILoaderManager; import hw.storage.SharedObjectStorage;
import haxework.net.manage.LoaderManager; import hw.view.popup.PopupManager;
import haxework.resources.IResources; import hw.view.theme.ITheme;
import haxework.resources.Resources;
import haxework.view.popup.PopupManager;
import haxework.view.theme.ITheme;
import lime.ui.Gamepad; import lime.ui.Gamepad;
import lime.ui.Joystick; import lime.ui.Joystick;
import ru.m.connect.IConnection; import ru.m.connect.IConnection;
@@ -16,35 +13,23 @@ import ru.m.control.ControlBus;
import ru.m.control.IControlBus; import ru.m.control.IControlBus;
import ru.m.control.JoystickDevice; import ru.m.control.JoystickDevice;
import ru.m.control.KeyboardDevice; import ru.m.control.KeyboardDevice;
import ru.m.tankz.bundle.CachedLevelBundle;
import ru.m.tankz.bundle.ClientLevelSource;
import ru.m.tankz.bundle.ConfigBundle; import ru.m.tankz.bundle.ConfigBundle;
import ru.m.tankz.bundle.IConfigBundle; import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.bundle.ILevelBundle; import ru.m.tankz.bundle.ILevelBundle;
import ru.m.tankz.bundle.LevelBundle;
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.update.Updater;
import ru.m.tankz.storage.GameStorage;
import ru.m.tankz.storage.NetworkStorage;
import ru.m.tankz.storage.RecordStorage;
import ru.m.tankz.storage.SettingsStorage;
class Init { class Init {
@:provide static var theme:ITheme; @:provide static var theme:ITheme;
@:provide static var resources:IResources;
@:provide static var levelBundle:ILevelBundle; @:provide static var levelBundle:ILevelBundle;
@:provide static var configBundle:IConfigBundle; @:provide static var configBundle:IConfigBundle;
@:provide static var settingsStorage:SettingsStorage;
@:provide static var multiplayerStorage:NetworkStorage;
@:provide static var gameStorage:GameStorage;
@:provide static var recordStorage:RecordStorage;
@:provide static var soundManager:SoundManager;
@:provide static var networkManager:NetworkManager;
@:provide static var popupManager:PopupManager; @:provide static var popupManager:PopupManager;
@:provide static var connection:IConnection<Request, Response>; @:provide static var connection:IConnection<Request, Response>;
@:provide static var bus:IControlBus; @:provide static var bus:IControlBus;
@:provide static var loaderManager:ILoaderManager;
@:provide static var updater:Updater; @:provide static var updater:Updater;
private static function buildConnection():IConnection<Request, Response> { private static function buildConnection():IConnection<Request, Response> {
@@ -62,26 +47,18 @@ class Init {
public static function init():Void { public static function init():Void {
theme = new AppTheme(); theme = new AppTheme();
resources = new Resources(); levelBundle = new CachedLevelBundle(new ClientLevelSource(), new SharedObjectStorage());
levelBundle = new LevelBundle(); levelBundle.load();
configBundle = new ConfigBundle(); configBundle = new ConfigBundle();
settingsStorage = new SettingsStorage();
multiplayerStorage = new NetworkStorage();
gameStorage = new GameStorage();
recordStorage = new RecordStorage();
soundManager = new SoundManager();
popupManager = new PopupManager();
popupManager.showAnimateFactory = function(v) return new UnFadeAnimate(v, 100); popupManager.showAnimateFactory = function(v) return new UnFadeAnimate(v, 100);
popupManager.closeAnimateFactory = function(v) return new FadeAnimate(v, 100); popupManager.closeAnimateFactory = function(v) return new FadeAnimate(v, 100);
connection = buildConnection(); connection = buildConnection();
networkManager = new NetworkManager();
bus = new ControlBus(); bus = new ControlBus();
bus.connect(new KeyboardDevice(Lib.current.stage)); bus.connect(new KeyboardDevice(Lib.current.stage));
loaderManager = new LoaderManager();
updater = new Updater(Const.VERSION, "https://shmyga.ru/repo/tankz/packages.json"); updater = new Updater(Const.VERSION, "https://shmyga.ru/repo/tankz/packages.json");
for (device in Gamepad.devices) { for (device in Gamepad.devices) {

View File

@@ -5,7 +5,7 @@ import flash.display.Sprite;
import flash.events.Event; import flash.events.Event;
import flash.events.ProgressEvent; import flash.events.ProgressEvent;
import flash.Lib; import flash.Lib;
import haxework.view.geometry.Size; import hw.view.geometry.Size;
import ru.m.tankz.AppTheme; import ru.m.tankz.AppTheme;
class Progress extends Sprite { class Progress extends Sprite {

View File

@@ -0,0 +1,33 @@
package ru.m.tankz.bundle;
import openfl.Assets;
import openfl.utils.AssetType;
import ru.m.tankz.bundle.ILevelBundle;
import ru.m.tankz.config.Config;
import ru.m.tankz.Type;
import ru.m.tankz.util.LevelUtil;
class ClientLevelSource implements ILevelSource {
public function new() {}
public function resolveMeta(id:PackId):LevelPackMeta {
var bytes = Assets.getBytes('level/${id}.zip');
return LevelUtil.getMeta(bytes);
}
public function resolve(id:PackId):LevelPack {
var bytes = Assets.getBytes('level/${id}.zip');
return LevelUtil.unpack(bytes);
}
public function list():Array<PackId> {
var result = [];
for (path in Assets.list(AssetType.BINARY)) {
if (StringTools.startsWith(path, "level")) {
result.push(PackId.fromString(path.split("/").pop().split(".").shift()));
}
}
return result;
}
}

View File

@@ -15,7 +15,7 @@ class ConfigBundle implements IConfigBundle {
public function get(type:GameType):Config { public function get(type:GameType):Config {
if (!_cache.exists(type)) { if (!_cache.exists(type)) {
var source:ConfigSource = Yaml.parse(Assets.getText('resources/config/${type}.yaml'), Parser.options().useObjects()); var source:ConfigSource = Yaml.parse(Assets.getText('config/${type}.yaml'), Parser.options().useObjects());
_cache.set(type, Config.fromSource(type, source)); _cache.set(type, Config.fromSource(type, source));
} }
return _cache.get(type); return _cache.get(type);

View File

@@ -1,42 +0,0 @@
package ru.m.tankz.bundle;
import openfl.Assets;
import openfl.utils.AssetType;
import ru.m.tankz.config.Config;
import ru.m.tankz.Type;
import ru.m.tankz.util.LevelUtil;
class LevelBundle implements ILevelBundle {
private var _cache:Map<String, LevelPack> = new Map();
public function new() {}
private function resolve(id:PackId):LevelPack {
var bytes = Assets.getBytes('resources/level/${id}.zip');
return {
id: id,
data: LevelUtil.unpack(bytes).map(function(level) {
level.packId = id;
return level;
}),
};
}
public function get(id:PackId):LevelPack {
if (!_cache.exists(id)) {
_cache.set(id, resolve(id));
}
return _cache.get(id);
}
public function list():Array<PackId> {
var result = [];
for (path in Assets.list(AssetType.BINARY)) {
if (StringTools.startsWith(path, "resources/level")) {
result.push(PackId.fromString(path.split("/").pop().split(".").shift()));
}
}
return result;
}
}

View File

@@ -81,7 +81,8 @@ class HumanControl extends Control {
case TankAction.SHOT(weapon): case TankAction.SHOT(weapon):
if (on) { if (on) {
if (!shotTimers.exists(weapon)) { if (!shotTimers.exists(weapon)) {
var timer = new Timer(300); // ToDo: weapon.config.delay
var timer = new Timer(350);
timer.run = shooter(weapon); timer.run = shooter(weapon);
timer.run(); timer.run();
shotTimers.set(weapon, timer); shotTimers.set(weapon, timer);

View File

@@ -19,7 +19,8 @@ class LocalGame extends GameRunner {
override public function onGameEvent(event:GameEvent):Void { override public function onGameEvent(event:GameEvent):Void {
super.onGameEvent(event); super.onGameEvent(event);
switch event { switch event {
case COMPLETE(result): updateProgress(result); case COMPLETE(result):
updateProgress(result);
case _: case _:
} }
} }
@@ -34,7 +35,7 @@ class LocalGame extends GameRunner {
} }
if (humansTeams.length == 1 && result.winner == humansTeams[0]) { if (humansTeams.length == 1 && result.winner == humansTeams[0]) {
var progress = gameStorage.get(result.level.packId); var progress = gameStorage.get(result.level.packId);
progress.completeLevel(result.level.id, result.state.presetId); progress.completeLevel(result.level.id, result.state.presetId, {});
gameStorage.set(progress); gameStorage.set(progress);
} }
} }

View File

@@ -0,0 +1,31 @@
package ru.m.tankz.local;
import flash.display.Stage;
import flash.events.Event;
import ru.m.tankz.engine.ICaller;
class StageCaller implements ICaller {
private var stage:Stage;
private var event:String;
private var calback:Void -> Void;
public function new(stage:Stage, ?event:String) {
this.stage = stage;
this.event = event != null ? event : Event.ENTER_FRAME;
}
private function onEvent(_):Void {
calback();
}
public function start(calback:Void -> Void):Void {
this.calback = calback;
stage.addEventListener(event, onEvent);
}
public function stop():Void {
stage.removeEventListener(event, onEvent);
calback = null;
}
}

View File

@@ -1,14 +1,12 @@
package ru.m.tankz.network; package ru.m.tankz.network;
import ru.m.tankz.proto.game.GameEventProto;
import ru.m.tankz.proto.room.SlotProto;
import ru.m.tankz.proto.room.SlotRequest;
import haxe.Serializer; import haxe.Serializer;
import haxework.signal.Signal; import hw.signal.Signal;
import ru.m.connect.IConnection; import ru.m.connect.IConnection;
import ru.m.tankz.control.Control; import ru.m.tankz.control.Control;
import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.GameEvent;
import ru.m.tankz.proto.core.UserProto; import ru.m.tankz.proto.core.UserProto;
import ru.m.tankz.proto.game.GameEventProto;
import ru.m.tankz.proto.pack.GameEventRequest; import ru.m.tankz.proto.pack.GameEventRequest;
import ru.m.tankz.proto.pack.GameEventResponse; import ru.m.tankz.proto.pack.GameEventResponse;
import ru.m.tankz.proto.pack.LoginRequest; import ru.m.tankz.proto.pack.LoginRequest;
@@ -21,8 +19,11 @@ import ru.m.tankz.proto.room.LeaveRequest;
import ru.m.tankz.proto.room.RoomListRequest; import ru.m.tankz.proto.room.RoomListRequest;
import ru.m.tankz.proto.room.RoomProto; import ru.m.tankz.proto.room.RoomProto;
import ru.m.tankz.proto.room.RoomRequest; import ru.m.tankz.proto.room.RoomRequest;
import ru.m.tankz.proto.room.SlotProto;
import ru.m.tankz.proto.room.SlotRequest;
import ru.m.tankz.proto.room.StartRequest; import ru.m.tankz.proto.room.StartRequest;
import ru.m.tankz.storage.NetworkStorage; import ru.m.tankz.storage.NetworkStorage;
import ru.m.tankz.storage.SettingsStorage;
typedef ClientConnection = IConnection<Request, Response>; typedef ClientConnection = IConnection<Request, Response>;
@@ -35,7 +36,9 @@ enum ConnectionState {
ERROR(error:Dynamic); ERROR(error:Dynamic);
} }
class NetworkManager { @:provide class NetworkManager {
private static inline var TAG = "NetworkManager";
public var state(default, null):ConnectionState; public var state(default, null):ConnectionState;
public var room(default, null):RoomProto; public var room(default, null):RoomProto;
@@ -48,6 +51,7 @@ class NetworkManager {
@:provide private var connection:ClientConnection; @:provide private var connection:ClientConnection;
@:provide private var storage:NetworkStorage; @:provide private var storage:NetworkStorage;
@:provide private var settings:SettingsStorage;
private var reconnectTimer:Timer; private var reconnectTimer:Timer;
private var reconnectDelay:Int; private var reconnectDelay:Int;
@@ -61,10 +65,26 @@ class NetworkManager {
updateState(OFFLINE); updateState(OFFLINE);
connection.handler.connect(onConnectionEvent); connection.handler.connect(onConnectionEvent);
connection.receiveHandler.connect(onResponse); connection.receiveHandler.connect(onResponse);
//connect(); // ToDo: disable network if (settings.enableNetwork) {
connect();
}
settings.signal.connect(onSettingChange);
}
private function onSettingChange(setting:Setting):Void {
switch setting {
case ENABLE_NETWORK(value):
if (value) {
connect();
} else {
disconnect();
}
case _:
}
} }
private function updateState(value:ConnectionState):Void { private function updateState(value:ConnectionState):Void {
L.d(TAG, 'State: ${value}');
state = value; state = value;
stateSignal.emit(value); stateSignal.emit(value);
} }
@@ -131,6 +151,10 @@ class NetworkManager {
} }
} }
private function disconnect():Void {
connection.disconnect();
}
private function onConnectionEvent(event:ConnectionEvent):Void { private function onConnectionEvent(event:ConnectionEvent):Void {
updateState(switch event { updateState(switch event {
case CONNECTED: CONNECTED; case CONNECTED: CONNECTED;
@@ -145,9 +169,11 @@ class NetworkManager {
login(user.name, user.uuid); login(user.name, user.uuid);
} }
case DISCONNECTED | ERROR(_): case DISCONNECTED | ERROR(_):
if (settings.enableNetwork) {
reconnect(); reconnect();
} }
} }
}
private function onResponse(packet:Response):Void { private function onResponse(packet:Response):Void {
if (packet.hasLogin()) { if (packet.hasLogin()) {

View File

@@ -1,6 +1,6 @@
package ru.m.tankz.render; package ru.m.tankz.render;
import haxework.view.IView; import hw.view.IView;
import ru.m.tankz.config.Config; import ru.m.tankz.config.Config;
import ru.m.tankz.game.IGame; import ru.m.tankz.game.IGame;

View File

@@ -1,14 +1,16 @@
package ru.m.tankz.render; package ru.m.tankz.render;
import hw.view.utils.DrawUtil;
import flash.display.DisplayObjectContainer; import flash.display.DisplayObjectContainer;
import flash.display.Graphics; import flash.display.Graphics;
import flash.display.Sprite; import flash.display.Sprite;
import flash.events.Event; import flash.events.Event;
import haxe.Timer; import haxe.Timer;
import haxework.view.form.LabelView; import hw.view.form.LabelView;
import haxework.view.SpriteView; import hw.view.SpriteView;
import promhx.Promise; import promhx.Promise;
import ru.m.animate.Animate; import ru.m.animate.Animate;
import ru.m.animate.AnimateManager;
import ru.m.animate.OnceAnimate; import ru.m.animate.OnceAnimate;
import ru.m.geom.Point; import ru.m.geom.Point;
import ru.m.tankz.config.Config; import ru.m.tankz.config.Config;
@@ -31,6 +33,7 @@ class Render extends SpriteView implements IRender {
private var mapWidth(get, null):Float; private var mapWidth(get, null):Float;
private var mapHeight(get, null):Float; private var mapHeight(get, null):Float;
private var container:Sprite;
private var backgroundLayer:Sprite; private var backgroundLayer:Sprite;
private var groundLayer:Sprite; private var groundLayer:Sprite;
private var entryLayer:Sprite; private var entryLayer:Sprite;
@@ -38,20 +41,25 @@ class Render extends SpriteView implements IRender {
private var upperLayer:Sprite; private var upperLayer:Sprite;
private var items:Map<Int, IRenderItem>; private var items:Map<Int, IRenderItem>;
private var paused:Bool;
@:provide private static var animateManager:AnimateManager;
public function new() { public function new() {
super(); super();
items = new Map(); items = new Map();
container = new Sprite();
content.addChild(container);
backgroundLayer = new Sprite(); backgroundLayer = new Sprite();
groundLayer = new Sprite(); groundLayer = new Sprite();
entryLayer = new Sprite(); entryLayer = new Sprite();
upLayer = new Sprite(); upLayer = new Sprite();
upperLayer = new Sprite(); upperLayer = new Sprite();
content.addChild(backgroundLayer); container.addChild(backgroundLayer);
content.addChild(groundLayer); container.addChild(groundLayer);
content.addChild(entryLayer); container.addChild(entryLayer);
content.addChild(upLayer); container.addChild(upLayer);
content.addChild(upperLayer); container.addChild(upperLayer);
reset(); reset();
} }
@@ -65,15 +73,15 @@ class Render extends SpriteView implements IRender {
private function set_config(value:Config):Config { private function set_config(value:Config):Config {
config = value; config = value;
setSize(mapWidth, mapHeight, "render");
drawBackground(); drawBackground();
toRedraw();
return config; return config;
} }
private function set_gridSize(value:GridSize):GridSize { private function set_gridSize(value:GridSize):GridSize {
gridSize = value; gridSize = value;
setSize(mapWidth, mapHeight, "render");
drawBackground(); drawBackground();
toRedraw();
return gridSize; return gridSize;
} }
@@ -81,10 +89,19 @@ class Render extends SpriteView implements IRender {
var g:Graphics = backgroundLayer.graphics; var g:Graphics = backgroundLayer.graphics;
g.clear(); g.clear();
g.beginFill(0x000000); g.beginFill(0x000000);
g.lineStyle(2, 0xcccccc);
g.drawRect(0, 0, mapWidth, mapHeight); g.drawRect(0, 0, mapWidth, mapHeight);
g.endFill(); g.endFill();
} }
override public function redraw():Void {
super.redraw();
var scale = Math.min(width / mapWidth, height / mapHeight);
container.scaleX = container.scaleY = scale;
container.x = (width - (mapWidth * scale)) / 2;
container.y = (height - (mapHeight * scale)) / 2;
}
public function draw():Void { public function draw():Void {
for (item in items) { for (item in items) {
item.update(); item.update();
@@ -92,8 +109,10 @@ class Render extends SpriteView implements IRender {
} }
private function onEnterFrame(event:Event):Void { private function onEnterFrame(event:Event):Void {
if (!paused) {
draw(); draw();
} }
}
private function clearLayer(layer:DisplayObjectContainer) { private function clearLayer(layer:DisplayObjectContainer) {
while (layer.numChildren > 0) { while (layer.numChildren > 0) {
@@ -116,10 +135,14 @@ class Render extends SpriteView implements IRender {
public function onGameEvent(event:GameEvent):Void { public function onGameEvent(event:GameEvent):Void {
switch event { switch event {
case START(start): case START(start):
animateManager.playing = true;
gridSize = start.level.size; gridSize = start.level.size;
content.addEventListener(Event.ENTER_FRAME, onEnterFrame); content.addEventListener(Event.ENTER_FRAME, onEnterFrame);
case COMPLETE(_): case COMPLETE(_):
content.removeEventListener(Event.ENTER_FRAME, onEnterFrame); content.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
case PAUSE(paused):
this.paused = paused;
animateManager.playing = !paused;
case SPAWN(BRICK(bricks)): case SPAWN(BRICK(bricks)):
drawBackground(); drawBackground();
for (brick in bricks) { for (brick in bricks) {
@@ -144,13 +167,16 @@ class Render extends SpriteView implements IRender {
item.skin = tankConfig.skin; item.skin = tankConfig.skin;
item.hits = info.hits; item.hits = info.hits;
item.bonus = info.bonus; item.bonus = info.bonus;
item.boat = info.boat;
item.name = info.name == null ? "" : info.name; item.name = info.name == null ? "" : info.name;
items.set(id, item); items.set(id, item);
entryLayer.addChild(item.view); entryLayer.addChild(item.view);
item.update(); item.update();
playAnimate(item.rect.center, AnimateBundle.tankSpawn()); playAnimate(item.rect.center, AnimateBundle.tankSpawn());
case SPAWN(BULLET(id, rect, playerId, skin)): case SPAWN(BULLET(id, rect, playerId, skin, color)):
var item = new BulletRenderItem(rect, skin); var item = new BulletRenderItem(rect);
item.color = color;
item.skin = skin;
items.set(id, item); items.set(id, item);
entryLayer.addChild(item.view); entryLayer.addChild(item.view);
item.update(); item.update();
@@ -180,12 +206,13 @@ class Render extends SpriteView implements IRender {
var item = items[id]; var item = items[id];
cast(item, TankRenderItem).moves = false; cast(item, TankRenderItem).moves = false;
} }
case CHANGE(TANK(id, type, hits, bonus)): case CHANGE(TANK(id, type, hits, bonus, boat)):
if (items.exists(id)) { if (items.exists(id)) {
var item:TankRenderItem = cast items[id]; var item:TankRenderItem = cast items[id];
item.skin = config.getTank(type).skin; item.skin = config.getTank(type).skin;
item.hits = hits; item.hits = hits;
item.bonus = bonus; item.bonus = bonus;
item.boat = boat;
} }
case CHANGE(TANK_PROTECT(id, state)): case CHANGE(TANK_PROTECT(id, state)):
if (items.exists(id)) { if (items.exists(id)) {

View File

@@ -22,4 +22,8 @@ class RenderUtil {
public static function bulletImage(skin:String):BitmapData { public static function bulletImage(skin:String):BitmapData {
return Assets.getBitmapData('resources/image/bullet/${skin}.png'); return Assets.getBitmapData('resources/image/bullet/${skin}.png');
} }
public static function brickImage(type:BrickType, frame:Int = 0):BitmapData {
return Assets.getBitmapData('resources/image/map/${type}${frame > 0 ? ("-" + frame) : ""}.png');
}
} }

View File

@@ -13,7 +13,7 @@ class BitmapRenderItem extends RenderItem {
public function new(rect:Rectangle) { public function new(rect:Rectangle) {
super(rect); super(rect);
this.bitmap = new Bitmap(null, PixelSnapping.AUTO, true); this.bitmap = new Bitmap(null, PixelSnapping.NEVER, false);
} }
override private function get_view():DisplayObject { override private function get_view():DisplayObject {

View File

@@ -1,62 +1,88 @@
package ru.m.tankz.render.item; package ru.m.tankz.render.item;
import flash.display.BitmapData; import flash.display.BitmapData;
import flash.display.Shape;
import openfl.Assets; import openfl.Assets;
import openfl.display.DisplayObject; import ru.m.geom.GridPoint;
import ru.m.geom.Point;
import ru.m.geom.Rectangle; import ru.m.geom.Rectangle;
import ru.m.tankz.Type.BrickType; import ru.m.tankz.Type;
enum BrickState { class BrickBitmapBundle {
UNBROKEN;
BROKEN; private var data:Map<String, BitmapData>;
DESTROYED;
public function new() {
data = new Map();
} }
class BrickRenderItem extends RenderItem { private function resolve(type:BrickType, cells:Array<GridPoint>, frame:Int):BitmapData {
return switch cells.length {
case 0:
null;
case 4:
type == "none" ? null : RenderUtil.brickImage(type, frame);
case _:
var image = RenderUtil.brickImage(type, frame);
var result = new BitmapData(image.width, image.height, true, 0x00000000);
for (point in cells) {
var rect = new flash.geom.Rectangle(
point.x * image.width / 2,
point.y * image.height / 2,
image.width / 2,
image.height / 2);
result.draw(image, null, null, null, rect);
}
return result;
}
}
public function get(type:BrickType, cells:Array<GridPoint>, frame:Int = 0):BitmapData {
var key:String = '${type}_${cells.map(function(point) return point.toString()).join(",")}_${frame}';
if (!data.exists(key)) {
data.set(key, resolve(type, cells, frame));
}
return data.get(key);
}
}
class BrickRenderItem extends BitmapRenderItem {
private static var bundle:BrickBitmapBundle = new BrickBitmapBundle();
public var type(default, set):BrickType; public var type(default, set):BrickType;
public var state(get, never):BrickState;
private var image:BitmapData; private var cells:Array<GridPoint>;
private var shape:Shape;
private var cells:Array<Point>;
private static function buildCells():Array<Point> { private var frames:Int;
private var currentFrame:Int;
private var ticks:Int;
private static function buildCells():Array<GridPoint> {
return [ return [
new Point(0, 0), new GridPoint(0, 0),
new Point(0, 1), new GridPoint(0, 1),
new Point(1, 0), new GridPoint(1, 0),
new Point(1, 1), new GridPoint(1, 1),
]; ];
} }
public function new(rect:Rectangle, type:BrickType) { public function new(rect:Rectangle, type:BrickType) {
super(rect); super(rect);
this.shape = new Shape();
cells = buildCells(); cells = buildCells();
this.frames = 1;
this.currentFrame = 0;
this.ticks = 0;
this.type = type; this.type = type;
move(rect.position); move(rect.position);
} }
private function get_state():BrickState {
return switch cells.length {
case 0: DESTROYED;
case 4: UNBROKEN;
case _: BROKEN;
}
}
override private function get_view():DisplayObject {
return shape;
}
private function set_type(value:BrickType):BrickType { private function set_type(value:BrickType):BrickType {
if (type != value) { if (type != value) {
type = value; type = value;
frames = switch type {
case "water": 2;
case _: 1;
}
cells = buildCells(); cells = buildCells();
image = Assets.getBitmapData('resources/image/map/${type}.png');
redraw(); redraw();
} }
return type; return type;
@@ -73,24 +99,20 @@ class BrickRenderItem extends RenderItem {
} }
public function redraw():Void { public function redraw():Void {
shape.graphics.clear(); image = bundle.get(type, cells, currentFrame);
if (type == "none") return; }
switch state {
case UNBROKEN: override public function update():Void {
shape.graphics.beginBitmapFill(image); super.update();
shape.graphics.drawRect(0, 0, rect.width, rect.height); if (frames > 1) {
shape.graphics.endFill(); if (++ticks >= 30) {
case BROKEN: ticks = 0;
shape.graphics.beginBitmapFill(image); currentFrame++;
for (point in cells) { if (currentFrame >= frames) {
var x = point.x * (rect.width / 2); currentFrame = 0;
var y = point.y * (rect.width / 2); }
var width = rect.width / 2; redraw();
var height = rect.height / 2;
shape.graphics.drawRect(x, y, width, height);
} }
shape.graphics.endFill();
case DESTROYED:
} }
} }
} }

View File

@@ -1,20 +1,26 @@
package ru.m.tankz.render.item; package ru.m.tankz.render.item;
import hw.color.Color;
import hw.view.utils.BitmapUtil;
import ru.m.geom.Rectangle; import ru.m.geom.Rectangle;
class BulletRenderItem extends BitmapRenderItem { class BulletRenderItem extends BitmapRenderItem {
public var color(default, default):Null<Color>;
public var skin(default, set):String; public var skin(default, set):String;
public function new(rect:Rectangle, skin:String) { public function new(rect:Rectangle) {
super(rect); super(rect);
this.skin = skin;
move(rect.position); move(rect.position);
} }
private function set_skin(value:String):String { private function set_skin(value:String):String {
if (skin != value) { if (skin != value) {
skin = value; skin = value;
image = RenderUtil.bulletImage(skin); var image = RenderUtil.bulletImage(skin);
if (color != null) {
image = BitmapUtil.colorize(image, color);
}
this.image = image;
} }
return skin; return skin;
} }

View File

@@ -2,8 +2,8 @@ package ru.m.tankz.render.item;
import flash.display.DisplayObject; import flash.display.DisplayObject;
import flash.display.Sprite; import flash.display.Sprite;
import haxework.color.Color; import hw.color.Color;
import haxework.view.utils.BitmapUtil; import hw.view.utils.BitmapUtil;
import ru.m.animate.Animate; import ru.m.animate.Animate;
import ru.m.geom.Rectangle; import ru.m.geom.Rectangle;

View File

@@ -2,14 +2,15 @@ package ru.m.tankz.render.item;
import flash.display.BitmapData; import flash.display.BitmapData;
import flash.display.DisplayObject; import flash.display.DisplayObject;
import flash.display.Shape;
import flash.display.Sprite; import flash.display.Sprite;
import flash.text.TextField; import flash.text.TextField;
import flash.text.TextFieldAutoSize; import flash.text.TextFieldAutoSize;
import flash.text.TextFormat; import flash.text.TextFormat;
import haxework.color.Color; import hw.color.Color;
import haxework.text.BitmapTextField; import hw.text.BitmapTextField;
import haxework.view.theme.ITheme; import hw.view.theme.ITheme;
import haxework.view.utils.BitmapUtil; import hw.view.utils.BitmapUtil;
import ru.m.animate.Animate; import ru.m.animate.Animate;
import ru.m.geom.Rectangle; import ru.m.geom.Rectangle;
@@ -18,6 +19,7 @@ class TankRenderItem extends BitmapRenderItem {
public var skin(default, set):String; public var skin(default, set):String;
public var hits(default, set):Int; public var hits(default, set):Int;
public var bonus(default, set):Bool; public var bonus(default, set):Bool;
public var boat(default, set):Bool;
public var moves(default, set):Bool; public var moves(default, set):Bool;
public var protect(default, set):Bool; public var protect(default, set):Bool;
public var name(default, set):String; public var name(default, set):String;
@@ -26,6 +28,7 @@ class TankRenderItem extends BitmapRenderItem {
private var images:Array<BitmapData>; private var images:Array<BitmapData>;
private var frame:Int; private var frame:Int;
private var protectView:Animate; private var protectView:Animate;
private var boatView:Shape;
private var nameView:TextField; private var nameView:TextField;
@:provide static var theme:ITheme; @:provide static var theme:ITheme;
@@ -37,6 +40,9 @@ class TankRenderItem extends BitmapRenderItem {
protectView = AnimateBundle.tankProtect(); protectView = AnimateBundle.tankProtect();
protectView.visible = false; protectView.visible = false;
container.addChild(protectView); container.addChild(protectView);
boatView = buildBoatView();
boatView.visible = false;
container.addChild(boatView);
nameView = buildNameView(); nameView = buildNameView();
container.addChild(nameView); container.addChild(nameView);
move(rect.position); move(rect.position);
@@ -52,6 +58,13 @@ class TankRenderItem extends BitmapRenderItem {
return result; return result;
} }
private function buildBoatView():Shape {
var result = new Shape();
result.graphics.lineStyle(4, Color.fromString("green"), 0.8);
result.graphics.drawRoundRect(-1, -1, rect.width + 2, rect.height + 2, 10, 10);
return result;
}
override private function get_view():DisplayObject { override private function get_view():DisplayObject {
return container; return container;
} }
@@ -108,6 +121,14 @@ class TankRenderItem extends BitmapRenderItem {
return bonus; return bonus;
} }
private function set_boat(value:Bool):Bool {
if (boat != value) {
boat = value;
boatView.visible = boat;
}
return boat;
}
private function set_protect(value:Bool):Bool { private function set_protect(value:Bool):Bool {
if (protect != value) { if (protect != value) {
protect = value; protect = value;
@@ -143,7 +164,7 @@ class TankRenderItem extends BitmapRenderItem {
super.update(); super.update();
if (moves) { if (moves) {
frame++; frame++;
if (frame > images.length - 1) { if (frame >= images.length) {
frame = 0; frame = 0;
} }
bitmap.bitmapData = images[frame]; bitmap.bitmapData = images[frame];

View File

@@ -9,7 +9,7 @@ import ru.m.tankz.config.Config;
import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.IGame; import ru.m.tankz.game.IGame;
class SoundManager implements GameListener { @:provide class SoundManager implements GameListener {
private static var TAG(default, never):String = "SoundManager"; private static var TAG(default, never):String = "SoundManager";
#if flash #if flash

View File

@@ -1,10 +1,10 @@
package ru.m.tankz.storage; package ru.m.tankz.storage;
import haxework.storage.SharedObjectStorage; import hw.storage.SharedObjectStorage;
import ru.m.tankz.game.PackProgress; import ru.m.tankz.game.PackProgress;
import ru.m.tankz.Type; import ru.m.tankz.Type;
class GameStorage extends SharedObjectStorage { @:provide class GameStorage extends SharedObjectStorage {
private static inline var VERSION = 1; private static inline var VERSION = 1;

View File

@@ -1,8 +1,8 @@
package ru.m.tankz.storage; package ru.m.tankz.storage;
import haxework.storage.SharedObjectStorage; import hw.storage.SharedObjectStorage;
class NetworkStorage extends SharedObjectStorage { @:provide class NetworkStorage extends SharedObjectStorage {
public var user(get, set):User; public var user(get, set):User;

View File

@@ -1,10 +1,10 @@
package ru.m.tankz.storage; package ru.m.tankz.storage;
import haxe.DynamicAccess; import haxe.DynamicAccess;
import haxework.storage.SharedObjectStorage; import hw.storage.SharedObjectStorage;
import ru.m.tankz.game.record.GameRecord; import ru.m.tankz.game.record.GameRecord;
class RecordStorage extends SharedObjectStorage { @:provide class RecordStorage extends SharedObjectStorage {
private static inline var VERSION = 1; private static inline var VERSION = 1;

View File

@@ -1,18 +1,51 @@
package ru.m.tankz.storage; package ru.m.tankz.storage;
import flash.ui.Keyboard; import flash.ui.Keyboard;
import haxework.storage.SharedObjectStorage; import hw.signal.Signal;
import haxework.utils.ObjectUtil; import hw.storage.SharedObjectStorage;
import hw.utils.ObjectUtil;
import ru.m.control.DeviceAction; import ru.m.control.DeviceAction;
import ru.m.control.DeviceType; import ru.m.control.DeviceType;
import ru.m.geom.Direction; import ru.m.geom.Direction;
import ru.m.tankz.control.Binding; import ru.m.tankz.control.Binding;
import ru.m.tankz.control.Control; import ru.m.tankz.control.Control;
class SettingsStorage extends SharedObjectStorage { enum Setting {
CONTROL(index:Int, value:Binding);
DISPLAY_FPS(value:Bool);
ENABLE_NETWORK(value:Bool);
}
@:provide class SettingsStorage extends SharedObjectStorage {
private static inline var VERSION = 4.1; private static inline var VERSION = 4.1;
public var signal(default, null):Signal<Setting> = new Signal();
public var displayFPS(get, set):Bool;
private function get_displayFPS():Bool {
return read("setting:display_fps");
}
private function set_displayFPS(value:Bool):Bool {
write("setting:display_fps", value);
signal.emit(DISPLAY_FPS(value));
return get_displayFPS();
}
public var enableNetwork(get, set):Bool;
private function get_enableNetwork():Bool {
return read("setting:enable_network");
}
private function set_enableNetwork(value:Bool):Bool {
write("setting:enable_network", value);
signal.emit(ENABLE_NETWORK(value));
return get_enableNetwork();
}
public function new() { public function new() {
super('settings_${VERSION}'); super('settings_${VERSION}');
} }
@@ -23,6 +56,7 @@ class SettingsStorage extends SharedObjectStorage {
public function saveBinding(index:Int, value:Binding) { public function saveBinding(index:Int, value:Binding) {
write('action:$index', value); write('action:$index', value);
signal.emit(CONTROL(index, value));
} }
public static function getDefaultBinding(index:Int):Binding { public static function getDefaultBinding(index:Int):Binding {

View File

@@ -1,11 +1,12 @@
package ru.m.tankz.view; package ru.m.tankz.view;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard; import flash.ui.Keyboard;
import haxework.resources.IResources; import hw.resources.IResources;
import haxework.view.frame.FrameSwitcher; import hw.view.frame.FrameSwitcher;
import haxework.view.group.VGroupView; import hw.view.group.VGroupView;
import ru.m.tankz.game.IGame; import ru.m.control.DeviceAction;
import ru.m.control.DeviceType;
import ru.m.control.IControlBus;
import ru.m.tankz.network.NetworkManager; import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.sound.SoundManager; import ru.m.tankz.sound.SoundManager;
@@ -16,27 +17,28 @@ import ru.m.tankz.sound.SoundManager;
@:provide var resources:IResources; @:provide var resources:IResources;
@:provide var switcher:FrameSwitcher; @:provide var switcher:FrameSwitcher;
@:provide var soundManager:SoundManager; @:provide var soundManager:SoundManager;
@:provide var game:IGame; @:provide static var bus:IControlBus;
public function init():Void { public function new():Void {
super();
resources.text.put('version', '${Const.VERSION}'); resources.text.put('version', '${Const.VERSION}');
resources.text.put('name', '${Const.NAME}');
switcher = switcherView; switcher = switcherView;
} }
public function launch():Void { public function launch():Void {
content.stage.stageFocusRect = false; content.stage.stageFocusRect = false;
content.stage.addEventListener(KeyboardEvent.KEY_UP, function(event:KeyboardEvent):Void { bus.signal.connect(onDeviceAction);
switch event.keyCode {
case Keyboard.ESCAPE:
switcher.change(MenuFrame.ID); switcher.change(MenuFrame.ID);
case Keyboard.M: }
private function onDeviceAction(type:DeviceType, action:DeviceAction, state:Bool):Void {
switch [type, action, state] {
case [KEYBOARD, KEY(Keyboard.ESCAPE), true]:
switcher.change(MenuFrame.ID);
case [KEYBOARD, KEY(Keyboard.M), true]:
soundManager.mute = !soundManager.mute; soundManager.mute = !soundManager.mute;
case Keyboard.P: case _:
if (game != null) {
game.pause = !game.pause;
} }
} }
});
switcher.change(MenuFrame.ID);
}
} }

View File

@@ -1,6 +1,6 @@
--- ---
views: views:
- $type: haxework.view.frame.FrameSwitcher - $type: hw.view.frame.FrameSwitcher
id: switcher id: switcher
geometry.stretch: true geometry.stretch: true
style: dark style: dark
@@ -14,3 +14,7 @@ views:
_record_: {$class: ru.m.tankz.view.RecordFrame} _record_: {$class: ru.m.tankz.view.RecordFrame}
_room_list_: {$class: ru.m.tankz.view.network.RoomListFrame} _room_list_: {$class: ru.m.tankz.view.network.RoomListFrame}
_room_: {$class: ru.m.tankz.view.network.RoomFrame} _room_: {$class: ru.m.tankz.view.network.RoomFrame}
- $type: ru.m.tankz.view.common.NetworkStateView
geometry.position: absolute
geometry.hAlign: center
geometry.margin.top: 2

View File

@@ -1,14 +1,21 @@
package ru.m.tankz.view; package ru.m.tankz.view;
import haxework.view.frame.FrameSwitcher; import hw.view.text.TextView;
import haxework.view.frame.FrameView; import ru.m.tankz.view.popup.PausePopup;
import haxework.view.group.GroupView; import flash.ui.Keyboard;
import haxework.view.layout.DefaultLayout; import ru.m.control.DeviceAction;
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.DeviceType;
import ru.m.control.IControlBus; import ru.m.control.IControlBus;
import ru.m.tankz.control.HumanControl; import ru.m.tankz.control.HumanControl;
import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameInit; import ru.m.tankz.game.GameInit;
import ru.m.tankz.game.GameState.TeamState;
import ru.m.tankz.game.IGame; import ru.m.tankz.game.IGame;
import ru.m.tankz.game.record.GamePlayer; import ru.m.tankz.game.record.GamePlayer;
import ru.m.tankz.game.record.GameRecord; import ru.m.tankz.game.record.GameRecord;
@@ -17,10 +24,13 @@ import ru.m.tankz.network.NetworkGame;
import ru.m.tankz.sound.SoundManager; import ru.m.tankz.sound.SoundManager;
import ru.m.tankz.storage.GameStorage; import ru.m.tankz.storage.GameStorage;
import ru.m.tankz.storage.SettingsStorage; import ru.m.tankz.storage.SettingsStorage;
import ru.m.tankz.view.game.GameViewA; import ru.m.tankz.Type;
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.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 { @:template class GameFrame extends FrameView<GameInit> implements GameListener {
public static inline var ID = "game"; public static inline var ID = "game";
@@ -33,19 +43,18 @@ import ru.m.tankz.view.gamepad.GamepadView;
@:provide static var settings:SettingsStorage; @:provide static var settings:SettingsStorage;
@:provide static var bus:IControlBus; @: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; @:view private var gamepad(default, null):GamepadView;
private var gameView:IGameView; private var gamepadPlayerId:PlayerId;
private var game:IGame; private var game:IGame;
private var recorder:GameRecord; private var recorder:GameRecord;
public function new() { public function new() {
super(id, new DefaultLayout()); super(id, new DefaultLayout());
}
public function init():Void {
bus.connect(gamepad); bus.connect(gamepad);
} }
@@ -56,41 +65,120 @@ import ru.m.tankz.view.gamepad.GamepadView;
case NETWORK(network): new NetworkGame(network); case NETWORK(network): new NetworkGame(network);
case RECORD(record): new GamePlayer(record); 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; soundManager.config = game.config;
gameView.render.config = game.config; render.config = game.config;
game.connect(gameView.render); game.connect(render);
game.connect(soundManager); game.connect(soundManager);
game.connect(gameView);
game.connect(this); game.connect(this);
game.start(); game.start();
// ToDo: // TODO:
for (control in game.controls) { for (control in game.controls) {
if (Std.is(control, HumanControl)) { if (Std.is(control, HumanControl)) {
if (cast(control, HumanControl).hasDevice(SCREEN)) { if (cast(control, HumanControl).hasDevice(SCREEN)) {
gamepadPlayerId = control.playerId;
gamepad.visible = true; gamepad.visible = true;
break; break;
} }
} }
} }
bus.signal.connect(onDeviceAction);
}
private function onDeviceAction(type:DeviceType, action:DeviceAction, state:Bool):Void {
switch [type, action, state] {
case [KEYBOARD, KEY(Keyboard.P), true]:
game.pause = !game.pause;
case _:
}
} }
private function stop():Void { private function stop():Void {
bus.signal.disconnect(onDeviceAction);
if (game != null) { if (game != null) {
game.dispose(); game.dispose();
game = null; game = null;
} }
if (gameView != null) { render.reset();
gameView.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 { public function onGameEvent(event:GameEvent):Void {
switch event { 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);
gamepad.weapons = tankConfig.weapons;
}
case PAUSE(paused):
if (paused) {
PausePopup.instance.show().then(function(action) {
switch action {
case EXIT:
switcher.change(LevelFrame.ID, game.level.packId);
case RESUME | null:
game.pause = false;
}
});
} else {
PausePopup.instance.close(null);
}
case COMPLETE(result): case COMPLETE(result):
stop(); stop();
switcher.change(ResultFrame.ID, result); switcher.change(ResultFrame.ID, result);
@@ -101,13 +189,5 @@ import ru.m.tankz.view.gamepad.GamepadView;
override public function onHide():Void { override public function onHide():Void {
stop(); stop();
soundManager.stopAll(); soundManager.stopAll();
if (gameView != null) {
gameViewContainer.removeView(gameView);
gameView = null;
}
}
public function close():Void {
switcher.change(LevelFrame.ID, game.level.packId);
} }
} }

View File

@@ -1,21 +1,48 @@
--- ---
style: container style: container
overflow.x: crop
overflow.y: crop
views: views:
- id: game - id: game
$type: ru.m.tankz.view.game.GameViewContainer $type: hw.view.group.HGroupView
layout.hAlign: center geometry.stretch: true
views:
- id: left
$type: hw.view.group.GroupView
layout.vAlign: middle 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 - id: gamepad
$type: ru.m.tankz.view.gamepad.GamepadView $type: ru.m.tankz.view.gamepad.GamepadView
geometry.position: absolute geometry.position: absolute
geometry.stretch: true geometry.stretch: true
visible: false visible: false
- $type: haxework.view.form.ButtonView - $type: hw.view.form.ButtonView
style: button.close style: button.bars
geometry.position: absolute geometry.position: absolute
geometry.hAlign: left geometry.hAlign: left
geometry.vAlign: top geometry.vAlign: top
geometry.margin: 10 geometry.margin: 10
+onPress: ~close() +onPress: ~function(_) game.pause = true

View File

@@ -1,10 +1,10 @@
package ru.m.tankz.view; package ru.m.tankz.view;
import haxework.view.data.DataView; import hw.view.data.DataView;
import haxework.view.form.ButtonView; import hw.view.form.ButtonView;
import haxework.view.form.LabelView; import hw.view.form.LabelView;
import haxework.view.frame.FrameSwitcher; import hw.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView; import hw.view.frame.FrameView;
import ru.m.tankz.bundle.IConfigBundle; import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.bundle.ILevelBundle; import ru.m.tankz.bundle.ILevelBundle;
import ru.m.tankz.config.Config; import ru.m.tankz.config.Config;

View File

@@ -1,29 +1,29 @@
--- ---
views: views:
- $type: haxework.view.group.VGroupView - $type: hw.view.group.VGroupView
style: container style: container
views: views:
- id: header - id: header
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
style: text.header style: text.header
- id: levels - id: levels
$type: haxework.view.data.DataView $type: hw.view.data.DataView
geometry.width: 100% geometry.width: 100%
geometry.height: 100% geometry.height: 100%
overflow.y: scroll overflow.y: scroll
layout: layout:
$type: haxework.view.layout.TailLayout $type: hw.view.layout.TailLayout
rowSize: 10 rowSize: 10
margin: 5 margin: 5
factory: ~levelViewFactory factory: ~levelViewFactory
+onItemSelect: ~onLevelSelect +onItemSelect: ~onLevelSelect
geometry.padding: 10 geometry.padding: 10
- $type: haxework.view.group.HGroupView - $type: hw.view.group.HGroupView
style: panel style: panel
layout.margin: 10 layout.margin: 10
views: views:
- $type: haxework.view.SpriteView - $type: hw.view.SpriteView
geometry.width: 100% geometry.width: 100%
- $type: haxework.view.form.ButtonView - $type: hw.view.form.ButtonView
style: button.prev style: button.prev
+onPress: ~switcher.change("menu") +onPress: ~switcher.change("menu")

View File

@@ -1,18 +1,20 @@
package ru.m.tankz.view; package ru.m.tankz.view;
import haxework.view.data.DataView; import hw.view.data.DataView;
import haxework.view.form.ButtonView; import hw.view.form.ButtonView;
import haxework.view.form.LabelView; import hw.view.frame.FrameSwitcher;
import haxework.view.frame.FrameSwitcher; import hw.view.frame.FrameView;
import haxework.view.frame.FrameView;
import ru.m.tankz.bundle.ILevelBundle; import ru.m.tankz.bundle.ILevelBundle;
import ru.m.tankz.game.GameInit; import ru.m.tankz.game.GameInit;
import ru.m.tankz.game.GameState; import ru.m.tankz.game.GameState;
import ru.m.tankz.network.NetworkManager; import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.storage.SettingsStorage;
import ru.m.tankz.Type; import ru.m.tankz.Type;
import ru.m.tankz.view.common.PackView;
import ru.m.tankz.view.network.RoomFrame; import ru.m.tankz.view.network.RoomFrame;
import ru.m.tankz.view.network.RoomListFrame; import ru.m.tankz.view.network.RoomListFrame;
import ru.m.tankz.view.popup.LoginPopup; import ru.m.tankz.view.popup.LoginPopup;
import ru.m.update.Updater;
using ru.m.tankz.view.ViewUtil; using ru.m.tankz.view.ViewUtil;
@@ -25,12 +27,11 @@ using ru.m.tankz.view.ViewUtil;
@:provide static var network:NetworkManager; @:provide static var network:NetworkManager;
@:provide static var appUpdater:Updater; @:provide static var appUpdater:Updater;
@:provide static var levelBundle:ILevelBundle; @:provide static var levelBundle:ILevelBundle;
@:provide static var settings:SettingsStorage;
@:view var packs:DataView<PackId, ButtonView>; @:view var packs:DataView<PackId, PackView>;
@:view var username:LabelView;
@:view("login") var loginButton:ButtonView;
@:view("logout") var logoutButton:ButtonView;
@:view("update") var updateButton:ButtonView; @:view("update") var updateButton:ButtonView;
@:view("network") var networkButton:ButtonView;
public function new() { public function new() {
super(ID); super(ID);
@@ -38,29 +39,29 @@ using ru.m.tankz.view.ViewUtil;
override public function onShow(data:Dynamic):Void { override public function onShow(data:Dynamic):Void {
super.onShow(data); super.onShow(data);
network.stateSignal.connect(onConnectionState);
onConnectionState(network.state);
appUpdater.check().then(function(update:Bool) { appUpdater.check().then(function(update:Bool) {
updateButton.visible = update; updateButton.visible = update;
if (update) { if (update) {
updateButton.text = 'Update ${appUpdater.bundle.version}'; updateButton.text = 'Update ${appUpdater.bundle.version}';
} }
}); }).catchError(function(error) {});
var list = levelBundle.list(); var list = levelBundle.list();
list.sort(function(a:PackId, b:PackId) return a.toPackLabel() > b.toPackLabel() ? 1 : -1); list.sort(function(a:PackId, b:PackId) return a.toPackLabel() > b.toPackLabel() ? 1 : -1);
packs.data = list; packs.data = list;
networkButton.visible = settings.enableNetwork;
settings.signal.connect(onSettingChange);
} }
override public function onHide():Void { override public function onHide():Void {
super.onHide(); super.onHide();
network.stateSignal.disconnect(onConnectionState); settings.signal.disconnect(onSettingChange);
} }
private function packButtonFactory(index:Int, packId:PackId):ButtonView { private function onSettingChange(setting:Setting):Void {
var result = new ButtonView(); switch setting {
result.style = "button.menu"; case ENABLE_NETWORK(value): networkButton.visible = value;
result.text = packId.toPackLabel(); case _:
return result; }
} }
private function startGame(packId:PackId):Void { private function startGame(packId:PackId):Void {
@@ -87,37 +88,6 @@ using ru.m.tankz.view.ViewUtil;
} }
} }
private function onConnectionState(state:ConnectionState):Void {
L.d("ClientView", 'onConnectionState: ${state}');
switch state {
case ONLINE(user):
username.text = user.name;
logoutButton.visible = true;
loginButton.visible = false;
case CONNECTED:
username.text = "";
logoutButton.visible = false;
loginButton.visible = true;
case ERROR(error):
//L.e("ClientView", 'onConnectionState: ERROR', error);
L.w("ClientView", 'onConnectionState: ERROR');
case _:
username.text = "";
logoutButton.visible = false;
loginButton.visible = false;
}
}
private function login():Void {
LoginPopup.instance.show().then(function(user:User):Void {
L.d("Login", 'user: $user');
});
}
private function logout():Void {
network.logout();
}
private function appUpdate():Void { private function appUpdate():Void {
appUpdater.download(); appUpdater.download();
} }

View File

@@ -1,74 +1,61 @@
--- ---
views: views:
- $type: haxework.view.group.VGroupView - $type: hw.view.group.VGroupView
style: container style: container
overflow.y: scroll overflow.y: scroll
views: views:
- $type: haxework.view.group.VGroupView - $type: hw.view.group.VGroupView
geometry.width: 100%
layout.margin: 10 layout.margin: 10
layout.hAlign: center layout.hAlign: center
views: views:
- $type: haxework.view.form.LabelView - $type: hw.view.form.LabelView
text: Tank'z text: $r:text:name
style: font style: font
font.size: 100 font.size: 100
geometry.margin.bottom: 30 geometry.margin.bottom: 30
- id: packs - id: packs
$type: haxework.view.data.DataView $type: hw.view.data.DataView
geometry.width: 100%
layout: layout:
$type: haxework.view.layout.VerticalLayout $type: hw.view.layout.TailLayout
rowSize: 2
margin: 10 margin: 10
factory: ~packButtonFactory factory: ~ru.m.tankz.view.common.PackView.factory
+onDataSelect: ~startGame +onDataSelect: ~startGame
- $type: haxework.view.SpriteView - $type: hw.view.SpriteView
style: line style: line
geometry.width: 250 geometry.width: 250
geometry.margin: [0, 10] geometry.margin: [0, 10]
visible: false visible: false
- $type: haxework.view.form.ButtonView - $type: hw.view.form.ButtonView
style: button.menu
+onPress: ~switcher.change('record') +onPress: ~switcher.change('record')
text: Records text: Records
visible: false visible: false
- id: network - id: network
$type: haxework.view.form.ButtonView $type: hw.view.form.ButtonView
style: button.menu
+onPress: ~startNetwork() +onPress: ~startNetwork()
text: Network text: Network (alpha)
visible: false visible: false
- $type: haxework.view.form.LabelView - $type: hw.view.form.LabelView
geometry.hAlign: right geometry.hAlign: right
geometry.vAlign: top geometry.vAlign: top
geometry.position: absolute geometry.position: absolute
geometry.margin: [0, 20, 20, 0] geometry.margin: [0, 20, 20, 0]
style: text.box style: text.box
text: $r:text:version text: $r:text:version
- $type: haxework.view.group.HGroupView - $type: hw.view.group.HGroupView
style: panel style: panel
layout.margin: 10 layout.margin: 10
views: views:
- id: settings - id: settings
$type: haxework.view.form.ButtonView $type: hw.view.form.ButtonView
style: button.settings style: button.settings
+onPress: ~switcher.change('settings') +onPress: ~switcher.change('settings')
- $type: haxework.view.SpriteView - $type: hw.view.SpriteView
geometry.width: 50% geometry.width: 100%
- id: username
$type: haxework.view.form.LabelView
style: text
- id: login
$type: haxework.view.form.ButtonView
style: button.login
+onPress: ~login()
- id: logout
$type: haxework.view.form.ButtonView
style: button.logout
+onPress: ~logout()
visible: false
- $type: haxework.view.SpriteView
geometry.width: 50%
- id: update - id: update
$type: haxework.view.form.ButtonView $type: hw.view.form.ButtonView
style: button.active style: button.active
+onPress: ~appUpdate() +onPress: ~appUpdate()
visible: false visible: false

View File

@@ -1,8 +1,8 @@
package ru.m.tankz.view; package ru.m.tankz.view;
import haxework.view.frame.FrameSwitcher; import hw.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView; import hw.view.frame.FrameView;
import haxework.view.list.VListView; import hw.view.list.VListView;
import ru.m.tankz.game.record.GameRecord; import ru.m.tankz.game.record.GameRecord;
import ru.m.tankz.storage.RecordStorage; import ru.m.tankz.storage.RecordStorage;

View File

@@ -1,24 +1,24 @@
--- ---
views: views:
- $type: haxework.view.group.VGroupView - $type: hw.view.group.VGroupView
style: container style: container
views: views:
- $type: haxework.view.form.LabelView - $type: hw.view.form.LabelView
style: text.header style: text.header
text: Records text: Records
- id: data - id: data
$type: haxework.view.list.VListView $type: hw.view.list.VListView
factory: ~function() return new ru.m.tankz.view.common.RecordView() factory: ~function() return new ru.m.tankz.view.common.RecordView()
geometry.margin.top: 20 geometry.margin.top: 20
geometry.stretch: true geometry.stretch: true
scroll: scroll:
$type: haxework.view.list.VScrollBarView $type: hw.view.list.VScrollBarView
- $type: haxework.view.group.HGroupView - $type: hw.view.group.HGroupView
style: panel style: panel
layout.margin: 10 layout.margin: 10
views: views:
- $type: haxework.view.SpriteView - $type: hw.view.SpriteView
geometry.width: 100% geometry.width: 100%
- $type: haxework.view.form.ButtonView - $type: hw.view.form.ButtonView
style: button.prev style: button.prev
+onPress: ~switcher.change("menu") +onPress: ~switcher.change("menu")

View File

@@ -1,10 +1,10 @@
package ru.m.tankz.view; package ru.m.tankz.view;
import haxework.view.data.DataView; import hw.view.data.DataView;
import haxework.view.form.ButtonView; import hw.view.form.ButtonView;
import haxework.view.form.LabelView; import hw.view.form.LabelView;
import haxework.view.frame.FrameSwitcher; import hw.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView; import hw.view.frame.FrameView;
import ru.m.tankz.bundle.ILevelBundle; import ru.m.tankz.bundle.ILevelBundle;
import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameInit; import ru.m.tankz.game.GameInit;

View File

@@ -1,16 +1,16 @@
--- ---
views: views:
- $type: haxework.view.group.VGroupView - $type: hw.view.group.VGroupView
style: container style: container
views: views:
- id: level - id: level
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
style: text.header style: text.header
font.align: center font.align: center
- id: result - id: result
$type: haxework.view.data.DataView $type: hw.view.data.DataView
layout: layout:
$type: haxework.view.layout.TailLayout $type: hw.view.layout.TailLayout
factory: ~ru.m.tankz.view.result.ResultPlayerView.factory factory: ~ru.m.tankz.view.result.ResultPlayerView.factory
geometry.width: 100% geometry.width: 100%
geometry.height: 100% geometry.height: 100%
@@ -18,23 +18,24 @@ views:
geometry.margin.top: 20 geometry.margin.top: 20
layout.margin: 5 layout.margin: 5
layout.hAlign: center layout.hAlign: center
- $type: haxework.view.group.HGroupView - $type: hw.view.group.HGroupView
style: panel style: panel
layout.margin: 10 layout.margin: 10
views: views:
- $type: haxework.view.SpriteView - $type: hw.view.SpriteView
geometry.width: 50% geometry.width: 50%
- id: levels
$type: haxework.view.form.ButtonView
text: Levels
+onPress: ~levels()
- id: restart - id: restart
$type: haxework.view.form.ButtonView $type: hw.view.form.ButtonView
style: panel_button
text: Restart text: Restart
+onPress: ~restart() +onPress: ~restart()
- id: next - id: next
$type: haxework.view.form.ButtonView $type: hw.view.form.ButtonView
style: panel_button
text: Next text: Next
+onPress: ~next() +onPress: ~next()
- $type: haxework.view.SpriteView - $type: hw.view.SpriteView
geometry.width: 50% geometry.width: 50%
- $type: hw.view.form.ButtonView
style: button.prev
+onPress: ~levels()

View File

@@ -1,14 +1,39 @@
package ru.m.tankz.view; package ru.m.tankz.view;
import haxework.view.frame.FrameSwitcher; import hw.view.form.ToggleButtonView;
import haxework.view.frame.FrameView; import hw.view.frame.FrameSwitcher;
import hw.view.frame.FrameView;
import ru.m.tankz.storage.SettingsStorage;
@:template class SettingsFrame extends FrameView<Dynamic> { @:template class SettingsFrame extends FrameView<Dynamic> {
public static var ID(default, never):String = "settings"; public static var ID(default, never):String = "settings";
@:view("fps") var fpsButton:ToggleButtonView;
@:view("network") var networkButton:ToggleButtonView;
@:provide static var switcher:FrameSwitcher; @:provide static var switcher:FrameSwitcher;
@:provide static var settings:SettingsStorage;
public function new() { public function new() {
super(ID); super(ID);
} }
override public function onShow(data:Dynamic):Void {
super.onShow(data);
fpsButton.on = settings.displayFPS;
networkButton.on = settings.enableNetwork;
settings.signal.connect(onSettingChange);
}
override public function onHide():Void {
settings.signal.disconnect(onSettingChange);
}
private function onSettingChange(setting:Setting):Void {
switch setting {
case DISPLAY_FPS(value): fpsButton.on = value;
case ENABLE_NETWORK(value): networkButton.on = value;
case _:
}
}
} }

View File

@@ -1,17 +1,20 @@
--- ---
views: views:
- $type: haxework.view.group.VGroupView - $type: hw.view.group.VGroupView
style: container style: container
views: views:
- $type: haxework.view.form.LabelView - $type: hw.view.form.LabelView
style: text.header style: text.header
text: Settings text: Settings
- $type: haxework.view.group.GroupView - $type: hw.view.group.VGroupView
geometry.width: 100% geometry.stretch: true
geometry.height: 100% layout.hAlign: center
overflow.y: scroll overflow.y: scroll
views:
- $type: hw.view.group.GroupView
geometry.width: 100%
layout: layout:
$type: haxework.view.layout.TailLayout $type: hw.view.layout.TailLayout
vAlign: top vAlign: top
margin: 20 margin: 20
views: views:
@@ -21,12 +24,29 @@ views:
- id: settings1 - id: settings1
$type: ru.m.tankz.view.settings.SettingsEditor $type: ru.m.tankz.view.settings.SettingsEditor
controlIndex: 1 controlIndex: 1
- $type: haxework.view.group.HGroupView - $type: hw.view.group.GroupView
geometry.width: 100%
geometry.margin.top: 20
layout:
$type: hw.view.layout.TailLayout
hAlign: center
margin: 20
views:
- id: fps
$type: hw.view.form.ToggleButtonView
text: Display FPS
+onPress: ~function(button) settings.displayFPS = !cast(button,ToggleButtonView).on
- id: network
$type: hw.view.form.ToggleButtonView
geometry.margin.top: 20
text: Enable Network
+onPress: ~function(button) settings.enableNetwork = !cast(button,ToggleButtonView).on
- $type: hw.view.group.HGroupView
style: panel style: panel
layout.margin: 10 layout.margin: 10
views: views:
- $type: haxework.view.SpriteView - $type: hw.view.SpriteView
geometry.width: 100% geometry.width: 100%
- $type: haxework.view.form.ButtonView - $type: hw.view.form.ButtonView
style: button.prev style: button.prev
+onPress: ~switcher.change("menu") +onPress: ~switcher.change("menu")

View File

@@ -1,10 +1,10 @@
package ru.m.tankz.view; package ru.m.tankz.view;
import haxework.view.data.DataView; import hw.view.data.DataView;
import haxework.view.form.ButtonView; import hw.view.form.ButtonView;
import haxework.view.form.LabelView; import hw.view.form.LabelView;
import haxework.view.frame.FrameSwitcher; import hw.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView; import hw.view.frame.FrameView;
import ru.m.tankz.config.Config; import ru.m.tankz.config.Config;
import ru.m.tankz.control.Controller; import ru.m.tankz.control.Controller;
import ru.m.tankz.control.PlayerControl; import ru.m.tankz.control.PlayerControl;
@@ -114,7 +114,8 @@ using ru.m.tankz.view.ViewUtil;
private function presetViewFactory(index:Int, value:GamePreset):ButtonView { private function presetViewFactory(index:Int, value:GamePreset):ButtonView {
var result = new ButtonView(); var result = new ButtonView();
result.style = 'button${!progress.isPresetCompleted(start.level.id, value.id) ? ".active" : ""}'; result.style = 'button${!progress.isPresetCompleted(start.level.id, value.id) ? ".active" : ""}';
result.text = value.name; result.geometry.height = "100%";
result.text = value.name == "default" ? "start" : value.name;
result.disabled = !progress.isPresetAvailable(start.level.id, value.id); result.disabled = !progress.isPresetAvailable(start.level.id, value.id);
return result; return result;
} }

View File

@@ -1,13 +1,13 @@
--- ---
views: views:
- $type: haxework.view.group.VGroupView - $type: hw.view.group.VGroupView
style: container style: container
views: views:
- id: header - id: header
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
style: text.header style: text.header
- id: teams - id: teams
$type: haxework.view.data.DataView $type: hw.view.data.DataView
geometry.padding: 10 geometry.padding: 10
geometry.width: 100% geometry.width: 100%
geometry.height: 100% geometry.height: 100%
@@ -15,25 +15,26 @@ views:
overflow.y: scroll overflow.y: scroll
factory: ~teamViewFactory factory: ~teamViewFactory
layout: layout:
$type: haxework.view.layout.TailLayout $type: hw.view.layout.TailLayout
margin: 5 margin: 5
rowSize: 2 rowSize: 2
- $type: haxework.view.group.HGroupView - $type: hw.view.group.HGroupView
style: panel style: panel
layout.margin: 10 layout.margin: 10
views: views:
- $type: haxework.view.SpriteView - $type: hw.view.SpriteView
geometry.width: 50% geometry.width: 50%
- id: presets - id: presets
$type: haxework.view.data.DataView $type: hw.view.data.DataView
factory: ~presetViewFactory factory: ~presetViewFactory
+onDataSelect: ~onPresetSelect +onDataSelect: ~onPresetSelect
geometry.height: 100%
layout: layout:
$type: haxework.view.layout.HorizontalLayout $type: hw.view.layout.HorizontalLayout
hAlign: center hAlign: center
margin: 5 margin: 5
- $type: haxework.view.SpriteView - $type: hw.view.SpriteView
geometry.width: 50% geometry.width: 50%
- $type: haxework.view.form.ButtonView - $type: hw.view.form.ButtonView
style: button.prev style: button.prev
+onPress: ~switcher.change("level", start.level.packId) +onPress: ~switcher.change("level", start.level.packId)

View File

@@ -41,8 +41,8 @@ class ViewUtil {
return result.join(oneline ? " " : "\n"); return result.join(oneline ? " " : "\n");
} }
public static function toPackLabel(packId:PackId):String { public static function toPackLabel(packId:PackId, separator=" #"):String {
return packId.name != PackId.DEFAULT ? '${packId.type} #${packId.name}' : packId.type; return packId.name != PackId.DEFAULT ? '${packId.type}${separator}${packId.name}' : packId.type;
} }
public static function toActionLabel(action:TankAction):String { public static function toActionLabel(action:TankAction):String {

View File

@@ -0,0 +1,64 @@
package ru.m.tankz.view.common;
import hw.view.form.ButtonView;
import hw.view.form.LabelView;
import hw.view.group.HGroupView;
import hw.view.skin.SpriteSkin;
import hw.view.SpriteView;
import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.view.popup.LoginPopup;
@:template class NetworkStateView extends HGroupView {
@:view("state") var stateView:SpriteView;
@:view("user") var userLabel:LabelView;
@:view("login") var loginButton:ButtonView;
@:view("logout") var logoutButton:ButtonView;
@:provide static var network:NetworkManager;
public function new():Void {
super();
network.stateSignal.connect(onConnectionChange);
}
private function onConnectionChange(state:ConnectionState):Void {
visible = true;
stateView.visible = true;
userLabel.text = "";
loginButton.visible = false;
logoutButton.visible = false;
var skin:SpriteSkin = cast stateView.skin;
switch state {
case OFFLINE:
skin.background.color = "black";
stateView.visible = false;
visible = false;
case CONNECT:
skin.background.color = "yellow";
case CONNECTED:
skin.background.color = "gray";
loginButton.visible = true;
case LOGIN:
skin.background.color = "yellow";
case ONLINE(user):
skin.background.color = "green";
userLabel.text = user.name;
logoutButton.visible = true;
case ERROR(error):
skin.background.color = "red";
userLabel.text = Std.string(error).substr(0, 10);
}
stateView.toRedraw();
}
private function login():Void {
LoginPopup.instance.show().then(function(user:User):Void {
L.d("Login", 'user: $user');
});
}
private function logout():Void {
network.logout();
}
}

View File

@@ -0,0 +1,34 @@
---
geometry.padding: [5, 2]
layout.vAlign: middle
visible: false
skin:
$type: hw.view.skin.SpriteSkin
border.color: 0x95937D
round: 10
views:
- id: state
$type: hw.view.SpriteView
geometry.width: 20
geometry.height: 20
visible: false
skin:
$type: hw.view.skin.SpriteSkin
background.color: black
border.color: 0xE7E0BB
round: 20
- id: user
$type: hw.view.form.LabelView
font.size: 14
- id: login
$type: hw.view.form.ButtonView
style: button.small
text: login
+onPress: ~login()
visible: false
- id: logout
$type: hw.view.form.ButtonView
style: button.small
text: logout
+onPress: ~logout()
visible: false

View File

@@ -0,0 +1,37 @@
package ru.m.tankz.view.common;
import hw.view.form.LabelView;
import hw.view.group.VGroupView;
import ru.m.tankz.bundle.ILevelBundle;
import ru.m.tankz.storage.GameStorage;
import ru.m.tankz.Type;
using ru.m.tankz.view.ViewUtil;
@:template class PackView extends VGroupView {
public var data(default, set):PackId;
@:view var label:LabelView;
@:view var state:LabelView;
@:provide static var gameStorage:GameStorage;
@:provide static var levelBundle:ILevelBundle;
private function set_data(value:PackId):PackId {
if (data != value) {
data = value;
label.text = data.toPackLabel("\n");
var progress = gameStorage.get(data).progress;
var total = levelBundle.get(data).data.length;
state.text = '${progress}/${total}';
}
return data;
}
public static function factory(index:Int, value:PackId):PackView {
var result = new PackView();
result.data = value;
return result;
}
}

View File

@@ -0,0 +1,9 @@
---
style: button.pack
views:
- id: label
$type: hw.view.form.LabelView
font.size: 4h
- id: state
$type: hw.view.form.LabelView
font.size: 3.5h

View File

@@ -1,9 +1,9 @@
package ru.m.tankz.view.common; package ru.m.tankz.view.common;
import haxework.view.frame.FrameSwitcher; import hw.view.frame.FrameSwitcher;
import haxework.view.group.HGroupView; import hw.view.group.HGroupView;
import haxework.view.form.LabelView; import hw.view.form.LabelView;
import haxework.view.list.ListView; import hw.view.list.ListView;
import ru.m.tankz.game.GameInit; import ru.m.tankz.game.GameInit;
import ru.m.tankz.game.record.GameRecord; import ru.m.tankz.game.record.GameRecord;
import ru.m.tankz.storage.RecordStorage; import ru.m.tankz.storage.RecordStorage;

View File

@@ -4,26 +4,26 @@ layout.margin: 5
layout.vAlign: middle layout.vAlign: middle
views: views:
- id: play - id: play
$type: haxework.view.form.ButtonView $type: hw.view.form.ButtonView
style: button.start.small style: button.start.small
+onPress: ~play() +onPress: ~play()
- id: date - id: date
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
style: text.box style: text.box
geometry.width: 200 geometry.width: 200
- id: type - id: type
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
style: text.box style: text.box
geometry.width: 200 geometry.width: 200
- id: level - id: level
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
style: text.box style: text.box
geometry.width: 100 geometry.width: 100
- id: preset - id: preset
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
style: text.box style: text.box
geometry.width: 100 geometry.width: 100
- id: delete - id: delete
$type: haxework.view.form.ButtonView $type: hw.view.form.ButtonView
style: button.close.small style: button.close.small
+onPress: ~delete() +onPress: ~delete()

View File

@@ -1,11 +1,11 @@
package ru.m.tankz.view.common; package ru.m.tankz.view.common;
import openfl.Assets; import openfl.Assets;
import haxework.view.ImageView; import hw.view.ImageView;
import haxework.view.form.LabelView; import hw.view.form.LabelView;
import haxework.view.form.SelectView; import hw.view.form.SelectView;
import haxework.view.group.HGroupView; import hw.view.group.HGroupView;
import haxework.view.skin.SpriteSkin; import hw.view.skin.SpriteSkin;
import ru.m.tankz.control.Controller; import ru.m.tankz.control.Controller;
import ru.m.tankz.control.PlayerControl; import ru.m.tankz.control.PlayerControl;

View File

@@ -4,14 +4,14 @@ layout.margin: 10
layout.vAlign: middle layout.vAlign: middle
views: views:
- id: tank - id: tank
$type: haxework.view.ImageView $type: hw.view.ImageView
style: icon.tank style: icon.tank
- id: slot - id: slot
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
style: text.box style: text.box
geometry.width: 150 geometry.width: 150
- id: select - id: select
$type: haxework.view.form.SelectView<ru.m.tankz.control.Controller> $type: hw.view.form.SelectView<ru.m.tankz.control.Controller>
geometry.width: 150 geometry.width: 150
labelBuilder: | labelBuilder: |
~function(controller) { ~function(controller) {

View File

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

View File

@@ -1,27 +0,0 @@
package ru.m.tankz.view.game;
import haxework.view.data.DataView;
import haxework.view.form.LabelView;
import haxework.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,27 +0,0 @@
---
views:
- id: left
$type: haxework.view.group.GroupView
layout.vAlign: middle
geometry.height: 100%
geometry.width: 50%
- id: render
$type: ru.m.tankz.render.Render
- id: right
$type: haxework.view.group.VGroupView
geometry.height: 100%
geometry.width: 50%
geometry.padding: 5
layout.vAlign: top
layout.margin: 5
views:
- id: level
$type: haxework.view.form.LabelView
style: text.box
geometry.width: 100%
- $type: haxework.view.SpriteView
geometry.height: 30%
- id: teams
$type: haxework.view.data.DataView
layout.margin: 3
factory: ~TeamView.viewFactory

View File

@@ -1,27 +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.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,20 +0,0 @@
---
views:
- id: top
$type: haxework.view.group.HGroupView
layout.vAlign: middle
geometry.width: 100%
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
- id: render
$type: ru.m.tankz.render.Render

View File

@@ -1,30 +0,0 @@
package ru.m.tankz.view.game;
import haxework.view.geometry.HAlign;
import haxework.view.geometry.VAlign;
import haxework.view.group.GroupView;
class GameViewContainer extends GroupView {
override public function update():Void {
super.update();
if (parent != null) {
var s = Math.min(parent.width / width, parent.height / height);
if (s < 1) {
content.scaleX = content.scaleY = s;
content.x = switch layout.hAlign {
case LEFT | NONE: 0;
case CENTER: (parent.width - width * s) / 2;
case RIGHT: (parent.width - width * s);
}
content.y = switch layout.vAlign {
case TOP | NONE: 0;
case MIDDLE: (parent.height - height * s) / 2;
case BOTTOM: (parent.height - height * s);
}
} else {
content.scaleX = content.scaleY = 1;
}
}
}
}

View File

@@ -1,83 +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,
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 ru.m.tankz.render.IRender;
import haxework.view.data.DataView;
import haxework.view.form.LabelView;
import haxework.view.IView;
import ru.m.tankz.game.GameState;
import ru.m.tankz.game.IGame;
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,7 +1,7 @@
package ru.m.tankz.view.game; package ru.m.tankz.view.game;
import haxework.view.form.LabelView; import hw.view.form.LabelView;
import haxework.view.group.VGroupView; import hw.view.group.VGroupView;
import ru.m.tankz.game.GameState; import ru.m.tankz.game.GameState;
import ru.m.tankz.Type; import ru.m.tankz.Type;
import ru.m.tankz.view.common.TankView; import ru.m.tankz.view.common.TankView;

View File

@@ -1,19 +1,27 @@
--- ---
geometry.width: 100%
views:
- $type: hw.view.group.HGroupView
geometry.width: 100%
views: views:
- id: title - id: title
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
visible: false geometry.width: 50%
- $type: haxework.view.group.HGroupView 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.margin: 5
layout.vAlign: middle layout.vAlign: middle
views: views:
- id: tank - id: tank
$type: ru.m.tankz.view.common.TankView $type: ru.m.tankz.view.common.TankView
- id: life - id: life
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
style: text.box style: text.box
geometry.width: 55 geometry.width: 100%
- id: score
$type: haxework.view.form.LabelView
style: text.box
geometry.width: 100

View File

@@ -1,6 +1,6 @@
package ru.m.tankz.view.game; package ru.m.tankz.view.game;
import haxework.view.data.DataView; import hw.view.data.DataView;
import ru.m.tankz.game.GameState; import ru.m.tankz.game.GameState;
import ru.m.tankz.Type; import ru.m.tankz.Type;
@@ -13,6 +13,7 @@ class TeamView extends DataView<PlayerState, PlayerView> {
super(); super();
factory = PlayerView.factory; factory = PlayerView.factory;
layout.margin = 5; layout.margin = 5;
geometry.width = "100%";
} }
private function set_state(value:TeamState):TeamState { private function set_state(value:TeamState):TeamState {

View File

@@ -1,26 +1,34 @@
package ru.m.tankz.view.gamepad; package ru.m.tankz.view.gamepad;
import flash.display.Graphics; import flash.display.Graphics;
import haxework.color.Color; import hw.color.Color;
import haxework.view.skin.ISkin; import hw.view.skin.ISkin;
import ru.m.control.DeviceAction;
@:style class GamepadSkin implements ISkin<GamepadView> { @:style class GamepadSkin implements ISkin<GamepadView> {
@:style(0x00ff00) public var color(default, default):Null<Color>; @:style(0xffffff) public var color(default, default):Null<Color>;
@:style(0x00ff00) public var activeColor(default, default):Null<Color>;
public function new(?color:Color) { public function new(?color:Color) {
this.color = color; this.color = color;
} }
public function draw(view:GamepadView):Void { public function draw(view:GamepadView):Void {
var actives = [for (item in view.activeAreas.iterator()) item];
var graphics:Graphics = view.content.graphics; var graphics:Graphics = view.content.graphics;
graphics.clear(); graphics.clear();
graphics.beginFill(0, 0.0); for (area in view.areas) {
graphics.drawRect(0, 0, view.width, view.height); switch area.action {
graphics.endFill(); case KEY(code):
if (view.weapons.length < code + 1) {
continue;
}
case _:
}
var color = actives.indexOf(area) > -1 ? activeColor : color;
graphics.lineStyle(2, color); graphics.lineStyle(2, color);
graphics.beginFill(color, 0.2); graphics.beginFill(color, 0.2);
for (area in view.areas) {
area.draw(graphics); area.draw(graphics);
} }
graphics.lineStyle(); graphics.lineStyle();

View File

@@ -1,14 +1,15 @@
package ru.m.tankz.view.gamepad; package ru.m.tankz.view.gamepad;
import flash.display.Stage; import flash.display.Sprite;
import flash.events.MouseEvent; import flash.events.MouseEvent;
import flash.events.TouchEvent; import flash.events.TouchEvent;
import haxework.signal.Signal; import hw.signal.Signal;
import haxework.view.SpriteView; import hw.view.SpriteView;
import ru.m.control.DeviceAction; import ru.m.control.DeviceAction;
import ru.m.control.DeviceType; import ru.m.control.DeviceType;
import ru.m.control.IControlDevice; import ru.m.control.IControlDevice;
import ru.m.geom.Point; import ru.m.geom.Point;
import ru.m.tankz.config.Config;
class GamepadView extends SpriteView implements IControlDevice { class GamepadView extends SpriteView implements IControlDevice {
@@ -16,10 +17,19 @@ class GamepadView extends SpriteView implements IControlDevice {
public var signal(default, null):Signal2<DeviceAction, Bool>; public var signal(default, null):Signal2<DeviceAction, Bool>;
public var areas(default, null):Array<IActionArea>; public var areas(default, null):Array<IActionArea>;
public var currentAreas(default, null):Map<Int, IActionArea>; public var activeAreas(default, null):Map<Int, IActionArea>;
public var weapons(default, set):Array<WeaponConfig>;
private function set_weapons(value:Array<WeaponConfig>):Array<WeaponConfig> {
weapons = value;
toRedraw();
return weapons;
}
private var builder:IActionAreaBuilder; private var builder:IActionAreaBuilder;
private var stage:Stage;
private var actionLayer:Sprite;
public function new() { public function new() {
super(); super();
@@ -28,15 +38,17 @@ class GamepadView extends SpriteView implements IControlDevice {
builder = new SmartActionAreaBuilder(); builder = new SmartActionAreaBuilder();
signal = new Signal2(); signal = new Signal2();
areas = []; areas = [];
currentAreas = new Map(); weapons = [];
activeAreas = new Map();
skin = new GamepadSkin(); skin = new GamepadSkin();
content.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); actionLayer = new Sprite();
content.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin); actionLayer.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
actionLayer.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
content.addChild(actionLayer);
} }
private function onMouseDown(event:MouseEvent):Void { private function onMouseDown(event:MouseEvent):Void {
onMouseMove(event); onMouseMove(event);
stage = content.stage;
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
} }
@@ -54,7 +66,6 @@ class GamepadView extends SpriteView implements IControlDevice {
private function onTouchBegin(event:TouchEvent):Void { private function onTouchBegin(event:TouchEvent):Void {
onTouchMove(event); onTouchMove(event);
stage = content.stage;
stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd); stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd);
} }
@@ -66,43 +77,52 @@ class GamepadView extends SpriteView implements IControlDevice {
private function onTouchEnd(event:TouchEvent):Void { private function onTouchEnd(event:TouchEvent):Void {
endTouch(event.touchPointID); endTouch(event.touchPointID);
if (Lambda.count(currentAreas) == 0) { if (Lambda.count(activeAreas) == 0) {
stage.removeEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); stage.removeEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
stage.removeEventListener(TouchEvent.TOUCH_END, onTouchEnd); stage.removeEventListener(TouchEvent.TOUCH_END, onTouchEnd);
} }
} }
private function updateTouch(pointID:Int, point:Point):Void { private function updateTouch(pointID:Int, point:Point):Void {
if (currentAreas.exists(pointID)) { if (activeAreas.exists(pointID)) {
var area = currentAreas[pointID]; var area = activeAreas[pointID];
if (!area.contain(point)) { if (!area.contain(point)) {
currentAreas.remove(pointID); activeAreas.remove(pointID);
signal.emit(area.action, false); signal.emit(area.action, false);
toRedraw();
} }
} } else {
for (area in areas) { for (area in areas) {
if (area.contain(point)) { if (area.contain(point)) {
currentAreas[pointID] = area; activeAreas[pointID] = area;
signal.emit(area.action, true); signal.emit(area.action, true);
toRedraw();
break; break;
} }
} }
} }
}
private function endTouch(pointID:Int):Void { private function endTouch(pointID:Int):Void {
if (currentAreas.exists(pointID)) { if (activeAreas.exists(pointID)) {
signal.emit(currentAreas[pointID].action, false); signal.emit(activeAreas[pointID].action, false);
currentAreas.remove(pointID); activeAreas.remove(pointID);
toRedraw();
} }
} }
override public function update():Void { override public function update():Void {
super.update(); super.update();
areas = builder.build(width, height); areas = builder.build(width, height);
actionLayer.graphics.clear();
actionLayer.graphics.beginFill(0, 0.0);
actionLayer.graphics.drawRect(0, 0, width, height);
actionLayer.graphics.endFill();
} }
public function dispose():Void { public function dispose():Void {
actionLayer.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
actionLayer.removeEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
stage = null; stage = null;
} }
} }

View File

@@ -1,6 +1,6 @@
package ru.m.tankz.view.gamepad; package ru.m.tankz.view.gamepad;
import haxework.view.geometry.Box; import hw.view.geometry.Box;
import ru.m.control.DeviceAction; import ru.m.control.DeviceAction;
import ru.m.geom.Circle; import ru.m.geom.Circle;
import ru.m.geom.Direction; import ru.m.geom.Direction;

View File

@@ -1,10 +1,10 @@
package ru.m.tankz.view.network; package ru.m.tankz.view.network;
import haxework.view.data.DataView; import hw.view.data.DataView;
import haxework.view.form.ButtonView; import hw.view.form.ButtonView;
import haxework.view.frame.FrameSwitcher; import hw.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView; import hw.view.frame.FrameView;
import haxework.view.text.TextView; import hw.view.text.TextView;
import ru.m.tankz.game.GameInit; import ru.m.tankz.game.GameInit;
import ru.m.tankz.network.NetworkManager; import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.proto.room.RoomProto; import ru.m.tankz.proto.room.RoomProto;

View File

@@ -1,40 +1,40 @@
--- ---
geometry.stretch: true geometry.stretch: true
layout: layout:
$type: haxework.view.layout.VerticalLayout $type: hw.view.layout.VerticalLayout
views: views:
- $type: haxework.view.group.VGroupView - $type: hw.view.group.VGroupView
style: container style: container
geometry.padding: 20 geometry.padding: 20
layout.margin: 10 layout.margin: 10
views: views:
- id: header - id: header
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
geometry.margin.bottom: 20 geometry.margin.bottom: 20
style: text.header style: text.header
text: Game Room text: Game Room
- $type: haxework.view.group.HGroupView - $type: hw.view.group.HGroupView
layout.margin: 10 layout.margin: 10
views: views:
- id: info - id: info
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
geometry.padding: [30, 10] geometry.padding: [30, 10]
style: text.box style: text.box
- id: start - id: start
$type: haxework.view.form.ButtonView $type: hw.view.form.ButtonView
text: Start text: Start
+onPress: ~network.startGame() +onPress: ~network.startGame()
visible: false visible: false
- id: leave - id: leave
$type: haxework.view.form.ButtonView $type: hw.view.form.ButtonView
text: Leave text: Leave
+onPress: ~network.leaveGame() +onPress: ~network.leaveGame()
- $type: haxework.view.SpriteView - $type: hw.view.SpriteView
geometry.width: 100% geometry.width: 100%
geometry.height: 3 geometry.height: 3
style: line style: line
- id: slots - id: slots
$type: haxework.view.data.DataView $type: hw.view.data.DataView
layout.hAlign: center layout.hAlign: center
geometry.stretch: true geometry.stretch: true
overflow.y: scroll overflow.y: scroll

View File

@@ -2,10 +2,10 @@ package ru.m.tankz.view.network;
import ru.m.tankz.network.NetworkManager; import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.proto.room.RoomSlotProto; import ru.m.tankz.proto.room.RoomSlotProto;
import haxework.view.form.ButtonView; import hw.view.form.ButtonView;
import haxework.view.group.HGroupView; import hw.view.group.HGroupView;
import haxework.view.form.LabelView; import hw.view.form.LabelView;
import haxework.view.list.ListView; import hw.view.list.ListView;
import ru.m.tankz.proto.room.RoomProto; import ru.m.tankz.proto.room.RoomProto;
@:template class RoomItemView extends HGroupView implements IListItemView<RoomProto> { @:template class RoomItemView extends HGroupView implements IListItemView<RoomProto> {

View File

@@ -3,18 +3,18 @@ layout.margin: 10
layout.hAlign: center layout.hAlign: center
views: views:
- id: creator - id: creator
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
geometry.width: 200 geometry.width: 200
style: text.box style: text.box
- id: type - id: type
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
geometry.width: 200 geometry.width: 200
style: text.box style: text.box
- id: users - id: users
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
geometry.width: 150 geometry.width: 150
style: text.box style: text.box
- id: join - id: join
$type: haxework.view.form.ButtonView $type: hw.view.form.ButtonView
text: Join text: Join
+onPress: ~join() +onPress: ~join()

View File

@@ -1,8 +1,8 @@
package ru.m.tankz.view.network; package ru.m.tankz.view.network;
import haxework.view.data.DataView; import hw.view.data.DataView;
import haxework.view.frame.FrameSwitcher; import hw.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView; import hw.view.frame.FrameView;
import ru.m.tankz.network.NetworkManager; import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.proto.room.RoomProto; import ru.m.tankz.proto.room.RoomProto;
import ru.m.tankz.view.popup.CreateGamePopup; import ru.m.tankz.view.popup.CreateGamePopup;

View File

@@ -1,22 +1,22 @@
--- ---
geometry.stretch: true geometry.stretch: true
layout: layout:
$type: haxework.view.layout.VerticalLayout $type: hw.view.layout.VerticalLayout
views: views:
- $type: haxework.view.group.VGroupView - $type: hw.view.group.VGroupView
style: container style: container
geometry.padding: 20 geometry.padding: 20
views: views:
- id: header - id: header
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
geometry.margin.bottom: 20 geometry.margin.bottom: 20
style: text.header style: text.header
text: Games List text: Games List
- $type: haxework.view.form.ButtonView - $type: hw.view.form.ButtonView
text: Create text: Create
+onPress: ~create() +onPress: ~create()
- id: games - id: games
$type: haxework.view.data.DataView $type: hw.view.data.DataView
geometry.stretch: true geometry.stretch: true
factory: ~ru.m.tankz.view.network.RoomItemView.factory factory: ~ru.m.tankz.view.network.RoomItemView.factory
geometry.margin: 10 geometry.margin: 10

View File

@@ -1,9 +1,9 @@
package ru.m.tankz.view.network; package ru.m.tankz.view.network;
import haxework.view.form.ButtonView; import hw.view.form.ButtonView;
import haxework.view.group.HGroupView; import hw.view.group.HGroupView;
import haxework.view.form.LabelView; import hw.view.form.LabelView;
import haxework.view.list.ListView; import hw.view.list.ListView;
import ru.m.tankz.bundle.IConfigBundle; import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.network.NetworkManager; import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.proto.room.RoomSlotProto; import ru.m.tankz.proto.room.RoomSlotProto;

View File

@@ -3,19 +3,19 @@ geometry.padding: 2
layout.margin: 10 layout.margin: 10
views: views:
- id: type - id: type
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
style: text.box style: text.box
geometry.width: 150 geometry.width: 150
- $type: haxework.view.group.HGroupView - $type: hw.view.group.HGroupView
layout.hAlign: center layout.hAlign: center
layout.vAlign: middle layout.vAlign: middle
geometry.width: 300 geometry.width: 300
views: views:
- id: user - id: user
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
geometry.stretch: true geometry.stretch: true
style: text.box style: text.box
- id: select - id: select
$type: haxework.view.form.ButtonView $type: hw.view.form.ButtonView
text: Select text: Select
+onPress: ~select() +onPress: ~select()

View File

@@ -1,8 +1,8 @@
package ru.m.tankz.view.popup; package ru.m.tankz.view.popup;
import haxework.view.data.DataView; import hw.view.data.DataView;
import haxework.view.popup.PopupView; import hw.view.popup.PopupView;
import haxework.view.form.ToggleButtonView; import hw.view.form.ToggleButtonView;
import ru.m.tankz.bundle.IConfigBundle; import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.bundle.ILevelBundle; import ru.m.tankz.bundle.ILevelBundle;
import ru.m.tankz.config.Config; import ru.m.tankz.config.Config;

View File

@@ -2,42 +2,42 @@
layout.hAlign: center layout.hAlign: center
layout.vAlign: middle layout.vAlign: middle
view: view:
$type: haxework.view.group.VGroupView $type: hw.view.group.VGroupView
layout.hAlign: center layout.hAlign: center
geometry.stretch: true geometry.stretch: true
geometry.margin: 10 geometry.margin: 10
style: window style: window
views: views:
- $type: haxework.view.group.HGroupView - $type: hw.view.group.HGroupView
geometry.width: 100% geometry.width: 100%
geometry.padding: 10 geometry.padding: 10
layout.vAlign: middle layout.vAlign: middle
views: views:
- id: name - id: name
$type: haxework.view.form.LabelView $type: hw.view.form.LabelView
geometry.width: 100% geometry.width: 100%
geometry.margin.left: 10 geometry.margin.left: 10
layout.hAlign: left layout.hAlign: left
style: text style: text
text: New game text: New game
- $type: haxework.view.form.ButtonView - $type: hw.view.form.ButtonView
style: window.close style: window.close
+onPress: ~reject('close') +onPress: ~reject('close')
- $type: haxework.view.group.VGroupView - $type: hw.view.group.VGroupView
geometry.stretch: true geometry.stretch: true
geometry.padding: [5, 20] geometry.padding: [5, 20]
layout.margin: 5 layout.margin: 5
layout.hAlign: center layout.hAlign: center
views: views:
- $type: haxework.view.form.LabelView - $type: hw.view.form.LabelView
geometry.width: 100% geometry.width: 100%
style: text style: text
text: Type text: Type
- id: type - id: type
$type: haxework.view.data.DataView $type: hw.view.data.DataView
geometry.width: 100% geometry.width: 100%
layout: layout:
$type: haxework.view.layout.TailLayout $type: hw.view.layout.TailLayout
margin: 10 margin: 10
factory: ~gameTypeViewFactory factory: ~gameTypeViewFactory
+onItemSelect: ~onGameTypeSelect +onItemSelect: ~onGameTypeSelect
@@ -45,27 +45,27 @@ view:
- "classic" - "classic"
- "dota" - "dota"
- "death" - "death"
- $type: haxework.view.form.LabelView - $type: hw.view.form.LabelView
geometry.width: 100% geometry.width: 100%
style: text style: text
text: Level text: Level
- id: level - id: level
$type: haxework.view.data.DataView $type: hw.view.data.DataView
geometry.width: 100% geometry.width: 100%
geometry.height: 100% geometry.height: 100%
overflow.y: scroll overflow.y: scroll
layout: layout:
$type: haxework.view.layout.TailLayout $type: hw.view.layout.TailLayout
rowSize: 10 rowSize: 10
margin: 5 margin: 5
factory: ~levelViewFactory factory: ~levelViewFactory
+onItemSelect: ~onLevelSelect +onItemSelect: ~onLevelSelect
geometry.padding: 10 geometry.padding: 10
- $type: haxework.view.group.HGroupView - $type: hw.view.group.HGroupView
layout.hAlign: center layout.hAlign: center
layout.margin: 5 layout.margin: 5
style: panel style: panel
views: views:
- $type: haxework.view.form.ButtonView - $type: hw.view.form.ButtonView
text: Create text: Create
+onPress: ~submit() +onPress: ~submit()

Some files were not shown because too many files have changed in this diff Show More