-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayer.gd
176 lines (146 loc) · 5.85 KB
/
player.gd
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
extends CharacterBody2D
class_name Player
@export_category("Movement")
@export var dash_cooldown = 0.4
@export_category("Animation")
@export var squash_and_stretch = 0.2
@export var turn_speed = 20
@export var squash_and_stretch_speed = 50
@export var shield_follow_speed = 20
@export var damage_ring_follow_speed = 15
@export var damage_ring_spin_speed = 100
@export var helper_radius = 40
@onready var sprite := $Sprite
@onready var dash_timer := $DashTimer
@onready var dash_cooldown_timer := $DashCooldownTimer
@onready var move_particles := $MoveParticles
@onready var hitbox := $Hitbox
@onready var hitbox_collider := $Hitbox/CollisionShape
@onready var shield_anchor := $ShieldAnchor
@onready var shield := $ShieldAnchor/Shield
@onready var damage_ring := $DamageRing
var target_rotation = 0.0
var target_scale = Vector2.ONE
var next_time_to_fire = 0.0
var health: float
var bullet_scene = preload("res://player_bullet.tscn")
var wind_force = Vector2.ZERO
var can_move = true
var whirlpool_force = 0
var explosion_scene = preload("res://particles/explosion.tscn")
var helper_scene = preload("res://helper.tscn")
func _enter_tree() -> void:
Globals.player = self
func _ready() -> void:
dash_timer.wait_time = Stats.current.dash_duration
dash_cooldown_timer.wait_time = dash_cooldown
hitbox.set_collision_mask_value(4, true)
Events.go_in_portal.connect(_on_go_into_portal)
scale = Stats.current.player_size * Vector2.ONE
health = Stats.current.max_health
shield.scale = Stats.current.shield_size * Vector2.ONE
for i in Stats.current.helper_amount:
var helper = helper_scene.instantiate()
helper.player_offset = Vector2.from_angle(PI * 2 / Stats.current.helper_amount * i) * helper_radius
Globals.world.call_deferred("add_child", helper)
func _process(delta: float) -> void:
if not can_move: return
sprite.rotation = lerp_angle(sprite.rotation, target_rotation, turn_speed * delta)
sprite.scale = sprite.scale.move_toward(target_scale, squash_and_stretch_speed * delta)
shield_anchor.position = shield_anchor.position.lerp(position, shield_follow_speed * delta)
shield_anchor.rotation = get_angle_to(get_global_mouse_position()) - PI / 2
damage_ring.position = damage_ring.position.lerp(position, damage_ring_follow_speed * delta)
damage_ring.rotation_degrees += damage_ring_spin_speed * delta
func _physics_process(_delta: float) -> void:
if not can_move: return
var input = Input.get_vector("left", "right", "up", "down")
if input:
target_scale = Vector2.ONE + Vector2(squash_and_stretch, -squash_and_stretch)
target_rotation = input.angle()
else:
target_scale = Vector2.ONE
var speed = Stats.current.dash_speed if is_dashing() else Stats.current.run_speed
var whirlpool = (Vector2.ZERO - position).normalized() * whirlpool_force
velocity = input * speed + wind_force + whirlpool
if Input.is_action_just_pressed("dash") and can_dash():
dash()
if Input.is_action_pressed("fire") and Globals.time >= next_time_to_fire:
fire()
move_and_slide()
func fire():
next_time_to_fire = Globals.time + 1.0 / Stats.current.fire_rate
Globals.mouse.impact_rotation()
AudioManager.play_sound(AudioManager.shoot)
var bullet = bullet_scene.instantiate() as PlayerBullet
var mouse_pos = get_global_mouse_position()
bullet.global_position = global_position + ((mouse_pos - global_position).normalized() * 12)
bullet.look_at(mouse_pos)
bullet.rotation_degrees += randf_range(-Stats.current.bullet_spread, Stats.current.bullet_spread)
bullet.scale = Vector2.ONE * Stats.current.bullet_size
bullet.speed = Stats.current.bullet_speed
Globals.world.add_child(bullet)
func dash():
AudioManager.play_sound(AudioManager.dash)
dash_timer.start()
dash_cooldown_timer.start()
move_particles.emitting = false
hitbox.set_collision_mask_value(4, false)
hitbox.set_collision_mask_value(3, false)
func is_dashing() -> bool:
return not dash_timer.is_stopped()
func can_dash():
return dash_cooldown_timer.is_stopped()
func get_hurt(damage: float):
AudioManager.play_sound(AudioManager.hurt)
health -= damage
update_health_ui()
Scoring.total_health_lost += damage
Globals.camera.impact()
Globals.camera.shake(0.1, 1)
if health <= 0: die()
else: Globals.hitstop(0.15)
func die():
AudioManager.play_sound(AudioManager.explosion)
Events.player_die.emit()
Engine.time_scale = 0.2
visible = false
can_move = false
hitbox_collider.set_deferred("disabled", true)
var explosion = explosion_scene.instantiate() as CPUParticles2D
explosion.position = position
explosion.emitting = true
Globals.world.add_child(explosion)
await Globals.wait(1.5)
SceneManager.change_scene(SceneManager.game_over_scene)
Engine.time_scale = 1
func update_health_ui():
Globals.canvas.player_health.value = 100.0 / Stats.current.max_health * health
func change_to_next_scene():
if Globals.world.name == "Level 4":
SceneManager.change_scene(SceneManager.win_scene)
else:
SceneManager.change_scene(SceneManager.exchange_scene)
func _on_go_into_portal(portal: Portal):
can_move = false
velocity = Vector2.ZERO
move_particles.emitting = false
hitbox_collider.disabled = true
var tweener = get_tree().create_tween().set_parallel(true)
tweener.tween_property(sprite, "scale", Vector2.ZERO, 1)
tweener.tween_property(sprite, "global_position", portal.position, 1)
tweener.tween_property(sprite, "global_rotation_degrees", sprite.global_rotation_degrees + 360, 1)
tweener.tween_callback(change_to_next_scene).set_delay(1)
func _on_dash_timer_timeout() -> void:
move_particles.emitting = true
hitbox.set_collision_mask_value(4, true)
hitbox.set_collision_mask_value(3, true)
func _on_hitbox_area_entered(area: Area2D) -> void:
if area is EnemyBullet or area is Fish:
area.queue_free()
get_hurt(Stats.current.enemy_damage)
elif area is Rock or area is EnemyTile:
get_hurt(Stats.current.enemy_damage)
func _on_regen_timer_timeout() -> void:
if health < Stats.current.max_health:
health += Stats.current.regen
update_health_ui()