Merge branch 'master' of https://git.ghostguild.org/henry/tojam20-elevator
This commit is contained in:
commit
f6d66e0101
14 changed files with 383 additions and 78 deletions
|
|
@ -1,44 +1,43 @@
|
|||
extends Node3D
|
||||
|
||||
var survivors: int = 5
|
||||
var survivor_rate: float = .75
|
||||
var speed_modifer: int = 0
|
||||
var spawn_readiness: bool = false
|
||||
@export var batch_duration: float = 16.0
|
||||
@export var lateral_variance: float = 1.5
|
||||
|
||||
var _active_walkers: Array[Node] = []
|
||||
var _batch_generation: int = 0
|
||||
|
||||
@onready var survivor = preload("res://scenes/survivor.tscn")
|
||||
@onready var world = preload("res://scenes/world.tscn")
|
||||
|
||||
@onready var survivor_spawn = get_node("/root/Game/World/SuvivorSpawn")
|
||||
@onready var start_pos = survivor_spawn.global_position
|
||||
@onready var start_pos: Vector3 = survivor_spawn.global_position
|
||||
|
||||
func _ready() -> void:
|
||||
start()
|
||||
func _enter_tree() -> void:
|
||||
EventBus.floor_started.connect(_on_floor_started, CONNECT_DEFERRED)
|
||||
|
||||
func start() -> void:
|
||||
spawn_readiness = true
|
||||
spawn_survivor()
|
||||
func _on_floor_started(count: int) -> void:
|
||||
_batch_generation += 1
|
||||
_clear_active_walkers()
|
||||
if count <= 0:
|
||||
return
|
||||
_run_batch(count, _batch_generation)
|
||||
|
||||
#func _physics_process(delta):
|
||||
#if spawn_readiness == true:
|
||||
#spawn_survivor()
|
||||
#spawn_readiness = false
|
||||
#
|
||||
#else: pass
|
||||
func _clear_active_walkers() -> void:
|
||||
for w in _active_walkers:
|
||||
if is_instance_valid(w):
|
||||
w.queue_free()
|
||||
_active_walkers.clear()
|
||||
|
||||
func spawn_survivor():
|
||||
func _run_batch(count: int, generation: int) -> void:
|
||||
var gap: float = batch_duration / float(count)
|
||||
for i in range(count):
|
||||
if generation != _batch_generation:
|
||||
return
|
||||
_spawn_one()
|
||||
var jitter: float = randf_range(-gap * 0.25, gap * 0.25)
|
||||
await get_tree().create_timer(max(0.05, gap + jitter)).timeout
|
||||
|
||||
if spawn_readiness == false: pass
|
||||
|
||||
else:
|
||||
|
||||
var survivor_delay: float = randf_range(1, 2.5)
|
||||
var start_variance = Vector3((randf_range(-1, 2)),0,0)
|
||||
|
||||
for x in range(survivors):
|
||||
func _spawn_one() -> void:
|
||||
var s = survivor.instantiate()
|
||||
var offset := Vector3(randf_range(-lateral_variance, lateral_variance), 0, 0)
|
||||
get_tree().root.add_child.call_deferred(s)
|
||||
#get_node("/root/Game/World").add_child(s)
|
||||
s.position = start_pos + start_variance
|
||||
await get_tree().create_timer(survivor_rate * survivor_delay).timeout
|
||||
spawn_readiness = true
|
||||
|
||||
s.position = start_pos + offset
|
||||
_active_walkers.append(s)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ extends PanelContainer
|
|||
var current_floor := 10
|
||||
var saved_count := 0
|
||||
var doors_closing_flag := false
|
||||
var _onboarded := false
|
||||
|
||||
# Survivors per floor: more at top, fewer as you descend
|
||||
var base_survivors := 2
|
||||
|
|
@ -19,14 +20,6 @@ var points_per_person := 100 # base + bonus per person above threshold
|
|||
|
||||
var people_in_elevator := 0
|
||||
|
||||
const CHASE_SHORT_1 := preload("res://audio/Shortchase1.wav")
|
||||
const CHASE_SHORT_2 := preload("res://audio/Shortchase2.wav")
|
||||
const CHASE_MID := preload("res://audio/Midchase1.wav")
|
||||
const CHASE_LONG := preload("res://audio/Chase1.wav")
|
||||
const CHASE_TRACKS := [CHASE_SHORT_1, CHASE_SHORT_2, CHASE_MID, CHASE_LONG]
|
||||
var _last_chase: AudioStream = null
|
||||
var _chase_tween: Tween = null
|
||||
|
||||
func _ready():
|
||||
var button = $PanelMargin/PanelColumn/CloseButton
|
||||
button.text = "BLOCK"
|
||||
|
|
@ -36,12 +29,14 @@ func _ready():
|
|||
screen.pulse_blocked.connect(_on_pulse_blocked)
|
||||
screen.doors_closing.connect(_on_doors_closing)
|
||||
|
||||
_start_floor()
|
||||
EventBus.game_started.connect(_start_floor)
|
||||
|
||||
func _unhandled_input(event):
|
||||
if event is InputEventKey and event.pressed and not event.echo:
|
||||
if event.keycode == KEY_SPACE:
|
||||
_on_block_pressed()
|
||||
elif event.keycode == KEY_R:
|
||||
get_tree().reload_current_scene()
|
||||
|
||||
# --- Floor lifecycle ---
|
||||
|
||||
|
|
@ -56,11 +51,22 @@ func _start_floor():
|
|||
|
||||
EventBus.people_changed.emit(people_in_elevator, threshold)
|
||||
EventBus.floor_changed.emit(current_floor)
|
||||
EventBus.floor_started.emit(survivors_remaining)
|
||||
|
||||
var screen = $PanelMargin/PanelColumn/Screen
|
||||
screen.start()
|
||||
|
||||
if not _onboarded:
|
||||
_onboarded = true
|
||||
screen.show_onboarding("BLOCK\nIN GREEN ZONE")
|
||||
get_tree().create_timer(3.0).timeout.connect(
|
||||
func():
|
||||
screen.end_onboarding()
|
||||
screen.launch_pulse(),
|
||||
CONNECT_ONE_SHOT
|
||||
)
|
||||
else:
|
||||
screen.launch_pulse() # first survivor arrives
|
||||
_start_chase()
|
||||
|
||||
# --- Input ---
|
||||
|
||||
|
|
@ -72,7 +78,6 @@ func _on_block_pressed():
|
|||
# --- Pulse callbacks ---
|
||||
|
||||
func _on_pulse_blocked():
|
||||
_stop_chase()
|
||||
# This survivor made it in
|
||||
survivors_remaining -= 1
|
||||
people_in_elevator += 1
|
||||
|
|
@ -91,8 +96,7 @@ func _on_pulse_blocked():
|
|||
get_tree().create_timer(gap).timeout.connect(
|
||||
func():
|
||||
if not doors_closing_flag:
|
||||
screen.launch_pulse()
|
||||
_start_chase(),
|
||||
screen.launch_pulse(),
|
||||
CONNECT_ONE_SHOT
|
||||
)
|
||||
|
||||
|
|
@ -101,8 +105,6 @@ func _on_doors_closing():
|
|||
return
|
||||
doors_closing_flag = true
|
||||
|
||||
_stop_chase()
|
||||
|
||||
var screen = $PanelMargin/PanelColumn/Screen
|
||||
|
||||
# Lose: not enough people
|
||||
|
|
@ -137,22 +139,3 @@ func _on_doors_closing():
|
|||
var tween = create_tween()
|
||||
tween.tween_interval(2.0)
|
||||
tween.tween_callback(_start_floor)
|
||||
|
||||
func _start_chase():
|
||||
if _chase_tween and _chase_tween.is_valid():
|
||||
_chase_tween.kill()
|
||||
|
||||
var candidates: Array = CHASE_TRACKS.filter(func(s): return s != _last_chase)
|
||||
var stream: AudioStream = candidates[randi() % candidates.size()]
|
||||
_last_chase = stream
|
||||
|
||||
$SfxChase.stream = stream
|
||||
$SfxChase.volume_db = 0.0
|
||||
$SfxChase.play()
|
||||
|
||||
func _stop_chase():
|
||||
if _chase_tween and _chase_tween.is_valid():
|
||||
_chase_tween.kill()
|
||||
_chase_tween = create_tween()
|
||||
_chase_tween.tween_property($SfxChase, "volume_db", -80.0, 0.3)
|
||||
_chase_tween.tween_callback($SfxChase.stop)
|
||||
|
|
|
|||
52
scenes/end_screen.gd
Normal file
52
scenes/end_screen.gd
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
extends CanvasLayer
|
||||
|
||||
var _score := 0
|
||||
var _saved := 0
|
||||
|
||||
func _ready():
|
||||
visible = false
|
||||
EventBus.game_won.connect(_on_game_won)
|
||||
EventBus.game_lost.connect(_on_game_lost)
|
||||
EventBus.score_changed.connect(func(s): _score = s)
|
||||
EventBus.saved_changed.connect(func(s): _saved = s)
|
||||
$Center/Card/Margin/Column/RestartButton.pressed.connect(_on_restart_pressed)
|
||||
|
||||
func _on_game_won():
|
||||
$Center/Card/Margin/Column/Headline.text = "YOU ESCAPED"
|
||||
_show()
|
||||
|
||||
func _on_game_lost():
|
||||
$Center/Card/Margin/Column/Headline.text = "TOO FEW"
|
||||
_apply_loss_palette()
|
||||
_show()
|
||||
|
||||
func _apply_loss_palette():
|
||||
var border := Color(1, 0.3, 0.3, 1)
|
||||
var subtle := Color(0.95, 0.7, 0.7, 1)
|
||||
|
||||
var card_style := ($Center/Card.get_theme_stylebox("panel") as StyleBoxFlat).duplicate() as StyleBoxFlat
|
||||
if card_style:
|
||||
card_style.border_color = border
|
||||
card_style.bg_color = Color(0.18, 0.05, 0.05, 1)
|
||||
$Center/Card.add_theme_stylebox_override("panel", card_style)
|
||||
|
||||
var button = $Center/Card/Margin/Column/RestartButton
|
||||
var button_style := (button.get_theme_stylebox("normal") as StyleBoxFlat).duplicate() as StyleBoxFlat
|
||||
if button_style:
|
||||
button_style.border_color = border
|
||||
button_style.bg_color = Color(0.3, 0.1, 0.1, 1)
|
||||
for state in ["normal", "hover", "pressed", "focus"]:
|
||||
button.add_theme_stylebox_override(state, button_style)
|
||||
button.add_theme_color_override("font_color", border)
|
||||
|
||||
$Center/Card/Margin/Column/Headline.add_theme_color_override("font_color", border)
|
||||
$Center/Card/Margin/Column/ScoreLabel.add_theme_color_override("font_color", subtle)
|
||||
$Center/Card/Margin/Column/SavedLabel.add_theme_color_override("font_color", subtle)
|
||||
|
||||
func _show():
|
||||
$Center/Card/Margin/Column/ScoreLabel.text = "Score: %d" % _score
|
||||
$Center/Card/Margin/Column/SavedLabel.text = "Survivors saved: %d" % _saved
|
||||
visible = true
|
||||
|
||||
func _on_restart_pressed():
|
||||
get_tree().reload_current_scene()
|
||||
1
scenes/end_screen.gd.uid
Normal file
1
scenes/end_screen.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://cpewgbefcp3wn
|
||||
86
scenes/end_screen.tscn
Normal file
86
scenes/end_screen.tscn
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
[gd_scene load_steps=4 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/end_screen.gd" id="1"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="CardStyle"]
|
||||
bg_color = Color(0.05, 0.18, 0.05, 1)
|
||||
border_width_left = 3
|
||||
border_width_top = 3
|
||||
border_width_right = 3
|
||||
border_width_bottom = 3
|
||||
border_color = Color(0.2, 1, 0.2, 1)
|
||||
corner_radius_top_left = 6
|
||||
corner_radius_top_right = 6
|
||||
corner_radius_bottom_right = 6
|
||||
corner_radius_bottom_left = 6
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="ButtonStyle"]
|
||||
bg_color = Color(0.1, 0.3, 0.1, 1)
|
||||
border_width_left = 2
|
||||
border_width_top = 2
|
||||
border_width_right = 2
|
||||
border_width_bottom = 2
|
||||
border_color = Color(0.2, 1, 0.2, 1)
|
||||
corner_radius_top_left = 4
|
||||
corner_radius_top_right = 4
|
||||
corner_radius_bottom_right = 4
|
||||
corner_radius_bottom_left = 4
|
||||
content_margin_left = 24
|
||||
content_margin_right = 24
|
||||
content_margin_top = 12
|
||||
content_margin_bottom = 12
|
||||
|
||||
[node name="EndScreen" type="CanvasLayer"]
|
||||
layer = 10
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="Dim" type="ColorRect" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
mouse_filter = 2
|
||||
color = Color(0, 0, 0, 0.85)
|
||||
|
||||
[node name="Center" type="CenterContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
mouse_filter = 1
|
||||
|
||||
[node name="Card" type="PanelContainer" parent="Center"]
|
||||
theme_override_styles/panel = SubResource("CardStyle")
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="Center/Card"]
|
||||
theme_override_constants/margin_left = 56
|
||||
theme_override_constants/margin_right = 56
|
||||
theme_override_constants/margin_top = 40
|
||||
theme_override_constants/margin_bottom = 40
|
||||
|
||||
[node name="Column" type="VBoxContainer" parent="Center/Card/Margin"]
|
||||
theme_override_constants/separation = 24
|
||||
|
||||
[node name="Headline" type="Label" parent="Center/Card/Margin/Column"]
|
||||
text = "YOU ESCAPED"
|
||||
horizontal_alignment = 1
|
||||
theme_override_colors/font_color = Color(0.2, 1, 0.2, 1)
|
||||
theme_override_font_sizes/font_size = 56
|
||||
|
||||
[node name="ScoreLabel" type="Label" parent="Center/Card/Margin/Column"]
|
||||
text = "Score: 0"
|
||||
horizontal_alignment = 1
|
||||
theme_override_colors/font_color = Color(0.7, 0.95, 0.7, 1)
|
||||
theme_override_font_sizes/font_size = 28
|
||||
|
||||
[node name="SavedLabel" type="Label" parent="Center/Card/Margin/Column"]
|
||||
text = "Survivors saved: 0"
|
||||
horizontal_alignment = 1
|
||||
theme_override_colors/font_color = Color(0.7, 0.95, 0.7, 1)
|
||||
theme_override_font_sizes/font_size = 28
|
||||
|
||||
[node name="RestartButton" type="Button" parent="Center/Card/Margin/Column"]
|
||||
text = "RESTART"
|
||||
theme_override_colors/font_color = Color(0.2, 1, 0.2, 1)
|
||||
theme_override_colors/font_hover_color = Color(0.5, 1, 0.5, 1)
|
||||
theme_override_font_sizes/font_size = 24
|
||||
theme_override_styles/normal = SubResource("ButtonStyle")
|
||||
theme_override_styles/hover = SubResource("ButtonStyle")
|
||||
theme_override_styles/pressed = SubResource("ButtonStyle")
|
||||
theme_override_styles/focus = SubResource("ButtonStyle")
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
extends Node3D
|
||||
|
||||
func _ready() -> void:
|
||||
$ComponentSpawn.spawn_survivor()
|
||||
|
||||
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
[ext_resource type="AudioStream" uid="uid://bavo8f76jr7i6" path="res://audio/ElevatorOpen1.wav" id="5_u5sy4"]
|
||||
[ext_resource type="AudioStream" uid="uid://dgqb1rovgwuan" path="res://audio/ElevatorClose1.wav" id="6_gee14"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/component_spawn.tscn" id="9_0tnpc"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/end_screen.tscn" id="10_endsc"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/title_screen.tscn" id="11_title"]
|
||||
|
||||
[node name="Game" type="Node3D" unique_id=1456297160]
|
||||
script = ExtResource("1_lbhrr")
|
||||
|
|
@ -35,3 +37,7 @@ stream = ExtResource("6_gee14")
|
|||
[node name="SfxChase" type="AudioStreamPlayer3D" parent="CanvasPanel/ElevatorPanel" unique_id=812445001]
|
||||
|
||||
[node name="ComponentSpawn" parent="." unique_id=649225939 instance=ExtResource("9_0tnpc")]
|
||||
|
||||
[node name="EndScreen" parent="." instance=ExtResource("10_endsc")]
|
||||
|
||||
[node name="TitleScreen" parent="." instance=ExtResource("11_title")]
|
||||
|
|
|
|||
|
|
@ -13,12 +13,23 @@ var pulse_gap_min := 0.3
|
|||
var block_zone_shrink := 3.0
|
||||
var block_zone_min := 12.0
|
||||
|
||||
const TRAIL_GHOSTS := 8
|
||||
const TRAIL_SPACING := 3.0
|
||||
const TRAIL_ALPHAS := [0.5, 0.42, 0.34, 0.27, 0.2, 0.14, 0.09, 0.05]
|
||||
const GLOW_PADDING := Vector2(6, 6)
|
||||
const GLOW_COLOR := Color(1, 0.3, 0.3, 0.35)
|
||||
|
||||
# Visual
|
||||
var base_color: Color
|
||||
|
||||
# State
|
||||
var active := false
|
||||
var pulses_blocked := 0
|
||||
var _ready_pulse_tween: Tween = null
|
||||
var _trail: Array[ColorRect] = []
|
||||
var _glow: ColorRect
|
||||
var _face_scale_tween: Tween
|
||||
var _face_shake_tween: Tween
|
||||
|
||||
signal pulse_blocked
|
||||
signal doors_closing
|
||||
|
|
@ -41,6 +52,23 @@ func _ready():
|
|||
face.size = Vector2(size.x, 30)
|
||||
face.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
face.text = ">:)"
|
||||
face.pivot_offset = face.size / 2
|
||||
|
||||
_glow = ColorRect.new()
|
||||
_glow.color = GLOW_COLOR
|
||||
_glow.size = Vector2($SweepLine.size.x + GLOW_PADDING.x * 2, $SweepLine.size.y + GLOW_PADDING.y * 2)
|
||||
_glow.visible = false
|
||||
add_child(_glow)
|
||||
move_child(_glow, 0)
|
||||
|
||||
for i in TRAIL_GHOSTS:
|
||||
var ghost := ColorRect.new()
|
||||
ghost.color = Color($SweepLine.color.r, $SweepLine.color.g, $SweepLine.color.b, TRAIL_ALPHAS[i])
|
||||
ghost.size = $SweepLine.size
|
||||
ghost.visible = false
|
||||
add_child(ghost)
|
||||
move_child(ghost, 0)
|
||||
_trail.append(ghost)
|
||||
|
||||
# Duplicate the StyleBoxFlat so flash tweens don't bleed into other panels
|
||||
var style = get_theme_stylebox("panel") as StyleBoxFlat
|
||||
|
|
@ -62,7 +90,8 @@ func start():
|
|||
func stop():
|
||||
active = false
|
||||
pulse_active = false
|
||||
$SweepLine.visible = false
|
||||
_hide_pulse_visuals()
|
||||
_stop_ready_pulse()
|
||||
|
||||
func shrink_block_zone():
|
||||
var bz = $TargetZone
|
||||
|
|
@ -80,7 +109,11 @@ func launch_pulse():
|
|||
pulse_active = true
|
||||
$SweepLine.visible = true
|
||||
$SweepLine.position.x = 0
|
||||
_glow.visible = true
|
||||
for ghost in _trail:
|
||||
ghost.visible = true
|
||||
$AIFace.text = ">:)"
|
||||
_start_ready_pulse()
|
||||
|
||||
func get_pulse_gap() -> float:
|
||||
return pulse_gap
|
||||
|
|
@ -91,12 +124,18 @@ func _process(delta):
|
|||
|
||||
pulse_x += pulse_speed * delta
|
||||
$SweepLine.position.x = pulse_x
|
||||
_glow.position = Vector2(pulse_x - GLOW_PADDING.x, $SweepLine.position.y - GLOW_PADDING.y)
|
||||
for i in _trail.size():
|
||||
var gx = pulse_x - (i + 1) * TRAIL_SPACING
|
||||
_trail[i].visible = gx >= 0
|
||||
_trail[i].position = Vector2(gx, $SweepLine.position.y)
|
||||
|
||||
# Pulse reached the far side unblocked: AI wins, doors close
|
||||
if pulse_x >= size.x:
|
||||
pulse_active = false
|
||||
$SweepLine.visible = false
|
||||
_hide_pulse_visuals()
|
||||
$AIFace.text = ":D"
|
||||
_punch_face(1.5, 0.0)
|
||||
flash(Color.RED)
|
||||
active = false
|
||||
doors_closing.emit()
|
||||
|
|
@ -116,16 +155,18 @@ func attempt_block() -> bool:
|
|||
pulses_blocked += 1
|
||||
pulse_speed += pulse_speed_increase
|
||||
pulse_gap = max(pulse_gap - pulse_gap_decrease, pulse_gap_min)
|
||||
$SweepLine.visible = false
|
||||
_hide_pulse_visuals()
|
||||
$AIFace.text = ">:("
|
||||
_punch_face(1.4, 4.0)
|
||||
flash(Color.GREEN)
|
||||
pulse_blocked.emit()
|
||||
return true
|
||||
else:
|
||||
# Mistimed: same result as letting it through
|
||||
pulse_active = false
|
||||
$SweepLine.visible = false
|
||||
_hide_pulse_visuals()
|
||||
$AIFace.text = ":D"
|
||||
_punch_face(1.5, 0.0)
|
||||
flash(Color.RED)
|
||||
active = false
|
||||
doors_closing.emit()
|
||||
|
|
@ -163,3 +204,50 @@ func show_loss(message: String):
|
|||
$TargetZone.visible = false
|
||||
$AIFace.text = message
|
||||
flash(Color.RED)
|
||||
|
||||
func show_onboarding(msg: String):
|
||||
$AIFace.add_theme_font_size_override("font_size", 18)
|
||||
$AIFace.size = Vector2(size.x, 60)
|
||||
$AIFace.text = msg
|
||||
|
||||
func end_onboarding():
|
||||
$AIFace.add_theme_font_size_override("font_size", 32)
|
||||
$AIFace.size = Vector2(size.x, 30)
|
||||
|
||||
func _start_ready_pulse():
|
||||
if _ready_pulse_tween:
|
||||
_ready_pulse_tween.kill()
|
||||
$TargetZone.modulate.a = 1.0
|
||||
_ready_pulse_tween = create_tween()
|
||||
_ready_pulse_tween.set_loops()
|
||||
_ready_pulse_tween.tween_property($TargetZone, "modulate:a", 0.6, 0.5)
|
||||
_ready_pulse_tween.tween_property($TargetZone, "modulate:a", 1.0, 0.5)
|
||||
|
||||
func _stop_ready_pulse():
|
||||
if _ready_pulse_tween:
|
||||
_ready_pulse_tween.kill()
|
||||
_ready_pulse_tween = null
|
||||
$TargetZone.modulate.a = 1.0
|
||||
|
||||
func _hide_pulse_visuals():
|
||||
$SweepLine.visible = false
|
||||
_glow.visible = false
|
||||
for ghost in _trail:
|
||||
ghost.visible = false
|
||||
|
||||
func _punch_face(scale_amount: float, shake_amount: float):
|
||||
if _face_scale_tween:
|
||||
_face_scale_tween.kill()
|
||||
if _face_shake_tween:
|
||||
_face_shake_tween.kill()
|
||||
var face := $AIFace
|
||||
face.position = Vector2(0, 0)
|
||||
face.scale = Vector2(scale_amount, scale_amount)
|
||||
_face_scale_tween = create_tween()
|
||||
_face_scale_tween.tween_property(face, "scale", Vector2.ONE, 0.25).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
|
||||
if shake_amount > 0:
|
||||
_face_shake_tween = create_tween()
|
||||
_face_shake_tween.tween_property(face, "position:x", -shake_amount, 0.04)
|
||||
_face_shake_tween.tween_property(face, "position:x", shake_amount, 0.04)
|
||||
_face_shake_tween.tween_property(face, "position:x", -shake_amount * 0.5, 0.04)
|
||||
_face_shake_tween.tween_property(face, "position:x", 0.0, 0.04)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
extends CharacterBody3D
|
||||
|
||||
const CHASE_SHORT_1 := preload("res://audio/Shortchase1.wav")
|
||||
const CHASE_SHORT_2 := preload("res://audio/Shortchase2.wav")
|
||||
const CHASE_MID := preload("res://audio/Midchase1.wav")
|
||||
const CHASE_LONG := preload("res://audio/Chase1.wav")
|
||||
const CHASE_TRACKS := [CHASE_SHORT_1, CHASE_SHORT_2, CHASE_MID, CHASE_LONG]
|
||||
static var _last_chase: AudioStream = null
|
||||
|
||||
var speed: int = 3
|
||||
var clumsiness: int = 0
|
||||
|
||||
|
|
@ -10,6 +17,17 @@ var clumsiness: int = 0
|
|||
#transform = xform
|
||||
#velocity = (-xform.basis.z * speed).rotated(Vector3.UP, randf_range(-PI/4, PI/4))
|
||||
|
||||
func _ready():
|
||||
var candidates: Array = CHASE_TRACKS.filter(func(s): return s != _last_chase)
|
||||
var stream: AudioStream = candidates[randi() % candidates.size()]
|
||||
_last_chase = stream
|
||||
$ScreamPlayer.stream = stream
|
||||
var delay := randf_range(0.0, 0.5)
|
||||
get_tree().create_timer(delay).timeout.connect(
|
||||
func(): $ScreamPlayer.play(),
|
||||
CONNECT_ONE_SHOT
|
||||
)
|
||||
|
||||
func _physics_process(delta):
|
||||
velocity.z -= speed * delta
|
||||
move_and_slide()
|
||||
|
|
|
|||
|
|
@ -55,4 +55,6 @@ frame_progress = 0.99938977
|
|||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.080844045, -0.14428711)
|
||||
shape = SubResource("BoxShape3D_7yc2n")
|
||||
|
||||
[node name="ScreamPlayer" type="AudioStreamPlayer3D" parent="."]
|
||||
|
||||
[connection signal="area_entered" from="Area3D" to="." method="_on_area_3d_area_entered"]
|
||||
|
|
|
|||
14
scenes/title_screen.gd
Normal file
14
scenes/title_screen.gd
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
extends CanvasLayer
|
||||
|
||||
func _ready():
|
||||
get_tree().paused = true
|
||||
|
||||
func _unhandled_input(event):
|
||||
if event is InputEventKey and event.pressed and not event.echo:
|
||||
if event.keycode == KEY_SPACE or event.keycode == KEY_ENTER:
|
||||
_start()
|
||||
|
||||
func _start():
|
||||
get_tree().paused = false
|
||||
EventBus.game_started.emit()
|
||||
queue_free()
|
||||
1
scenes/title_screen.gd.uid
Normal file
1
scenes/title_screen.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://ba3of2ykdjqcl
|
||||
55
scenes/title_screen.tscn
Normal file
55
scenes/title_screen.tscn
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
[gd_scene load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/title_screen.gd" id="1"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="CardStyle"]
|
||||
bg_color = Color(0.05, 0.18, 0.05, 1)
|
||||
border_width_left = 3
|
||||
border_width_top = 3
|
||||
border_width_right = 3
|
||||
border_width_bottom = 3
|
||||
border_color = Color(0.2, 1, 0.2, 1)
|
||||
corner_radius_top_left = 6
|
||||
corner_radius_top_right = 6
|
||||
corner_radius_bottom_right = 6
|
||||
corner_radius_bottom_left = 6
|
||||
|
||||
[node name="TitleScreen" type="CanvasLayer"]
|
||||
layer = 20
|
||||
process_mode = 3
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="Dim" type="ColorRect" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
mouse_filter = 2
|
||||
color = Color(0, 0, 0, 0.85)
|
||||
|
||||
[node name="Center" type="CenterContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
mouse_filter = 1
|
||||
|
||||
[node name="Card" type="PanelContainer" parent="Center"]
|
||||
theme_override_styles/panel = SubResource("CardStyle")
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="Center/Card"]
|
||||
theme_override_constants/margin_left = 64
|
||||
theme_override_constants/margin_right = 64
|
||||
theme_override_constants/margin_top = 48
|
||||
theme_override_constants/margin_bottom = 48
|
||||
|
||||
[node name="Column" type="VBoxContainer" parent="Center/Card/Margin"]
|
||||
theme_override_constants/separation = 24
|
||||
|
||||
[node name="Title" type="Label" parent="Center/Card/Margin/Column"]
|
||||
text = "ELEVATOR"
|
||||
horizontal_alignment = 1
|
||||
theme_override_colors/font_color = Color(0.2, 1, 0.2, 1)
|
||||
theme_override_font_sizes/font_size = 72
|
||||
|
||||
[node name="Prompt" type="Label" parent="Center/Card/Margin/Column"]
|
||||
text = "PRESS SPACE TO START"
|
||||
horizontal_alignment = 1
|
||||
theme_override_colors/font_color = Color(0.5, 1, 0.5, 1)
|
||||
theme_override_font_sizes/font_size = 28
|
||||
|
|
@ -6,7 +6,9 @@ signal floor_changed(floor_num: int)
|
|||
signal saved_changed(count: int)
|
||||
signal score_changed(new_score: int)
|
||||
signal people_changed(count: int, threshold: int)
|
||||
signal game_started
|
||||
signal game_won
|
||||
signal game_lost
|
||||
signal floor_started(survivor_count: int)
|
||||
|
||||
@warning_ignore_restore("unused_signal") # put any future signals you add between the two ignore annotations
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue