A player component controlling a chicken character's movement and actions. It reads keyboard input to move, jump, dodge, and fly, updates animation parameters and sounds, traces for ground detection, and syncs score and time with ScoreManager.
using Sandbox;
using Sandbox.Citizen;
using Sandbox.Utility;
using Sandbox.VR;
using System;
using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
using static Sandbox.ModelPhysics;
using static Sandbox.Sprite;
public sealed class ChickenControls : Component
{
[Property] public Rigidbody controller { get; set; }
[Property] public SkinnedModelRenderer model { get; set; }
private Vector3 moveDirection = Vector3.Zero;
[Property] public float gravity { get; set; } = 2f;
[Property] public float jumpforce { get; set; } = 6f;
[Property] public float dodgeforce { get; set; } = 6f;
[Property] public float speed { get; set; } = 2f;
[Property] public float timer { get; set; } = 0f;
[Property] public float flyforce { get; set; } = 20f;
[Property] public float flyspeed { get; set; } = 4f;
[Property] public float dodgedir { get; set; } = 0f;
[Property] public int tapCount { get; set; } = 0;
[Property] public SoundEvent chickenrun { get; set; }
[Property] public SoundEvent cluck { get; set; }
[Property] public SoundEvent wingsflap { get; set; }
[Property] public SoundEvent wingsfly { get; set; }
[Property]public SoundEvent dodge { get; set; }
[Property] public float TraceDistance { get; set; } = 2.0f;
[Property] public float TraceRadius { get; set; } = 0.4f;
[Property] public bool IsOnGround;
[Property] public int cornpoints { get; set; }
[Property] public TimeSince gametime { get; set; }
[Property] public AnimatedVelocityComponent chickenVel { get; set; }
protected override void OnStart()
{
gametime = ScoreManager.CurrentTime;
}
protected override void OnUpdate()
{
cornpoints = ScoreManager.CurrentScore;
ScoreManager.CurrentTime = gametime;
}
protected override void OnFixedUpdate()
{
ProcessGroundMovement();
ProcessGroundJump();
ProcessFly();
ProcessFlyMovement();
ProcessDodge();
moveDirection = controller.Velocity;
var startPos = Transform.Position + Vector3.Up * 0.1f;
var endPos = startPos + Vector3.Down * TraceDistance;
// Perform a sphere/capsule trace to check for solid objects
var tr = Scene.Trace.Sphere( TraceRadius, startPos, endPos )
.IgnoreGameObject( GameObject ) // Don't hit the player
.Run();
// If the trace hit anything solid, we are grounded
IsOnGround = tr.Hit;
}
void ProcessGroundMovement()
{
if ( IsOnGround && Input.Keyboard.Down( "D" ) && (timer < 1) )
{
MoveRight();
if ( IsOnGround && Input.Keyboard.Pressed( "SHIFT" ) )
{
Dodge();
}
}
else if ( IsOnGround && !Input.Keyboard.Pressed( "D" ) && !Input.Keyboard.Pressed( "A" ) && !Input.Keyboard.Down( "SHIFT" ) && !Input.Keyboard.Down( "Space" ) )
{
StopFlying();
}
if ( IsOnGround && Input.Keyboard.Down( "A" ) && (timer < 1) )
{
MoveLeft();
}
if ( IsOnGround && Input.Keyboard.Pressed( "D" ) )
{
GameObject.PlaySound( chickenrun );
}
if ( Input.Keyboard.Released( "D" ) )
{
GameObject.StopAllSounds();
}
if ( IsOnGround && Input.Keyboard.Pressed( "A" ) )
{
GameObject.PlaySound( chickenrun );
}
if ( Input.Keyboard.Released( "A" ) )
{
GameObject.StopAllSounds();
}
}
void ProcessDodge()
{
if ( IsOnGround && Input.Keyboard.Pressed( "SHIFT" ) )
{
Dodge();
}
}
void ProcessGroundJump()
{
if ( IsOnGround && Input.Keyboard.Pressed( "Space" ) && (timer < 1) )
{
Jump();
}
if ( Input.Keyboard.Pressed( "Space" ) )
{
tapCount += 1;
}
if ( Input.Keyboard.Released( "Space" ) )
{
timer = 0;
}
if ( IsOnGround )
{
tapCount = 0;
}
}
void ProcessFly()
{
if ( (tapCount > 0) && (tapCount < 2) && Input.Keyboard.Pressed( "Space" ) && !IsOnGround && (timer < .5f) )
{
DoubleJump();
timer += Time.Delta;
}
if ( (tapCount > 1) && (tapCount < 3) && Input.Keyboard.Pressed( "Space" ) && !IsOnGround && (timer < .5f) )
{
TripleJump();
timer += Time.Delta;
}
}
void ProcessFlyMovement()
{
if ( !IsOnGround && Input.Keyboard.Down( "D" ) && !Input.Keyboard.Pressed( "Space" ) )
{
FlyRight();
}
if ( !IsOnGround && Input.Keyboard.Down( "A" ) && !Input.Keyboard.Pressed( "Space" ) )
{
FlyLeft();
}
if ( !IsOnGround && !Input.Keyboard.Pressed( "Space" ) && !Input.Keyboard.Pressed( "SHIFT" ) && (tapCount >= 2) && (timer < .5f) )
{
FlyIdle();
}
}
void MoveRight()
{
model.Set( "AnimPar", 1 );
controller.Velocity = (Vector3.Backward * speed) + chickenVel.CurrentVelocity;
LocalRotation = Rotation.From( 0f, 0f, 0f );
Rotation.FromYaw(0);
dodgedir = 0;
if (Input.Keyboard.Pressed( "Space" ))
{
model.Set( "AnimPar", 2 );
}
}
void MoveLeft()
{
model.Set( "AnimPar", 1 );
controller.Velocity = (Vector3.Forward * speed) + chickenVel.CurrentVelocity;
LocalRotation = Rotation.From( 0f, 180f, 0f );
Rotation.FromYaw( 180 );
dodgedir = 1;
if ( Input.Keyboard.Pressed( "Space" ) )
{
model.Set( "AnimPar", 2 );
}
}
void Dodge()
{
model.Set( "AnimPar", 5 );
controller.Velocity = 0;
if ( dodgedir == 0 )
{
controller.ApplyImpulse(( Vector3.Up * dodgeforce ) + chickenVel.CurrentVelocity);
controller.ApplyImpulse(( Vector3.Forward * dodgeforce ) + chickenVel.CurrentVelocity);
}
if ( dodgedir == 1 )
{
controller.ApplyImpulse(( Vector3.Up * dodgeforce ) + chickenVel.CurrentVelocity);
controller.ApplyImpulse(( Vector3.Backward * dodgeforce ) + chickenVel.CurrentVelocity);
}
GameObject.PlaySound( dodge );
}
void Jump()
{
model.Set( "AnimPar", 2 );
controller.ApplyImpulse(( Vector3.Up * jumpforce ) + chickenVel.CurrentVelocity);
timer += Time.Delta * 100;
GameObject.PlaySound( wingsflap );
if ( (tapCount > 0) && (tapCount == 1) )
{
GameObject.PlaySound( wingsfly );
}
}
void TripleJump()
{
model.Set( "AnimPar", 4 );
controller.ApplyImpulse( Vector3.Up * flyforce );
GameObject.PlaySound( cluck );
}
void DoubleJump()
{
model.Set( "AnimPar", 4 );
controller.ApplyImpulse( Vector3.Up * flyforce );
GameObject.PlaySound( wingsfly );
if ( tapCount > 1 )
{
GameObject.PlaySound( cluck );
}
}
void StopFlying()
{
model.Set( "AnimPar", 0 );
}
void FlyIdle()
{
model.Set( "AnimPar", 3 );
}
void FlyLeft()
{
controller.ApplyImpulse( Vector3.Forward * flyspeed );
Transform.LocalRotation = Rotation.From( 0f, 180f, 0f );
Rotation.FromYaw( 180 );
dodgedir = 1;
}
void FlyRight()
{
controller.ApplyImpulse( Vector3.Backward * flyspeed );
Transform.LocalRotation = Rotation.From( 0f, 0f, 0f );
Rotation.FromYaw( 0 );
dodgedir = 0;
}
public void Addcornpoints( int cornAmount )
{
ScoreManager.CurrentScore += cornAmount;
}
public string GetTimeString()
{
var time = gametime;
var minutes = (int)time / 60;
var seconds = (int)time % 60;
return $"{minutes:00}:{seconds:00}";
}
}