Commits

Anonymous committed 38935e7

"Dramatically" improve yoob.Joystick.

  • Participants
  • Parent commits 61806fc

Comments (0)

Files changed (2)

File eg/joystick.html

 
 <div id="thing"></div>
 
+<p>Use arrow keys to move the black square, and the Control key to fire.</p>
+
+<p id='status'></p>
+
 </body>
 <script src="../src/yoob/joystick.js"></script>
 <script>
       y += j.dy;
       thing.style.left = x + "px";
       thing.style.top = y + "px";
-      thing.style.background = j.button ? "red" : "black";
+      thing.style.background = j.buttonPressed ? "red" : "black";
   }, 1000/60);
+  j.onchange = function() {
+    document.getElementById('status').innerHTML =
+      '<p>' + j.dx + ',' + j.dy + ',' + j.buttonPressed + '</p>';
+  };
 </script>

File src/yoob/joystick.js

  */
 if (window.yoob === undefined) yoob = {};
 
+/*
+ * Emulates a joystick.  Be default, this is with the cursor keys and (either)
+ * control key as the fire button, but the keys can be reconfigured by changing
+ * values in the keyMap map, for example:
+ *
+ *     var joystick = new yoob.Joystick().init();
+ *     joystick.keyMap[32] = joystick.fire;
+ *     joystick.keyMap[17] = undefined;
+ *
+ * Control is used by default rather than space because, on all browsers I have
+ * tried on both Ubuntu (FF, Chrome) and Windows (FF, IE), down+right and
+ * up+left combinations both prevent the space key from registering.
+ *
+ * Some finesse is built into this design; for example, the user may hold
+ * down right, then additionally hold down left (and the stick will register
+ * no horizontal movement), then release right (and the stick will then
+ * register leftward movement.)
+ *
+ * The joystick may either be used in a polled mode (and if you are animating
+ * using setInterval or setTimeout or requestAnimationFrame, you may wish to
+ * use this method; simply poll the joystick's dx and dy and buttonPressed
+ * on each frame) or evented mode, by assigning an onchange method.  (see
+ * eg/joystick.html for an example)
+ */
 yoob.Joystick = function() {
     this.init = function() {
         this.dx = 0;
         this.dy = 0;
-        this.button = false;
+        this.leftPressed = false;
+        this.rightPressed = false;
+        this.upPressed = false;
+        this.downPressed = false;
+        this.buttonPressed = false;
+        this.keyMap = {
+            17: this.fire,
+            37: this.left,
+            38: this.up,
+            39: this.right,
+            40: this.down
+        };
+        this.onchange = undefined;
         return this;
     };
 
-    this.keyMap = {
-        32: 'fire',
-        37: 'left',
-        38: 'up',
-        39: 'right',
-        40: 'down'
-    };
-
     this.fire = function(obj, pressed) {
-        obj.button = pressed;
+        if (obj.buttonPressed === pressed) return;
+        obj.buttonPressed = pressed;
+        if (obj.onchange !== undefined) obj.onchange();
     };
 
     this.left = function(obj, pressed) {
-        obj.dx = pressed ? -1 : 0;
+        if (obj.leftPressed === pressed) return;
+        obj.leftPressed = pressed;
+        obj.dx = (obj.leftPressed ? -1 : 0) + (obj.rightPressed ? 1 : 0);
+        if (obj.onchange !== undefined) obj.onchange();
     };
 
     this.up = function(obj, pressed) {
-        obj.dy = pressed ? -1 : 0;
+        if (obj.upPressed === pressed) return;
+        obj.upPressed = pressed;
+        obj.dy = (obj.upPressed ? -1 : 0) + (obj.downPressed ? 1 : 0);
+        if (obj.onchange !== undefined) obj.onchange();
     };
 
     this.right = function(obj, pressed) {
-        obj.dx = pressed ? 1 : 0;
+        if (obj.rightPressed === pressed) return;
+        obj.rightPressed = pressed;
+        obj.dx = (obj.leftPressed ? -1 : 0) + (obj.rightPressed ? 1 : 0);
+        if (obj.onchange !== undefined) obj.onchange();
     };
 
     this.down = function(obj, pressed) {
-        obj.dy = pressed ? 1 : 0;
+        if (obj.downPressed === pressed) return;
+        obj.downPressed = pressed;
+        obj.dy = (obj.upPressed ? -1 : 0) + (obj.downPressed ? 1 : 0);
+        if (obj.onchange !== undefined) obj.onchange();
     };
 
     this.attach = function(element) {
         var $this = this;
         element.addEventListener('keydown', function(e) {
-            var u = $this[$this.keyMap[e.keyCode]];
+            var u = $this.keyMap[e.keyCode];
             if (u !== undefined) {
                 u($this, true);
                 e.cancelBubble = true;
             }
         }, true);
         element.addEventListener('keyup', function(e) {
-            var u = $this[$this.keyMap[e.keyCode]];
+            var u = $this.keyMap[e.keyCode];
             if (u !== undefined) {
                 u($this, false);
                 e.cancelBubble = true;