sexta-feira, 8 de junho de 2012

Platformer Kit: SPG_Camera class (UnrealScript)


O Platformer Starter Kit usa uma visão lateral semelhante aos antigos jogos 2D de plataforma. São utilizados as classes SPG_Camera e SPG_CameraProperties para a definição da câmera.

A classe SPG_CameraProperties possui apenas um Vector usado para definir a posição relativa da câmera em relação ao jogador. O código da classe está abaixo:
class SPG_CameraProperties extends Object
      HideCategories(Object);

// How much to offset the camera by
var(CameraProperties) const Vector CameraOffset;

defaultproperties
{
}

Foi criado um Archetype baseado nesta classe no pacote "StarterPlatformGameContent.Archetypes.CameraProperties", conforme imagem abaixo.


A classe SPG_Camera possui uma instância da classe SPG_CameraProperties carregada a partir do Archetype:
class SPG_Camera extends Camera;

var const archetype SPG_CameraProperties CameraProperties;

/**
 * Updates the camera's view target. Called once per tick
 *
 * @param    OutVT        Outputted camera view target
 * @param    DeltaTime    Time since the last tick was executed
 */
function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime)
{
    // Early exit if:
    // - We have a pending view target
    // - OutVT currently equals ViewTarget
    // - Blending parameter is lock out going
    if (PendingViewTarget.Target != None && OutVT == ViewTarget && BlendParams.bLockOutgoing)
    {
        return;
    }

    // Add the camera offset to the target's location to get the location of the camera
    OutVT.POV.Location = OutVT.Target.Location + CameraProperties.CameraOffset;
    // Make the camera point towards the target's location
    OutVT.POV.Rotation = Rotator(OutVT.Target.Location - OutVT.POV.Location);
}

defaultproperties
{
    CameraProperties=SPG_CameraProperties'StarterPlatformGameContent.Archetypes.CameraProperties'
}

Se você não sabe nada sobre a classe Camera, recomendo a leitura do meu artigo "Classe Camera (UnrealScript)".

A classe SPG_Camera modifica a câmera de uma forma bem simples, apenas sobrescrevendo a função UpdateViewTarget() da classe Camera. Esta função recebe como parâmetro de saída uma variável do tipo TViewTarget, que é uma estrutura (struct) definida na classe Camera:
//Extraído da classe Camera...

/**
 * View Target definition
 * A View Target is responsible for providing the Camera with an ideal Point of View (POV)
 */
struct native TViewTarget
{
    /** Target Actor used to compute ideal POV */
    var()    Actor                   Target;

    /** Controller of Target (only for non Locally controlled Pawns) */
    var()    Controller              Controller;

    /** Point of View */
    var()    TPOV                    POV;

    /** Aspect ratio */
    var()    float                   AspectRatio;

    /** PlayerReplicationInfo (used to follow same player through pawn transitions, etc., when spectating) */
    var()    PlayerReplicationInfo   PRI;
};

Dentro da estrutura TViewTarget existe uma variável chamada POV que representa o Ponto de Visão. Ela é do tipo TPOV que é uma estrutura definida na classe Object:
//Extraído da classe Object...

/**
 * Point Of View type.
 */
struct TPOV
{
    /** Location */
    var() Vector    Location;

    /** Rotation */
    var() Rotator    Rotation;

    /** FOV angle */
    var() float        FOV;

    structdefaultproperties
    {
        FOV=90.f
    }
};

Em relação ao código existente na função UpdateViewTarget() da classe SPG_Camera, o teste condicional abaixo foi copiado da função UpdateViewTarget() da classe Camera e é usado apenas para evitar que a ViewTarget seja alterada enquanto estiver ocorrendo uma interpolação.
if (PendingViewTarget.Target != None && OutVT == ViewTarget && BlendParams.bLockOutgoing)

O ajuste da câmera é feito na duas linhas de código abaixo, que define a posição do Ponto de Visão como sendo a posição do jogador somado com o Vector existente na classe SPG_CameraProperties. Após isso é definida a rotação necessária para que a câmera aponte em direção ao jogador.
OutVT.POV.Location = OutVT.Target.Location + CameraProperties.CameraOffset;
OutVT.POV.Rotation = Rotator(OutVT.Target.Location - OutVT.POV.Location);