Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using Godot;
- using System;
- public partial class PlayerController : CharacterBody2D
- {
- // --- Movement ---
- [Export] public float MoveSpeed = 200f;
- [Export] public float Gravity = 1200f;
- [Export] public float MaxFallSpeed = 1000f;
- [Export] public float FastFallSpeed = 1500f;
- // --- Jump ---
- [Export] public float JumpVelocity = -400f;
- [Export] public float JumpCutMultiplier = 0.5f; // How much to cut jump if button released early
- [Export] public int MaxAirJumps = 1;
- private int remainingAirJumps;
- // --- Coyote Time / Jump Buffer ---
- [Export] public float CoyoteTime = 0.15f;
- private float coyoteTimer = 0f;
- [Export] public float JumpBufferTime = 0.15f;
- private float jumpBufferTimer = 0f;
- // --- Dash ---
- [Export] public float DashSpeed = 600f;
- [Export] public float DashTime = 0.2f;
- [Export] public float DashCooldown = 0.5f;
- [Export] public float DashInvincibilityTime = 0.2f;
- private bool isDashing = false;
- private bool hasDashed = false;
- private float dashTimer = 0f;
- private float dashCooldownTimer = 0f;
- private Vector2 dashDirection = Vector2.Zero;
- // --- Wall ---
- [Export] public float WallSlideSpeed = 100f;
- [Export] public float WallJumpVelocityX = 250f;
- [Export] public float WallJumpVelocityY = -400f;
- private bool isWallSliding = false;
- private int wallDirection = 0;
- // --- FX ---
- private Timer trailTimer;
- [Export] public PackedScene DashTrailScene;
- [Export] public PackedScene DoubleJumpParticlesScene;
- // --- Hurtbox ---
- private bool isInvincible = false;
- private float invincibilityTimer = 0f;
- private Vector2 velocity = Vector2.Zero;
- public override void _Ready()
- {
- trailTimer = new Timer();
- trailTimer.WaitTime = 0.05f;
- trailTimer.OneShot = false;
- trailTimer.Timeout += SpawnTrail;
- AddChild(trailTimer);
- }
- public override void _PhysicsProcess(double delta)
- {
- float dt = (float)delta;
- HandleTimers(dt);
- if (!isDashing)
- {
- HandleInput(dt);
- ApplyGravity(dt);
- HandleWallSlide();
- HandleJumpBuffer();
- HandleFastFall();
- }
- else
- {
- velocity = dashDirection * DashSpeed;
- dashTimer -= dt;
- if (dashTimer <= 0)
- {
- isDashing = false;
- isInvincible = false;
- trailTimer.Stop();
- }
- }
- HandleDash(dt);
- MoveAndSlide();
- }
- private void HandleTimers(float dt)
- {
- if (IsOnFloor())
- {
- coyoteTimer = CoyoteTime;
- hasDashed = false;
- remainingAirJumps = MaxAirJumps;
- }
- else
- {
- coyoteTimer -= dt;
- }
- if (jumpBufferTimer > 0)
- jumpBufferTimer -= dt;
- if (invincibilityTimer > 0)
- invincibilityTimer -= dt;
- }
- private void HandleInput(float dt)
- {
- Vector2 input = new Vector2(
- Input.GetActionStrength("ui_right") - Input.GetActionStrength("ui_left"),
- 0
- );
- velocity.X = input.X * MoveSpeed;
- }
- private void ApplyGravity(float dt)
- {
- if (!IsOnFloor() && !isWallSliding)
- {
- velocity.Y += Gravity * dt;
- if (velocity.Y > MaxFallSpeed)
- velocity.Y = MaxFallSpeed;
- }
- }
- private void HandleJumpBuffer()
- {
- if (Input.IsActionJustPressed("jump"))
- {
- jumpBufferTimer = JumpBufferTime;
- }
- if (jumpBufferTimer > 0)
- {
- if (coyoteTimer > 0)
- {
- Jump();
- }
- else if (isWallSliding)
- {
- WallJump();
- }
- else if (remainingAirJumps > 0)
- {
- DoubleJump();
- }
- }
- // Variable jump height
- if (Input.IsActionJustReleased("jump") && velocity.Y < 0)
- {
- velocity.Y *= JumpCutMultiplier;
- }
- }
- private void Jump()
- {
- velocity.Y = JumpVelocity;
- jumpBufferTimer = 0;
- coyoteTimer = 0;
- }
- private void DoubleJump()
- {
- velocity.Y = JumpVelocity;
- remainingAirJumps--;
- jumpBufferTimer = 0;
- SpawnDoubleJumpParticles();
- }
- private void WallJump()
- {
- velocity.X = -wallDirection * WallJumpVelocityX;
- velocity.Y = WallJumpVelocityY;
- isWallSliding = false;
- jumpBufferTimer = 0;
- }
- private void HandleFastFall()
- {
- if (Input.IsActionPressed("ui_down") && !IsOnFloor())
- {
- velocity.Y = Mathf.Min(velocity.Y + Gravity * 1.5f * (float)GetPhysicsProcessDeltaTime(), FastFallSpeed);
- }
- }
- private void HandleDash(float dt)
- {
- if (dashCooldownTimer > 0)
- dashCooldownTimer -= dt;
- if (Input.IsActionJustPressed("dash") && !isDashing && !hasDashed && dashCooldownTimer <= 0)
- {
- StartDash();
- }
- }
- private void StartDash()
- {
- isDashing = true;
- dashTimer = DashTime;
- dashCooldownTimer = DashCooldown;
- hasDashed = true;
- isInvincible = true;
- invincibilityTimer = DashInvincibilityTime;
- Vector2 input = new Vector2(
- Input.GetActionStrength("ui_right") - Input.GetActionStrength("ui_left"),
- Input.GetActionStrength("ui_down") - Input.GetActionStrength("ui_up")
- );
- dashDirection = Get8Direction(input);
- if (dashDirection == Vector2.Zero)
- {
- dashDirection = new Vector2(FacingRight() ? 1 : -1, 0);
- }
- trailTimer.Start();
- }
- private void HandleWallSlide()
- {
- wallDirection = 0;
- isWallSliding = false;
- if (!IsOnFloor() && Velocity.Y > 0)
- {
- if (IsOnWall())
- {
- wallDirection = GetWallNormal().X > 0 ? -1 : 1;
- isWallSliding = true;
- velocity.Y = WallSlideSpeed;
- }
- }
- }
- private Vector2 GetWallNormal()
- {
- for (int i = 0; i < GetSlideCollisionCount(); i++)
- {
- var col = GetSlideCollision(i);
- if (Mathf.Abs(col.Normal.X) > 0.9)
- {
- return col.Normal;
- }
- }
- return Vector2.Zero;
- }
- private bool FacingRight()
- {
- return Input.GetActionStrength("ui_right") >= Input.GetActionStrength("ui_left");
- }
- private Vector2 Get8Direction(Vector2 input)
- {
- if (input == Vector2.Zero)
- return Vector2.Zero;
- input = input.Normalized();
- float angle = Mathf.RadToDeg(Mathf.Atan2(input.Y, input.X));
- angle = (angle + 360f) % 360f;
- if (angle >= 337.5f || angle < 22.5f) return Vector2.Right;
- if (angle >= 22.5f && angle < 67.5f) return new Vector2(1, -1).Normalized();
- if (angle >= 67.5f && angle < 112.5f) return Vector2.Up;
- if (angle >= 112.5f && angle < 157.5f) return new Vector2(-1, -1).Normalized();
- if (angle >= 157.5f && angle < 202.5f) return Vector2.Left;
- if (angle >= 202.5f && angle < 247.5f) return new Vector2(-1, 1).Normalized();
- if (angle >= 247.5f && angle < 292.5f) return Vector2.Down;
- if (angle >= 292.5f && angle < 337.5f) return new Vector2(1, 1).Normalized();
- return Vector2.Zero;
- }
- private void SpawnTrail()
- {
- if (DashTrailScene == null) return;
- Node2D trail = (Node2D)DashTrailScene.Instantiate();
- trail.GlobalPosition = GlobalPosition;
- GetParent().AddChild(trail);
- }
- private void SpawnDoubleJumpParticles()
- {
- if (DoubleJumpParticlesScene == null) return;
- Node2D particles = (Node2D)DoubleJumpParticlesScene.Instantiate();
- particles.GlobalPosition = GlobalPosition;
- GetParent().AddChild(particles);
- }
- public void TakeDamage(int amount)
- {
- if (isInvincible)
- {
- GD.Print("Damage ignored (invincible!)");
- return;
- }
- GD.Print("Player took " + amount + " damage!");
- // TODO: Add health reduction
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement