Code cleanup + state machine for player - WIP

This commit is contained in:
Sagi Dayan 2020-10-03 22:50:07 -04:00
parent 628ad64eef
commit 3997d6e378
29 changed files with 1217 additions and 138 deletions

BIN
assets/HUD/time_hud.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/time_hud.png-0544f5cdebd62aa844aeedf56f01d694.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/HUD/time_hud.png"
dest_files=[ "res://.import/time_hud.png-0544f5cdebd62aa844aeedf56f01d694.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -19,6 +19,16 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://src/Items/Coin.gd"
}, {
"base": "Node2D",
"class": "CutScene",
"language": "GDScript",
"path": "res://src/Scripts/CutScene.gd"
}, {
"base": "Control",
"class": "DialogBubble",
"language": "GDScript",
"path": "res://src/CutScenes/DialogBubble/DialogBubble.gd"
}, {
"base": "KinematicBody2D",
"class": "Enemy",
"language": "GDScript",
@ -42,6 +52,8 @@ _global_script_classes=[ {
_global_script_class_icons={
"CheckPoint": "",
"Coin": "",
"CutScene": "",
"DialogBubble": "",
"Enemy": "",
"HUD": "",
"Player": "",
@ -61,11 +73,13 @@ config/icon="res://icon.png"
AudioManager="*res://src/Singletons/AudioManager.tscn"
GameState="*res://src/Singletons/GameState.gd"
Utils="*res://src/Singletons/Utils.gd"
[display]
window/size/width=480
window/size/height=270
window/size/fullscreen=true
window/stretch/mode="viewport"
window/stretch/aspect="keep"
@ -79,6 +93,15 @@ theme/custom="res://assets/Theme/Theme.tres"
[input]
ui_accept={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777221,"unicode":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777222,"unicode":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":90,"unicode":0,"echo":false,"script":null)
]
}
direction_up={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"unicode":0,"echo":false,"script":null)

26
src/Actors/LightBeam.gd Normal file
View file

@ -0,0 +1,26 @@
extends Particles2D
export var direction = Vector2.LEFT
export var speed = 300
func _ready() -> void:
$AnimationPlayer.play("lights_on")
func _physics_process(delta: float) -> void:
if emitting:
position = position + (direction * speed * delta)
func _on_Area2D_body_entered(body: Node) -> void:
call_deferred("_disable_area")
emitting = false
$AnimationPlayer.play("lights_out")
yield($AnimationPlayer, "animation_finished")
queue_free()
pass # Replace with function body.
func _disable_area():
print("beam area off")
$Area2D/CollisionShape2D.disabled = true

138
src/Actors/LightBeam.tscn Normal file
View file

@ -0,0 +1,138 @@
[gd_scene load_steps=11 format=2]
[ext_resource path="res://src/Actors/ligt_beam.png" type="Texture" id=1]
[ext_resource path="res://src/Actors/LightBeam.gd" type="Script" id=2]
[sub_resource type="Gradient" id=1]
offsets = PoolRealArray( 0, 0.189655, 0.366379, 0.616379, 1 )
colors = PoolColorArray( 1, 1, 1, 1, 0, 0.992157, 0.894118, 1, 0.844238, 0.964844, 0.95297, 0.826387, 0.0330963, 0.941406, 0.852792, 0.712057, 0.0627451, 0.992157, 0.901961, 0.203922 )
[sub_resource type="GradientTexture" id=2]
gradient = SubResource( 1 )
[sub_resource type="Curve" id=3]
_data = [ Vector2( 0.00784314, 0.894318 ), 0.0, 1.34604, 0, 0, Vector2( 1, 0.237591 ), 0.0, 0.0, 0, 0 ]
[sub_resource type="CurveTexture" id=4]
curve = SubResource( 3 )
[sub_resource type="ParticlesMaterial" id=5]
emission_shape = 1
emission_sphere_radius = 1.0
flag_disable_z = true
direction = Vector3( 0, 0, 0 )
gravity = Vector3( 0, 0, 0 )
angular_velocity = 0.2
angular_velocity_random = 1.0
orbit_velocity = 0.0
orbit_velocity_random = 0.0
angle = 90.0
angle_random = 0.6
scale = 0.7
scale_random = 0.5
scale_curve = SubResource( 4 )
color_ramp = SubResource( 2 )
[sub_resource type="CircleShape2D" id=6]
radius = 3.0
[sub_resource type="Animation" id=8]
resource_name = "lights_on"
length = 0.5
loop = true
tracks/0/type = "value"
tracks/0/path = NodePath("Light2D:texture_scale")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.25, 0.5 ),
"transitions": PoolRealArray( 1, 1, 1 ),
"update": 0,
"values": [ 1.0, 1.5, 1.0 ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("Light2D:rotation_degrees")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0, 0.25, 0.5 ),
"transitions": PoolRealArray( 1, 1, 1 ),
"update": 0,
"values": [ 0.0, -86.4, 33.4 ]
}
[sub_resource type="Animation" id=7]
resource_name = "lights_out"
length = 0.5
step = 0.25
tracks/0/type = "value"
tracks/0/path = NodePath("Light2D:energy")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.5 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ 2.0, 0.0 ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("Light2D:texture_scale")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0, 0.25, 0.5 ),
"transitions": PoolRealArray( 1, 1, 1 ),
"update": 0,
"values": [ 2.0, 1.5, 2.0 ]
}
tracks/2/type = "value"
tracks/2/path = NodePath("Light2D:rotation_degrees")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/keys = {
"times": PoolRealArray( 0, 0.25, 0.5 ),
"transitions": PoolRealArray( 1, 1, 1 ),
"update": 0,
"values": [ 0.0, -86.4, 0.0 ]
}
[node name="LightBeam" type="Particles2D"]
amount = 50
lifetime = 0.4
explosiveness = 0.1
local_coords = false
process_material = SubResource( 5 )
texture = ExtResource( 1 )
script = ExtResource( 2 )
[node name="Light2D" type="Light2D" parent="."]
rotation = -0.253422
texture = ExtResource( 1 )
texture_scale = 0.8
energy = 2.0
range_item_cull_mask = 15375
shadow_enabled = true
shadow_item_cull_mask = 28
[node name="Area2D" type="Area2D" parent="."]
collision_layer = 0
collision_mask = 2147483660
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
shape = SubResource( 6 )
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
autoplay = "lights_on"
anims/lights_on = SubResource( 8 )
anims/lights_out = SubResource( 7 )
[connection signal="body_entered" from="Area2D" to="." method="_on_Area2D_body_entered"]

View file

@ -9,12 +9,13 @@ export var gravity: = 500.0
export var max_gravity:= 450.0
export var respawn_position:=Vector2.ZERO
export var wall_slide_friction:=.2
export var wall_jump_speed_factor := Vector2(2.5 ,.85)
export var wall_jump_speed_factor := Vector2(1 ,.8)
export var dash_thrust = 500.0
export var max_wall_slide_gravity := 100.0
var LandingDust = load("res://src/Actors/LandingDust.tscn")
var JumpDust = load("res://src/Actors/JumpDust.tscn")
var LightBeam = load("res://src/Actors/LightBeam.tscn")
signal landed
@ -23,13 +24,21 @@ signal died
var _velocity: Vector2 = Vector2.ZERO
var _landing_position:Vector2 = Vector2.ZERO
var _in_air = false;
var _is_wall_jumping := false
var _alive := false;
var _is_wall_sliding := false;
var _is_dashing := false;
var _can_dash := true;
var _is_attaking := false;
var _alive := false
var _can_dash := true
var _is_jump_canceled := false
var _direction := Vector2.ZERO
enum States {
IDLE,
IN_AIR,
DASHING,
WALL_SLIDING,
ATTACKING
}
var _state = States.IDLE
enum Direction{
RIGHT = 1,
@ -39,7 +48,8 @@ enum Direction{
export var abilities:= {
"dash": false,
"wall_jump": false,
"attack": false
"attack": false,
"light_beam": false
}
func _ready() -> void:
$AnimationPlayer.play("fade_in")
@ -47,92 +57,142 @@ func _ready() -> void:
func _physics_process(delta: float) -> void:
if _alive:
var is_jump_canceled: = Input.is_action_just_released("jump") and !_is_wall_jumping and _velocity.y < 0.0
var direction: = get_direction()
var prev_wall_slide_state = _is_wall_sliding
_is_wall_sliding = _velocity.y >=0 and is_on_wall() and _in_air
_velocity = calculate_move_velocity(direction,is_jump_canceled, delta)
if _is_wall_sliding and not prev_wall_slide_state:
_velocity.y=0
_update_state()
_input_check()
_velocity = calculate_move_velocity(_direction,_is_jump_canceled, delta)
_velocity = move_and_slide(_velocity, Vector2.UP)
update_sprite(direction)
if is_on_floor() and !_is_dashing: _can_dash = true;
if is_on_floor() and _in_air and !_is_dashing:
var dust = LandingDust.instance()
dust.position = position
get_parent().add_child(dust)
_in_air = false
_is_wall_jumping = false
emit_signal("landed", position)
if _is_wall_sliding:
_is_wall_jumping = false
func get_direction() -> Vector2:
var right_strength = min(Input.get_action_strength("direction_right") , 1)
var left_strength = min(Input.get_action_strength("direction_left"), 1)
return Vector2(
right_strength - left_strength if _in_air or not _is_attaking else 0,
-1.0 if Input.is_action_just_pressed("jump") and (is_on_floor() or _is_wall_sliding) else 1.0
)
func calculate_move_velocity(direction:Vector2, is_jump_canceled:bool, delta:float)->Vector2:
var output: = _velocity
var current_gravity = gravity * wall_slide_friction if _is_wall_sliding else gravity
output.x = lerp(_velocity.x, run_speed * direction.x, .09 if _in_air else .5)
output.y += current_gravity * delta
if direction.y == -1.0: # we are jumping
_in_air = true
if _is_wall_sliding:
# wall jump
var walljump__x_direction = -1 * direction.x
_is_wall_jumping = true
var desired = (run_speed * wall_jump_speed_factor.x * walljump__x_direction)
output.x = desired
output.y = jump_power * wall_jump_speed_factor.y * direction.y
else:
#jump
output.y = jump_power * direction.y
var dust = JumpDust.instance()
dust.position = position;
get_parent().add_child(dust)
emit_signal("jumping", position)
if not _is_dashing:
if is_jump_canceled:
output.y = 0
if output.y < max_gravity * -1:
output.y = max_gravity
if output.y > 0 and !is_on_floor():
_in_air = true;
if _is_dashing:
return _velocity
if _is_wall_sliding and output.y > max_wall_slide_gravity:
output.y = max_wall_slide_gravity
var dash_velocity := Vector2(
$Sprite.scale.x * dash_thrust,
0
)
if Input.is_action_just_pressed("dash") and _can_dash:
update_sprite(_direction)
func _input_check() -> void:
if GameState.get_state() == GameState.States.GAME:
_is_jump_canceled = Input.is_action_just_released("jump") and !_is_wall_jumping and _velocity.y < 0.0;
_get_direction()
_check_dash()
if Input.is_action_just_pressed("attack") and abilities.attack:
_attack()
else:
_direction = Vector2.ZERO
func _update_state(new_state:int = -1):
var auto_update = new_state == -1;
if new_state == -1:
new_state = _state
if _state == States.DASHING: return
if _state == States.ATTACKING: return
if _state == States.IDLE:
if _velocity.y > 0 and not is_on_floor():
# Falling from ground
new_state = States.IN_AIR
elif _state == States.IN_AIR:
if is_on_floor():
_on_landed()
new_state = States.IDLE
elif _velocity.y >=0 and is_on_wall():
if _state != States.WALL_SLIDING:
_velocity.y=0
new_state = States.WALL_SLIDING
elif _state == States.WALL_SLIDING:
if is_on_floor() or not is_on_wall():
new_state = States.IDLE
else: new_state = States.IDLE
_transition_state(_state, new_state, auto_update)
func _transition_state(old_state, new_state, auto_update):
if new_state != old_state:
print("[Player]: State Update: [%s] -> [%s] | Automatic: %s" % [old_state, new_state, auto_update])
_state = new_state
if old_state == States.IDLE:
# idle -> attak = ground attack - stop _velocity.x
if new_state == States.ATTACKING:
_direction.x = 0;
_velocity.x = 0;
if old_state == States.DASHING:
if new_state == States.IDLE:
_can_dash = true
if old_state == States.WALL_SLIDING:
if new_state == States.IDLE:
_on_landed()
func _on_landed():
_can_dash = true
var dust = LandingDust.instance()
dust.position = position
get_parent().add_child(dust)
emit_signal("landed", position)
func _on_jump(wall_jump:bool = false):
var dust:Node = JumpDust.instance()
dust.position = position;
get_parent().add_child(dust)
if wall_jump:
dust.position.x += 2 * -$Sprite.scale.x
dust.get_node("Sprite").rotate(deg2rad(90) * -$Sprite.scale.x)
emit_signal("jumping", position)
func _get_direction() -> void:
var right_strength = round(Input.get_action_strength("direction_right"))
var left_strength = round(Input.get_action_strength("direction_left"))
var vertical_movement = right_strength - left_strength if not _state == States.DASHING else 0
var is_in_jumpable_state = _state == States.IDLE or _state == States.WALL_SLIDING
_direction = Vector2(
vertical_movement,
-1.0 if Input.is_action_just_pressed("jump") and is_in_jumpable_state else 1.0
)
func _check_dash():
if Input.is_action_just_pressed("dash") and _can_dash and abilities.dash:
var dash_velocity := Vector2($Sprite.scale.x * dash_thrust,0)
_can_dash = false
_is_dashing = true # turn off gravity while dashing
# Wall dash first
if _is_wall_sliding:
if _state == States.WALL_SLIDING:
dash_velocity.x = $Sprite.scale.x * dash_thrust * -1
if dash_velocity.x < 0 :
$DashParticlesLeft.emitting = true;
else:
$DashParticlesRight.emitting = true
output = dash_velocity
_velocity = dash_velocity
$DashTimeout.start()
_update_state(States.DASHING) # turn off gravity while dashing
func calculate_move_velocity(direction:Vector2, is_jump_canceled:bool, delta:float)->Vector2:
var output: = _velocity
var current_gravity = gravity * wall_slide_friction if _state == States.WALL_SLIDING else gravity
output.x = lerp(_velocity.x, run_speed * direction.x, .1 if _state == States.IN_AIR else .5)
output.y += current_gravity * delta
if _state == States.DASHING:
return _velocity
if direction.y == -1.0: # we are jumping
var wall_jump := false
if _state == States.WALL_SLIDING and abilities.wall_jump:
# wall jump
wall_jump = true
var walljump__x_direction = -1 * direction.x
var desired = (run_speed * wall_jump_speed_factor.x * walljump__x_direction)
output.x = desired
output.y = jump_power * wall_jump_speed_factor.y * direction.y
else:
#jump
output.y = jump_power * direction.y
_update_state(States.IN_AIR)
_on_jump(wall_jump)
else:
if is_jump_canceled:
output.y = 0
if output.y < max_gravity * -1:
output.y = max_gravity
if _state == States.WALL_SLIDING and output.y > max_wall_slide_gravity:
output.y = max_wall_slide_gravity
return output;
@ -147,40 +207,45 @@ func _revive():
func update_sprite(_direction:Vector2) -> void:
var air_animation = "jump" if _velocity.y <= 0 else "fall"
if _is_attaking: return
if _state == States.ATTACKING: return
var attack = Input.is_action_just_pressed("attack") and abilities.attack
if _velocity.x > .5 and not _is_wall_sliding:
if _velocity.x > .5 and not _state == States.WALL_SLIDING:
$Sprite.scale = Vector2(1,1)
$AnimationPlayer.play("run" if is_on_floor() else air_animation)
elif _velocity.x < -.5 and not _is_wall_sliding:
elif _velocity.x < -.5 and not _state == States.WALL_SLIDING:
$Sprite.scale = Vector2(-1,1)
$AnimationPlayer.play("run" if is_on_floor() else air_animation)
else:
if not _in_air: $AnimationPlayer.play("idle")
if not _state == States.IN_AIR: $AnimationPlayer.play("idle")
if _is_wall_sliding:
if _state == States.WALL_SLIDING:
$AnimationPlayer.play("wall_slide")
return
if attack:
_is_attaking = true
AudioManager.play_sfx(AudioManager.Sfx.PLAYER_ATTACK)
var attack_animation = "attack_right" if $Sprite.scale.x > 0 else "attack_left"
$AnimationPlayer.play(attack_animation)
$AnimationPlayer.playback_speed = 2.5
$AnimationPlayer.seek(0)
yield($AnimationPlayer, "animation_finished")
$AnimationPlayer.playback_speed = 1
_is_attaking = false
return
if _in_air:
if _state == States.IN_AIR:
$AnimationPlayer.play(air_animation)
return
if _is_dashing:
if _state == States.DASHING:
$AnimationPlayer.play("jump")
return
func _attack():
if _state == States.DASHING:
var beam = LightBeam.instance()
beam.direction = Vector2($Sprite.scale.x, 0)
beam.position = $Sprite/LightBeamInitPoint.get_global_transform().get_origin()
get_parent().add_child(beam)
$DashTimeout.stop()
_on_DashTimeout_timeout(false)
_update_state(States.ATTACKING)
AudioManager.play_sfx(AudioManager.Sfx.PLAYER_ATTACK)
var attack_animation = "attack_right" if $Sprite.scale.x > 0 else "attack_left"
$AnimationPlayer.play(attack_animation)
$AnimationPlayer.playback_speed = 2.5
yield($AnimationPlayer, "animation_finished")
$AnimationPlayer.seek(0)
$AnimationPlayer.playback_speed = 1
_update_state(States.IDLE)
func _on_die_animation_done():
emit_signal("died")
@ -201,11 +266,12 @@ func setAbility(ability:String, enabled:bool=false):
else:
pass
func _on_DashTimeout_timeout() -> void:
func _on_DashTimeout_timeout(timed_out=true) -> void:
$AnimationPlayer.playback_speed = 1
$DashParticlesLeft.emitting = false
$DashParticlesRight.emitting = false
_velocity.x = run_speed * _velocity.normalized().x;
_is_dashing = false
if timed_out: _update_state(States.IN_AIR)
pass # Replace with function body.

View file

@ -836,6 +836,9 @@ collision_mask = 2
position = Vector2( 14, -6 )
shape = SubResource( 2 )
[node name="LightBeamInitPoint" type="Position2D" parent="Sprite"]
position = Vector2( 14, 2 )
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
autoplay = "idle"
anims/attack_left = SubResource( 3 )
@ -881,5 +884,15 @@ position = Vector2( 0, -8.04107 )
enabled = true
cast_to = Vector2( -5.2, 0 )
collision_mask = 8
[node name="Camera2D" type="Camera2D" parent="."]
current = true
limit_left = -45
limit_smoothed = true
drag_margin_h_enabled = true
drag_margin_v_enabled = true
smoothing_enabled = true
drag_margin_left = 0.09
drag_margin_right = 0.09
[connection signal="body_entered" from="Sprite/SordRange" to="." method="_on_SordRange_body_entered"]
[connection signal="timeout" from="DashTimeout" to="." method="_on_DashTimeout_timeout"]

View file

@ -0,0 +1,33 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://src/Actors/WiseOldDude/wize_old_dude.png" type="Texture" id=1]
[sub_resource type="Animation" id=1]
resource_name = "idle"
length = 0.8
loop = true
tracks/0/type = "value"
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.2, 0.4, 0.6, 0.8 ),
"transitions": PoolRealArray( 1, 1, 1, 1, 1 ),
"update": 1,
"values": [ 17, 18, 19, 20, 21 ]
}
[node name="WiseOldDude" type="Node2D"]
[node name="Sprite" type="Sprite" parent="."]
position = Vector2( 0, -16 )
texture = ExtResource( 1 )
vframes = 6
hframes = 9
frame = 18
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
autoplay = "idle"
anims/idle = SubResource( 1 )

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/wize_old_dude.png-2d29b22f4c54a0aed9056fec7199f29e.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://src/Actors/WiseOldDude/wize_old_dude.png"
dest_files=[ "res://.import/wize_old_dude.png-2d29b22f4c54a0aed9056fec7199f29e.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
src/Actors/ligt_beam.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/ligt_beam.png-10d3dd70473d3611e41e8dbba9e0477b.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://src/Actors/ligt_beam.png"
dest_files=[ "res://.import/ligt_beam.png-10d3dd70473d3611e41e8dbba9e0477b.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -0,0 +1,101 @@
extends CutScene
var _dialog_bubble = load("res://src/CutScenes/DialogBubble/DialogBubble.tscn")
var _old_man_dialog = [
{
"text": "Hi there young one!",
"callback": null
},
{
"text": "You do look stupid enough\nfor my challenge...",
"callback": null
},
{
"text": "You see that tree over there?",
"callback": null
},
]
var _old_man_dialog2 = [
{
"text": "Oh, yeah - not there...",
"callback": null
},
{
"text": "Forgive me, never thought you would really take a look",
"callback": null
},
{
"text": "Never mind Bro. See the path ahead? There is a tree in that cave.",
"callback": null
},
]
func start_scene(camera:Camera2D):
_main_camera_ref = camera
position = camera.get_global_transform().get_origin()
_camera = camera.duplicate()
add_child(_camera)
_main_camera_ref.current = false
_camera.current = true
$AnimationPlayer.play("start")
yield($AnimationPlayer, "animation_finished")
yield(get_tree().create_timer(.5), "timeout")
# Dialog 1
$AnimationPlayer.play("old_dude_slide_in")
yield($AnimationPlayer, "animation_finished")
var dialog_bubble:DialogBubble = _dialog_bubble.instance()
dialog_bubble.allow_fast_skip = bool(GameState.get_statistics().total_time_played)
dialog_bubble.dialog = _old_man_dialog
$Overlay.add_child(dialog_bubble)
dialog_bubble.start_dialog()
yield(dialog_bubble, "dialog_finished")
$AnimationPlayer.play("old_dude_slide_out")
yield($AnimationPlayer, "animation_finished")
# pan Camera
$Tween.interpolate_property(_camera, "position", _camera.position, Vector2( _camera.position.x - 400, _camera.position.y), 2)
$Tween.start()
yield($Tween, "tween_completed")
# wait a bit to get a "haha" timing
yield(get_tree().create_timer(2), "timeout")
#pan back
$Tween.interpolate_property(_camera, "position", _camera.position, _camera.get_parent().position, 2, Tween.TRANS_BOUNCE, Tween.EASE_OUT)
$Tween.start()
yield($Tween, "tween_completed")
camera.get_parent()._velocity.y = -100
# Dialog 2
$AnimationPlayer.play("old_dude_slide_in")
yield($AnimationPlayer, "animation_finished")
dialog_bubble = _dialog_bubble.instance()
dialog_bubble.dialog = _old_man_dialog2
$Overlay.add_child(dialog_bubble)
dialog_bubble.start_dialog()
yield(dialog_bubble, "dialog_finished")
$AnimationPlayer.play("old_dude_slide_out")
yield($AnimationPlayer, "animation_finished")
#
_on_scene_exited()
pass
func _on_scene_exited():
$Tween.interpolate_property(_camera, "position", _camera.position, _camera.get_parent().position, 2, Tween.TRANS_BOUNCE, Tween.EASE_OUT)
$Tween.start()
yield($Tween, "tween_completed")
_main_camera_ref.current = true
$AnimationPlayer.play_backwards("start")
yield($AnimationPlayer, "animation_finished")
end_scene()

View file

@ -0,0 +1,112 @@
[gd_scene load_steps=6 format=2]
[ext_resource path="res://src/CutScenes/ChallengeCutscene.gd" type="Script" id=1]
[ext_resource path="res://src/CutScenes/red-wizzard-large.png" type="Texture" id=2]
[sub_resource type="Animation" id=1]
resource_name = "old_dude_slide_in"
length = 0.5
tracks/0/type = "value"
tracks/0/path = NodePath("Overlay/FigureOldDude:offset")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.5 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Vector2( 900, 50 ), Vector2( 600, 50 ) ]
}
[sub_resource type="Animation" id=2]
resource_name = "old_dude_slide_out"
length = 0.5
tracks/0/type = "value"
tracks/0/path = NodePath("Overlay/FigureOldDude:offset")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.5 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Vector2( 600, 50 ), Vector2( 900, 50 ) ]
}
[sub_resource type="Animation" id=3]
length = 0.2
tracks/0/type = "value"
tracks/0/path = NodePath("Overlay/ColorRect2:rect_position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.2 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Vector2( 0, 270 ), Vector2( 0, 245 ) ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("Overlay/ColorRect:rect_position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0, 0.2 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Vector2( 0, -25 ), Vector2( 0, 0 ) ]
}
tracks/2/type = "value"
tracks/2/path = NodePath("Overlay/FigureOldDude:offset")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Vector2( 900, 50 ) ]
}
[node name="ChallengeCutscene" type="Node2D"]
script = ExtResource( 1 )
[node name="Overlay" type="CanvasLayer" parent="."]
layer = 2
[node name="FigureOldDude" type="Sprite" parent="Overlay"]
scale = Vector2( 0.533333, 0.533333 )
texture = ExtResource( 2 )
centered = false
offset = Vector2( 600, 50 )
flip_h = true
[node name="ColorRect" type="ColorRect" parent="Overlay"]
margin_top = -25.0
margin_right = 480.0
color = Color( 0, 0, 0, 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ColorRect2" type="ColorRect" parent="Overlay"]
margin_top = 270.0
margin_right = 480.0
margin_bottom = 295.0
color = Color( 0, 0, 0, 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
anims/old_dude_slide_in = SubResource( 1 )
anims/old_dude_slide_out = SubResource( 2 )
anims/start = SubResource( 3 )
[node name="Tween" type="Tween" parent="."]

View file

@ -0,0 +1,49 @@
extends Control
class_name DialogBubble
signal dialog_finished
var allow_fast_skip := false
var dialog = [] # Dictionary[] {text:string, callback:function}[]
var _position := 0
var _done := false
var _paused := false
var _started :=false
func resume_dialog():
_paused = false
func start_dialog():
$AnimationPlayer.play("slide_in")
yield($AnimationPlayer, "animation_finished")
_started = true
_show_text()
func _show_text():
if _position >= dialog.size():
# we are done
_done = true
dismiss()
return
var sentence = dialog[_position]
$NinePatchRect/Label.text = sentence.text
$AnimationPlayer.play("show_text")
yield($AnimationPlayer, "animation_finished")
if sentence.callback != null:
sentence.callback()
func _input(event: InputEvent) -> void:
if not _started: return
if Input.is_action_just_pressed("jump"):
if allow_fast_skip: dismiss()
else:
_position += 1
$AnimationPlayer.play_backwards("show_text")
yield($AnimationPlayer, "animation_finished")
_show_text()
func dismiss():
$AnimationPlayer.play_backwards("slide_in")
yield($AnimationPlayer, "animation_finished")
emit_signal("dialog_finished")
queue_free()

View file

@ -0,0 +1,107 @@
[gd_scene load_steps=7 format=2]
[ext_resource path="res://src/CutScenes/DialogBubble/DialogBubble.gd" type="Script" id=1]
[ext_resource path="res://src/CutScenes/DialogBubble/hud_stats_bg.png" type="Texture" id=2]
[ext_resource path="res://assets/Theme/slkscr.ttf" type="DynamicFontData" id=3]
[sub_resource type="DynamicFont" id=1]
size = 17
outline_size = 1
outline_color = Color( 0, 0, 0, 1 )
font_data = ExtResource( 3 )
[sub_resource type="Animation" id=2]
resource_name = "show_text"
length = 0.2
tracks/0/type = "value"
tracks/0/path = NodePath("NinePatchRect/Label:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.2 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 0 ), Color( 1, 1, 1, 1 ) ]
}
[sub_resource type="Animation" id=3]
length = 0.5
tracks/0/type = "value"
tracks/0/path = NodePath("NinePatchRect:margin_bottom")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.5 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ 135.0, -15.0 ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("NinePatchRect:margin_top")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0, 0.5 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ 300.0, 150.0 ]
}
tracks/2/type = "value"
tracks/2/path = NodePath("NinePatchRect/Label:modulate")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 0 ) ]
}
[node name="DialogBubble" type="Control"]
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="NinePatchRect" type="NinePatchRect" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 40.0
margin_top = 300.0
margin_right = -40.0
margin_bottom = 135.0
texture = ExtResource( 2 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="NinePatchRect"]
modulate = Color( 1, 1, 1, 0 )
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 20.0
margin_top = 20.0
margin_right = -20.0
margin_bottom = -20.0
custom_fonts/font = SubResource( 1 )
custom_colors/font_color = Color( 1, 1, 1, 0.890196 )
text = "Hello there young one!"
align = 1
autowrap = true
__meta__ = {
"_edit_use_anchors_": false
}
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
anims/show_text = SubResource( 2 )
anims/slide_in = SubResource( 3 )

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/hud_stats_bg.png-52f55fa7703387ba6f7baf17aea738e4.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://src/CutScenes/DialogBubble/hud_stats_bg.png"
dest_files=[ "res://.import/hud_stats_bg.png-52f55fa7703387ba6f7baf17aea738e4.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/red-wizzard-large.png-bc152bcfbf1b2206bc916eefc4b9a5e6.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://src/CutScenes/red-wizzard-large.png"
dest_files=[ "res://.import/red-wizzard-large.png-bc152bcfbf1b2206bc916eefc4b9a5e6.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -0,0 +1,27 @@
extends Node2D
var _Cutscenes = {
"old_man_intro": "res://src/CutScenes/ChallengeCutscene.tscn"
}
func _ready() -> void:
$Player/Camera2D.limit_bottom = 250
$Player/Camera2D.limit_left = -45
$Player/Camera2D.limit_right = 700
func _on_OldDudeIntroArea_body_entered(body: Node) -> void:
if body.name == 'Player':
AudioManager.play_music(AudioManager.Music.Abandon)
GameState.start_cutscene()
var scene = (load(_Cutscenes.old_man_intro)).instance()
add_child(scene)
scene.start_scene($Player/Camera2D)
yield(scene, "cutscene_finished")
GameState.end_cutscene()
pass # Replace with function body.

File diff suppressed because one or more lines are too long

View file

@ -16,18 +16,24 @@ func _physics_process(delta: float) -> void:
var fresh_data = GameState.get_run_data()
for key in fresh_data:
if not fresh_data[key] == _data_ref[key]:
print("[%s]: %s -> %s" % [str(key), str(_data_ref[key]), str(fresh_data[key])])
match(str(key)):
"coins":
$UI/CoinLabel.text = str(fresh_data.coins)
$UI/CoinLabel/AnimationPlayer.seek(0)
$UI/CoinLabel/AnimationPlayer.play("updated")
_play_update_label_animation($UI/CoinLabel/AnimationPlayer)
"deaths":
$UI/DeathsLabel.text = str(fresh_data.deaths)
_play_update_label_animation($UI/DeathsLabel/AnimationPlayer)
"time":
var time_remaining = (GameState.GAME_TIMEOUT_MIN * 60) - fresh_data.time
$UI/TimeLabel.text = Utils.parse_seconds_to_display_str(time_remaining)
pass
_data_ref = fresh_data
func _play_update_label_animation(player:AnimationPlayer):
player.seek(0)
player.play("updated")
func _handle_pause():
if Input.is_action_just_pressed("pause"):
if _paused:

View file

@ -1,10 +1,11 @@
[gd_scene load_steps=7 format=2]
[gd_scene load_steps=9 format=2]
[ext_resource path="res://src/HUD/HUD.gd" type="Script" id=1]
[ext_resource path="res://src/Menu/PauseMenu.tscn" type="PackedScene" id=2]
[ext_resource path="res://assets/Theme/Theme.tres" type="Theme" id=3]
[ext_resource path="res://assets/HUD/coins_hud.png" type="Texture" id=4]
[ext_resource path="res://assets/HUD/lifes_icon.png" type="Texture" id=5]
[ext_resource path="res://assets/HUD/time_hud.png" type="Texture" id=6]
[sub_resource type="Animation" id=1]
resource_name = "updated"
@ -22,6 +23,22 @@ tracks/0/keys = {
"values": [ Vector2( 2, 2 ), Vector2( 1, 1 ) ]
}
[sub_resource type="Animation" id=2]
resource_name = "updated"
length = 0.2
tracks/0/type = "value"
tracks/0/path = NodePath(".:rect_scale")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.2 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Vector2( 2, 2 ), Vector2( 1, 1 ) ]
}
[node name="HUD" type="CanvasLayer"]
script = ExtResource( 1 )
PauseMenu = ExtResource( 2 )
@ -35,10 +52,11 @@ __meta__ = {
[node name="Coin" type="TextureRect" parent="UI"]
margin_left = 18.0
margin_top = 13.0
margin_right = 27.0
margin_top = 8.0
margin_right = 32.0
margin_bottom = 22.0
texture = ExtResource( 4 )
expand = true
__meta__ = {
"_edit_use_anchors_": false
}
@ -58,18 +76,18 @@ __meta__ = {
anims/updated = SubResource( 1 )
[node name="Deaths" type="TextureRect" parent="UI"]
margin_left = 11.0
margin_top = 22.0
margin_right = 33.0
margin_bottom = 44.0
margin_left = 80.0
margin_top = 4.0
margin_right = 102.0
margin_bottom = 26.0
texture = ExtResource( 5 )
expand = true
[node name="DeathsLabel" type="Label" parent="UI"]
margin_left = 38.0
margin_top = 30.0
margin_right = 78.0
margin_bottom = 44.0
margin_left = 107.0
margin_top = 13.0
margin_right = 147.0
margin_bottom = 27.0
theme = ExtResource( 3 )
text = "0"
__meta__ = {
@ -77,3 +95,26 @@ __meta__ = {
}
[node name="AnimationPlayer" type="AnimationPlayer" parent="UI/DeathsLabel"]
anims/updated = SubResource( 2 )
[node name="Time" type="TextureRect" parent="UI"]
margin_left = 152.0
margin_top = 8.0
margin_right = 167.0
margin_bottom = 23.0
texture = ExtResource( 6 )
expand = true
__meta__ = {
"_edit_use_anchors_": false
}
[node name="TimeLabel" type="Label" parent="UI"]
margin_left = 174.0
margin_top = 13.0
margin_right = 214.0
margin_bottom = 27.0
theme = ExtResource( 3 )
text = "0"
__meta__ = {
"_edit_use_anchors_": false
}

View file

@ -8,27 +8,27 @@
[ext_resource path="res://src/Menu/MainMenu.gd" type="Script" id=6]
[ext_resource path="res://assets/Theme/menu_font.tres" type="DynamicFont" id=7]
[sub_resource type="Gradient" id=2]
[sub_resource type="Gradient" id=1]
colors = PoolColorArray( 0.996094, 0.996094, 0.996094, 1, 1, 1, 1, 0 )
[sub_resource type="GradientTexture" id=3]
gradient = SubResource( 2 )
[sub_resource type="GradientTexture" id=2]
gradient = SubResource( 1 )
[sub_resource type="Curve" id=7]
[sub_resource type="Curve" id=3]
min_value = -200.0
max_value = 200.0
_data = [ Vector2( 0, 7.83957 ), 0.0, 166.434, 0, 0, Vector2( 1, 44.2032 ), -4.82953, 0.0, 0, 0 ]
[sub_resource type="CurveTexture" id=8]
curve = SubResource( 7 )
[sub_resource type="CurveTexture" id=4]
curve = SubResource( 3 )
[sub_resource type="Curve" id=4]
[sub_resource type="Curve" id=5]
_data = [ Vector2( 0, 0.285227 ), 0.0, 0.0, 0, 0, Vector2( 1, 1 ), 0.0, 0.0, 0, 0 ]
[sub_resource type="CurveTexture" id=5]
curve = SubResource( 4 )
[sub_resource type="CurveTexture" id=6]
curve = SubResource( 5 )
[sub_resource type="ParticlesMaterial" id=6]
[sub_resource type="ParticlesMaterial" id=7]
emission_shape = 2
emission_box_extents = Vector3( 10, 1, 1 )
flag_disable_z = true
@ -39,14 +39,13 @@ initial_velocity = 20.0
initial_velocity_random = 0.7
orbit_velocity = 0.0
orbit_velocity_random = 0.0
linear_accel_curve = SubResource( 8 )
linear_accel_curve = SubResource( 4 )
scale = 3.0
scale_random = 1.0
scale_curve = SubResource( 5 )
color_ramp = SubResource( 3 )
scale_curve = SubResource( 6 )
color_ramp = SubResource( 2 )
[sub_resource type="Animation" id=1]
resource_name = "main"
[sub_resource type="Animation" id=8]
length = 6.0
loop = true
step = 1.0
@ -160,7 +159,7 @@ amount = 50
lifetime = 2.5
speed_scale = 0.4
explosiveness = 0.1
process_material = SubResource( 6 )
process_material = SubResource( 7 )
[node name="Sprite3" type="Sprite" parent="Node2D"]
light_mask = 4
@ -170,7 +169,7 @@ centered = false
[node name="AnimationPlayer" type="AnimationPlayer" parent="Node2D"]
autoplay = "main"
anims/main = SubResource( 1 )
anims/main = SubResource( 8 )
[node name="CanvasLayer" type="CanvasLayer" parent="."]

View file

@ -68,6 +68,7 @@ pause_mode = 2
script = ExtResource( 3 )
[node name="CanvasLayer" type="CanvasLayer" parent="."]
layer = 3
[node name="TextureRect" type="TextureRect" parent="CanvasLayer"]
self_modulate = Color( 1, 1, 1, 0 )

21
src/Scripts/CutScene.gd Normal file
View file

@ -0,0 +1,21 @@
extends Node2D
class_name CutScene
signal cutscene_finished
export var scene:PackedScene
var _main_camera_ref:Camera2D
var _camera:Camera2D
func start_scene(camera:Camera2D):
var scene_inst = scene.instance()
add_child(scene_inst)
scene_inst.connect("tree_exited", self, "_on_scene_exited")
pass
func end_scene():
emit_signal("cutscene_finished")
queue_free()

View file

@ -8,7 +8,7 @@ enum States{
GAME,
PUSE,
STATS,
CUT_SCENE,
CUTSCENE,
}
var _SAVE_FILE_PATH = "user://data"
# Change key in release
@ -16,9 +16,11 @@ var _ENCRYPTION_KEY = "fas3uyf076HJsiUDs24dfI9"
var _SCENES := {
States.MAIN_MENU: "res://src/Menu/MainMenu.tscn",
States.GAME: "res://src/Levels/LevelTemplate/LevelTemplate.tscn",
States.GAME: "res://src/GameWorld/GameWorld.tscn",
}
var GAME_TIMEOUT_MIN = 10
var _data := {
"statistics": {
"deaths": 0,
@ -51,6 +53,11 @@ var _state = States.INTRO
func _ready() -> void:
load_data()
print(get_statistics())
func _physics_process(delta: float) -> void:
if _state == States.GAME:
_run_data.time += delta
_data.statistics.total_time_played += delta
func load_data():
var data_file = File.new()
@ -77,13 +84,18 @@ func start_new_game():
_data.statistics.runs += 1
save_data()
get_tree().change_scene_to(load(_SCENES[_state]))
func start_cutscene():
_state = States.CUTSCENE
func end_cutscene():
_state = States.GAME
func get_heigh_score():
return _data.heigh_score.duplicate()
func get_statistics():
return _data.statistics.duplicate()
func get_run_data():
return _run_data.duplicate()
func get_state():
return int(_state)
func go_to_main_menu():
_state = States.MAIN_MENU
save_data()

13
src/Singletons/Utils.gd Normal file
View file

@ -0,0 +1,13 @@
extends Node
func parse_seconds_to_display_str(_seconds:float, show_hours:bool=false)->String:
var rounded_input = int(floor(_seconds))
var hours_in_seconds = 3600
var minute_in_seconds = 60
var hours = 0
var minutes_seconds_str = "%02d:%02d" % [(rounded_input / minute_in_seconds) % 60, rounded_input % 60]
if show_hours:
return "%02d:%s" % [floor(rounded_input / hours_in_seconds), minutes_seconds_str]
return minutes_seconds_str