initial add

This commit is contained in:
2026-04-10 17:53:31 -05:00
commit ebd36e4ef3
196 changed files with 51603 additions and 0 deletions

BIN
gobbos_delivery/scripts/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,215 @@
using Godot;
using gobbos_logic;
public partial class Player : CharacterBody2D, IPlayer
{
[Signal]
public delegate void BlinkTimerTimeoutEventHandler();
[Signal]
public delegate void WallCastDelayTimeoutEventHandler();
// Constants
const double COYOTE_JUMP_WINDOW = 0.15;
// private readonly Vector2 TILE_SIZE = new(8, 8);
[Export]
public AnimationPlayer Blinkplayer { get; set; }
private double timeSinceLeavingGround = 0.0;
public bool CanCoyoteJump => timeSinceLeavingGround < COYOTE_JUMP_WINDOW;
public void ResetCoyoteTimer()
{
timeSinceLeavingGround = 0.0;
}
public float Acceleration { get; set; } = 4.0f;
public float Friction { get; set; } = 4.0f;
public float AirFriction { get; set; } = 0.1f;
public float WallFriction { get; set; } = 1200.0f;
public int Speed { get; set; } = 40;
public int WallSpeed { get; set; } = 15;
public float SlowMod { get; set; } = 0.5f;
public int Gravity { get; set; } = 250;
public int Jump { get; set; } = -95;
public int WallJump { get; set; } = 55;
public int LedgeJump { get; set; } = -70;
public float FallMod { get; set; } = 1.5f;
public float ParachuteMod { get; set; } = 0.2f;
public bool OnLedge { get; set; } = false;
public bool InParachute { get; set; } = false;
public bool CanParachute { get; set; } = false;
public Vector2 AnimDir { get; set; } = Vector2.Zero;
public Vector2 LastDir { get; set; } = Vector2.Zero;
public Vector2 MoveDir { get; set; } = Vector2.Zero;
public Label StateLabel { get; set; }
public RayCast2D WallCastTop { get; set; }
public RayCast2D WallCastMid { get; set; }
public RayCast2D WallCastLow { get; set; }
public AnimationNodeStateMachinePlayback AnimStateMachine { get; set; }
public AnimationNodeStateMachinePlayback GroundedStateMachine { get; set; }
public AnimationNodeStateMachinePlayback AirborneStateMachine { get; set; }
public AnimationNodeStateMachinePlayback SprintStateMachine { get; set; }
public float LastVelocityY { get; set; } = 0.0f;
public float WallCastLength { get; set; } = 3.8f;
public Timer WallCastDelayTimer { get; set; }
private RayCast2D cameraOffsetCast;
private RayCast2D cameraDownCast;
private Node2D modelContainer;
private Timer blinkTimer;
public AnimationTree animTree;
private StateMachine stateMachine;
public override void _Ready()
{
modelContainer = GetNode<Node2D>("ModelContainer");
blinkTimer = GetNode<Timer>("BlinkTimer");
animTree = GetNode<AnimationTree>("AnimationTree");
cameraOffsetCast = GetNode<RayCast2D>("CameraOffsetCast");
cameraDownCast = GetNode<RayCast2D>("CameraOffsetCast/CameraDownCast");
stateMachine = GetNode<StateMachine>("StateMachine");
animTree.Set("parameters/Airborne/Standard/blend_position", 1.0f);
animTree.Set("parameters/Airborne/Parachute/blend_position", 1.0f);
WallCastTop = GetNode<RayCast2D>("WallCastTop");
WallCastMid = GetNode<RayCast2D>("WallCastMid");
WallCastLow = GetNode<RayCast2D>("WallCastLow");
WallCastDelayTimer = GetNode<Timer>("WallCastDelay");
WallCastDelayTimer.Timeout += OnWallCastDelayTimeout;
AnimStateMachine = (AnimationNodeStateMachinePlayback)animTree.Get("parameters/playback");
GroundedStateMachine = (AnimationNodeStateMachinePlayback)animTree.Get("parameters/Grounded/playback");
AirborneStateMachine = (AnimationNodeStateMachinePlayback)animTree.Get("parameters/Airborne/playback");
SprintStateMachine = (AnimationNodeStateMachinePlayback)animTree.Get("parameters/Grounded/Sprint/playback");
StateLabel = GetNode<Label>("StateLabel");
}
public override void _PhysicsProcess(double delta)
{
var floatDelta = (float)delta;
Vector2 inputDir = new(Input.GetAxis("move_left", "move_right"), Input.GetAxis("move_up", "move_down"));
if (inputDir.X != 0.0f)
{
MoveDir = new(Mathf.MoveToward(MoveDir.X, inputDir.X, 20 * floatDelta), MoveDir.Y);
LastDir = new(inputDir.X, LastDir.Y);
}
else
{
MoveDir = new Vector2(
Mathf.MoveToward(MoveDir.X, 0.0f, 20 * floatDelta),
MoveDir.Y);
}
if (inputDir.Y != 0.0f)
{
MoveDir = new(MoveDir.X, Mathf.MoveToward(MoveDir.Y, inputDir.Y, 20 * floatDelta));
LastDir = new(LastDir.X, inputDir.Y);
}
else
{
MoveDir = new(MoveDir.X, Mathf.MoveToward(MoveDir.Y, 0.0f, 20 * floatDelta));
}
AnimDir = new(Mathf.MoveToward(AnimDir.X, LastDir.X, 20 * floatDelta), AnimDir.Y);
// Set wall cast positions based on input direction
if (inputDir.X > 0)
{
WallCastTop.TargetPosition = new(WallCastLength, WallCastTop.TargetPosition.Y);
WallCastMid.TargetPosition = new(WallCastLength, WallCastMid.TargetPosition.Y);
WallCastLow.TargetPosition = new(WallCastLength, WallCastLow.TargetPosition.Y);
}
else if (inputDir.X < 0)
{
WallCastTop.TargetPosition = new(0.0f - WallCastLength, WallCastTop.TargetPosition.Y);
WallCastMid.TargetPosition = new(0.0f - WallCastLength, WallCastMid.TargetPosition.Y);
WallCastLow.TargetPosition = new(0.0f - WallCastLength, WallCastLow.TargetPosition.Y);
}
else
{
WallCastTop.TargetPosition = new(0.0f, WallCastTop.TargetPosition.Y);
WallCastMid.TargetPosition = new(0.0f, WallCastMid.TargetPosition.Y);
WallCastLow.TargetPosition = new(0.0f, WallCastLow.TargetPosition.Y);
}
// Update animation parameters
animTree.Set("parameters/Airborne/Standard/0/blend_position", Velocity.Y);
animTree.Set("parameters/Airborne/Standard/1/blend_position", Velocity.Y);
animTree.Set("parameters/Airborne/Parachute/0/blend_position", Velocity.Y);
animTree.Set("parameters/Airborne/Parachute/1/blend_position", Velocity.Y);
// Create tweens for animation blending
var idleBlend = GetTree().CreateTween();
var walkBlend = GetTree().CreateTween();
var airBlend = GetTree().CreateTween();
var parachuteBlend = GetTree().CreateTween();
idleBlend.TweenProperty(animTree, "parameters/Grounded/Idle/blend_position", AnimDir.X, 0.2f);
walkBlend.TweenProperty(animTree, "parameters/Grounded/Walk/blend_position", AnimDir.X, 0.2f);
airBlend.TweenProperty(animTree, "parameters/Airborne/Standard/blend_position", AnimDir.X, 0.2f);
parachuteBlend.TweenProperty(animTree, "parameters/Airborne/Parachute/blend_position", AnimDir.X, 0.5f);
TiltModel(floatDelta);
CameraOffset();
// Increment time since leaving ground if not on floor
if (!IsOnFloor())
{
timeSinceLeavingGround += delta;
}
// Call StateMachine PhysicsUpdate to handle state-specific movement
stateMachine?.PhysicsUpdate(floatDelta);
MoveAndSlide();
}
private void CameraOffset()
{
var targetX = Mathf.Lerp(cameraOffsetCast.TargetPosition.X, AnimDir.X * 50.0f, 0.6f);
cameraOffsetCast.TargetPosition = new(targetX, cameraOffsetCast.TargetPosition.Y);
if (cameraOffsetCast.IsColliding())
{
cameraDownCast.Position = cameraOffsetCast.GetCollisionPoint();
cameraDownCast.Position = new(cameraDownCast.Position.X, cameraDownCast.Position.Y + 1);
}
else
{
cameraDownCast.Position = cameraOffsetCast.GlobalPosition + cameraOffsetCast.TargetPosition;
}
}
private void TiltModel(float delta)
{
var floorNormal = GetFloorNormal();
var tilt = 0.0f;
if (floorNormal != new Vector2(0.0f, -1.0f))
{
tilt = Mathf.Atan2(floorNormal.X, floorNormal.Y);
tilt /= 10;
}
modelContainer.Rotation = Mathf.Lerp(modelContainer.Rotation, tilt, 5 * delta);
}
private void OnBlinkTimerTimeout()
{
Blinkplayer?.Play("blink");
var randomWaitTime = GD.RandRange(1.0f, 7.0f);
blinkTimer?.WaitTime = randomWaitTime;
}
private void OnWallCastDelayTimeout()
{
WallCastTop.Enabled = true;
WallCastMid.Enabled = true;
WallCastLow.Enabled = true;
}
}

View File

@@ -0,0 +1 @@
uid://dvytggb7uhxsf

View File

@@ -0,0 +1,24 @@
extends Camera2D
@onready var zoom_target : Vector2
@export var CameraCast : RayCast2D
@export var Player : CharacterBody2D
func _ready():
zoom_target = zoom
pass
func _process(delta):
if CameraCast.is_colliding():
self.position = lerp(self.position,CameraCast.get_collision_point(),4*delta)
else:
self.position = lerp(self.position,CameraCast.target_position + CameraCast.global_position,4*delta)
pass
_zoom(delta)
func _zoom(delta):
if Input.is_action_just_pressed("camera_zoom_in"):
zoom_target *= 1.1
if Input.is_action_just_pressed("camera_zoom_out"):
zoom_target *= 0.9
zoom = zoom.slerp(zoom_target, 10 * delta)

View File

@@ -0,0 +1 @@
uid://dfbwgobderch6

View File

@@ -0,0 +1,5 @@
extends Sprite2D
@export var CameraCast : RayCast2D
func _process(delta):
self.position = CameraCast.get_collision_point()

View File

@@ -0,0 +1 @@
uid://ye1xyv5al3dq

View File

@@ -0,0 +1,19 @@
extends Node
@onready var fpsValue := $VBoxContainer/fpsBox/fpsValue
@onready var simSpeedValue := $VBoxContainer/simSpeedBox/simSpeedValue
func _ready():
simSpeedValue.text = str(Engine.time_scale)
func _process(_delta):
fpsValue.text = str(Engine.get_frames_per_second())
if Input.is_action_just_pressed("speed_engine"):
Engine.time_scale += 0.05
simSpeedValue.text = str(Engine.time_scale)
print(Engine.time_scale)
if Input.is_action_just_pressed("slow_engine"):
Engine.time_scale -= 0.05
simSpeedValue.text = str(Engine.time_scale)
print(Engine.time_scale)

View File

@@ -0,0 +1 @@
uid://dqks36qvuhn7y

BIN
gobbos_delivery/scripts/states/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,11 @@
using Godot;
public partial class State : Node {
[Signal]
public delegate void TransitionedEventHandler(Node sender, string newState);
public virtual void Enter() { }
public virtual void Exit() { }
public virtual void Update(double delta) { }
public virtual void PhysicsUpdate(double delta) { }
}

View File

@@ -0,0 +1 @@
uid://ch2q7bjkugikg

View File

@@ -0,0 +1,54 @@
using Godot;
using System.Collections.Generic;
public partial class StateMachine : State {
[Export]
public State InitialState { get; set; }
private State currentState;
private readonly Dictionary<string, State> stateList = [];
public override void _Ready() {
foreach (var child in GetChildren()) {
if (child is State state)
{
stateList.Add(child.Name.ToString().ToLower(), state);
state.Transitioned += OnChildTransition;
}
}
if (InitialState != null)
{
InitialState.Enter();
currentState = InitialState;
}
}
public void Process(float delta)
{
currentState?.Update(delta);
}
public override void PhysicsUpdate(double delta)
{
currentState?.PhysicsUpdate(delta);
}
public void OnChildTransition(Node sender, string newStateName)
{
if (sender != currentState)
{
return;
}
var newState = stateList[newStateName.ToLower()];
if (newState == null)
{
return;
}
currentState?.Exit();
newState.Enter();
currentState = newState;
}
}

View File

@@ -0,0 +1 @@
uid://dwbhtjvpv0utl

View File

@@ -0,0 +1,2 @@
[*.cs]
csharp_new_line_before_open_brace = none

View File

@@ -0,0 +1,77 @@
using Godot;
public partial class PlayerAirborn : State {
private Player player;
public override void _Ready() {
player = GetNode<Player>("../..");
}
public override void Enter() {
GD.Print("airborn");
player.StateLabel?.Text = Name;
player.InParachute = false;
player.AnimStateMachine?.Travel("Airborne");
}
public override void PhysicsUpdate(double delta) {
var floatDelta = (float)delta;
if (player.IsOnFloor()) {
EmitSignal(SignalName.Transitioned, this, "PlayerGrounded");
}
if (player.MoveDir.X != 0) {
player.Velocity = new(
Mathf.MoveToward(player.Velocity.X, player.MoveDir.X * player.Speed, player.Acceleration),
player.Velocity.Y);
}
else {
player.Velocity = new(
Mathf.MoveToward(player.Velocity.X, 0.0f, player.AirFriction),
player.Velocity.Y);
}
if (player.Velocity.Y >= 0) {
player.Velocity = new(
player.Velocity.X,
player.Velocity.Y + player.Gravity * floatDelta * player.FallMod);
}
else {
player.Velocity = new(
player.Velocity.X,
player.Velocity.Y + player.Gravity * floatDelta);
}
var wcl = player.WallCastLow != null && player.WallCastLow.IsColliding();
var wcm = player.WallCastMid != null && player.WallCastLow.IsColliding();
var wct = player.WallCastTop != null && player.WallCastTop.IsColliding();
if (wcl && wcm && wct) {
EmitSignal(SignalName.Transitioned, this, "PlayerWallGrab");
}
if (Input.IsActionJustPressed("jump") && player.CanCoyoteJump) {
player.Velocity = new(player.Velocity.X, player.Jump);
}
LedgeLogic();
player.LastVelocityY = player.Velocity.Y;
}
private void LedgeLogic() {
if (player.IsOnFloor() || player.Velocity.Y <= -30 || player.MoveDir == Vector2.Zero) {
return;
}
if (!player.WallCastMid.IsColliding() || player.WallCastTop.IsColliding()) {
return;
}
var desiredPos = player.WallCastMid.GetCollisionPoint().Snapped(new Vector2(4, 4)) + new Vector2(-2 * player.MoveDir.X, -1);
var posTween = CreateTween().SetTrans(Tween.TransitionType.Sine);
posTween.TweenProperty(player, "global_position", desiredPos, 0.05);
player.LastVelocityY = 0.0f;
player.Velocity = new (0.0f, player.LedgeJump);
}
}

View File

@@ -0,0 +1 @@
uid://desj0bmav00ec

View File

@@ -0,0 +1,83 @@
using Godot;
public partial class PlayerGrounded : State {
private Player player;
private Node3D modelRoot;
public override void _Ready() {
player = GetNode<Player>("../..");
modelRoot = GetNode<Node3D>("../../ModelContainer/SubViewportContainer/SubViewport/blockbench_export");
}
public override void Enter() {
player.StateLabel?.Text = Name;
player.ResetCoyoteTimer();
player.InParachute = false;
player.AnimStateMachine?.Travel("Grounded");
var fall_speed = Mathf.Abs(player.LastVelocityY);
fall_speed *= 0.0025f;
if (modelRoot != null) {
modelRoot.Scale = new (
modelRoot.Scale.X + fall_speed,
modelRoot.Scale.Y - fall_speed,
modelRoot.Scale.Z + fall_speed);
var fallTween = GetTree().CreateTween();
fallTween.TweenProperty(
modelRoot,
"scale",
new Vector3(1.0f, 1.0f, 1.0f),
0.2);
}
// if (player.SprintStateMachine) {
// if (move_dir < 0) {
// player.SprintStateMachine.travel("sprint_left");
// }
// else if (move_dir > 0) {
// player.SprintStateMachine.travel("sprint_right");
// }
// }
}
public override void PhysicsUpdate(double delta) {
if (!player.IsOnFloor()) {
EmitSignal(SignalName.Transitioned, this, "PlayerAirborne");
}
if (player.MoveDir.X != 0) {
if (Input.IsActionPressed("slow_walk")) {
player.Velocity = new (
Mathf.MoveToward(player.Velocity.X, player.MoveDir.X * player.Speed * player.SlowMod, player.Acceleration),
player.Velocity.Y);
player.GroundedStateMachine?.Travel("Walk");
}
else {
player.Velocity = new (
Mathf.MoveToward(player.Velocity.X, player.MoveDir.X * player.Speed, player.Acceleration),
player.Velocity.Y);
player.GroundedStateMachine?.Travel("Sprint");
if (player.MoveDir.X < 0) {
player.SprintStateMachine?.Travel("sprint_left");
}
else if (player.MoveDir.X > 0) {
player.SprintStateMachine?.Travel("sprint_right");
}
}
}
else {
player.Velocity = new (
Mathf.MoveToward(player.Velocity.X, 0.0f, player.Friction),
player.Velocity.Y);
player.GroundedStateMachine?.Travel("Idle");
}
if (Input.IsActionJustPressed("jump") && player.IsOnFloor()) {
player.Velocity = new (player.Velocity.X, player.Jump);
EmitSignal(SignalName.Transitioned, this, "PlayerAirborne");
}
}
}

View File

@@ -0,0 +1 @@
uid://dv3sve5vfcn55

View File

@@ -0,0 +1,61 @@
using Godot;
public partial class PlayerWallGrab : State {
private Player player;
private float wallDirection;
public override void _Ready() {
player = GetNode<Player>("../..");
}
public override void Enter() {
player.StateLabel?.Text = Name;
player.InParachute = false;
Vector2 desiredPos = new (
(player.WallCastLow.GetCollisionPoint().Snapped(new Vector2(4, 4)) + new Vector2(-2 * player.MoveDir.X, 0)).X,
player.GlobalPosition.Y);
var posTween = CreateTween().SetTrans(Tween.TransitionType.Sine);
posTween.TweenProperty(player, "global_position", desiredPos, 0.05);
wallDirection = player.MoveDir.X;
}
public override void PhysicsUpdate(double delta) {
var floatDelta = (float)delta;
player.Velocity = new (0.0f, player.Velocity.Y);
if (player.MoveDir.X != 0.0) {
if (!player.WallCastLow.IsColliding() ||
!player.WallCastMid.IsColliding() ||
!player.WallCastTop.IsColliding()) {
EmitSignal(SignalName.Transitioned, this, "PlayerAirborne");
}
}
if (player.MoveDir.Y != 0) {
player.Velocity = new (
player.Velocity.X,
Mathf.MoveToward(player.Velocity.Y, player.MoveDir.Y * player.WallSpeed, player.Acceleration));
}
else {
player.Velocity = new (
player.Velocity.X,
Mathf.MoveToward(player.Velocity.Y, 0.0f, floatDelta * player.WallFriction));
}
if (Input.IsActionJustPressed("jump")) {
player.WallCastTop?.Enabled = false;
player.WallCastMid?.Enabled = false;
player.WallCastLow?.Enabled = false;
player.WallCastDelayTimer.Start();
EmitSignal(SignalName.Transitioned, this, "PlayerAirborne");
player.Velocity = new (player.Velocity.X, player.Jump * 0.85f);
if (wallDirection > 0) {
player.Velocity = new (-player.WallJump, player.Velocity.Y);
}
else {
player.Velocity = new (player.WallJump, player.Velocity.Y);
}
}
}
}

View File

@@ -0,0 +1 @@
uid://dn3js76wk06we

Binary file not shown.

View File

@@ -0,0 +1,29 @@
extends Node
var config = ConfigFile.new()
const SETTINGS_FILE_PATH = "user://settings.ini"
signal ControlSettingsChanged
func _ready():
if !FileAccess.file_exists(SETTINGS_FILE_PATH):
config.set_value("control","camera_sensitivity", 0.5)
config.set_value("control","invert_mouse_y", true)
config.save(SETTINGS_FILE_PATH)
else:
config.load(SETTINGS_FILE_PATH)
func save_control_setting(key: String, value):
config.set_value("control", key, value)
config.save(SETTINGS_FILE_PATH)
func load_control_settings():
var control_settings = {}
for key in config.get_section_keys("control"):
control_settings[key] = config.get_value("control", key)
return control_settings

View File

@@ -0,0 +1 @@
uid://ceogo7m8ehjpt

View File

@@ -0,0 +1,21 @@
extends Control
@onready var sceneName
@onready var scene_load_status : float = 0
@onready var progress = []
@onready var progressBar = $TextureProgressBar
func _ready():
sceneName = SceneSwitcher.new_scene
ResourceLoader.load_threaded_request(sceneName)
func _process(_delta):
scene_load_status = ResourceLoader.load_threaded_get_status(sceneName,progress)
progressBar.value = lerp(progressBar.value,progress[0]*100,0.25)
#print(progressBar.value)
if scene_load_status == ResourceLoader.THREAD_LOAD_LOADED and progressBar.value >= 99:
var newScene = ResourceLoader.load_threaded_get(sceneName)
get_tree().change_scene_to_packed(newScene)

View File

@@ -0,0 +1 @@
uid://8yal1fqglvut

View File

@@ -0,0 +1,40 @@
extends Control
@onready var settings_menu : Control = $SettingsMenu
@onready var goto_scene : String = "res://scenes/user_interface/title_screen.tscn"
var paused : bool = false
func _ready():
hide()
settings_menu.hide()
func _input(event):
if event.is_action_pressed("ui_cancel") and get_tree().paused and settings_menu.visible == false:
resume()
elif event.is_action_pressed("ui_cancel") and !get_tree().paused:
pause()
func pause():
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
get_tree().paused = true
show()
func resume():
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
get_tree().paused = false
hide()
settings_menu.hide()
func _on_resume_pressed():
resume()
func _on_settings_button_pressed():
settings_menu.show()
func _on_quit_button_pressed():
get_tree().paused = false
SceneSwitcher.transition_scene(goto_scene)

View File

@@ -0,0 +1 @@
uid://cydmxkxpei0o3

View File

@@ -0,0 +1,8 @@
extends Node
@export var new_scene : String
func transition_scene(goto_scene):
new_scene = goto_scene
var loadingScreen = load("res://scenes/user_interface/loading_screen.tscn")
get_tree().change_scene_to_packed(loadingScreen)

View File

@@ -0,0 +1 @@
uid://d3a3svfiul3li

View File

@@ -0,0 +1,29 @@
extends Control
@onready var InvertMouseY := $VBoxContainer/TabContainer/Control/InvertMouse/InvertMouse
@onready var CameraSensSlider := $VBoxContainer/TabContainer/Control/CameraSens/CameraSens
func _ready():
var control_settings = ConfigHandler.load_control_settings()
InvertMouseY.button_pressed = control_settings.invert_mouse_y
CameraSensSlider.value = control_settings.camera_sensitivity * 100
func _input(event):
if event.is_action_released("ui_cancel"):
_on_exit_button_pressed()
func _on_invert_mouse_toggled(toggled_on):
ConfigHandler.save_control_setting("invert_mouse_y", toggled_on)
ConfigHandler.ControlSettingsChanged.emit()
func _on_camera_sens_drag_ended(value_changed):
if value_changed:
ConfigHandler.save_control_setting("camera_sensitivity", CameraSensSlider.value / 100)
ConfigHandler.ControlSettingsChanged.emit()
func _on_exit_button_pressed():
hide()

View File

@@ -0,0 +1 @@
uid://f1f4otkm5x0r

View File

@@ -0,0 +1,9 @@
extends Label
@export var LabeledSlider : Slider
# Called when the node enters the scene tree for the first time.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
text = str(LabeledSlider.value)

View File

@@ -0,0 +1 @@
uid://3uqf5dorg2et

View File

@@ -0,0 +1,4 @@
extends Button
func _on_pressed():
get_tree().quit()

View File

@@ -0,0 +1 @@
uid://cx5wq6cs2lqxg

View File

@@ -0,0 +1,6 @@
extends Button
@export var goto_scene : String
func _on_pressed():
SceneSwitcher.transition_scene(goto_scene)

View File

@@ -0,0 +1 @@
uid://b34ocehefekp3

View File

@@ -0,0 +1,11 @@
extends Control
@onready var settings_menu : Control = $SettingsMenu
func _ready():
settings_menu.hide()
func _on_settings_button_pressed():
settings_menu.show()

View File

@@ -0,0 +1 @@
uid://bs1g3xjxf8i3k