Browse code

gamepad configuration compatible with poor gamepad api implementations

devnewton authored on 11/03/2018 18:11:15
Showing 8 changed files
... ...
@@ -1,5 +1,5 @@
1 1
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
-<TextureAtlas imagePath="bunny01.png">
2
+<TextureAtlas imagePath="buttons.png">
3 3
     <SubTexture name="out" x="0" y="0" width="857" height="105" />
4 4
     <SubTexture name="over" x="0" y="105" width="857" height="104" />
5 5
     <SubTexture name="down" x="0" y="210" width="857" height="104" />
6 6
new file mode 100644
7 7
Binary files /dev/null and b/app/assets/menu/mini-buttons.png differ
8 8
new file mode 100644
... ...
@@ -0,0 +1,6 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<TextureAtlas imagePath="mini-buttons.png">
3
+    <SubTexture name="out" x="0" y="0" width="108" height="105" />
4
+    <SubTexture name="over" x="0" y="105" width="108" height="104" />
5
+    <SubTexture name="down" x="0" y="210" width="108" height="104" />
6
+</TextureAtlas>
... ...
@@ -1,7 +1,9 @@
1 1
 /// <reference path="../../typings/phaser.d.ts"/>
2 2
 import { AbstractState } from "./AbstractState";
3 3
 import { Menu } from "../ui/Menu";
4
+import { MenuMiniButton } from "../ui/MenuMiniButton";
4 5
 import { UnderthiefGame } from "../UnderthiefGame";
6
+import { GamepadUtils } from "../utils/GamepadUtils";
5 7
 
6 8
 export class GamepadOptionsBindAxisOrButton extends AbstractState {
7 9
 
... ...
@@ -16,7 +18,8 @@ export class GamepadOptionsBindAxisOrButton extends AbstractState {
16 18
     currentBinding: number = 0;
17 19
     pad: Phaser.SinglePad;
18 20
     padIndex = 1;
19
-    waitForNoInput: number;
21
+    axisButtons: Phaser.Group;
22
+    buttonsButtons: Phaser.Group;
20 23
 
21 24
     constructor() {
22 25
         super();
... ...
@@ -24,6 +27,7 @@ export class GamepadOptionsBindAxisOrButton extends AbstractState {
24 27
 
25 28
     preload() {
26 29
         Menu.preload(this.game);
30
+        MenuMiniButton.preload(this.game);
27 31
     }
28 32
 
29 33
     init(padIndex: number, binding: number = 0) {
... ...
@@ -37,7 +41,6 @@ export class GamepadOptionsBindAxisOrButton extends AbstractState {
37 41
         } else {
38 42
             this.currentBinding = binding;
39 43
         }
40
-        this.waitForNoInput = 60;
41 44
     }
42 45
 
43 46
     create() {
... ...
@@ -47,54 +50,96 @@ export class GamepadOptionsBindAxisOrButton extends AbstractState {
47 50
         logo.scale.y = 2;
48 51
         logo.anchor.setTo(0.5, 0);
49 52
         const menu = new Menu(this.game, false);
50
-        menu.button("Back", 200, 500, () => this.game.state.start('GamepadOptions'));
53
+        menu.button("Back", 200, 600, () => this.game.state.start('GamepadOptions'));
54
+        this.createAxisButtons();
55
+        this.createButtonsButtons();
56
+
57
+    }
58
+
59
+    createAxisButtons() {
60
+        this.axisButtons = this.game.add.group();
61
+        this.axisButtons.visible = false;
62
+        const nbButtonsPerColumn = Math.ceil(Math.sqrt(GamepadUtils.NB_AXIS));
63
+        for (let y = 0, axisCode =0; axisCode< GamepadUtils.NB_AXIS; ++y) {
64
+            for (let x = 0; x < nbButtonsPerColumn; ++x) {
65
+                const buttonAxisCode = axisCode++;
66
+                let miniButton = new AxisButton(this.game, this.pad, buttonAxisCode, 250 + x * 200, 100 + y * 120, () => this.bindAxis(buttonAxisCode));
67
+                this.axisButtons.add(miniButton);
68
+            }
69
+        }
70
+    }
71
+
72
+    createButtonsButtons() {
73
+        this.buttonsButtons = this.game.add.group();
74
+        this.buttonsButtons.visible = false;
75
+        const nbButtonsPerColumn = Math.ceil(Math.sqrt(GamepadUtils.NB_BUTTONS));
76
+        for (let y = 0, buttonCode =0; buttonCode< GamepadUtils.NB_BUTTONS; ++y) {
77
+            for (let x = 0; x < nbButtonsPerColumn; ++x) {
78
+                const buttonButtonCode = buttonCode++;
79
+                let miniButton = new ButtonButton(this.game, this.pad, buttonButtonCode, 250 + x * 200, 100 + y * 120, () => this.bindButton(buttonButtonCode));
80
+                this.buttonsButtons.add(miniButton);
81
+            }
82
+        }
51 83
     }
52 84
 
53 85
     update() {
54 86
         super.update();
55
-
56 87
         if (this.bindings[this.currentBinding].localStorageKeySuffix.match(/axis/gi)) {
57
-            this.detectAxis();
88
+            this.axisButtons.visible = true;
89
+            this.buttonsButtons.visible = false;
58 90
         } else {
59
-            this.detectButton();
91
+            this.axisButtons.visible = false;
92
+            this.buttonsButtons.visible = true;
60 93
         }
61 94
     }
62 95
 
63
-    detectAxis() {
64
-        let activationZone = Math.max(0.99, Math.min(0.8, 4 * this.pad.deadZone));
65
-        for (var k in Phaser.Gamepad) {
66
-            if (k.startsWith('AXIS_')) {
67
-                let axisCode = Phaser.Gamepad[k];
68
-                if (Math.abs(this.pad.axis(axisCode)) >= activationZone) {
69
-                    if (this.waitForNoInput > 0) {
70
-                        return;
71
-                    } else {
72
-                        localStorage.setItem('gamepad' + this.padIndex + '.layout.custom.' + this.bindings[this.currentBinding].localStorageKeySuffix, axisCode);
73
-                        this.game.state.start('GamepadOptionsBindAxis', true, false, this.padIndex, this.currentBinding + 1);
74
-                        return;
75
-                    }
76
-                }
77
-            }
78
-        }
79
-        this.waitForNoInput--;
96
+    bindAxis(axisCode: number) {
97
+        localStorage.setItem('gamepad' + this.padIndex + '.layout.custom.' + this.bindings[this.currentBinding].localStorageKeySuffix, '' + axisCode);
98
+        this.game.state.start('GamepadOptionsBindAxis', true, false, this.padIndex, this.currentBinding + 1);
80 99
     }
81 100
 
82
-    detectButton() {
83
-        let activationZone = Math.max(0.99, Math.min(0.8, 4 * this.pad.deadZone));
84
-        for (var k in Phaser.Gamepad) {
85
-            if (k.startsWith('BUTTON_')) {
86
-                let buttonCode = Phaser.Gamepad[k];
87
-                if (Math.abs(this.pad.buttonValue(buttonCode)) >= activationZone) {
88
-                    if (this.waitForNoInput > 0) {
89
-                        return;
90
-                    } else {
91
-                        localStorage.setItem('gamepad' + this.padIndex + '.layout.custom.' + this.bindings[this.currentBinding].localStorageKeySuffix, buttonCode);
92
-                        this.game.state.start('GamepadOptionsBindAxis', true, false, this.padIndex, this.currentBinding + 1);
93
-                        return;
94
-                    }
95
-                }
96
-            }
101
+    bindButton(buttonCode: number) {
102
+        localStorage.setItem('gamepad' + this.padIndex + '.layout.custom.' + this.bindings[this.currentBinding].localStorageKeySuffix, '' + buttonCode);
103
+        this.game.state.start('GamepadOptionsBindAxis', true, false, this.padIndex, this.currentBinding + 1);
104
+    }
105
+}
106
+
107
+class AxisButton extends MenuMiniButton {
108
+    pad: Phaser.SinglePad;
109
+    axisCode: number;
110
+    constructor(game: Phaser.Game, pad: Phaser.SinglePad, axisCode: number, x: number, y: number, callback: Function) {
111
+        super(game, axisCode.toString(), x, y, callback);
112
+        this.pad = pad;
113
+        this.axisCode = axisCode;
114
+    }
115
+    update() {
116
+        super.update();
117
+
118
+        if (Math.abs(this.pad.axis(this.axisCode)) > this.pad.deadZone) {
119
+            this.tint = 0xFF6666;
120
+        } else {
121
+            this.tint = 0xFFFFFF;
97 122
         }
98
-        this.waitForNoInput--;
99 123
     }
124
+
100 125
 }
126
+
127
+class ButtonButton extends MenuMiniButton {
128
+    pad: Phaser.SinglePad;
129
+    buttonCode: number;
130
+    constructor(game: Phaser.Game, pad: Phaser.SinglePad, buttonCode: number, x: number, y: number, callback: Function) {
131
+        super(game, buttonCode.toString(), x, y, callback);
132
+        this.pad = pad;
133
+        this.buttonCode = buttonCode;
134
+    }
135
+    update() {
136
+        super.update();
137
+
138
+        if (this.pad.isDown(this.buttonCode)) {
139
+            this.tint = 0xFF6666;
140
+        } else {
141
+            this.tint = 0xFFFFFF;
142
+        }
143
+    }
144
+
145
+}
101 146
\ No newline at end of file
... ...
@@ -43,14 +43,14 @@ export class MenuCursor extends Phaser.Text {
43 43
     processPad(): boolean {
44 44
         const pad = this.firstPadConnected();
45 45
         if (pad) {
46
-            for (let b = 0; b < 16; ++b) {
46
+            for (let b = 0; b < 4; ++b) {
47 47
                 let button = pad.getButton(b);
48 48
                 if (button && button.isDown) {
49 49
                     this.activateButton();
50 50
                     return true;
51 51
                 }
52 52
             }
53
-            for (let a = 0; a < 16; ++a) {
53
+            for (let a = 0; a < 2; ++a) {
54 54
                 const axis = pad.axis(a);
55 55
                 if (axis > pad.deadZone) {
56 56
                     this.moveToButton(1);
57 57
new file mode 100644
... ...
@@ -0,0 +1,24 @@
1
+/// <reference path="../../typings/phaser.d.ts"/>
2
+export class MenuMiniButton extends Phaser.Button {
3
+
4
+    labelText: Phaser.Text;
5
+    callback: Function;
6
+    constructor(game: Phaser.Game, label: string, x: number, y: number, callback: Function) {
7
+        super(game, x, y, 'menu-mini-buttons', callback, null, 'over', 'out', 'down');
8
+        this.callback = callback;
9
+        this.labelText = new Phaser.Text(this.game, 15, 15, label, { font: "64px monospace", fill: 'white' });
10
+        this.addChild(this.labelText);
11
+    }
12
+    
13
+    static preload(game: Phaser.Game) {
14
+        game.load.atlasXML('menu-mini-buttons', 'menu/mini-buttons.png', 'menu/mini-buttons.xml');
15
+    }
16
+
17
+    toggle() {
18
+        this.callback();
19
+    }
20
+
21
+    setText(text: string) {
22
+        this.labelText.setText(text);
23
+    }
24
+}
0 25
\ No newline at end of file
... ...
@@ -272,7 +272,7 @@ export class PadControls extends AbstractControls {
272 272
         this.moveYAxis = this.readNumberFromLocalStorage('gamepad' + padIndex + '.layout.custom.moveYAxis', Phaser.Gamepad.XBOX360_STICK_LEFT_Y);
273 273
         this.dashButton = this.readNumberFromLocalStorage('gamepad' + padIndex + '.layout.custom.dashButton', Phaser.Gamepad.XBOX360_X);
274 274
         this.menuButton = this.readNumberFromLocalStorage('gamepad' + padIndex + '.layout.custom.menuButton', Phaser.Gamepad.XBOX360_START);
275
-        this.hammerTimeButton = this.readNumberFromLocalStorage('gamepad' + padIndex + '.layout.custom.hammerTimeButton', Phaser.Gamepad.XBOX360_A);
275
+        this.hammerTimeButton = this.readNumberFromLocalStorage('gamepad' + padIndex + '.layout.custom.hammerButton', Phaser.Gamepad.XBOX360_A);
276 276
         localStorage.setItem('gamepad' + padIndex + '.layout', 'custom');
277 277
     }
278 278
 
279 279
new file mode 100644
... ...
@@ -0,0 +1,5 @@
1
+/// <reference path="../../typings/phaser.d.ts"/>
2
+export class GamepadUtils {
3
+    static NB_BUTTONS=16;
4
+    static NB_AXIS=10;
5
+}
0 6
\ No newline at end of file