sexta-feira, 22 de junho de 2012

Platformer Kit: SPG_PlayerController class (UnrealScript)

A classe SPG_PlayerController é responsável por adaptar os comandos do jogador para o estilo Plataforma.

Se você não conhece a classe Controller, dê uma lida no artigo: "Classe Controller (UnrealScript)".

Uma das funções que é sobrescrita é a UpdateRotation() cujo código está abaixo.
function UpdateRotation(float DeltaTime)
{
    local Rotator DeltaRot;

    // Set the delta rotation to that of the desired rotation, as the desired rotation represents
    // the rotation derived from the acceleration of the pawn
    DeltaRot = DesiredRotation;

    // Set the delta pitch to read from the look up input
    DeltaRot.Pitch = PlayerInput.aLookUp;

    // Never need to roll the delta rotation
    DeltaRot.Roll = 0;

    // Shake the camera if necessary
    ViewShake(DeltaTime);

    // If we have a pawn, update its facing rotation
    if (Pawn != None)
    {
        Pawn.FaceRotation(DeltaRot, DeltaTime);
    }
}

Existem dois tipos de Rotações que podem ocorrer no Platformer Kit. Uma é a rotação que ocorre quando o jogador muda a direção em que está se movendo. A outra é a rotação da mira que altera a direção do tiro.

A rotação do jogador é manipulada através do uso da variável DesiredRotation. A rotação da mira é obtida a partir da variável aLookUp da classe PlayerInput. A variável aLookUp mapeia o movimento para frente e para trás do Mouse. A imagem logo abaixo mostra o jogador mirando para cima.

A função FaceRotation() que será chamada a partir do objeto Pawn, é a que está definida na classe SPG_PlayerPawn.


Na função PlayerMove() é calculada uma aceleração baseada na variável "PlayerInput.aStrafe" que representa a movimentação na horizontal. Esta aceleração é armazenada na variável do tipo Vector "NewAccel". O código da função está abaixo.
state PlayerWalking
{
    function PlayerMove(float DeltaTime)
    {
        local Vector X, Y, Z, NewAccel, CameraLocation;
        local Rotator OldRotation, CameraRotation;
        local bool bSaveJump;

        // If we don't have a pawn to control, then we should go to the dead state
        if (Pawn == None)
        {
            GotoState('Dead');
        }
        else
        {
            // Grab the camera view point as we want to have movement aligned to the camera
            PlayerCamera.GetCameraViewPoint(CameraLocation, CameraRotation);

            // Get the individual axes of the rotation
            GetAxes(CameraRotation, X, Y, Z);

            // Update acceleration
            NewAccel = PlayerInput.aStrafe * Y;
            NewAccel.Z = 0;
            NewAccel = Pawn.AccelRate * Normal(NewAccel);

            // Set the desired rotation
            DesiredRotation = Rotator(NewAccel);

            // Update rotation
            OldRotation = Rotation;
            UpdateRotation(DeltaTime);

            // Update crouch
            Pawn.ShouldCrouch(bool(bDuck));

            // Handle jumping
            if (bPressedJump && Pawn.CannotJumpNow())
            {
                bSaveJump = true;
                bPressedJump = false;
            }
            else
            {
                bSaveJump = false;
            }

            // Update the movement, either replicate it or process it
            if (Role < ROLE_Authority)
            {
                ReplicateMove(DeltaTime, NewAccel, DCLICK_None, OldRotation - Rotation);
            }
            else
            {
                ProcessMove(DeltaTime, NewAccel, DCLICK_None, OldRotation - Rotation);
            }

            bPressedJump = bSaveJump;
        }
    }
}

No final da função PlayerMove() existe o seguinte teste: "if (Role < ROLE_Authority)". Isto é usado para verificar se o jogo é um cliente que está utilizando um servidor. Caso este código estiver sendo executado em um servidor ou em um jogo single player então o valor da variável "Role" será igual a "ROLE_Authority".