1 module re.input.virtual.joystick; 2 3 import re.input; 4 import re.math; 5 import std.algorithm; 6 7 /// a virtual joystick 8 class VirtualJoystick : VirtualInput { 9 // monitors four of inputs to make a joystick 10 static abstract class Node : VirtualInput.Node { 11 @property public Vector2 value(); 12 } 13 14 /// logic-controllable joystick 15 static class LogicJoystick : Node { 16 public Vector2 logic_value = Vector2Zero; 17 18 @property public override Vector2 value() { 19 return logic_value; 20 } 21 } 22 23 /// monitors a pair of keyboard keys 24 static class KeyboardKeys : Node { 25 public OverlapBehavior overlap_behavior; 26 public Keys left; 27 public Keys right; 28 public Keys up; 29 public Keys down; 30 private Vector2 _value; 31 private bool _turned_x; 32 private bool _turned_y; 33 34 /// creates a keyboard keys node 35 this(Keys left, Keys right, Keys up, Keys down, 36 OverlapBehavior overlap_behavior = OverlapBehavior.init) { 37 this.left = left; 38 this.right = right; 39 this.up = up; 40 this.down = down; 41 this.overlap_behavior = overlap_behavior; 42 } 43 44 @property public override Vector2 value() { 45 return _value; 46 } 47 48 public override void update() { 49 // x axis 50 if (Input.is_key_down(left)) { 51 if (Input.is_key_down(right)) { 52 switch (overlap_behavior) { 53 case OverlapBehavior.Cancel: 54 _value.x = 0; 55 break; 56 case OverlapBehavior.Newer: 57 if (!_turned_x) { 58 _value.x *= -1; 59 _turned_x = true; 60 } 61 break; 62 case OverlapBehavior.Older: 63 break; // we don't touch the value 64 default: 65 assert(0); 66 } 67 } else { 68 _turned_x = false; 69 _value.x = -1; 70 } 71 } else if (Input.is_key_down(right)) { 72 _turned_x = false; 73 _value.x = 1; 74 } else { 75 _turned_x = false; 76 _value.x = 0; 77 } 78 // y axis 79 if (Input.is_key_down(up)) { 80 if (Input.is_key_down(down)) { 81 switch (overlap_behavior) { 82 case OverlapBehavior.Cancel: 83 _value.y = 0; 84 break; 85 case OverlapBehavior.Newer: 86 if (!_turned_y) { 87 _value.y *= -1; 88 _turned_y = true; 89 } 90 break; 91 case OverlapBehavior.Older: 92 break; // we don't touch the value 93 default: 94 assert(0); 95 } 96 } else { 97 _turned_y = false; 98 _value.y = -1; 99 } 100 } else if (Input.is_key_down(down)) { 101 _turned_y = false; 102 _value.y = 1; 103 } else { 104 _turned_y = false; 105 _value.y = 0; 106 } 107 } 108 } 109 110 @property public Vector2 value() { 111 foreach (node; nodes) { 112 auto val = (cast(Node) node).value; 113 if (val != raymath.Vector2Zero()) { 114 return val; 115 } 116 } 117 return raymath.Vector2Zero(); 118 } 119 } 120 121 @("input-joystick") 122 unittest { 123 auto the_joy = new VirtualJoystick(); 124 the_joy.nodes ~= new VirtualJoystick.KeyboardKeys(Keys.KEY_LEFT, 125 Keys.KEY_RIGHT, Keys.KEY_UP, Keys.KEY_DOWN); 126 127 assert(the_joy.nodes.length > 0); 128 }