feat: caterpillar sprite, vacuum sprite fix, level balance

This commit is contained in:
Jakob Feldmann 2023-10-03 19:21:59 +02:00
parent 5fe48cdf90
commit 522e472c4d
22 changed files with 633 additions and 650 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

After

Width:  |  Height:  |  Size: 604 B

View File

@ -9,11 +9,6 @@
config_version=4
_global_script_classes=[ {
"base": "AudioStreamPlayer",
"class": "ACVoiceBox",
"language": "GDScript",
"path": "res://addons/ACVoicebox/ACVoicebox.gd"
}, {
"base": "KinematicBody2D",
"class": "Actor",
"language": "GDScript",
@ -95,7 +90,6 @@ _global_script_classes=[ {
"path": "res://src/StateMachines/StateMachine.gd"
} ]
_global_script_class_icons={
"ACVoiceBox": "",
"Actor": "",
"AudibleButton": "",
"AudibleCheckbox": "",

View File

@ -20,14 +20,14 @@ var initial_velocity_dependence := 0.7
var floor_friction := base_floor_friction
# TODO Mixing Vectors and ints is questionable
var max_velocity := {
"walk": 120,
"run": 160,
"jump": Vector2(120, 420),
"fall": Vector2(120, 420),
"walljump": 200,
"idle": 12000,
"duck": 165,
"duck_walk": 165
"walk": 120,
"run": 160,
"jump": Vector2(120, 420),
"fall": Vector2(120, 420),
"walljump": 200,
"idle": 12000,
"duck": 165,
"duck_walk": 165
}
# x is applied directly to velocity and y is multiplied with acceleration
var duck_boost = Vector2(2, 0.75)
@ -37,15 +37,15 @@ var init_acceleration_force := {"": 0, "idle_walk": 4181, "idle_run": 5765, "wal
# Oriented around deltas of 0.0166666...s
# newtonmeters is the unit
var acceleration_force := {
"walk": Vector2(1800, 1300),
"fall": Vector2(1800, 1050),
"jump": Vector2(1800, 0),
"idle": Vector2(1800, 1233),
"duck": Vector2(500, 1300),
"duck_walk": Vector2(500, 1300),
"run": Vector2(2500, 1400),
"walljump": Vector2(600, 1050),
"air_strafe": Vector2(333, 2000)
"walk": Vector2(1800, 1300),
"fall": Vector2(1800, 1050),
"jump": Vector2(1800, 0),
"idle": Vector2(1800, 1300),
"duck": Vector2(500, 1300),
"duck_walk": Vector2(500, 1300),
"run": Vector2(2500, 1400),
"walljump": Vector2(600, 1050),
"air_strafe": Vector2(333, 2000)
}
var velocity := Vector2.ZERO
var max_air_strafe_charges := 0

View File

@ -28,489 +28,489 @@ var shielded = false
func execute_movement() -> void:
if level_state.is_dead:
return
var snap = Vector2.DOWN * 128
var center_floor_rot = 0
var floor_rot = 0
var onfloor = is_on_floor()
if level_state.is_dead:
return
var snap = Vector2.DOWN * 128
var center_floor_rot = 0
var floor_rot = 0
var onfloor = is_on_floor()
# get rotation of floor, compare collided floor with floor under center
if onfloor:
# TODO: Problem when correctly rotating?
center_floor_rot = $SlopeRaycast.get_collision_normal().rotated(PI / 2).angle()
floor_rot = get_floor_normal().rotated(PI / 2).angle()
if abs(center_floor_rot) > PI / 4 + 0.1:
center_floor_rot = floor_rot
# snap when on slopes
if (abs(floor_rot) > 0.1 || abs(center_floor_rot) > 0.1) && snap_possible:
velocity = move_and_slide_with_snap(velocity.rotated(floor_rot), snap, FLOOR_NORMAL, true)
# normal slide on flat floor
else:
velocity = move_and_slide(velocity.rotated(floor_rot), FLOOR_NORMAL)
rotation = 0
if (
$SlopeRaycastLeft.is_colliding()
&& $SlopeRaycastRight.is_colliding()
&& $SlopeRaycast.is_colliding()
):
rotation = calculate_slope_rotation(onfloor)
# rotate related to floor slope
# Convert velocity back to local space.
# TODO: Downward velocity should be increased by gravity
velocity = velocity.rotated(-floor_rot) if snap_possible else velocity
# get rotation of floor, compare collided floor with floor under center
if onfloor:
# TODO: Problem when correctly rotating?
center_floor_rot = $SlopeRaycast.get_collision_normal().rotated(PI / 2).angle()
floor_rot = get_floor_normal().rotated(PI / 2).angle()
if abs(center_floor_rot) > PI / 4 + 0.1:
center_floor_rot = floor_rot
# snap when on slopes
if (abs(floor_rot) > 0.1 || abs(center_floor_rot) > 0.1) && snap_possible:
velocity = move_and_slide_with_snap(velocity.rotated(floor_rot), snap, FLOOR_NORMAL, true)
# normal slide on flat floor
else:
velocity = move_and_slide(velocity.rotated(floor_rot), FLOOR_NORMAL)
rotation = 0
if (
$SlopeRaycastLeft.is_colliding()
&& $SlopeRaycastRight.is_colliding()
&& $SlopeRaycast.is_colliding()
):
rotation = calculate_slope_rotation(onfloor)
# rotate related to floor slope
# Convert velocity back to local space.
# TODO: Downward velocity should be increased by gravity
velocity = velocity.rotated(-floor_rot) if snap_possible else velocity
func calculate_duck_velocity(linear_velocity: Vector2, delta: float, direction: Vector2) -> Vector2:
var state = player_state_machine.state
var out_vel := linear_velocity
var velocity_direction = 1.0
if velocity.x < 0:
velocity_direction = -1.0
var state = player_state_machine.state
var out_vel := linear_velocity
var velocity_direction = 1.0
if velocity.x < 0:
velocity_direction = -1.0
# TODO Improve this to separate crawling(slow) and sliding
var deceleration_force = calculate_deceleration_force(_gravity, mass) * 0.333
# TODO Improve this to separate crawling(slow) and sliding
var deceleration_force = calculate_deceleration_force(_gravity, mass) * 0.333
# Slowing down movement when not controlling direction
if is_equal_approx(direction.x, 0):
# TODO Handle Deadzones
out_vel.x = PhysicsFunc.two_step_euler(
out_vel.x, deceleration_force * -1 * velocity_direction, mass, delta
)
if abs(out_vel.x) > abs(velocity.x):
out_vel.x = 0
else:
# Reversing movement
# When turning the opposite direction, friction is added to the opposite acceleration movement
var reverse_move = is_reversing_horizontal_movement(direction)
if reverse_move:
# TODO dont put constants in here
out_vel.x = PhysicsFunc.two_step_euler(
out_vel.x, deceleration_force * -3.42 * velocity_direction, mass, delta
)
# Normal movement
if abs(velocity.x) < max_velocity[state]:
out_vel.x = PhysicsFunc.two_step_euler(
out_vel.x, (acceleration_force[state].x) * direction.x, mass, delta
)
elif !reverse_move:
out_vel.x = max_velocity[state] * direction.x
# TODO is_on_dropThrough does the action, is that ok? yEs, MaAsTeR-ChAn
# TODO Drop Through coyote time?
if Input.is_action_just_pressed("jump") && is_on_dropThrough():
return Vector2(out_vel.x, _gravity * delta)
# Jumping when grounded or jump is buffered
if Input.is_action_just_pressed("jump") || (jump_buffer_filled && is_on_floor()) || stomping:
snap_possible = false
return calculate_jump_velocity(velocity, delta, direction)
# Slowing down movement when not controlling direction
if is_equal_approx(direction.x, 0):
# TODO Handle Deadzones
out_vel.x = PhysicsFunc.two_step_euler(
out_vel.x, deceleration_force * -1 * velocity_direction, mass, delta
)
if abs(out_vel.x) > abs(velocity.x):
out_vel.x = 0
else:
# Reversing movement
# When turning the opposite direction, friction is added to the opposite acceleration movement
var reverse_move = is_reversing_horizontal_movement(direction)
if reverse_move:
# TODO dont put constants in here
out_vel.x = PhysicsFunc.two_step_euler(
out_vel.x, deceleration_force * -3.42 * velocity_direction, mass, delta
)
# Normal movement
if abs(velocity.x) < max_velocity[state]:
out_vel.x = PhysicsFunc.two_step_euler(
out_vel.x, (acceleration_force[state].x) * direction.x, mass, delta
)
elif !reverse_move:
out_vel.x = max_velocity[state] * direction.x
# TODO is_on_dropThrough does the action, is that ok? yEs, MaAsTeR-ChAn
# TODO Drop Through coyote time?
if Input.is_action_just_pressed("jump") && is_on_dropThrough():
return Vector2(out_vel.x, _gravity * delta)
# Jumping when grounded or jump is buffered
if Input.is_action_just_pressed("jump") || (jump_buffer_filled && is_on_floor()) || stomping:
snap_possible = false
return calculate_jump_velocity(velocity, delta, direction)
elif player_state_machine.coyote_hanging:
out_vel.y = 0
elif player_state_machine.coyote_hanging:
out_vel.y = 0
else:
out_vel.y = _gravity * delta
else:
out_vel.y = _gravity * delta
return out_vel
return out_vel
func is_on_dropThrough():
var bodies: Array = $BlobbySkin.get_overlapping_bodies()
for i in range(0, bodies.size()):
if bodies[i].get_collision_mask_bit(7):
set_collision_mask_bit(7, false)
return true
return false
var bodies: Array = $BlobbySkin.get_overlapping_bodies()
for i in range(0, bodies.size()):
if bodies[i].get_collision_mask_bit(7):
set_collision_mask_bit(7, false)
return true
return false
func calculate_grounded_velocity(
linear_velocity: Vector2, delta: float, direction: Vector2
linear_velocity: Vector2, delta: float, direction: Vector2
) -> Vector2:
var state = player_state_machine.state
var out_vel := linear_velocity
var velocity_direction = 1.0
if velocity.x < 0:
velocity_direction = -1.0
var state = player_state_machine.state
var out_vel := linear_velocity
var velocity_direction = 1.0
if velocity.x < 0:
velocity_direction = -1.0
var deceleration_force = calculate_deceleration_force(_gravity, mass)
var deceleration_force = calculate_deceleration_force(_gravity, mass)
# Slowing down movement when not controlling direction
if is_equal_approx(direction.x, 0):
# TODO Handle Deadzones
out_vel.x = PhysicsFunc.two_step_euler(
out_vel.x, deceleration_force * -1 * velocity_direction, mass, delta
)
if abs(out_vel.x) > abs(velocity.x):
out_vel.x = 0
else:
# Reversing movement
# When turning the opposite direction, friction is added to the opposite acceleration movement
var reverse_move = is_reversing_horizontal_movement(direction)
if reverse_move:
# TODO dont put constants in here
out_vel.x = PhysicsFunc.two_step_euler(
out_vel.x, deceleration_force * -3.42 * velocity_direction, mass, delta
)
# Normal movement
if abs(velocity.x) < max_velocity[state]:
out_vel.x = PhysicsFunc.two_step_euler(
out_vel.x,
(
(
acceleration_force[state].x
+ (init_acceleration_force[init_boost_type] * int(init_boost))
)
* direction.x
),
mass,
delta
)
elif !reverse_move:
out_vel.x = max_velocity[state] * direction.x
# Jumping when grounded or jump is buffered
if Input.is_action_just_pressed("jump") || (jump_buffer_filled && is_on_floor()) || stomping:
snap_possible = false
#velocity += get_floor_velocity() * 0.5
return calculate_jump_velocity(velocity, delta, direction)
# Slowing down movement when not controlling direction
if is_equal_approx(direction.x, 0):
# TODO Handle Deadzones
out_vel.x = PhysicsFunc.two_step_euler(
out_vel.x, deceleration_force * -1 * velocity_direction, mass, delta
)
if abs(out_vel.x) > abs(velocity.x):
out_vel.x = 0
else:
# Reversing movement
# When turning the opposite direction, friction is added to the opposite acceleration movement
var reverse_move = is_reversing_horizontal_movement(direction)
if reverse_move:
# TODO dont put constants in here
out_vel.x = PhysicsFunc.two_step_euler(
out_vel.x, deceleration_force * -3.42 * velocity_direction, mass, delta
)
# Normal movement
if abs(velocity.x) < max_velocity[state]:
out_vel.x = PhysicsFunc.two_step_euler(
out_vel.x,
(
(
acceleration_force[state].x
+ (init_acceleration_force[init_boost_type] * int(init_boost))
)
* direction.x
),
mass,
delta
)
elif !reverse_move:
out_vel.x = max_velocity[state] * direction.x
# Jumping when grounded or jump is buffered
if Input.is_action_just_pressed("jump") || (jump_buffer_filled && is_on_floor()) || stomping:
snap_possible = false
#velocity += get_floor_velocity() * 0.5
return calculate_jump_velocity(velocity, delta, direction)
elif player_state_machine.coyote_hanging:
out_vel.y = 0
elif player_state_machine.coyote_hanging:
out_vel.y = 0
else:
out_vel.y = _gravity * delta
else:
out_vel.y = _gravity * delta
return out_vel
return out_vel
# Determines if the player has reversed the steering direction
# in reference to the current movement direction
func is_reversing_horizontal_movement(direction: Vector2) -> bool:
return (direction.x > 0 && velocity.x < 0) || (direction.x < 0 && velocity.x > 0)
return (direction.x > 0 && velocity.x < 0) || (direction.x < 0 && velocity.x > 0)
# Returns if the character is touching a wall with its whole body
# Being able to touch a vertical surface over this length also makes it a qualified "wall"
# Also sets wall_touch_direction
func is_touching_wall_completely() -> bool:
var value = true
for left_raycast in left_wall_raycasts.get_children():
wall_touch_direction = -1
if !left_raycast.is_colliding():
value = false
continue
if value == true:
return value
var value = true
for left_raycast in left_wall_raycasts.get_children():
wall_touch_direction = -1
if !left_raycast.is_colliding():
value = false
continue
if value == true:
return value
value = true
for right_raycast in right_wall_raycasts.get_children():
wall_touch_direction = 1
if !right_raycast.is_colliding():
value = false
continue
return value
value = true
for right_raycast in right_wall_raycasts.get_children():
wall_touch_direction = 1
if !right_raycast.is_colliding():
value = false
continue
return value
func is_crushed() -> bool:
var touching_left = false
for left_raycast in left_wall_raycasts.get_children():
if left_raycast.is_colliding():
touching_left = true
var touching_right = false
for right_raycast in right_wall_raycasts.get_children():
if right_raycast.is_colliding():
touching_right = true
return touching_left && touching_right
var touching_left = false
for left_raycast in left_wall_raycasts.get_children():
if left_raycast.is_colliding():
touching_left = true
var touching_right = false
for right_raycast in right_wall_raycasts.get_children():
if right_raycast.is_colliding():
touching_right = true
return touching_left && touching_right
# Attached to wall state is in the PlayerStateMachine
func is_correct_walljump_input(direction: Vector2) -> bool:
if is_touching_wall_completely():
return (
Input.is_action_pressed("jump")
&& abs(direction.x + wall_touch_direction) < 1
&& abs(direction.x + wall_touch_direction) >= 0
)
return false
if is_touching_wall_completely():
return (
Input.is_action_pressed("jump")
&& abs(direction.x + wall_touch_direction) < 1
&& abs(direction.x + wall_touch_direction) >= 0
)
return false
func is_correct_airstrafe_input() -> bool:
return (
air_strafe_charges > 0
&& (Input.is_action_just_pressed("move_right") || Input.is_action_just_pressed("move_left"))
)
return (
air_strafe_charges > 0
&& (Input.is_action_just_pressed("move_right") || Input.is_action_just_pressed("move_left"))
)
# Calculates the force of the ground friction
func calculate_deceleration_force(_gravity: float, mass: float) -> float:
return floor_friction * _gravity * mass
return floor_friction * _gravity * mass
func calculate_stomp_velocity(delta: float) -> float:
var v = 0
if Input.is_action_pressed("jump"):
v += stomp_feedback
# print(stomp_time)
stomp_time -= delta
# print(stomp_time)
if stomp_time <= 0:
# print("stomping over")
stomping = false
stomp_time = init_stomp_time
return v
var v = 0
if Input.is_action_pressed("jump"):
v += stomp_feedback
# print(stomp_time)
stomp_time -= delta
# print(stomp_time)
if stomp_time <= 0:
# print("stomping over")
stomping = false
stomp_time = init_stomp_time
return v
func calculate_jump_velocity(linear_velocity: Vector2, delta: float, direction: Vector2) -> Vector2:
var state = player_state_machine.state
var additive_jump_force = velocity_jump_boost_ratio * abs(velocity.x) * mass
#TODO Single out stomping and make betta
#TODO too much force intially and too high with frog jump
if stomping:
additive_jump_force += calculate_stomp_velocity(delta)
var state = player_state_machine.state
var additive_jump_force = velocity_jump_boost_ratio * abs(velocity.x) * mass
#TODO Single out stomping and make betta
#TODO too much force intially and too high with frog jump
if stomping:
additive_jump_force += calculate_stomp_velocity(delta)
var y_acceleration_force = acceleration_force[state].y
var x_acceleration_force = acceleration_force[state].x
var y_acceleration_force = acceleration_force[state].y
var x_acceleration_force = acceleration_force[state].x
if duck_jumping:
y_acceleration_force *= duck_boost.y
linear_velocity.x += duck_boost.x * direction.x
if duck_jumping:
y_acceleration_force *= duck_boost.y
linear_velocity.x += duck_boost.x * direction.x
if state != "jump":
linear_velocity.y = PhysicsFunc.two_step_euler(
linear_velocity.y,
(y_acceleration_force / delta + additive_jump_force) * -1,
mass,
delta
)
if state != "jump":
linear_velocity.y = PhysicsFunc.two_step_euler(
linear_velocity.y,
(y_acceleration_force / delta + additive_jump_force) * -1,
mass,
delta
)
# print(acceleration_force[state].y)
# print(linear_velocity.y)
var y_velocity = 0
if !Input.is_action_pressed("jump") && !stomping:
# Smooth transition from jumping to falling
if velocity.y > _gravity * delta * 10:
y_velocity += _gravity * delta * 10
else:
y_velocity += (max(abs(linear_velocity.y), _gravity * delta) / 2)
var y_velocity = 0
if !Input.is_action_pressed("jump") && !stomping:
# Smooth transition from jumping to falling
if velocity.y > _gravity * delta * 10:
y_velocity += _gravity * delta * 10
else:
y_velocity += (max(abs(linear_velocity.y), _gravity * delta) / 2)
else:
y_velocity += _gravity * delta
#if linear_velocity.y < max_velocity["jump"].y:
linear_velocity.y += y_velocity
else:
y_velocity += _gravity * delta
#if linear_velocity.y < max_velocity["jump"].y:
linear_velocity.y += y_velocity
# TODO This is poop too
if (
-max_velocity["jump"].x < velocity.x and direction.x < 0
|| max_velocity["jump"].x > velocity.x and direction.x > 0
):
var absolut = 1 - initial_velocity_dependence
var divisor = 1 / max(0.1, initial_velocity_dependence)
var movement_factor = absolut + abs(velocity.x) / (max_velocity["fall"].x * divisor)
linear_velocity.x = PhysicsFunc.two_step_euler(
linear_velocity.x, x_acceleration_force * movement_factor * direction.x, mass, delta
)
# TODO This is poop too
if (
-max_velocity["jump"].x < velocity.x and direction.x < 0
|| max_velocity["jump"].x > velocity.x and direction.x > 0
):
var absolut = 1 - initial_velocity_dependence
var divisor = 1 / max(0.1, initial_velocity_dependence)
var movement_factor = absolut + abs(velocity.x) / (max_velocity["fall"].x * divisor)
linear_velocity.x = PhysicsFunc.two_step_euler(
linear_velocity.x, x_acceleration_force * movement_factor * direction.x, mass, delta
)
if is_correct_airstrafe_input():
linear_velocity = execute_airstrafe(linear_velocity, delta, direction)
if is_correct_airstrafe_input():
linear_velocity = execute_airstrafe(linear_velocity, delta, direction)
# print(linear_velocity.y)
return linear_velocity
return linear_velocity
# Only applicable to downwards gravity
# Can set the jump buffer
func calculate_fall_velocity(linear_velocity: Vector2, delta: float, direction: Vector2) -> Vector2:
var state = player_state_machine.state
if velocity.y < max_velocity["fall"].y:
linear_velocity.y = PhysicsFunc.two_step_euler(
linear_velocity.y, _gravity * mass, mass, delta
)
else:
linear_velocity.y = max_velocity["fall"].y
if (
-max_velocity["fall"].x < velocity.x and direction.x < 0
|| max_velocity["fall"].x > velocity.x and direction.x > 0
):
# TODO This is poop
var absolut = 1 - initial_velocity_dependence
var divisor = 1 / max(0.1, initial_velocity_dependence)
var movementFactor = absolut + abs(velocity.x) / (max_velocity["fall"].x * divisor)
linear_velocity.x = PhysicsFunc.two_step_euler(
linear_velocity.x,
acceleration_force[state].x * movementFactor * direction.x,
mass,
delta
)
if Input.is_action_just_pressed("jump"):
jump_buffer_filled = true
if is_correct_airstrafe_input():
linear_velocity = execute_airstrafe(linear_velocity, delta, direction)
if stomping:
linear_velocity = calculate_jump_velocity(Vector2(linear_velocity.x, 0), delta, direction)
return linear_velocity
var state = player_state_machine.state
if velocity.y < max_velocity["fall"].y:
linear_velocity.y = PhysicsFunc.two_step_euler(
linear_velocity.y, _gravity * mass, mass, delta
)
else:
linear_velocity.y = max_velocity["fall"].y
if (
-max_velocity["fall"].x < velocity.x and direction.x < 0
|| max_velocity["fall"].x > velocity.x and direction.x > 0
):
# TODO This is poop
var absolut = 1 - initial_velocity_dependence
var divisor = 1 / max(0.1, initial_velocity_dependence)
var movementFactor = absolut + abs(velocity.x) / (max_velocity["fall"].x * divisor)
linear_velocity.x = PhysicsFunc.two_step_euler(
linear_velocity.x,
acceleration_force[state].x * movementFactor * direction.x,
mass,
delta
)
if Input.is_action_just_pressed("jump"):
jump_buffer_filled = true
if is_correct_airstrafe_input():
linear_velocity = execute_airstrafe(linear_velocity, delta, direction)
if stomping:
linear_velocity = calculate_jump_velocity(Vector2(linear_velocity.x, 0), delta, direction)
return linear_velocity
func calculate_wallslide_velocity(
linear_velocity: Vector2, delta: float, direction: Vector2
linear_velocity: Vector2, delta: float, direction: Vector2
) -> Vector2:
# Walljump mechanics
if is_correct_walljump_input(direction):
linear_velocity.x = PhysicsFunc.two_step_euler(
0, acceleration_force["walljump"].x / delta * direction.x, mass, delta
)
linear_velocity.y = PhysicsFunc.two_step_euler(
0, acceleration_force["walljump"].y / delta * -1, mass, delta
)
elif is_correct_airstrafe_input():
# var rev = 1 if !is_reversing_horizontal_movement(direction) else -1
linear_velocity = execute_airstrafe(linear_velocity, delta, direction)
elif (
abs(direction.x + wall_touch_direction) < 1
&& abs(direction.x + wall_touch_direction) >= 0
):
var absolut = 1 - initial_velocity_dependence
var divisor = 1 / max(0.1, initial_velocity_dependence)
var movementFactor = absolut + abs(velocity.x) / (max_velocity["fall"].x * divisor)
linear_velocity.x = PhysicsFunc.two_step_euler(
linear_velocity.x,
acceleration_force["fall"].x * movementFactor * direction.x,
mass,
delta
)
else:
# TODO dont put constants in here
linear_velocity.y = PhysicsFunc.two_step_euler(
linear_velocity.y * 0.94, _gravity * mass, mass, delta
)
# TODO single out to function
air_strafe_charges = (
air_strafe_charges + 1
if max_air_strafe_charges > air_strafe_charges
else 0
)
return linear_velocity.rotated(rotation)
# Walljump mechanics
if is_correct_walljump_input(direction):
linear_velocity.x = PhysicsFunc.two_step_euler(
0, acceleration_force["walljump"].x / delta * direction.x, mass, delta
)
linear_velocity.y = PhysicsFunc.two_step_euler(
0, acceleration_force["walljump"].y / delta * -1, mass, delta
)
elif is_correct_airstrafe_input():
# var rev = 1 if !is_reversing_horizontal_movement(direction) else -1
linear_velocity = execute_airstrafe(linear_velocity, delta, direction)
elif (
abs(direction.x + wall_touch_direction) < 1
&& abs(direction.x + wall_touch_direction) >= 0
):
var absolut = 1 - initial_velocity_dependence
var divisor = 1 / max(0.1, initial_velocity_dependence)
var movementFactor = absolut + abs(velocity.x) / (max_velocity["fall"].x * divisor)
linear_velocity.x = PhysicsFunc.two_step_euler(
linear_velocity.x,
acceleration_force["fall"].x * movementFactor * direction.x,
mass,
delta
)
else:
# TODO dont put constants in here
linear_velocity.y = PhysicsFunc.two_step_euler(
linear_velocity.y * 0.94, _gravity * mass, mass, delta
)
# TODO single out to function
air_strafe_charges = (
air_strafe_charges + 1
if max_air_strafe_charges > air_strafe_charges
else 0
)
return linear_velocity.rotated(rotation)
func execute_airstrafe(linear_velocity: Vector2, delta: float, direction: Vector2) -> Vector2:
# var rev = 1 if !is_reversing_horizontal_movement(direction) else -1
# TODO Consider adding a extra state for airstrafing
# TODO Make airstrafing less instantaneous and moderate the impulse
if direction.x > 0:
effect_player.play("airstrafing")
else:
effect_player.play("airstrafingLeft")
if is_reversing_horizontal_movement(direction):
linear_velocity.x = 0
linear_velocity.x = PhysicsFunc.two_step_euler(
linear_velocity.x, acceleration_force["air_strafe"].x / delta * direction.x, mass, delta
)
if linear_velocity.y > 0:
# TODO Put constant elsewhere
linear_velocity.y = linear_velocity.y * 0.33
air_strafe_charges -= 1
return linear_velocity
# var rev = 1 if !is_reversing_horizontal_movement(direction) else -1
# TODO Consider adding a extra state for airstrafing
# TODO Make airstrafing less instantaneous and moderate the impulse
if direction.x > 0:
effect_player.play("airstrafing")
else:
effect_player.play("airstrafingLeft")
if is_reversing_horizontal_movement(direction):
linear_velocity.x = 0
linear_velocity.x = PhysicsFunc.two_step_euler(
linear_velocity.x, acceleration_force["air_strafe"].x / delta * direction.x, mass, delta
)
if linear_velocity.y > 0:
# TODO Put constant elsewhere
linear_velocity.y = linear_velocity.y * 0.33
air_strafe_charges -= 1
return linear_velocity
func calculate_slope_rotation(_onfloor: bool) -> float:
var angle = 0
var slope_angle_left = $SlopeRaycastLeft.get_collision_normal().rotated(PI / 2).angle()
var slope_angle_right = $SlopeRaycastRight.get_collision_normal().rotated(PI / 2).angle()
# avoid invalid angles and stay in rotation when touching ground completely
if (
!(-PI / 2 <= slope_angle_left && slope_angle_left <= PI / 2)
|| !(-PI / 2 <= slope_angle_right && slope_angle_right <= PI / 2)
|| (is_equal_approx(abs(slope_angle_left), abs(slope_angle_right)))
):
return (
previous_rotation
if abs(rad2deg(previous_rotation)) > 1 && !is_equal_approx(slope_angle_left, 0)
else 0.0
)
# downturn
if (
abs(slope_angle_left) > abs(slope_angle_right) && velocity.x < -10
|| abs(slope_angle_right) > abs(slope_angle_left) && velocity.x > 10
):
var length_vector: Vector2 = (
$SlopeRaycastRight.get_collision_point()
- $SlopeRaycastLeft.get_collision_point()
)
angle = length_vector.angle()
# upturn
else:
var length_vector: Vector2 = (
$SlopeRaycastLeft.get_collision_point()
- $SlopeRaycastRight.get_collision_point()
)
angle = length_vector.angle() - PI
previous_rotation = angle
if is_equal_approx(deg2rad(angle), 0):
pass
return angle
var angle = 0
var slope_angle_left = $SlopeRaycastLeft.get_collision_normal().rotated(PI / 2).angle()
var slope_angle_right = $SlopeRaycastRight.get_collision_normal().rotated(PI / 2).angle()
# avoid invalid angles and stay in rotation when touching ground completely
if (
!(-PI / 2 <= slope_angle_left && slope_angle_left <= PI / 2)
|| !(-PI / 2 <= slope_angle_right && slope_angle_right <= PI / 2)
|| (is_equal_approx(abs(slope_angle_left), abs(slope_angle_right)))
):
return (
previous_rotation
if abs(rad2deg(previous_rotation)) > 1 && !is_equal_approx(slope_angle_left, 0)
else 0.0
)
# downturn
if (
abs(slope_angle_left) > abs(slope_angle_right) && velocity.x < -10
|| abs(slope_angle_right) > abs(slope_angle_left) && velocity.x > 10
):
var length_vector: Vector2 = (
$SlopeRaycastRight.get_collision_point()
- $SlopeRaycastLeft.get_collision_point()
)
angle = length_vector.angle()
# upturn
else:
var length_vector: Vector2 = (
$SlopeRaycastLeft.get_collision_point()
- $SlopeRaycastRight.get_collision_point()
)
angle = length_vector.angle() - PI
previous_rotation = angle
if is_equal_approx(deg2rad(angle), 0):
pass
return angle
# TODO could be expanded with a parameter about what got stomped
func stomp() -> void:
#print("stomping")
#print(player_state_machine.state)
scene_audio.play_parallel_sound(
"res://assets/sounds/FABRIC_Flap_03_mono.wav", -15, false, 1.5, 0.2
)
scene_audio.play_parallel_sound("res://assets/sounds/CLASP_Plastic_Open_stereo.wav", -12)
stomping = true
#print("stomping")
#print(player_state_machine.state)
scene_audio.play_parallel_sound(
"res://assets/sounds/FABRIC_Flap_03_mono.wav", -15, false, 1.5, 0.2
)
scene_audio.play_parallel_sound("res://assets/sounds/CLASP_Plastic_Open_stereo.wav", -12)
stomping = true
# TOD lose_power_up function
func receive_power_up(kind: String) -> void:
if kind == "shield":
$BubbleShieldViewport/IridescenceBall.visible = true
shielded = true
if kind == "shield":
$BubbleShieldViewport/IridescenceBall.visible = true
shielded = true
# TODO Maybe this should be a state in itself?
func die(animation_number: int = 0) -> void:
if level_state.is_dead:
return
if shielded:
shielded = false
$BubbleShieldViewport/IridescenceBall.visible = false
$InvincibilityTimer.start()
$BlobbySprite.material = invincible_shader
return
elif !$InvincibilityTimer.is_stopped():
return
z_index = 1
$BlobbySprite.material = death_shader
signal_manager.emit_signal("player_died", animation_number)
$"%BlobbymationTree".active = false
$"%BlobbymationPlayer".play("dying3")
if animation_number == 0:
$"%BlobbymationPlayer".play("expandingDisolve")
if animation_number == -1:
respawn()
return
scene_audio.play_parallel_sound(death_sound_1, -15)
scene_audio.play_parallel_sound(death_sound_2, -16)
if level_state.is_dead:
return
if shielded:
shielded = false
$BubbleShieldViewport/IridescenceBall.visible = false
$InvincibilityTimer.start()
$BlobbySprite.material = invincible_shader
return
elif !$InvincibilityTimer.is_stopped():
return
z_index = 1
$BlobbySprite.material = death_shader
signal_manager.emit_signal("player_died", animation_number)
$"%BlobbymationTree".active = false
$"%BlobbymationPlayer".play("dying3")
if animation_number == 0:
$"%BlobbymationPlayer".play("expandingDisolve")
if animation_number == -1:
respawn()
return
scene_audio.play_parallel_sound(death_sound_1, -15)
scene_audio.play_parallel_sound(death_sound_2, -16)
func die_for_real(animation_number: int = 0) -> void:
shielded = false
$BubbleShieldViewport/IridescenceBall.visible = false
die(animation_number)
shielded = false
$BubbleShieldViewport/IridescenceBall.visible = false
die(animation_number)
# TODO Checkpoint system
func respawn() -> void:
# Is tied to the death animation
get_tree().reload_current_scene()
# Is tied to the death animation
get_tree().reload_current_scene()
# When the Enemy stomp AREA enters the enemy collision area -> stomp
func _on_BlobbySkin_area_entered(area: Area2D) -> void:
if area.is_in_group("harmful"):
die()
if area.is_in_group("pit"):
#scene_audio.play_parallel_sound(death_sound_1, -15)
scene_audio.play_parallel_sound(death_sound_2, -16)
$PitfallTimer.start()
if area.is_in_group("harmful"):
die()
if area.is_in_group("pit"):
#scene_audio.play_parallel_sound(death_sound_1, -15)
scene_audio.play_parallel_sound(death_sound_2, -16)
$PitfallTimer.start()
# This problem stems from trying to decelerate a walk
@ -518,54 +518,54 @@ func _on_BlobbySkin_area_entered(area: Area2D) -> void:
# It is particularly usefull for moving floor physics
# TODO Setting y velocity this way stopped is_on_floor() from working correctly
func _on_Blobby_got_grounded() -> void:
velocity.x -= get_floor_velocity().x
snap_possible = true
var floor_object = get_last_slide_collision().collider.get_parent()
#TODO There is already a friction property in engine
if "slide_friction" in floor_object:
floor_friction = floor_object.slide_friction
else:
floor_friction = base_floor_friction
air_strafe_charges = (
air_strafe_charges + 1
if max_air_strafe_charges > air_strafe_charges
else 0
)
velocity.x -= get_floor_velocity().x
snap_possible = true
var floor_object = get_last_slide_collision().collider.get_parent()
#TODO There is already a friction property in engine
if "slide_friction" in floor_object:
floor_friction = floor_object.slide_friction
else:
floor_friction = base_floor_friction
air_strafe_charges = (
air_strafe_charges + 1
if max_air_strafe_charges > air_strafe_charges
else 0
)
func _on_BlobbySkin_body_exited(body: Node) -> void:
# This is for drop through platforms
if body.get_collision_mask_bit(7):
set_collision_mask_bit(7, true)
# This is for drop through platforms
if body.get_collision_mask_bit(7):
set_collision_mask_bit(7, true)
func _on_InvincibilityTimer_timeout() -> void:
$BlobbySprite.material = null
for area in $BlobbySkin.get_overlapping_areas():
if area.is_in_group("harmful"):
die()
$BlobbySprite.material = null
for area in $BlobbySkin.get_overlapping_areas():
if area.is_in_group("harmful"):
die()
func _on_CrushTimer_timeout() -> void:
if is_crushed():
die_for_real()
if is_crushed():
die_for_real()
func handle_grounded_movement(delta: float, direction: Vector2) -> Vector2:
return calculate_grounded_velocity(velocity, delta, direction)
return calculate_grounded_velocity(velocity, delta, direction)
func handle_jump_movement(delta: float, direction: Vector2) -> Vector2:
return calculate_jump_velocity(velocity, delta, direction)
return calculate_jump_velocity(velocity, delta, direction)
func handle_duck_movement(delta: float, direction: Vector2) -> Vector2:
return calculate_duck_velocity(velocity, delta, direction)
return calculate_duck_velocity(velocity, delta, direction)
func handle_fall_movement(delta: float, direction: Vector2) -> Vector2:
return calculate_fall_velocity(velocity, delta, direction)
return calculate_fall_velocity(velocity, delta, direction)
func handle_wallslide_movement(delta: float, direction: Vector2) -> Vector2:
return calculate_wallslide_velocity(velocity, delta, direction)
return calculate_wallslide_velocity(velocity, delta, direction)

View File

@ -10,33 +10,33 @@ export(String, FILE, "*.tscn") var next_scene
export(bool) var is_active
func _ready() -> void:
if(!is_active):
monitoring = false
signal_manager.connect("terminal_activated", self, "activate_portal")
else:
$portal.frame = 0
if(!is_active):
monitoring = false
signal_manager.connect("terminal_activated", self, "activate_portal")
else:
$portal.frame = 0
func _get_configuration_warning() -> String:
return "The next scene property can't be empty" if not next_scene else ""
return "The next scene property can't be empty" if not next_scene else ""
func level_completion() -> void:
GlobalState.remove_savepoint(levelName)
signal_manager.emit_signal("level_completed")
GlobalState.remove_savepoint(levelName)
signal_manager.emit_signal("level_completed")
func activate_portal(_time: float) -> void:
$AnimationPlayer.play("activatePortal")
monitoring = true
$AnimationPlayer.play("activatePortal")
monitoring = true
func teleport() -> void:
GlobalAudio.play_scene_independent("res://assets/sounds/MAGIC_SPELL_Morphing_Synth_Harp_Scales_stereo.wav", "Music", -15)
get_tree().paused = true
anim_player.play("fade_in")
# TODO This doesn't pause the game but should
yield(anim_player, "animation_finished")
if ResourceLoader.exists(next_scene):
get_tree().change_scene(next_scene)
GlobalAudio.play_scene_independent("res://assets/sounds/MAGIC_SPELL_Morphing_Synth_Harp_Scales_stereo.wav", "Music", -15)
get_tree().paused = true
anim_player.play("fade_in")
# TODO This doesn't pause the game but should
yield(anim_player, "animation_finished")
if ResourceLoader.exists(next_scene):
get_tree().change_scene(next_scene)
func _on_body_entered(_body: Node) -> void:
level_completion()
teleport()
level_completion()
teleport()

View File

@ -57,7 +57,6 @@
[ext_resource path="res://assets/environment/decor/longductor/Longductor9.png" type="Texture" id=55]
[ext_resource path="res://assets/environment/decor/screen/Screen1.png" type="Texture" id=56]
[ext_resource path="res://assets/environment/decor/Ceiling-Struct.png" type="Texture" id=57]
[ext_resource path="res://addons/ACVoicebox/ACVoicebox.tscn" type="PackedScene" id=58]
[sub_resource type="Shader" id=15]
code = "shader_type canvas_item;
@ -1078,10 +1077,6 @@ __meta__ = {
"_edit_vertical_guides_": [ 2880.0 ]
}
[node name="ACVoicebox" parent="." instance=ExtResource( 58 )]
volume_db = -23.016
base_pitch = 2.5
[node name="SceneAudio" parent="." instance=ExtResource( 14 )]
visible = false

View File

@ -235,10 +235,6 @@ visible = false
unique_name_in_owner = true
position = Vector2( -180, 113 )
scale = Vector2( 0.878906, 0.936025 )
mass = null
jump_buffer_filled = null
death_sound_1 = null
death_sound_2 = null
[node name="BlobbySprite" parent="Blobby" index="5"]
frame = 7

View File

@ -124,13 +124,9 @@ drag_margin_bottom = 0.3
unique_name_in_owner = true
position = Vector2( -70, 1 )
scale = Vector2( 0.878906, 0.936025 )
mass = null
jump_buffer_filled = null
death_sound_1 = null
death_sound_2 = null
[node name="BlobbySprite" parent="Blobby" index="5"]
frame = 9
frame = 8
[node name="BlobbymationTree" parent="Blobby/BlobbySprite" index="0"]
parameters/playback = SubResource( 6 )

View File

@ -131,6 +131,9 @@ unique_name_in_owner = true
position = Vector2( -64, -1.90735e-06 )
scale = Vector2( 0.878906, 0.936025 )
[node name="BlobbySprite" parent="Blobby" index="5"]
frame = 10
[node name="BlobbymationTree" parent="Blobby/BlobbySprite" index="0"]
parameters/playback = SubResource( 6 )

View File

@ -1010,7 +1010,7 @@ position = Vector2( -88, 96 )
scale = Vector2( 0.878906, 0.936025 )
[node name="BlobbySprite" parent="Blobby" index="5"]
frame = 8
frame = 7
[node name="BlobbymationTree" parent="Blobby/BlobbySprite" index="0"]
parameters/playback = SubResource( 6 )

View File

@ -119,7 +119,7 @@ position = Vector2( -183, 111 )
scale = Vector2( 0.878906, 0.936025 )
[node name="BlobbySprite" parent="Blobby" index="5"]
frame = 7
frame = 6
[node name="BlobbymationTree" parent="Blobby/BlobbySprite" index="0"]
parameters/playback = SubResource( 6 )
@ -185,7 +185,7 @@ position = Vector2( -112, -748 )
rotation = -3.14159
[node name="FlyingLaserCutter7" parent="." instance=ExtResource( 13 )]
position = Vector2( -58, -808 )
position = Vector2( -48, -799 )
rotation = -3.14159
[node name="FlyingLaserCutter8" parent="." instance=ExtResource( 13 )]

View File

@ -194,7 +194,7 @@ position = Vector2( -45, -5.96046e-08 )
scale = Vector2( 0.878906, 0.936025 )
[node name="BlobbySprite" parent="Blobby" index="5"]
frame = 8
frame = 5
[node name="BlobbymationTree" parent="Blobby/BlobbySprite" index="0"]
parameters/playback = SubResource( 6 )

View File

@ -11,19 +11,19 @@ onready var level_state := $"%LevelState"
func _ready() -> void:
$TransitionLayer.visible = true
var transition_tween = Tween.new()
add_child(transition_tween)
var property = "shader_param/position"
var node = $TransitionLayer/SceneTransition
transition_tween.interpolate_property(node.material, property,-1.5, 1.0, 0.94, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
transition_tween.start()
# should spawn the tutorial thingies which are still remembered in the progress dictionary
signal_manager.connect("terminal_activated", self, "stop_level_music")
signal_manager.emit_signal("level_loaded")
get_tree().paused = false
$SceneAudio.play_parallel_sound(level_music, level_music_attenuation, false, 1.0, 0, "Music")
$SceneAudio.play_parallel_sound(level_ambiance, level_ambiance_attenuation)
$TransitionLayer.visible = true
var transition_tween = Tween.new()
add_child(transition_tween)
var property = "shader_param/position"
var node = $TransitionLayer/SceneTransition
transition_tween.interpolate_property(node.material, property,-1.5, 1.0, 0.94, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
transition_tween.start()
# should spawn the tutorial thingies which are still remembered in the progress dictionary
signal_manager.connect("terminal_activated", self, "stop_level_music")
signal_manager.emit_signal("level_loaded")
get_tree().paused = false
$SceneAudio.play_parallel_sound(level_music, level_music_attenuation, false, 1.0, 0, "Music")
$SceneAudio.play_parallel_sound(level_ambiance, level_ambiance_attenuation)
func stop_level_music(_unused: float) -> void:
$SceneAudio.stop_parallel_sound(level_music)
$SceneAudio.stop_parallel_sound(level_music)

View File

@ -41,7 +41,7 @@ resource_name = "LowPassFilter"
cutoff_hz = 3000.0
[resource]
bus/0/volume_db = inf_neg
bus/0/volume_db = -20.0
bus/1/name = "Music"
bus/1/solo = false
bus/1/mute = false

View File

@ -11,58 +11,58 @@ var paused := false setget set_paused
var block_ui_cancel = false
func _ready():
#signal_manager.connect("player_died", self, "_on_GlobalState_player_died")
$ControlsMenu.visible = false
$ControlsMenu.set_process_input(false)
$AudioMenu.set_process_input(false)
signal_manager.connect("game_paused", self, "set_paused")
pass
#signal_manager.connect("player_died", self, "_on_GlobalState_player_died")
$ControlsMenu.visible = false
$ControlsMenu.set_process_input(false)
$AudioMenu.set_process_input(false)
signal_manager.connect("game_paused", self, "set_paused")
pass
func open_audio_menu():
block_ui_cancel = true
pause_overlay.visible = false
$AudioMenu.visible = true
$AudioMenu.set_process_input(true)
$"%MasterSlider".grab_focus()
block_ui_cancel = true
pause_overlay.visible = false
$AudioMenu.visible = true
$AudioMenu.set_process_input(true)
$"%MasterSlider".grab_focus()
func close_audio_menu():
$AudioMenu.visible = false
pause_overlay.visible = true
$AudioMenu.set_process_input(false)
$"%Continue".grab_focus()
get_tree().set_input_as_handled()
$AudioMenu.visible = false
pause_overlay.visible = true
$AudioMenu.set_process_input(false)
$"%Continue".grab_focus()
get_tree().set_input_as_handled()
func _on_GlobalState_player_died() -> void:
self.paused = true
pause_title.text = "You lost"
self.paused = true
pause_title.text = "You lost"
func _input(event: InputEvent) -> void:
if !event.is_action("pause"):
return
if block_ui_cancel || $"%ControlsMenu".visible:
block_ui_cancel = false
get_tree().set_input_as_handled()
return
#not oder ! schaltet einen boolean um
#Ist self hier notwendig?
self.paused = not paused
block_ui_cancel = true
if !event.is_action("pause"):
return
if block_ui_cancel || $"%ControlsMenu".visible:
block_ui_cancel = false
get_tree().set_input_as_handled()
return
#not oder ! schaltet einen boolean um
#Ist self hier notwendig?
self.paused = not paused
block_ui_cancel = true
func set_paused(value: bool) -> void:
paused = value
get_tree().paused = value
pause_overlay.visible = value
if value == true:
$"%Continue".grab_focus()
paused = value
get_tree().paused = value
pause_overlay.visible = value
if value == true:
$"%Continue".grab_focus()
func _on_Controls_button_up() -> void:
$ControlsMenu.visible = true
$ControlsMenu.set_process_input(true)
block_ui_cancel = true
pause_overlay.visible = false
$"%ProfilesMenu".grab_focus()
$ControlsMenu.visible = true
$ControlsMenu.set_process_input(true)
block_ui_cancel = true
pause_overlay.visible = false
$"%ProfilesMenu".grab_focus()

View File

@ -2,5 +2,5 @@ extends Control
func _ready() -> void:
$"%PlayButton".grab_focus()
GlobalAudio.play_scene_independent("res://assets/music/Shopping For The Future (LOOP).wav","Music", -17, true)
$"%PlayButton".grab_focus()
GlobalAudio.play_scene_independent("res://assets/music/Shopping For The Future (LOOP).wav","Music", -17, true)

View File

@ -225,8 +225,7 @@ scroll_horizontal_enabled = false
script = ExtResource( 11 )
[node name="VBoxContainer" type="VBoxContainer" parent="MenuContainer/Panel/LevelList"]
margin_right = 123.0
margin_bottom = 102.0
margin_right = 119.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3

View File

@ -11,105 +11,105 @@ var freed_frogs := []
var is_dead: = false setget set_dead
func _ready() -> void:
GlobalState.gsr.last_played_level = levelName
SaveManager.save_default()
signal_manager.connect("level_completed", self, "_on_level_completed")
signal_manager.connect("player_died", self, "player_dying")
GlobalState.gsr.last_played_level = levelName
SaveManager.save_default()
signal_manager.connect("level_completed", self, "_on_level_completed")
signal_manager.connect("player_died", self, "player_dying")
func reset() -> void:
deaths = 0
currency = 0
freed_frogs = []
# TODO Maybe not the place for this?
if GlobalState.gsr.progress_dict.has(levelName):
GlobalState.gsr.progress_dict[levelName].erase("savepoint")
deaths = 0
currency = 0
freed_frogs = []
# TODO Maybe not the place for this?
if GlobalState.gsr.progress_dict.has(levelName):
GlobalState.gsr.progress_dict[levelName].erase("savepoint")
func set_currency(value: int) -> void:
currency = value
signal_manager.emit_signal("currency_updated")
currency = value
signal_manager.emit_signal("currency_updated")
func set_deaths(value: int) -> void:
deaths = value
deaths = value
func set_dead(value: bool) -> void:
is_dead = value
is_dead = value
func register_frog(number: int, freed: bool = false) -> void:
update_global_state()
if(!GlobalState.gsr.progress_dict[levelName]["froggies"].has(number)):
GlobalState.gsr.progress_dict[levelName]["froggies"][number] = freed
GlobalState.save()
update_global_state()
if(!GlobalState.gsr.progress_dict[levelName]["froggies"].has(number)):
GlobalState.gsr.progress_dict[levelName]["froggies"][number] = freed
GlobalState.save()
func free_a_frog(number: int) -> void:
freed_frogs.append(number)
freed_frogs.append(number)
func needs_tutorial(lesson: String) -> bool:
if(!GlobalState.gsr.tutorial_prompts.has(lesson)):
return false
return GlobalState.gsr.tutorial_prompts[lesson]
if(!GlobalState.gsr.tutorial_prompts.has(lesson)):
return false
return GlobalState.gsr.tutorial_prompts[lesson]
func register_tutorial(lesson: String) -> void:
if(GlobalState.gsr.tutorial_prompts.has(lesson)):
return
GlobalState.gsr.tutorial_prompts[lesson] = true
GlobalState.save()
if(GlobalState.gsr.tutorial_prompts.has(lesson)):
return
GlobalState.gsr.tutorial_prompts[lesson] = true
GlobalState.save()
func absolved_tutorial(lesson: String) -> void:
if(!GlobalState.gsr.tutorial_prompts.has(lesson)):
return
GlobalState.gsr.tutorial_prompts[lesson] = false
GlobalState.save()
if(!GlobalState.gsr.tutorial_prompts.has(lesson)):
return
GlobalState.gsr.tutorial_prompts[lesson] = false
GlobalState.save()
# Spends the currency when enough is available
# and returns true if so. Else it does not spend and return false.
func spend_currency(cost: int) -> bool:
# TODO member that
if(OS.is_debug_build()):
return true
if GlobalState.gsr.wallet + currency < cost:
return false
var remainder = currency - cost
if remainder >= 0:
currency = remainder
else:
currency = 0
GlobalState.set_wallet(GlobalState.gsr.wallet + remainder)
return true
# TODO member that
if(OS.is_debug_build()):
return true
if GlobalState.gsr.wallet + currency < cost:
return false
var remainder = currency - cost
if remainder >= 0:
currency = remainder
else:
currency = 0
GlobalState.set_wallet(GlobalState.gsr.wallet + remainder)
return true
func _on_level_completed():
#if(OS.is_debug_build()):
# return
update_global_state()
reset()
#if(OS.is_debug_build()):
# return
update_global_state()
reset()
func update_global_state() -> void:
var progress_dict : Dictionary = GlobalState.get_progress()
var levelProgress : Dictionary = {}
var progress_dict : Dictionary = GlobalState.get_progress()
var levelProgress : Dictionary = {}
levelProgress["currency"] = currency
levelProgress["deaths"] = deaths
# TODO Doesnt account for multiple plays of same level
if !progress_dict.has(levelName):
progress_dict[levelName] = levelProgress
else:
progress_dict[levelName]["currency"] = GlobalState.get_property_value(levelName,"currency") + currency
progress_dict[levelName]["deaths"] = GlobalState.get_property_value(levelName,"deaths") + deaths
if !progress_dict[levelName].has("froggies"):
progress_dict[levelName]["froggies"] = {}
else:
for frog_number in freed_frogs:
if progress_dict[levelName]["froggies"].has(frog_number):
progress_dict[levelName]["froggies"][frog_number] = true
levelProgress["currency"] = currency
levelProgress["deaths"] = deaths
# TODO Doesnt account for multiple plays of same level
if !progress_dict.has(levelName):
progress_dict[levelName] = levelProgress
else:
progress_dict[levelName]["currency"] = GlobalState.get_property_value(levelName,"currency") + currency
progress_dict[levelName]["deaths"] = GlobalState.get_property_value(levelName,"deaths") + deaths
if !progress_dict[levelName].has("froggies"):
progress_dict[levelName]["froggies"] = {}
else:
for frog_number in freed_frogs:
if progress_dict[levelName]["froggies"].has(frog_number):
progress_dict[levelName]["froggies"][frog_number] = true
# TODO Wallet is independant from progress_dict because???
GlobalState.set_wallet(GlobalState.gsr.wallet + currency)
GlobalState.set_progress(progress_dict)
# TODO Wallet is independant from progress_dict because???
GlobalState.set_wallet(GlobalState.gsr.wallet + currency)
GlobalState.set_progress(progress_dict)
func player_dying(animation_number: int = 0) -> void:
currency = 0
is_dead = true
freed_frogs = []
deaths += 1
update_global_state()
deaths = 0
currency = 0
is_dead = true
freed_frogs = []
deaths += 1
update_global_state()
deaths = 0

View File

@ -8,74 +8,74 @@ onready var static_player: AudioStreamPlayer = $StaticPlayer
# Plays sound with the static player, interrupting sounds if currently playing
func play_sound(
sound_name: String,
attenuation: float = 0.0,
random_pitch = false,
pitch = 1.0,
start_time = 0.0,
bus: String = "Effects"
sound_name: String,
attenuation: float = 0.0,
random_pitch = false,
pitch = 1.0,
start_time = 0.0,
bus: String = "Effects"
) -> void:
# TODO is it bad to grab the stream each time?
var stream = GlobalState.sound_library[sound_name]
if random_pitch:
stream = AudioStreamRandomPitch.new()
stream.audio_stream = GlobalState.sound_library[sound_name]
static_player.stream = stream
static_player.volume_db = attenuation
static_player.bus = bus
static_player.pitch_scale = pitch
static_player.stream_paused = false
static_player.play(start_time)
# TODO is it bad to grab the stream each time?
var stream = GlobalState.sound_library[sound_name]
if random_pitch:
stream = AudioStreamRandomPitch.new()
stream.audio_stream = GlobalState.sound_library[sound_name]
static_player.stream = stream
static_player.volume_db = attenuation
static_player.bus = bus
static_player.pitch_scale = pitch
static_player.stream_paused = false
static_player.play(start_time)
func stop_sound():
static_player.stream_paused = true
static_player.stream_paused = true
# Mirrors the GlobalAudio Method which can play sounds across scenes
func play_parallel_sound(
sound_name: String,
attenuation: float = 0.0,
random_pitch = false,
pitch = 1.0,
start_time = 0.0,
bus: String = "Effects",
singleton = false
sound_name: String,
attenuation: float = 0.0,
random_pitch = false,
pitch = 1.0,
start_time = 0.0,
bus: String = "Effects",
singleton = false
) -> void:
if singleton && players.has(sound_name):
return
var disposable_player = AudioStreamPlayer.new()
add_child(disposable_player)
var stream = GlobalState.sound_library[sound_name]
if random_pitch:
stream = AudioStreamRandomPitch.new()
stream.audio_stream = GlobalState.sound_library[sound_name]
disposable_player.stream = stream
disposable_player.volume_db = attenuation
disposable_player.bus = bus
disposable_player.pitch_scale = pitch
disposable_player.play(start_time)
disposable_player.connect("finished", self, "dispose_parallel_player", [weakref(disposable_player)])
players[sound_name] = weakref(disposable_player)
if singleton && players.has(sound_name):
return
var disposable_player = AudioStreamPlayer.new()
add_child(disposable_player)
var stream = GlobalState.sound_library[sound_name]
if random_pitch:
stream = AudioStreamRandomPitch.new()
stream.audio_stream = GlobalState.sound_library[sound_name]
disposable_player.stream = stream
disposable_player.volume_db = attenuation
disposable_player.bus = bus
disposable_player.pitch_scale = pitch
disposable_player.play(start_time)
disposable_player.connect("finished", self, "dispose_parallel_player", [weakref(disposable_player)])
players[sound_name] = weakref(disposable_player)
func dispose_parallel_player(player: WeakRef) -> void:
if !player.get_ref():
return
player.get_ref().queue_free()
if !player.get_ref():
return
player.get_ref().queue_free()
func pause_parallel_sound(sound_name: String):
if players.has(sound_name) && players[sound_name].get_ref():
players[sound_name].set_stream_paused(true)
if players.has(sound_name) && players[sound_name].get_ref():
players[sound_name].set_stream_paused(true)
func continue_parallel_sound(sound_name: String):
if players.has(sound_name) && players[sound_name].get_ref():
players[sound_name].set_stream_paused(false)
if players.has(sound_name) && players[sound_name].get_ref():
players[sound_name].set_stream_paused(false)
func stop_parallel_sound(sound_name: String):
if players.has(sound_name) && players[sound_name].get_ref():
dispose_parallel_player(players[sound_name])
players.erase(sound_name)
if players.has(sound_name) && players[sound_name].get_ref():
dispose_parallel_player(players[sound_name])
players.erase(sound_name)

View File

@ -17,4 +17,4 @@ signal savemanager_saved()
signal game_paused(value)
func _on_Timer_timeout() -> void:
emit_signal("getback_timer_up")
emit_signal("getback_timer_up")