Movement refactor
This commit is contained in:
@@ -64,13 +64,13 @@ public partial class BrickThrowComponent : Node, ISkill
|
||||
var instance = BrickScene.Instantiate<Node2D>();
|
||||
var init = instance.GetNodeOrNull<ProjectileInitComponent>("ProjectileInitComponent");
|
||||
|
||||
if (init != null && PlayerController.CurrentMovement is PlatformMovementComponent)
|
||||
if (init != null)
|
||||
{
|
||||
var @params = new ProjectileInitParams()
|
||||
{
|
||||
Position = PlayerController.GlobalPosition,
|
||||
Rotation = PlayerController.Rotation,
|
||||
Direction = PlayerController.CurrentMovement.LastDirection,
|
||||
Direction = PlayerController.LastDirection,
|
||||
PowerMultiplier = powerMultiplier,
|
||||
};
|
||||
|
||||
|
@@ -21,10 +21,11 @@ public partial class JumpPadComponent : Node
|
||||
var canBeLaunched = body.GetNodeOrNull<CanBeLaunchedComponent>("CanBeLaunchedComponent");
|
||||
if (canBeLaunched == null) return;
|
||||
|
||||
if (body is not PlayerController { CurrentMovement: PlatformMovementComponent movement }) return;
|
||||
if (body is not PlayerController player) return;
|
||||
|
||||
_ = HandleLaunchPadAnimation();
|
||||
movement.Body.Velocity = new Vector2(movement.Body.Velocity.X, -JumpForce);
|
||||
movement.JumpSfx?.Play();
|
||||
player.Velocity = new Vector2(player.Velocity.X, -JumpForce);
|
||||
player.EmitSignal(PlayerController.SignalName.JumpInitiated);
|
||||
}
|
||||
|
||||
private async Task HandleLaunchPadAnimation()
|
||||
|
28
scripts/components/Movement/GravityAbility.cs
Normal file
28
scripts/components/Movement/GravityAbility.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class GravityAbility : MovementAbility
|
||||
{
|
||||
public float AscendGravity { get; set; }
|
||||
public float DescendGravity { get; set; }
|
||||
|
||||
private float _gravity;
|
||||
|
||||
public override void Initialize(PlayerController controller)
|
||||
{
|
||||
base.Initialize(controller);
|
||||
_gravity = (float)ProjectSettings.GetSetting("physics/2d/default_gravity");
|
||||
}
|
||||
|
||||
public override Vector2 ProcessMovement(Vector2 velocity, double delta)
|
||||
{
|
||||
if (_body.IsOnFloor()) return velocity;
|
||||
|
||||
var gravityToApply = velocity.Y < 0 ? AscendGravity : DescendGravity;
|
||||
velocity.Y += gravityToApply * (float)delta;
|
||||
|
||||
return velocity;
|
||||
}
|
||||
}
|
1
scripts/components/Movement/GravityAbility.cs.uid
Normal file
1
scripts/components/Movement/GravityAbility.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://chgw53qwt7rt8
|
26
scripts/components/Movement/GroundMovementAbility.cs
Normal file
26
scripts/components/Movement/GroundMovementAbility.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class GroundMovementAbility : MovementAbility
|
||||
{
|
||||
[Export] public float MaxSpeed { get; set; } = 300.0f;
|
||||
[Export] public float Acceleration { get; set; } = 2000.0f;
|
||||
[Export] public float Friction { get; set; } = 1500.0f;
|
||||
|
||||
public override Vector2 ProcessMovement(Vector2 velocity, double delta)
|
||||
{
|
||||
if (_input == null) return Vector2.Zero;
|
||||
|
||||
var direction = _input.MoveDirection.X;
|
||||
var targetSpeed = direction * MaxSpeed;
|
||||
|
||||
if (direction != 0)
|
||||
velocity.X = Mathf.MoveToward(velocity.X, targetSpeed, Acceleration * (float)delta);
|
||||
else
|
||||
velocity.X = Mathf.MoveToward(velocity.X, 0, Friction * (float)delta);
|
||||
|
||||
return velocity;
|
||||
}
|
||||
}
|
1
scripts/components/Movement/GroundMovementAbility.cs.uid
Normal file
1
scripts/components/Movement/GroundMovementAbility.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bf4yclropol43
|
41
scripts/components/Movement/JumpAbility.cs
Normal file
41
scripts/components/Movement/JumpAbility.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class JumpAbility : MovementAbility
|
||||
{
|
||||
[Export] public float JumpVelocity { get; set; } = -400.0f;
|
||||
[Export] public int CoyoteFrames { get; set; } = 6;
|
||||
|
||||
private Timer _coyoteTimer;
|
||||
private bool _wasOnFloor = false;
|
||||
|
||||
public override void Initialize(PlayerController controller)
|
||||
{
|
||||
base.Initialize(controller);
|
||||
_coyoteTimer = new Timer { OneShot = true, WaitTime = CoyoteFrames / (float)Engine.GetPhysicsTicksPerSecond() };
|
||||
AddChild(_coyoteTimer);
|
||||
}
|
||||
|
||||
public override Vector2 ProcessMovement(Vector2 velocity, double delta)
|
||||
{
|
||||
if (!_body.IsOnFloor() && _wasOnFloor)
|
||||
{
|
||||
_coyoteTimer.Start();
|
||||
}
|
||||
|
||||
if (_input.JumpHeld)
|
||||
{
|
||||
if (_body.IsOnFloor() || !_coyoteTimer.IsStopped())
|
||||
{
|
||||
velocity.Y = JumpVelocity;
|
||||
_controller.EmitSignal(PlayerController.SignalName.JumpInitiated);
|
||||
_coyoteTimer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
_wasOnFloor = _body.IsOnFloor();
|
||||
return velocity;
|
||||
}
|
||||
}
|
1
scripts/components/Movement/JumpAbility.cs.uid
Normal file
1
scripts/components/Movement/JumpAbility.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://d0bb48upefu20
|
38
scripts/components/Movement/MovementAbility.cs
Normal file
38
scripts/components/Movement/MovementAbility.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public abstract partial class MovementAbility : Node
|
||||
{
|
||||
protected PlayerController _controller;
|
||||
protected CharacterBody2D _body;
|
||||
protected PlayerInputHandler _input;
|
||||
|
||||
public virtual void Initialize(PlayerController controller)
|
||||
{
|
||||
Name = $"{GetType().Name}";
|
||||
|
||||
_controller = controller;
|
||||
if (_controller == null)
|
||||
{
|
||||
GD.PushError($"Movement ability '{Name}' must be a child of a PlayerController.");
|
||||
SetProcess(false);
|
||||
SetPhysicsProcess(false);
|
||||
return;
|
||||
}
|
||||
|
||||
_body = _controller;
|
||||
_input = _controller.GetNode<PlayerInputHandler>("PlayerInputHandler");
|
||||
if (_input == null)
|
||||
{
|
||||
GD.PushError($"PlayerController '{_controller.Name}' must have a PlayerInputHandler child.");
|
||||
SetProcess(false);
|
||||
SetPhysicsProcess(false);
|
||||
}
|
||||
|
||||
_body.Velocity = Vector2.Zero;
|
||||
}
|
||||
|
||||
public abstract Vector2 ProcessMovement(Vector2 currentVelocity, double delta);
|
||||
}
|
1
scripts/components/Movement/MovementAbility.cs.uid
Normal file
1
scripts/components/Movement/MovementAbility.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cmlwisjpoxk7f
|
15
scripts/components/Movement/OneWayPlatformAbility.cs
Normal file
15
scripts/components/Movement/OneWayPlatformAbility.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class OneWayPlatformAbility : MovementAbility
|
||||
{
|
||||
public override Vector2 ProcessMovement(Vector2 velocity, double delta)
|
||||
{
|
||||
if (_input.DownHeld && _controller != null)
|
||||
_controller.Position += new Vector2(0, 1);
|
||||
|
||||
return velocity;
|
||||
}
|
||||
}
|
1
scripts/components/Movement/OneWayPlatformAbility.cs.uid
Normal file
1
scripts/components/Movement/OneWayPlatformAbility.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ck6kmnbwhsttt
|
28
scripts/components/Movement/PlayerInputHandler.cs
Normal file
28
scripts/components/Movement/PlayerInputHandler.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class PlayerInputHandler : Node
|
||||
{
|
||||
public Vector2 MoveDirection { get; private set; } = Vector2.Zero;
|
||||
public bool JumpPressed { get; private set; }
|
||||
public bool JumpReleased { get; private set; }
|
||||
public bool JumpHeld { get; private set; }
|
||||
public bool DownPressed { get; private set; }
|
||||
public bool DownReleased { get; private set; }
|
||||
public bool DownHeld { get; private set; }
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
MoveDirection = Input.GetVector("left", "right", "up", "down");
|
||||
|
||||
JumpPressed = Input.IsActionJustPressed("jump");
|
||||
JumpReleased = Input.IsActionJustReleased("jump");
|
||||
JumpHeld = Input.IsActionPressed("jump");
|
||||
|
||||
DownPressed = Input.IsActionJustPressed("down");
|
||||
DownReleased = Input.IsActionJustReleased("down");
|
||||
DownHeld = Input.IsActionPressed("down");
|
||||
}
|
||||
}
|
1
scripts/components/Movement/PlayerInputHandler.cs.uid
Normal file
1
scripts/components/Movement/PlayerInputHandler.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dssa2taiwktis
|
29
scripts/components/Movement/SpaceshipMovementAbility.cs
Normal file
29
scripts/components/Movement/SpaceshipMovementAbility.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class SpaceshipMovementAbility : MovementAbility
|
||||
{
|
||||
[Export] public float MaxSpeed { get; set; } = 300f;
|
||||
[Export] public float Acceleration { get; set; } = 2000f;
|
||||
[Export] public float Friction { get; set; } = 1700f;
|
||||
|
||||
public override Vector2 ProcessMovement(Vector2 currentVelocity, double delta)
|
||||
{
|
||||
if (_input == null) return Vector2.Zero;
|
||||
|
||||
var inputVector = _input.MoveDirection;
|
||||
|
||||
if (inputVector != Vector2.Zero)
|
||||
{
|
||||
currentVelocity = currentVelocity.MoveToward(inputVector * MaxSpeed, Acceleration * (float)delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentVelocity = currentVelocity.MoveToward(Vector2.Zero, Friction * (float)delta);
|
||||
}
|
||||
|
||||
return currentVelocity;
|
||||
}
|
||||
}
|
@@ -0,0 +1 @@
|
||||
uid://drgwa5q5k2tbm
|
68
scripts/components/Movement/VariableJumpAbility.cs
Normal file
68
scripts/components/Movement/VariableJumpAbility.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class VariableJumpAbility : MovementAbility
|
||||
{
|
||||
[ExportGroup("Jump Design")]
|
||||
[Export] public float JumpHeight { get; set; } = 100f;
|
||||
[Export] public float JumpTimeToPeak { get; set; } = 0.5f;
|
||||
[Export] public float JumpTimeToDescent { get; set; } = 0.4f;
|
||||
|
||||
[ExportGroup("Jump Feel")]
|
||||
// How much to reduce upward velocity when the jump button is released mid-air.
|
||||
[Export(PropertyHint.Range, "0.0, 1.0, 0.05")] public float JumpCutMultiplier { get; set; } = 0.5f;
|
||||
[Export(PropertyHint.Range, "0,10,1")] public int CoyoteFrames { get; set; } = 6;
|
||||
|
||||
private float _jumpVelocity;
|
||||
private bool _wasOnFloor = false;
|
||||
private bool _hasJumpedInAir = false;
|
||||
private Timer _coyoteTimer;
|
||||
|
||||
public float AscendGravity { get; private set; }
|
||||
public float DescendGravity { get; private set; }
|
||||
|
||||
public override void Initialize(PlayerController controller)
|
||||
{
|
||||
base.Initialize(controller);
|
||||
|
||||
_jumpVelocity = (2.0f * JumpHeight) / JumpTimeToPeak * -1.0f;
|
||||
AscendGravity = (-2.0f * JumpHeight) / (JumpTimeToPeak * JumpTimeToPeak) * -1.0f;
|
||||
DescendGravity = (-2.0f * JumpHeight) / (JumpTimeToDescent * JumpTimeToDescent) * -1.0f;
|
||||
|
||||
_coyoteTimer = new Timer { OneShot = true, WaitTime = CoyoteFrames / (float)Engine.GetPhysicsTicksPerSecond() };
|
||||
AddChild(_coyoteTimer);
|
||||
}
|
||||
|
||||
|
||||
public override Vector2 ProcessMovement(Vector2 velocity, double delta)
|
||||
{
|
||||
var isGrounded = _body.IsOnFloor();
|
||||
|
||||
if (!isGrounded && _wasOnFloor) _coyoteTimer.Start();
|
||||
if (isGrounded) _hasJumpedInAir = false;
|
||||
|
||||
if (_input.JumpHeld && !_hasJumpedInAir)
|
||||
{
|
||||
if (isGrounded || !_coyoteTimer.IsStopped())
|
||||
{
|
||||
velocity.Y = _jumpVelocity;
|
||||
_controller.EmitSignal(PlayerController.SignalName.JumpInitiated);
|
||||
_coyoteTimer.Stop();
|
||||
_hasJumpedInAir = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_input.JumpReleased)
|
||||
{
|
||||
if (velocity.Y < 0.0f)
|
||||
{
|
||||
velocity.Y *= JumpCutMultiplier;
|
||||
}
|
||||
}
|
||||
|
||||
_wasOnFloor = isGrounded;
|
||||
return velocity;
|
||||
}
|
||||
}
|
1
scripts/components/Movement/VariableJumpAbility.cs.uid
Normal file
1
scripts/components/Movement/VariableJumpAbility.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ccksp2e76s7sr
|
37
scripts/components/Movement/WallJumpAbility.cs
Normal file
37
scripts/components/Movement/WallJumpAbility.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class WallJumpAbility : MovementAbility
|
||||
{
|
||||
[ExportGroup("Wall Jump Design")]
|
||||
[Export] public Vector2 WallJumpVelocity { get; set; } = new(500.0f, -350.0f);
|
||||
|
||||
[ExportGroup("Wall Slide Feel")]
|
||||
[Export(PropertyHint.Range, "0.0, 1.0, 0.05")] public float WallSlideGravityMultiplier { get; set; } = 0.7f;
|
||||
[Export] public float MaxWallSlideSpeed { get; set; } = 150.0f;
|
||||
|
||||
public override Vector2 ProcessMovement(Vector2 velocity, double delta)
|
||||
{
|
||||
var isOnWall = _body.IsOnWall();
|
||||
|
||||
if (isOnWall && !_body.IsOnFloor() && velocity.Y > 0f)
|
||||
{
|
||||
var gravity = (float)ProjectSettings.GetSetting("physics/2d/default_gravity");
|
||||
var newYVelocity = velocity.Y + gravity * WallSlideGravityMultiplier * (float)delta;
|
||||
|
||||
velocity.Y = Mathf.Min(newYVelocity, MaxWallSlideSpeed);
|
||||
}
|
||||
|
||||
if (isOnWall && _input.JumpHeld)
|
||||
{
|
||||
var wallNormal = _body.GetWallNormal();
|
||||
|
||||
_controller.EmitSignal(PlayerController.SignalName.JumpInitiated);
|
||||
velocity = new Vector2(wallNormal.X * WallJumpVelocity.X, WallJumpVelocity.Y);
|
||||
}
|
||||
|
||||
return velocity;
|
||||
}
|
||||
}
|
1
scripts/components/Movement/WallJumpAbility.cs.uid
Normal file
1
scripts/components/Movement/WallJumpAbility.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://6foetukqmyoe
|
@@ -1,103 +1,125 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Godot;
|
||||
using Mr.BrickAdventures.scripts.interfaces;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class PlayerController : CharacterBody2D
|
||||
{
|
||||
[Export]
|
||||
public string DefaultMovementType { get; set; } = "platform";
|
||||
|
||||
[Export]
|
||||
public Godot.Collections.Dictionary<string, NodePath> MovementTypes { get; set; }
|
||||
|
||||
[Export]
|
||||
public Sprite2D ShipSprite { get; set; }
|
||||
|
||||
public IMovement CurrentMovement = null;
|
||||
[Signal]
|
||||
public delegate void MovementSwitchedEventHandler(string movementType);
|
||||
|
||||
[Export] private Node MovementAbilitiesContainer { get; set; }
|
||||
|
||||
[ExportGroup("Movement Ability Scenes")]
|
||||
[Export] public PackedScene GroundMovementScene { get; set; }
|
||||
[Export] public PackedScene JumpMovementScene { get; set; }
|
||||
[Export] public PackedScene GravityScene { get; set; }
|
||||
[Export] public PackedScene OneWayPlatformScene { get; set; }
|
||||
[Export] public PackedScene SpaceshipMovementScene { get; set; }
|
||||
[Export] public PackedScene WallJumpScene { get; set; }
|
||||
|
||||
[Signal] public delegate void JumpInitiatedEventHandler();
|
||||
|
||||
public Vector2 LastDirection { get; private set; } = Vector2.Right;
|
||||
public Vector2 PreviousVelocity { get; private set; } = Vector2.Zero;
|
||||
|
||||
private List<MovementAbility> _abilities = [];
|
||||
private PlayerInputHandler _inputHandler;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
base._Ready();
|
||||
|
||||
foreach (var movementType in MovementTypes.Keys)
|
||||
_inputHandler = GetNode<PlayerInputHandler>("PlayerInputHandler");
|
||||
foreach (var child in MovementAbilitiesContainer.GetChildren())
|
||||
{
|
||||
var movementNode = GetNodeOrNull(movementType);
|
||||
if (movementNode is IMovement playerMovement)
|
||||
if (child is MovementAbility ability)
|
||||
{
|
||||
playerMovement.Enabled = false;
|
||||
ability.Initialize(this);
|
||||
_abilities.Add(ability);
|
||||
}
|
||||
}
|
||||
|
||||
SwitchMovement(DefaultMovementType);
|
||||
|
||||
_ = ConnectJumpAndGravityAbilities();
|
||||
}
|
||||
|
||||
public override void _UnhandledInput(InputEvent @event)
|
||||
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
base._UnhandledInput(@event);
|
||||
|
||||
if (@event is InputEventKey inputEventKey && inputEventKey.IsActionPressed("switch_movement"))
|
||||
var velocity = Velocity;
|
||||
|
||||
foreach (var ability in _abilities)
|
||||
{
|
||||
var nextMovementType = GetNextMovementType();
|
||||
SwitchMovement(nextMovementType);
|
||||
velocity = ability.ProcessMovement(velocity, delta);
|
||||
}
|
||||
}
|
||||
|
||||
private void SwitchMovement(string movementType)
|
||||
{
|
||||
if (CurrentMovement != null)
|
||||
|
||||
if (_inputHandler.MoveDirection.X != 0)
|
||||
{
|
||||
CurrentMovement.Enabled = false;
|
||||
LastDirection = new Vector2(_inputHandler.MoveDirection.X > 0 ? 1 : -1, 0);
|
||||
}
|
||||
|
||||
if (MovementTypes.TryGetValue(movementType, out var movement))
|
||||
PreviousVelocity = Velocity;
|
||||
Velocity = velocity;
|
||||
MoveAndSlide();
|
||||
}
|
||||
|
||||
public void AddAbility(MovementAbility ability)
|
||||
{
|
||||
MovementAbilitiesContainer.AddChild(ability);
|
||||
ability.Initialize(this);
|
||||
_abilities.Add(ability);
|
||||
}
|
||||
|
||||
private void ClearMovementAbilities()
|
||||
{
|
||||
foreach (var ability in _abilities)
|
||||
{
|
||||
CurrentMovement = GetNodeOrNull<IMovement>(movement);
|
||||
if (CurrentMovement == null)
|
||||
ability.QueueFree();
|
||||
}
|
||||
_abilities.Clear();
|
||||
}
|
||||
|
||||
public void RemoveAbility<T>() where T : MovementAbility
|
||||
{
|
||||
for (var i = _abilities.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (_abilities[i] is T)
|
||||
{
|
||||
GD.PushError($"Movement type '{movementType}' not found in MovementTypes.");
|
||||
return;
|
||||
var ability = _abilities[i];
|
||||
_abilities.RemoveAt(i);
|
||||
ability.QueueFree();
|
||||
break;
|
||||
}
|
||||
CurrentMovement.Enabled = true;
|
||||
EmitSignalMovementSwitched(movementType);
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.PushError($"Movement type '{movementType}' not found in MovementTypes.");
|
||||
}
|
||||
|
||||
if (CurrentMovement == null)
|
||||
{
|
||||
GD.PushError("No current movement set after switching.");
|
||||
}
|
||||
}
|
||||
|
||||
private string GetNextMovementType()
|
||||
public void SetPlatformMovement()
|
||||
{
|
||||
var keys = new List<string>(MovementTypes.Keys);
|
||||
var currentIndex = keys.IndexOf(CurrentMovement?.MovementType);
|
||||
|
||||
if (currentIndex == -1)
|
||||
ClearMovementAbilities();
|
||||
|
||||
if (GroundMovementScene != null) AddAbility(GroundMovementScene.Instantiate<MovementAbility>());
|
||||
if (JumpMovementScene != null) AddAbility(JumpMovementScene.Instantiate<MovementAbility>());
|
||||
if (GravityScene != null) AddAbility(GravityScene.Instantiate<MovementAbility>());
|
||||
if (OneWayPlatformScene != null) AddAbility(OneWayPlatformScene.Instantiate<MovementAbility>());
|
||||
|
||||
_ = ConnectJumpAndGravityAbilities();
|
||||
}
|
||||
|
||||
public void SetSpaceshipMovement()
|
||||
{
|
||||
ClearMovementAbilities();
|
||||
|
||||
if (SpaceshipMovementScene != null) AddAbility(SpaceshipMovementScene.Instantiate<MovementAbility>());
|
||||
}
|
||||
|
||||
private async Task ConnectJumpAndGravityAbilities()
|
||||
{
|
||||
await ToSignal(GetTree(), SceneTree.SignalName.ProcessFrame);
|
||||
|
||||
var jumpAbility = _abilities.OfType<VariableJumpAbility>().FirstOrDefault();
|
||||
var gravityAbility = _abilities.OfType<GravityAbility>().FirstOrDefault();
|
||||
|
||||
if (jumpAbility != null && gravityAbility != null)
|
||||
{
|
||||
return DefaultMovementType;
|
||||
gravityAbility.AscendGravity = jumpAbility.AscendGravity;
|
||||
gravityAbility.DescendGravity = jumpAbility.DescendGravity;
|
||||
}
|
||||
|
||||
currentIndex = (currentIndex + 1) % keys.Count;
|
||||
return keys[currentIndex];
|
||||
}
|
||||
|
||||
public void OnSpaceshipEntered()
|
||||
{
|
||||
SwitchMovement("ship");
|
||||
ShipSprite.Visible = true;
|
||||
}
|
||||
|
||||
public void OnSpaceshipExited()
|
||||
{
|
||||
SwitchMovement(DefaultMovementType);
|
||||
ShipSprite.Visible = false;
|
||||
}
|
||||
}
|
29
scripts/components/PlayerSfxComponent.cs
Normal file
29
scripts/components/PlayerSfxComponent.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class PlayerSfxComponent : Node
|
||||
{
|
||||
[Export] public AudioStreamPlayer2D JumpSfx { get; set; }
|
||||
|
||||
private PlayerController _controller;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_controller = GetOwner<PlayerController>();
|
||||
if (_controller == null)
|
||||
{
|
||||
GD.PrintErr("PlayerSfxComponent must be a child of a PlayerController.");
|
||||
SetProcess(false);
|
||||
}
|
||||
|
||||
_controller.JumpInitiated += OnJumpInitiated;
|
||||
}
|
||||
|
||||
private void OnJumpInitiated()
|
||||
{
|
||||
if (JumpSfx is { Playing: false })
|
||||
JumpSfx.Play();
|
||||
}
|
||||
}
|
1
scripts/components/PlayerSfxComponent.cs.uid
Normal file
1
scripts/components/PlayerSfxComponent.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b1h8r5irryxcx
|
@@ -13,7 +13,8 @@ public partial class SpaceshipEnterComponent : Area2D
|
||||
|
||||
private void OnBodyEntered(Node2D body)
|
||||
{
|
||||
if (body is not PlayerController) return;
|
||||
if (body is not PlayerController player) return;
|
||||
player.SetSpaceshipMovement();
|
||||
EmitSignalSpaceshipEntered();
|
||||
QueueFree();
|
||||
}
|
||||
|
@@ -13,7 +13,8 @@ public partial class SpaceshipExitComponent : Area2D
|
||||
|
||||
private void OnBodyEntered(Node2D body)
|
||||
{
|
||||
if (body is not PlayerController) return;
|
||||
if (body is not PlayerController player) return;
|
||||
EmitSignalSpaceshipExit();
|
||||
player.SetPlatformMovement();
|
||||
}
|
||||
}
|
40
scripts/components/SpriteTilterComponent.cs
Normal file
40
scripts/components/SpriteTilterComponent.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class SpriteTilterComponent : Node
|
||||
{
|
||||
[Export] public Node2D RotationTarget { get; set; }
|
||||
[Export(PropertyHint.Range, "0,45,1")] public float MaxTiltAngle { get; set; } = 10.0f;
|
||||
|
||||
private CharacterBody2D _body;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_body = GetOwner<CharacterBody2D>();
|
||||
if (_body == null)
|
||||
{
|
||||
GD.PrintErr("SpriteTilterComponent must be a direct child of a CharacterBody2D.");
|
||||
SetProcess(false);
|
||||
}
|
||||
if (RotationTarget == null)
|
||||
{
|
||||
GD.PrintErr("SpriteTilterComponent needs a RotationTarget to be set in the inspector.");
|
||||
SetProcess(false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
var targetAngleRad = 0.0f;
|
||||
var horizontalVelocity = _body.Velocity.X;
|
||||
|
||||
if (horizontalVelocity > 0.1f)
|
||||
targetAngleRad = -Mathf.DegToRad(MaxTiltAngle);
|
||||
else if (horizontalVelocity < -0.1f) targetAngleRad = Mathf.DegToRad(MaxTiltAngle);
|
||||
else targetAngleRad = 0.0f;
|
||||
|
||||
RotationTarget.Rotation = targetAngleRad;
|
||||
}
|
||||
}
|
1
scripts/components/SpriteTilterComponent.cs.uid
Normal file
1
scripts/components/SpriteTilterComponent.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ceoxet1nqws8w
|
@@ -23,7 +23,7 @@ public partial class StompDamageComponent : Node
|
||||
|
||||
if (!(Root.GlobalPosition.Y < body.GlobalPosition.Y)) return;
|
||||
|
||||
var velocity = Root.CurrentMovement.PreviousVelocity;
|
||||
var velocity = Root.PreviousVelocity;
|
||||
if (!(velocity.Y > 0f)) return;
|
||||
|
||||
DealDamage(health);
|
||||
|
Reference in New Issue
Block a user