[client] add screen gamepad

This commit is contained in:
2019-06-17 17:33:35 +03:00
parent c0ab953115
commit 2b3f368e0f
11 changed files with 228 additions and 37 deletions

View File

@@ -4,6 +4,7 @@ import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.Lib;
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;
@@ -14,7 +15,7 @@ class HumanControl extends Control {
@:provide var storage:SettingsStorage;
private var keyBinding:KeyBinding;
private var moveQueue:Array<Int>;
private var moveQueue:Array<Direction>;
private var shotTimer:Timer;
public function new(playerId:PlayerId, controlIndex:Int) {
@@ -40,34 +41,43 @@ class HumanControl extends Control {
}
}
private function onKeyDown(event:KeyboardEvent):Void {
if (keyBinding.exists(event.keyCode)) switch (keyBinding.get(event.keyCode)) {
public function toggleAction(action:TankAction, on:Bool):Void {
switch action {
case TankAction.MOVE(direction):
if (moveQueue.indexOf(event.keyCode) == -1) {
moveQueue.unshift(event.keyCode);
updateMove();
if (on) {
if (moveQueue.indexOf(direction) == -1) {
moveQueue.unshift(direction);
}
} else {
moveQueue.remove(direction);
}
updateMove();
case TankAction.SHOT:
if (shotTimer == null) {
shotTimer = new Timer(300);
shotTimer.run = shot;
shot();
if (on) {
if (shotTimer == null) {
shotTimer = new Timer(300);
shotTimer.run = shot;
shot();
}
} else {
if (shotTimer != null) {
shotTimer.stop();
shotTimer = null;
}
}
case _:
case TankAction.STOP:
}
}
private function onKeyDown(event:KeyboardEvent):Void {
if (keyBinding.exists(event.keyCode)) {
toggleAction(keyBinding.get(event.keyCode), true);
}
}
private function onKeyUp(event:KeyboardEvent):Void {
if (keyBinding.exists(event.keyCode)) switch (keyBinding.get(event.keyCode)) {
case TankAction.MOVE(direction):
moveQueue.remove(event.keyCode);
updateMove();
case TankAction.SHOT:
if (shotTimer != null) {
shotTimer.stop();
shotTimer = null;
}
case _:
if (keyBinding.exists(event.keyCode)) {
toggleAction(keyBinding.get(event.keyCode), false);
}
}
@@ -80,11 +90,7 @@ class HumanControl extends Control {
if (moveQueue.length == 0) {
action(TankAction.STOP);
} else {
switch (keyBinding.get(moveQueue[0])) {
case TankAction.MOVE(direction):
action(TankAction.MOVE(direction));
case _:
}
action(TankAction.MOVE(moveQueue[0]));
}
}

View File

@@ -9,10 +9,21 @@ import ru.m.tankz.control.Control.TankAction;
class SettingsStorage extends SharedObjectStorage {
public var screenGamepad(get, set):Bool;
public function new() {
super("settings");
}
private function get_screenGamepad():Bool {
return read("screenGamepad");
}
private function set_screenGamepad(value:Bool):Bool {
write("screenGamepad", value);
return value;
}
public function getActionConfig(index:Int):ActionConfig {
return exists('action:$index') ? read('action:$index') : getDefaultActionConfig(index);
}

View File

@@ -1,5 +1,9 @@
package ru.m.tankz.view;
import ru.m.tankz.storage.SettingsStorage;
import ru.m.tankz.control.Control.TankAction;
import ru.m.geom.Direction;
import ru.m.tankz.control.HumanControl;
import haxework.view.frame.FrameSwitcher;
import haxework.view.VGroupView;
import ru.m.tankz.game.GameEvent;
@@ -10,6 +14,7 @@ import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.sound.SoundManager;
import ru.m.tankz.storage.GameStorage;
import ru.m.tankz.view.game.GameView;
import ru.m.tankz.view.GamepadView;
@:template class GameFrame extends VGroupView implements GameListener {
public static inline var ID = "game";
@@ -17,6 +22,7 @@ import ru.m.tankz.view.game.GameView;
private static inline var TAG = "GameFrame";
@:view("game") private var gameView(default, null):GameView;
@:view private var gamepad(default, null):GamepadView;
@:provide var network:NetworkManager;
@:provide var soundManager:SoundManager;
@@ -24,10 +30,12 @@ import ru.m.tankz.view.game.GameView;
@:provide var record:GameRecord;
@:provide var switcher:FrameSwitcher;
@:provide var gameStorage:GameStorage;
@:provide var settings:SettingsStorage;
@:provide var game:IGame;
public function onShow():Void {
gamepad.visible = settings.screenGamepad;
gameView.type = game.type;
soundManager.config = game.config;
gameView.render.config = game.config;
@@ -66,4 +74,21 @@ import ru.m.tankz.view.game.GameView;
public function close():Void {
switcher.change(LevelFrame.ID);
}
private function onGamepadAction(action:GamepadAction, on:Bool):Void {
// ToDo:
for (control in game.controls) {
if (Std.is(control, HumanControl)) {
var tankAction:TankAction = switch action {
case UP: MOVE(Direction.TOP);
case LEFT: MOVE(Direction.LEFT);
case DOWN: MOVE(Direction.BOTTOM);
case RIGHT: MOVE(Direction.RIGHT);
case BUTTON_1: SHOT;
}
cast(control, HumanControl).toggleAction(tankAction, on);
break;
}
}
}
}

View File

@@ -2,6 +2,13 @@
views:
- $type: haxework.view.VGroupView
skinId: container
layout.overflow: true
views:
- id: game
$type: ru.m.tankz.view.game.GameView
- id: gamepad
$type: ru.m.tankz.view.GamepadView
geometry.position: absolute
geometry.size.stretch: true
+actionSignal: $this:onGamepadAction
visible: false

View File

@@ -0,0 +1,119 @@
package ru.m.tankz.view;
import flash.display.Graphics;
import flash.events.MouseEvent;
import haxework.signal.Signal;
import haxework.view.skin.ISkin;
import haxework.view.SpriteView;
import ru.m.geom.Point;
import ru.m.geom.Rectangle;
enum GamepadAction {
UP;
LEFT;
DOWN;
RIGHT;
BUTTON_1;
}
typedef ActionArea = {
var action:GamepadAction;
var rect:Rectangle;
}
class GamepadSkin implements ISkin<GamepadView> {
public var color(default, default):Int;
public function new(color:Int = 0) {
this.color = color;
}
public function draw(view:GamepadView):Void {
var graphics:Graphics = view.content.graphics;
graphics.clear();
graphics.beginFill(0, 0.0);
graphics.drawRect(0, 0, view.width, view.height);
graphics.endFill();
graphics.lineStyle(2, color);
graphics.beginFill(color, 0.2);
for (area in view.areas) {
graphics.drawRect(area.rect.x, area.rect.y, area.rect.width, area.rect.height);
}
graphics.lineStyle();
}
}
class GamepadView extends SpriteView {
public var actionSignal(default, null):Signal2<GamepadAction, Bool>;
public var areas(default, null):Array<ActionArea>;
public var currentArea(default, null):ActionArea;
public function new() {
super();
actionSignal = new Signal2();
skin = [new GamepadSkin(0x00ff00)];
content.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private function onMouseDown(event:MouseEvent):Void {
onMouseMove(event);
content.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
content.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function onMouseMove(event:MouseEvent):Void {
var point = new Point(event.localX, event.localY);
if (currentArea != null) {
if (!currentArea.rect.contain(point)) {
actionSignal.emit(currentArea.action, false);
currentArea = null;
}
}
for (area in areas) {
if (area.rect.contain(point)) {
currentArea = area;
actionSignal.emit(currentArea.action, true);
break;
}
}
}
private function onMouseUp(event:MouseEvent):Void {
content.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
content.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
if (currentArea != null) {
actionSignal.emit(currentArea.action, false);
currentArea = null;
}
}
override public function update():Void {
super.update();
areas = [];
var size = Math.min(width, height) / 8;
var padding = size / 2;
areas.push({
action: GamepadAction.UP,
rect: new Rectangle(padding + size, height - size * 3 - padding, size, size)
});
areas.push({
action: GamepadAction.LEFT,
rect: new Rectangle(padding, height - size * 2 - padding, size, size)
});
areas.push({
action: GamepadAction.DOWN,
rect: new Rectangle(padding + size, height - size - padding, size, size)
});
areas.push({
action: GamepadAction.RIGHT,
rect: new Rectangle(padding + size * 2, height - size * 2 - padding, size, size)
});
areas.push({
action: GamepadAction.BUTTON_1,
rect: new Rectangle(width - size * 1.5 - padding, height - size * 2 - padding, size, size)
});
}
}

View File

@@ -1,7 +1,21 @@
package ru.m.tankz.view;
import haxework.view.ToggleButtonView;
import haxework.view.VGroupView;
import ru.m.tankz.storage.SettingsStorage;
@:template class SettingsFrame extends VGroupView {
public static var ID(default, never):String = "settings";
@:view("gamepad") private var gamepadButton:ToggleButtonView;
@:provide private static var settings:SettingsStorage;
public function onShow():Void {
gamepadButton.on = settings.screenGamepad;
}
private function toggleGamepad():Void {
gamepadButton.on = settings.screenGamepad = !settings.screenGamepad;
}
}

View File

@@ -6,6 +6,12 @@ views:
- $type: haxework.view.LabelView
skinId: text.header
text: Settings
- id: gamepad
$type: haxework.view.ToggleButtonView
skinId: button.simple
text: Screen Gamepad Disabled
onText: Screen Gamepad Enabled
+onPress: $code:toggleGamepad()
- $type: haxework.view.HGroupView
layout.margin: 20
views: