-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTouchJoystick.tscn
139 lines (103 loc) · 5.65 KB
/
TouchJoystick.tscn
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
[gd_scene load_steps=5 format=2]
[sub_resource type="GDScript" id=1]
script/source = "extends Node2D
export var dead_zone = 5; #joystick deadzone radius
export var circle_pad_radius = 25; #radius of the circle pad
export var outer_ring_radius = 70; #radius of the outer ring of the joystick
export var touch_screen_only = false;
onready var CirclePadHitbox = get_node(\"Circle Pad/Circle Pad Hitbox\"); #retrieve useful nodes
onready var CirclePad = get_node(\"Circle Pad\");
onready var OuterRingHitbox = get_node(\"Outer Ring/Outer Ring Hitbox\");
onready var OuterRing = get_node(\"Outer Ring\");
var lastScreenTouch = Vector2(); #previous screentouch location
var lastTouchIndex = null; #records which touch index should be tracked
signal _joystick_pressed; #called when the user pressed the joystick
signal _joystick_released; #called when the user released the joystick
signal _joystick_axis_changed(value); #called when the axis is changed by user input
func _draw():
if((touch_screen_only && OS.has_touchscreen_ui_hint()) || !touch_screen_only):
draw_circle(Vector2(0,0), outer_ring_radius, Color(0,0,0)); #black circle shows outer ring
draw_circle(Vector2(0,0), dead_zone, Color(255, 0, 0)); #draw a red circle to show deadzone
func _ready():
CirclePadHitbox.shape.radius = circle_pad_radius; #set the user defined radii
OuterRingHitbox.shape.radius = outer_ring_radius;
if(touch_screen_only && !OS.has_touchscreen_ui_hint()): #conceal the joystick if restricted to touchscreens
visible = false;
func getStickPosition(): #returns vector scaled to return a vector between (-1, -1) and (1, 1)
if (abs(CirclePad.position.length()) > dead_zone):
return CirclePad.position / 70;
else:
return Vector2(0,0); #return 0,0 if circle pad is inside the deadzone
func _physics_process(delta):
CirclePad.move_and_collide(lastScreenTouch - CirclePad.position); #move and collide to is an offset so current location must be subtracted first
func _unhandled_input(event): #tracks screentouch events
if (event.is_class(\"InputEventScreenDrag\")): #if the last touch was outside the joystick range it will be ignored
if (lastTouchIndex == event.index):
var temp = to_local(event.position); #store and convert touch loaction into a local point
if (abs(temp.length()) > outer_ring_radius): #if the length exceeds the allowed range
lastScreenTouch = temp.normalized() * outer_ring_radius; #normalize the vector to keep its direction but reduce the length to the maximum radius
get_tree().set_input_as_handled(); #stops the input from being sent to other nodes
self.emit_signal(\"_joystick_axis_changed\", getStickPosition()); #emit a signal that the axis changed value
else:
lastScreenTouch = temp; #the circlepad will simply move to the vector if it's in bounds
get_tree().set_input_as_handled(); #stops the input from being sent to other nodes
self.emit_signal(\"_joystick_axis_changed\", getStickPosition()); #emit a signal that the axis changed value
elif (event.is_class(\"InputEventScreenTouch\")):
if (event.index == lastTouchIndex && !event.pressed): #if the tracked index is being released
lastScreenTouch = Vector2(0,0); #reset touch position to the center when released
lastTouchIndex = null; #reset touch index when released
self.emit_signal(\"_joystick_released\"); #emit a signal when released
func _on_Outer_Ring_input_event(viewport, event, shape_idx): #called when an input event happens inside outer ring
if (event.is_class(\"InputEventScreenTouch\")): #blocks undesired input
if (event.pressed): #if the screen is being pressed
lastScreenTouch = to_local(event.position); #log the previous screen touch relative to the joystick
lastTouchIndex = event.index; #record the touch index so it can tracked outside of outer ring
get_tree().set_input_as_handled(); #stops the input from being sent to other nodes
self.emit_signal(\"_joystick_pressed\"); #emit a signal when pressed"
[sub_resource type="GDScript" id=2]
script/source = "extends KinematicBody2D
func _draw():
if((get_node(\"..\").touch_screen_only && OS.has_touchscreen_ui_hint()) || !get_node(\"..\").touch_screen_only): #do not draw circle pad if touchscreen only
draw_circle(Vector2(0,0), get_node(\"Circle Pad Hitbox\").shape.radius, Color(255,255,255)); #draw a circle to represent circle pad"
[sub_resource type="CircleShape2D" id=3]
custom_solver_bias = 0.0
radius = 25.0
[sub_resource type="CircleShape2D" id=4]
custom_solver_bias = 0.0
radius = 70.0
[node name="Touch Joystick" type="Node2D"]
script = SubResource( 1 )
_sections_unfolded = [ "Transform" ]
__meta__ = {
"_edit_group_": true
}
dead_zone = 5
circle_pad_radius = 25
outer_ring_radius = 70
touch_screen_only = false
[node name="Circle Pad" type="KinematicBody2D" parent="." index="0"]
z_index = 1
input_pickable = true
collision_layer = 1
collision_mask = 1
collision/safe_margin = 0.08
script = SubResource( 2 )
_sections_unfolded = [ "Collision", "Pickable", "Transform", "Z Index" ]
[node name="Circle Pad Hitbox" type="CollisionShape2D" parent="Circle Pad" index="0"]
shape = SubResource( 3 )
_sections_unfolded = [ "Transform" ]
[node name="Outer Ring" type="Area2D" parent="." index="1"]
input_pickable = true
gravity_point = true
gravity_distance_scale = 70.0
gravity_vec = Vector2( 0, 0 )
gravity = 500.0
linear_damp = 0.1
angular_damp = 1.0
audio_bus_override = false
audio_bus_name = "Master"
_sections_unfolded = [ "Collision", "Material", "Transform" ]
[node name="Outer Ring Hitbox" type="CollisionShape2D" parent="Outer Ring" index="0"]
shape = SubResource( 4 )
_sections_unfolded = [ "Material", "Transform", "Visibility" ]
[connection signal="input_event" from="Outer Ring" to="." method="_on_Outer_Ring_input_event"]