Monday, June 25, 2012

Platformer Kit: SPG_PlayerPawn class (UnrealScript)

The SPG_PlayerPawn class represents the player's character. If you do not know about the Pawn class first read the article: "Pawn Class (UnrealScript)".

The variables below of the SPG_PlayerPawn class are available for changing in the editor.
class SPG_PlayerPawn extends Pawn;

// Dynamic light environment component to help speed up lighting calculations for the pawn
var(Pawn) const DynamicLightEnvironmentComponent LightEnvironment;

// How fast a pawn turns
var(Pawn) const float TurnRate;

// How high the pawn jumps
var(Pawn) const float JumpHeight;

// Socket to use for attaching weapons
var(Pawn) const Name WeaponSocketName;

// Height to set the collision cylinder when crouching
var(Pawn) const float CrouchHeightOverride<DisplayName=Crouch Height>;

// Radius to set the collision cylinder when crouching
var(Pawn) const float CrouchRadiusOverride<DisplayName=Crouch Radius>;

An Archetype was also created for SPG_PlayerPawn class. The image below shows the values ​​of some variables.


The FaceRotation() function of the SPG_PlayerPawn class is called from the UpdateRotation() function of the SPG_PlayerController class.

This function will adjust two types of rotation: the rotation of the aim and the rotation of the character.

The rotation of the aim is adjusted from the variable "AimNode.Aim.Y" based on the value of the Pitch variable of the Rotator that is passed as a parameter. The variable AimNode is of the AnimNodeAimOffset type.

The rotation of the character is done ​​based on the value of the Yaw variable of the Rotator that is passed as a parameter, using the SetRotation() function of the Pawn class.
simulated function FaceRotation(Rotator NewRotation, float DeltaTime)
{
    local Rotator FacingRotation;

    // Set the desired yaw the new rotation yaw
    if (NewRotation.Yaw != 0)
    {
        DesiredYaw = NewRotation.Yaw;
    }

    // If the current yaw doesn't match the desired yaw, then interpolate towards it
    if (CurrentYaw != DesiredYaw)
    {
        CurrentYaw = Lerp(CurrentYaw, DesiredYaw, TurnRate * DeltaTime);
    }

    // If we have a valid aim offset node
    if (AimNode != None)
    {
        // Clamp the current pitch to the view pitch min and view pitch max
        CurrentPitch = Clamp(CurrentPitch + NewRotation.Pitch, ViewPitchMin, ViewPitchMax);

        if (CurrentPitch > 0.f)
        {
            // Handle when we're aiming up
            AimNode.Aim.Y = float(CurrentPitch) / ViewPitchMax;
        }
        else if (CurrentPitch < 0.f)
        {
            // Handle when we're aiming down
            AimNode.Aim.Y = float(CurrentPitch) / ViewPitchMin;
           
            if (AimNode.Aim.Y > 0.f)
            {
                AimNode.Aim.Y *= -1.f;
            }
        }
        else
        {
            // Handle when we're aiming straight forward
            AimNode.Aim.Y = 0.f;
        }
    }

    // Update the facing rotation
    FacingRotation.Pitch = 0;
    FacingRotation.Yaw = CurrentYaw;
    FacingRotation.Roll = 0;

    SetRotation(FacingRotation);
}

The DoJump() function is called to perform the jump of the character. It takes into account the different types of Physics that the character can be.

In essence, the velocity along the Z axis (up) receives the value of the JumpHeight variable that was defined for this class and can be adjusted in the Archetype. After it is checked whether the player is on a moving platform. If true, then the velocitity of the platform (Base.Velocity.Z) influences the velocity of the jump of the player.
function bool DoJump(bool bUpdating)
{
    if (bJumpCapable && !bIsCrouched && !bWantsToCrouch && (Physics == PHYS_Walking || Physics == PHYS_Ladder || Physics == PHYS_Spider))
     {
        if (Physics == PHYS_Spider)
        {
            Velocity = JumpHeight * Floor;
        }
        else if (Physics == PHYS_Ladder)
        {
            Velocity.Z = 0.f;
        }
        else
        {
            Velocity.Z = JumpHeight;
        }

        if (Base != None && !Base.bWorldGeometry && Base.Velocity.Z > 0.f)
        {
            Velocity.Z += Base.Velocity.Z;
        }

        SetPhysics(PHYS_Falling);
        return true;
    }

    return false;
}