Movement Examples

Various movement patterns and player controllers.

WASD Movement

public class PlayerMovement : Component
{
    public float Speed = 5f;
    
    protected override void OnUpdate()
    {
        var move = Vector3.Zero;
        if (RaylibInput.IsKeyDown(KeyCode.W)) move.Z += 1;
        if (RaylibInput.IsKeyDown(KeyCode.S)) move.Z -= 1;
        if (RaylibInput.IsKeyDown(KeyCode.A)) move.X -= 1;
        if (RaylibInput.IsKeyDown(KeyCode.D)) move.X += 1;
        
        if (move.LengthSquared > 0)
            Transform!.Position += move.Normalized * Speed * Time.Delta;
    }
    
    protected override void OnRender(RaylibRenderer r)
    {
        r.DrawCube(Transform!.Position, Vector3.One, Color.Blue);
    }
}

Velocity with Friction

public class VelocityMovement : Component
{
    public float Acceleration = 20f;
    public float Friction = 8f;
    public float MaxSpeed = 10f;
    private Vector3 _velocity;
    
    protected override void OnUpdate()
    {
        var input = Vector3.Zero;
        if (RaylibInput.IsKeyDown(KeyCode.W)) input.Z += 1;
        if (RaylibInput.IsKeyDown(KeyCode.S)) input.Z -= 1;
        if (RaylibInput.IsKeyDown(KeyCode.A)) input.X -= 1;
        if (RaylibInput.IsKeyDown(KeyCode.D)) input.X += 1;
        
        if (input.LengthSquared > 0)
            _velocity += input.Normalized * Acceleration * Time.Delta;
        else
            _velocity = _velocity.LerpTo(Vector3.Zero, Friction * Time.Delta);
        
        _velocity = _velocity.ClampLength(MaxSpeed);
        Transform!.Position += _velocity * Time.Delta;
    }
}

Jump Mechanic

public class JumpingPlayer : Component
{
    public float MoveSpeed = 5f;
    public float JumpForce = 10f;
    public float Gravity = 25f;
    private float _velocityY;
    private bool _grounded = true;
    
    protected override void OnUpdate()
    {
        var pos = Transform!.Position;
        
        // Horizontal movement
        var move = Vector3.Zero;
        if (RaylibInput.IsKeyDown(KeyCode.W)) move.Z += 1;
        if (RaylibInput.IsKeyDown(KeyCode.S)) move.Z -= 1;
        if (RaylibInput.IsKeyDown(KeyCode.A)) move.X -= 1;
        if (RaylibInput.IsKeyDown(KeyCode.D)) move.X += 1;
        pos += move.Normalized * MoveSpeed * Time.Delta;
        
        // Jump
        if (_grounded && RaylibInput.IsKeyPressed(KeyCode.Space))
        {
            _velocityY = JumpForce;
            _grounded = false;
        }
        
        // Gravity
        _velocityY -= Gravity * Time.Delta;
        pos.Y += _velocityY * Time.Delta;
        
        // Ground check
        if (pos.Y <= 0.5f)
        {
            pos.Y = 0.5f;
            _velocityY = 0;
            _grounded = true;
        }
        
        Transform.Position = pos;
    }
}

Dash Ability

public class DashMovement : Component
{
    public float MoveSpeed = 5f;
    public float DashSpeed = 25f;
    public float DashDuration = 0.15f;
    public float DashCooldown = 0.5f;
    
    private Vector3 _dashDir;
    private float _dashTimer;
    private float _cooldownTimer;
    
    protected override void OnUpdate()
    {
        _cooldownTimer -= Time.Delta;
        
        var input = Vector3.Zero;
        if (RaylibInput.IsKeyDown(KeyCode.W)) input.Z += 1;
        if (RaylibInput.IsKeyDown(KeyCode.S)) input.Z -= 1;
        if (RaylibInput.IsKeyDown(KeyCode.A)) input.X -= 1;
        if (RaylibInput.IsKeyDown(KeyCode.D)) input.X += 1;
        
        // Start dash
        if (RaylibInput.IsKeyPressed(KeyCode.LeftShift) && _cooldownTimer <= 0 && input.LengthSquared > 0)
        {
            _dashTimer = DashDuration;
            _dashDir = input.Normalized;
            _cooldownTimer = DashCooldown;
        }
        
        // Apply movement
        if (_dashTimer > 0)
        {
            _dashTimer -= Time.Delta;
            Transform!.Position += _dashDir * DashSpeed * Time.Delta;
        }
        else if (input.LengthSquared > 0)
        {
            Transform!.Position += input.Normalized * MoveSpeed * Time.Delta;
        }
    }
}

Smooth Follow

public class SmoothFollower : Component
{
    public string TargetName = "Player";
    public float FollowSpeed = 5f;
    public float MinDistance = 2f;
    
    protected override void OnUpdate()
    {
        var target = Scene?.FindByName(TargetName);
        if (target == null) return;
        
        float dist = Transform!.Position.DistanceTo(target.Transform.Position);
        if (dist > MinDistance)
        {
            Transform.Position = Vector3.Lerp(
                Transform.Position, 
                target.Transform.Position, 
                FollowSpeed * Time.Delta
            );
        }
    }
}

Orbit Motion

public class OrbitMotion : Component
{
    public Vector3 Center = Vector3.Zero;
    public float Radius = 5f;
    public float Speed = 1f;
    private float _angle;
    
    protected override void OnUpdate()
    {
        _angle += Speed * Time.Delta;
        Transform!.Position = Center + new Vector3(
            MathF.Cos(_angle) * Radius,
            0.5f,
            MathF.Sin(_angle) * Radius
        );
    }
}

Waypoint Patrol

public class WaypointPatrol : Component
{
    public float Speed = 3f;
    public float ArriveThreshold = 0.2f;
    
    private Vector3[] _waypoints = new[]
    {
        new Vector3(-5, 0.5f, -5),
        new Vector3(5, 0.5f, -5),
        new Vector3(5, 0.5f, 5),
        new Vector3(-5, 0.5f, 5)
    };
    private int _currentIndex;
    
    protected override void OnUpdate()
    {
        var target = _waypoints[_currentIndex];
        var dir = (target - Transform!.Position).Normalized;
        Transform.Position += dir * Speed * Time.Delta;
        
        if (Transform.Position.DistanceTo(target) < ArriveThreshold)
            _currentIndex = (_currentIndex + 1) % _waypoints.Length;
    }
}

Bounded Movement

public class BoundedMovement : Component
{
    public float Speed = 5f;
    public float BoundarySize = 10f;
    
    protected override void OnUpdate()
    {
        var move = Vector3.Zero;
        if (RaylibInput.IsKeyDown(KeyCode.W)) move.Z += 1;
        if (RaylibInput.IsKeyDown(KeyCode.S)) move.Z -= 1;
        if (RaylibInput.IsKeyDown(KeyCode.A)) move.X -= 1;
        if (RaylibInput.IsKeyDown(KeyCode.D)) move.X += 1;
        
        var pos = Transform!.Position + move.Normalized * Speed * Time.Delta;
        pos.X = MathHelper.Clamp(pos.X, -BoundarySize, BoundarySize);
        pos.Z = MathHelper.Clamp(pos.Z, -BoundarySize, BoundarySize);
        Transform.Position = pos;
    }
}