diff --git a/package.json b/package.json index 3ce5009..f43a628 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tankz", - "version": "0.7.3", + "version": "0.7.4", "private": true, "devDependencies": { "dateformat": "^3.0.3", diff --git a/src/client/haxe/ru/m/tankz/Client.yaml b/src/client/haxe/ru/m/tankz/Client.yaml index 64eda98..ffaf918 100755 --- a/src/client/haxe/ru/m/tankz/Client.yaml +++ b/src/client/haxe/ru/m/tankz/Client.yaml @@ -20,10 +20,14 @@ views: $type: ru.m.tankz.frame.GameFrame - id: network $type: ru.m.tankz.frame.NetworkFrame + - id: settings + $type: ru.m.tankz.frame.SettingsFrame - $type: haxework.gui.LabelView $style: label inLayout: false contentSize: true vAlign: BOTTOM hAlign: RIGHT + rightMargin: 10 + bottomMargin: 10 text: "@res:text:version" diff --git a/src/client/haxe/ru/m/tankz/Init.hx b/src/client/haxe/ru/m/tankz/Init.hx index 137773f..a31495f 100644 --- a/src/client/haxe/ru/m/tankz/Init.hx +++ b/src/client/haxe/ru/m/tankz/Init.hx @@ -1,5 +1,6 @@ package ru.m.tankz; +import ru.m.tankz.storage.SettingsStorage; import haxework.provider.Provider; import haxework.resources.IResources; import haxework.resources.Resources; @@ -47,6 +48,7 @@ class Init { Provider.setFactory(IConfigBundle, ConfigBundle); Provider.setFactory(SaveStorage, SaveStorage); Provider.setFactory(UserStorage, UserStorage); + Provider.setFactory(SettingsStorage, SettingsStorage); Provider.setFactory(SoundManager, SoundManager); Provider.setFactory(NetworkManager, NetworkManager); Provider.setFactory(IControlFactory, ClientControlFactory); diff --git a/src/client/haxe/ru/m/tankz/Style.yaml b/src/client/haxe/ru/m/tankz/Style.yaml index 5d0b116..cdd2598 100644 --- a/src/client/haxe/ru/m/tankz/Style.yaml +++ b/src/client/haxe/ru/m/tankz/Style.yaml @@ -19,3 +19,14 @@ label: fontFamily: Courirer New fontSize: 16 shadowColor: 0x000000 + +close: + inLayout: false + hAlign: LEFT + vAlign: BOTTOM + leftMargin: 10 + bottomMargin: 10 + contentSize: true + skin: + $type: haxework.gui.skin.ButtonBitmapSkin + image: "@asset:image:resources/image/ui/close.png" diff --git a/src/client/haxe/ru/m/tankz/control/ActionConfig.hx b/src/client/haxe/ru/m/tankz/control/ActionConfig.hx new file mode 100644 index 0000000..3bac949 --- /dev/null +++ b/src/client/haxe/ru/m/tankz/control/ActionConfig.hx @@ -0,0 +1,86 @@ +package ru.m.tankz.control; + +import ru.m.geom.Direction; +import ru.m.tankz.control.Control.TankAction; +import yaml.Parser; +import yaml.Renderer; +import yaml.Yaml; + + +typedef ActionItem = { + public var action: TankAction; + public var key: Int; +} + +typedef KeyBinding = Map; + +typedef ActionItemRaw = { + public var action: String; + public var key: Int; +} + +class ActionConfig { + + public var data(default, null): Array; + + public function new(data: Array) { + this.data = data; + } + + public function asKeyBinding(): KeyBinding { + var result = new Map(); + for (item in data) { + result[item.key] = item.action; + } + return result; + } + + public static function action2string(action: TankAction): String { + return switch (action) { + case TankAction.SHOT: "SHOT"; + case TankAction.MOVE(Direction.TOP): "MOVE_TOP"; + case TankAction.MOVE(Direction.LEFT): "MOVE_LEFT"; + case TankAction.MOVE(Direction.BOTTOM): "MOVE_BOTTOM"; + case TankAction.MOVE(Direction.RIGHT): "MOVE_RIGHT"; + case _: throw 'Unsupported action "${action}"'; + } + } + + public static function string2action(value: String): TankAction { + return switch (value) { + case "SHOT": TankAction.SHOT; + case "MOVE_TOP": TankAction.MOVE(Direction.TOP); + case "MOVE_LEFT": TankAction.MOVE(Direction.LEFT); + case "MOVE_BOTTOM": TankAction.MOVE(Direction.BOTTOM); + case "MOVE_RIGHT": TankAction.MOVE(Direction.RIGHT); + case _: throw 'Unsupported value "${value}"'; + } + } + + public function clone(): ActionConfig { + return loads(dumps()); + } + + public function dumps(): String { + var raw: Array = []; + for (item in this.data) { + raw.push({ + action: action2string(item.action), + key: item.key, + }); + } + return Yaml.render(raw, Renderer.options().setFlowLevel(0)); + } + + public static function loads(value: String): ActionConfig { + var raw: Array = Yaml.parse(value, Parser.options().useObjects()); + var data: Array = []; + for (item in raw) { + data.push({ + action: string2action(item.action), + key: item.key, + }); + } + return new ActionConfig(data); + } +} diff --git a/src/client/haxe/ru/m/tankz/control/HumanControl.hx b/src/client/haxe/ru/m/tankz/control/HumanControl.hx index 52904e6..4a31ecf 100644 --- a/src/client/haxe/ru/m/tankz/control/HumanControl.hx +++ b/src/client/haxe/ru/m/tankz/control/HumanControl.hx @@ -5,22 +5,23 @@ import flash.events.KeyboardEvent; import flash.Lib; import flash.ui.Keyboard; import haxe.Timer; -import ru.m.geom.Direction; +import ru.m.tankz.control.ActionConfig; import ru.m.tankz.control.Control; +import ru.m.tankz.storage.SettingsStorage; import ru.m.tankz.Type; -typedef KeyBinding = Map; - class HumanControl extends Control { + @:provide var settings: SettingsStorage; + private var keyBinding:KeyBinding; private var moveQueue:Array; private var shotTimer:Timer; public function new(playerId:PlayerId, controlIndex:Int) { super(playerId); - this.keyBinding = resolve(controlIndex); + this.keyBinding = settings.read(controlIndex).asKeyBinding(); moveQueue = new Array(); Lib.current.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); Lib.current.stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); @@ -81,27 +82,4 @@ class HumanControl extends Control { private function shot():Void { action(TankAction.SHOT); } - - private static function resolve(controlIndex:Int):KeyBinding { - switch (controlIndex) { - case 0: - return [ - Keyboard.A => TankAction.MOVE(Direction.LEFT), - Keyboard.S => TankAction.MOVE(Direction.BOTTOM), - Keyboard.W => TankAction.MOVE(Direction.TOP), - Keyboard.D => TankAction.MOVE(Direction.RIGHT), - Keyboard.SPACE => TankAction.SHOT - ]; - case 1: - return [ - Keyboard.LEFT => TankAction.MOVE(Direction.LEFT), - Keyboard.DOWN => TankAction.MOVE(Direction.BOTTOM), - Keyboard.UP => TankAction.MOVE(Direction.TOP), - Keyboard.RIGHT => TankAction.MOVE(Direction.RIGHT), - Keyboard.NUMPAD_0 => TankAction.SHOT - ]; - case x: - throw 'Invalid control index ${x}'; - } - } } diff --git a/src/client/haxe/ru/m/tankz/frame/GameFrame.hx b/src/client/haxe/ru/m/tankz/frame/GameFrame.hx index 43e345c..f65305b 100755 --- a/src/client/haxe/ru/m/tankz/frame/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/frame/GameFrame.hx @@ -37,19 +37,24 @@ class GameFrame extends VGroupView { start(Provider.get(GameSave)); } + private function connectGame(game: Game) { + game.engine.connect(render); + game.engine.connect(Provider.get(SoundManager)); + } + private function start(save:GameSave):Void { switch (save.server) { case GameServer.LOCAL: game = new Game(save.state.type); + connectGame(game); game.start(save).then(onGameStateChange).endThen(onGameComplete); timer = new Timer(10); timer.run = updateEngine; case GameServer.NETWORK: game = new NetworkGame(save.state.type); + connectGame(game); network.game = cast game; } - game.engine.connect(render); - game.engine.connect(Provider.get(SoundManager)); content.addEventListener(Event.ENTER_FRAME, redraw); render.draw(game.engine); state.text = stateString(game); diff --git a/src/client/haxe/ru/m/tankz/frame/SettingsFrame.hx b/src/client/haxe/ru/m/tankz/frame/SettingsFrame.hx new file mode 100644 index 0000000..3f13ccb --- /dev/null +++ b/src/client/haxe/ru/m/tankz/frame/SettingsFrame.hx @@ -0,0 +1,24 @@ +package ru.m.tankz.frame; + +import haxework.gui.frame.IFrameSwitcher; +import haxework.gui.ButtonView; +import haxework.gui.VGroupView; + + +@:template("ru/m/tankz/frame/SettingsFrame.yaml", "ru/m/tankz/Style.yaml") +class SettingsFrame extends VGroupView { + + public static var ID(default, never):String = "settings"; + + @:provide var frameSwitcher:IFrameSwitcher; + + @:view var close:ButtonView; + + private function init():Void { + close.onPress = this; + } + + public function onPress(_):Void { + frameSwitcher.change(StartFrame.ID); + } +} diff --git a/src/client/haxe/ru/m/tankz/frame/SettingsFrame.yaml b/src/client/haxe/ru/m/tankz/frame/SettingsFrame.yaml new file mode 100644 index 0000000..40487cf --- /dev/null +++ b/src/client/haxe/ru/m/tankz/frame/SettingsFrame.yaml @@ -0,0 +1,24 @@ +--- +pWidth: 100 +pHeight: 100 +views: +- $type: haxework.gui.LabelView + $style: label + pWidth: 100 + height: 20 + text: Settings +- $type: haxework.gui.HGroupView + pWidth: 100 + pHeight: 100 + views: + - $type: ru.m.tankz.frame.settings.SettingsEditor + pWidth: 50 + pHeight: 100 + controlIndex: 0 + - $type: ru.m.tankz.frame.settings.SettingsEditor + pWidth: 50 + pHeight: 100 + controlIndex: 1 +- id: close + $type: haxework.gui.ButtonView + $style: close \ No newline at end of file diff --git a/src/client/haxe/ru/m/tankz/frame/StartFrame.hx b/src/client/haxe/ru/m/tankz/frame/StartFrame.hx index be27444..b95a06c 100644 --- a/src/client/haxe/ru/m/tankz/frame/StartFrame.hx +++ b/src/client/haxe/ru/m/tankz/frame/StartFrame.hx @@ -23,6 +23,7 @@ class StartFrame extends VGroupView { @:view var dota_2p_coop(default, null):ButtonView; @:view var dota_2p_vs(default, null):ButtonView; @:view var network(default, null):ButtonView; + @:view var settings(default, null):ButtonView; @:provide var frameSwitcher:IFrameSwitcher; @:provide var storage:SaveStorage; @@ -35,6 +36,7 @@ class StartFrame extends VGroupView { dota_2p_coop.onPress = this; dota_2p_vs.onPress = this; network.onPress = this; + settings.onPress = this; } public function onShow():Void { @@ -63,6 +65,8 @@ class StartFrame extends VGroupView { startGame(DotaGame.TYPE, DotaGame.PLAYER2_VS); case 'network': frameSwitcher.change(NetworkFrame.ID); + case 'settings': + frameSwitcher.change(SettingsFrame.ID); } } diff --git a/src/client/haxe/ru/m/tankz/frame/StartFrame.yaml b/src/client/haxe/ru/m/tankz/frame/StartFrame.yaml index 72544d9..0a29cda 100644 --- a/src/client/haxe/ru/m/tankz/frame/StartFrame.yaml +++ b/src/client/haxe/ru/m/tankz/frame/StartFrame.yaml @@ -70,3 +70,15 @@ views: $type: haxework.gui.ButtonView text: Network $style: button +# settings +- id: settings + $type: haxework.gui.ButtonView + inLayout: false + hAlign: LEFT + vAlign: BOTTOM + leftMargin: 10 + bottomMargin: 10 + contentSize: true + skin: + $type: haxework.gui.skin.ButtonBitmapSkin + image: "@asset:image:resources/image/ui/settings.png" diff --git a/src/client/haxe/ru/m/tankz/frame/settings/ActionView.hx b/src/client/haxe/ru/m/tankz/frame/settings/ActionView.hx new file mode 100755 index 0000000..2c12630 --- /dev/null +++ b/src/client/haxe/ru/m/tankz/frame/settings/ActionView.hx @@ -0,0 +1,88 @@ +package ru.m.tankz.frame.settings; + +import haxework.gui.ButtonView; +import haxework.gui.HGroupView; +import haxework.gui.LabelView; +import haxework.gui.list.ListView.IListItemView; +import haxework.gui.skin.ColorSkin; +import openfl.Assets; +import openfl.events.KeyboardEvent; +import promhx.Deferred; +import promhx.Promise; +import ru.m.tankz.control.ActionConfig; +import ru.m.tankz.control.Control; + + +class KeyboardMap { + + private var data:Map; + + public function new() { + this.data = new Map(); + var data = Assets.getText("resources/keyboard.txt"); + for (line in data.split("\n")) { + var arr = line.split("\t"); + if (arr.length == 2) { + this.data.set(Std.parseInt(arr[1]), arr[0]); + } + } + + } + + private static var instance: KeyboardMap; + + public static function getName(key: Int): String { + if (instance == null) instance = new KeyboardMap(); + return key == -1 ? "" : instance.data.exists(key) ? instance.data.get(key) : Std.string(key); + } +} + + +@:template("ru/m/tankz/frame/settings/ActionView.yaml", "ru/m/tankz/Style.yaml") +class ActionView extends HGroupView implements IListItemView { + + public var item_index(default, default):Int; + public var data(default, set):ActionItem; + + @:view var action(default, null):LabelView; + @:view var key(default, null):LabelView; + + private var editDeferred: Deferred; + + private function init():Void { + } + + private static function actionLabel(action: TankAction): String { + return ActionConfig.action2string(action); + } + + private static function keyLabel(key: Int): String { + return KeyboardMap.getName(key); + } + + private function set_data(value:ActionItem):ActionItem { + data = value; + action.text = actionLabel(data.action); + key.text = keyLabel(data.key); + return data; + } + + public function edit():Promise { + cast(this.skin, ColorSkin).color = 0x00ff00; + invalidate(); + editDeferred = new Deferred(); + content.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); + return editDeferred.promise(); + } + + private function onKeyDown(event: KeyboardEvent):Void { + content.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); + cast(this.skin, ColorSkin).color = 0x000000; + invalidate(); + + data.key = event.keyCode; + key.text = keyLabel(data.key); + editDeferred.resolve(data.key); + editDeferred = null; + } +} \ No newline at end of file diff --git a/src/client/haxe/ru/m/tankz/frame/settings/ActionView.yaml b/src/client/haxe/ru/m/tankz/frame/settings/ActionView.yaml new file mode 100644 index 0000000..eb07136 --- /dev/null +++ b/src/client/haxe/ru/m/tankz/frame/settings/ActionView.yaml @@ -0,0 +1,21 @@ +--- +width: 440 +height: 44 +margins: 5 +views: +- id: action + $type: haxework.gui.LabelView + $style: label + pWidth: 50 + pHeight: 100 + text: "" +- id: key + $type: haxework.gui.LabelView + $style: label + pWidth: 50 + pHeight: 100 + text: "" +skin: + $type: haxework.gui.skin.ColorSkin + color: "#000000" + alpha: 0.2 diff --git a/src/client/haxe/ru/m/tankz/frame/settings/SettingsEditor.hx b/src/client/haxe/ru/m/tankz/frame/settings/SettingsEditor.hx new file mode 100644 index 0000000..4b4992a --- /dev/null +++ b/src/client/haxe/ru/m/tankz/frame/settings/SettingsEditor.hx @@ -0,0 +1,75 @@ +package ru.m.tankz.frame.settings; + +import haxework.gui.LabelView; +import ru.m.tankz.control.ActionConfig; +import promhx.Promise; +import ru.m.tankz.storage.SettingsStorage; +import haxework.gui.ButtonView; +import ru.m.tankz.control.ActionConfig.ActionItem; +import haxework.gui.list.ListView; +import haxework.gui.VGroupView; + + +@:template("ru/m/tankz/frame/settings/SettingsEditor.yaml", "ru/m/tankz/Style.yaml") +class SettingsEditor extends VGroupView { + + public var controlIndex(default, set): Int; + + @:view var label:LabelView; + @:view var list:ListView; + @:view var change:ButtonView; + @:view var clear:ButtonView; + @:view var reset:ButtonView; + + @:provide var storage: SettingsStorage; + + private function init():Void { + change.onPress = this; + clear.onPress = this; + reset.onPress = this; + } + + private function set_controlIndex(value: Int): Int { + this.controlIndex = value; + label.text = 'Player ${controlIndex+1}'; + list.data = storage.read(controlIndex).data; + return this.controlIndex; + } + + public function onPress(view:ButtonView):Void { + switch (view.id) { + case "change": _change(); + case "clear": _clear(); + case "reset": _reset(); + case _: + } + } + + private function _change():Void { + var p: Promise = Promise.promise(0); + for (view in list.items) { + var v: ActionView = cast view; + if (v.data == null) break; + p = p.pipe(function(_):Promise return v.edit()); + } + p.then(function(_) _save()); + } + + private function _clear():Void { + for (item in list.data) { + item.key = -1; + } + list.invalidate(); + _save(); + } + + private function _reset():Void { + list.data = SettingsStorage.getDefault(controlIndex).data; + list.invalidate(); + _save(); + } + + private function _save():Void { + storage.write(controlIndex, new ActionConfig(list.data)); + } +} \ No newline at end of file diff --git a/src/client/haxe/ru/m/tankz/frame/settings/SettingsEditor.yaml b/src/client/haxe/ru/m/tankz/frame/settings/SettingsEditor.yaml new file mode 100644 index 0000000..7003587 --- /dev/null +++ b/src/client/haxe/ru/m/tankz/frame/settings/SettingsEditor.yaml @@ -0,0 +1,27 @@ +$type: haxework.gui.VGroupView +layoutMargin: 10 +views: +- id: label + $type: haxework.gui.LabelView + $style: label +- id: change + $type: haxework.gui.ButtonView + $style: button + text: Change +- id: clear + $type: haxework.gui.ButtonView + $style: button + text: Clear +- id: reset + $type: haxework.gui.ButtonView + $style: button + text: Reset +- id: list + $type: haxework.gui.list.VListView + factory: "@class:ru.m.tankz.frame.settings.ActionView" + pWidth: 100 + pHeight: 100 + scroll: + $type: haxework.gui.list.VScrollView + width: 1 + pHeight: 100 \ No newline at end of file diff --git a/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx b/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx new file mode 100644 index 0000000..9c4e926 --- /dev/null +++ b/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx @@ -0,0 +1,55 @@ +package ru.m.tankz.storage; + +import flash.net.SharedObject; +import flash.ui.Keyboard; +import ru.m.geom.Direction; +import ru.m.tankz.control.ActionConfig; +import ru.m.tankz.control.Control.TankAction; + + +class SettingsStorage { + + private static var TAG(default, never):String = 'SettingsStorage'; + + private var so:SharedObject; + + public function new() { + so = SharedObject.getLocal('settings'); + } + + public function read(index: Int):Null { + var data:String = Reflect.getProperty(so.data, Std.string(index)); + L.d(TAG, 'read: ${data}'); + if (data != null) { + return ActionConfig.loads(data); + } + return getDefault(index); + } + + public function write(index: Int, data: ActionConfig):Void { + L.d(TAG, 'write: ${data}'); + so.setProperty(Std.string(index), data.dumps()); + so.flush(); + } + + public static function getDefault(index: Int): ActionConfig { + return defaults.get(index).clone(); + } + + private static var defaults: Map = [ + 0 => new ActionConfig([ + {action:TankAction.MOVE(Direction.TOP), key:Keyboard.W}, + {action:TankAction.MOVE(Direction.LEFT), key:Keyboard.A}, + {action:TankAction.MOVE(Direction.BOTTOM), key:Keyboard.S}, + {action:TankAction.MOVE(Direction.RIGHT), key:Keyboard.D}, + {action:TankAction.SHOT, key:Keyboard.SPACE}, + ]), + 1 => new ActionConfig([ + {action:TankAction.MOVE(Direction.TOP), key:Keyboard.UP}, + {action:TankAction.MOVE(Direction.LEFT), key:Keyboard.LEFT}, + {action:TankAction.MOVE(Direction.BOTTOM), key:Keyboard.RIGHT}, + {action:TankAction.MOVE(Direction.RIGHT), key:Keyboard.DOWN}, + {action:TankAction.SHOT, key:Keyboard.NUMPAD_0}, + ]), + ]; +} diff --git a/src/client/resources/image/ui/close.png b/src/client/resources/image/ui/close.png new file mode 100644 index 0000000..1867d86 Binary files /dev/null and b/src/client/resources/image/ui/close.png differ diff --git a/src/client/resources/image/ui/close.source.png b/src/client/resources/image/ui/close.source.png new file mode 100644 index 0000000..a379169 Binary files /dev/null and b/src/client/resources/image/ui/close.source.png differ diff --git a/src/client/resources/image/ui/settings.png b/src/client/resources/image/ui/settings.png new file mode 100644 index 0000000..498edad Binary files /dev/null and b/src/client/resources/image/ui/settings.png differ diff --git a/src/client/resources/image/ui/settings.source.png b/src/client/resources/image/ui/settings.source.png new file mode 100644 index 0000000..5afd6fe Binary files /dev/null and b/src/client/resources/image/ui/settings.source.png differ diff --git a/src/client/resources/keyboard.txt b/src/client/resources/keyboard.txt new file mode 100644 index 0000000..2a773a9 --- /dev/null +++ b/src/client/resources/keyboard.txt @@ -0,0 +1,99 @@ +BACKSPACE 8 +TAB 9 +ENTER 13 +SHIFT 16 +CTRL 17 +ALT 18 +PAUSE/BREAK 19 +CAPS LOCK 20 +ESCAPE 27 +SPACE 32 +PAGE UP 33 +PAGE DOWN 34 +END 35 +HOME 36 +LEFT ARROW 37 +UP ARROW 38 +RIGHT ARROW 39 +DOWN ARROW 40 +INSERT 45 +DELETE 46 +0 48 +1 49 +2 50 +3 51 +4 52 +5 53 +6 54 +7 55 +8 56 +9 57 +A 65 +B 66 +C 67 +D 68 +E 69 +F 70 +G 71 +H 72 +I 73 +J 74 +K 75 +L 76 +M 77 +N 78 +O 79 +P 80 +Q 81 +R 82 +S 83 +T 84 +U 85 +V 86 +W 87 +X 88 +Y 89 +Z 90 +LEFT WINDOW KEY 91 +RIGHT WINDOW KEY 92 +SELECT KEY 93 +NUMPAD 0 96 +NUMPAD 1 97 +NUMPAD 2 98 +NUMPAD 3 99 +NUMPAD 4 100 +NUMPAD 5 101 +NUMPAD 6 102 +NUMPAD 7 103 +NUMPAD 8 104 +NUMPAD 9 105 +MULTIPLY 106 +ADD 107 +SUBTRACT 109 +DECIMAL POINT 110 +DIVIDE 111 +F1 112 +F2 113 +F3 114 +F4 115 +F5 116 +F6 117 +F7 118 +F8 119 +F9 120 +F10 121 +F11 122 +F12 123 +NUM LOCK 144 +SCROLL LOCK 145 +SEMI-COLON 186 +EQUAL SIGN 187 +COMMA 188 +DASH 189 +PERIOD 190 +FORWARD SLASH 191 +GRAVE ACCENT 192 +OPEN BRACKET 219 +BACK SLASH 220 +CLOSE BRAKET 221 +SINGLE QUOTE 222 \ No newline at end of file diff --git a/src/common/haxe/ru/m/geom/Direction.hx b/src/common/haxe/ru/m/geom/Direction.hx index 4541324..5169f3f 100644 --- a/src/common/haxe/ru/m/geom/Direction.hx +++ b/src/common/haxe/ru/m/geom/Direction.hx @@ -5,10 +5,10 @@ import haxe.ds.IntMap; class Direction { private static var directions:IntMap = new IntMap(); - public static var LEFT(default, null) = new Direction(-1, 0); - public static var TOP(default, null) = new Direction(0, -1); - public static var RIGHT(default, null) = new Direction(1, 0); - public static var BOTTOM(default, null) = new Direction(0, 1); + public static var LEFT(default, never) = new Direction(-1, 0); + public static var TOP(default, never) = new Direction(0, -1); + public static var RIGHT(default, never) = new Direction(1, 0); + public static var BOTTOM(default, never) = new Direction(0, 1); public var x(default, null):Int; public var y(default, null):Int;