-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbow_controller.gd
More file actions
93 lines (68 loc) · 2.22 KB
/
bow_controller.gd
File metadata and controls
93 lines (68 loc) · 2.22 KB
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
extends Node
@export var camera: Camera3D
@export var max_draw_time: float = 2
@export var muzzle: Marker3D
@export var arrow_scene: PackedScene
@export var max_inaccuracy = 10.0
@onready var draw_timer := $DrawTimer
var focus := 0.0
var drawing := false
var draw_tween: Tween
func _process(delta: float) -> void:
if Input.is_action_just_pressed("shoot"):
start_drawing()
if Input.is_action_just_released("shoot"):
release()
if drawing:
camera.fov = lerp(90.0, 20.0, focus)
else:
camera.fov = lerp(camera.fov, 90.0, 0.25)
func start_drawing() -> void:
drawing = true
draw_tween = get_tree().create_tween()
draw_tween.tween_property(self, "focus", 1.0, 3.0)
draw_tween.tween_callback(finished_drawing)
func finished_drawing() -> void:
draw_timer.start(max_draw_time)
func release() -> void:
if drawing:
drawing = false
draw_tween.stop()
draw_timer.stop()
shoot_arrow()
focus = 0.0
func shoot_arrow() -> void:
var arrow = arrow_scene.instantiate() as CharacterBody3D
get_parent().get_parent().add_child(arrow)
arrow.global_transform.origin = muzzle.global_transform.origin
arrow.global_transform.basis = camera.global_transform.basis
var min_speed = 50.0
var max_speed = 150.0
arrow.speed = lerp(min_speed, max_speed, focus)
var dir = -camera.global_transform.basis.z.normalized()
var inaccuracy = (1.0 - focus) * max_inaccuracy
var new_dir = random_cone(dir, inaccuracy)
arrow.velocity = new_dir * arrow.speed
func random_cone(dir: Vector3, deg: float) -> Vector3:
var rng = RandomNumberGenerator.new()
rng.randomize()
var rad = deg_to_rad(deg)
var cos = cos(rad)
var z = rng.randf_range(cos, 1.0)
var theta = rng.randf_range(0.0, TAU)
var sin_t = sqrt(1.0 - z * z)
var x = sin_t * cos(theta)
var y = sin_t * sin(theta)
var local_dir = Vector3(x, y, z)
var basis = Basis()
basis.z = dir.normalized()
if abs(dir.dot(Vector3.UP)) < 0.999:
basis.x = Vector3.UP.cross(basis.z).normalized()
else:
basis.x = Vector3.FORWARD.cross(basis.z).normalized()
basis.y = basis.z.cross(basis.x).normalized()
var global_dir = (basis.x * local_dir.x) + (basis.y * local_dir.y) + (basis.z * local_dir.z)
return global_dir.normalized()
func _on_draw_timer_timeout() -> void:
if drawing:
release()