A física do controlador de personagem do mecanismo de jogo Quake 3 Arena é responsável por lidar com o movimento e a detecção de colisão do personagem do jogador. Essas físicas são projetadas para simular o movimento de um personagem de tiro em primeira pessoa (FPS) em um ambiente 3D e são baseadas em uma combinação de física cinemática e dinâmica.

Alguns dos principais recursos da física do controlador de personagem do Quake 3 Arena incluem:

  • Altura do degrau: o personagem pode subir em superfícies de até uma certa altura, permitindo-lhe passar por cima de obstáculos.
  • Limite de inclinação: o personagem pode andar em superfícies inclinadas até um determinado ângulo, mas deslizará em superfícies mais íngremes.
  • Gravidade: o personagem é afetado pela gravidade, então ele cairá se não estiver em uma superfície sólida.
  • Controle aéreo: o personagem pode ajustar sua velocidade horizontal enquanto estiver no ar, permitindo que ele dê saltos no ar e controle sua aterrissagem.
  • Atrito: o movimento do personagem é afetado pelo atrito, então eles vão desacelerar em superfícies escorregadias e parar em superfícies ásperas.
  • Detecção de colisão: a forma de colisão do personagem é usada para detectar colisões com o ambiente, para que não passem por objetos sólidos.

A física do controlador de personagem em Quake 3 Arena foi projetada para criar uma experiência de jogo dinâmica e em ritmo acelerado. A física permite que o jogador execute uma variedade de técnicas de movimento, como bunny hopping, strafe jumping e circle strafing, que é um conjunto de técnicas que permite aos jogadores se mover e se esquivar de maneira muito rápida e precisa. No geral, a física do controlador de personagem do mecanismo de jogo Quake 3 Arena é projetada para fornecer um movimento suave e responsivo para o personagem do jogador, permitindo que ele navegue pelo mundo do jogo e interaja com o ambiente de uma maneira crível e realista.

Aqui está um tutorial sobre como criar um jogo U3D com um personagem jogável em primeira pessoa e câmera em primeira pessoa, usando a física de movimento do personagem Quake 3:

Crie o mundo da física e o controlador de personagem

  • Na classe Application, adicione um novo componente PhysicsWorld à cena. Isso será usado para lidar com a simulação de física para o controlador de personagem.
  • Crie um novo componente CharacterController e adicione-o à cena. Este componente irá lidar com o movimento do personagem e detecção de colisão.
#include <Urho3D/Urho3D.h>#include <Urho3D/Core/CoreEvents.h>#include <Urho3D/Engine/Application.h>#include <Urho3D/Engine/Engine.h>#include <Urho3D/Physics/PhysicsWorld.h>#include <Urho3D/Physics/RigidBody.h>#include <Urho3D/Physics/CollisionShape.h>#include <Urho3D/Physics/KinematicCharacterController.h>using namespace Urho3D;class MyApp : public Application{public:    MyApp(Context* context) : Application(context)    {    }    virtual void Start()    {        // Create the scene        Scene* scene = new Scene(context_);        // Create a physics world component        PhysicsWorld* physicsWorld = scene->CreateComponent<PhysicsWorld>();        // Create a character controller component        CharacterController* characterController = scene->CreateComponent<CharacterController>();    }    virtual void Setup()    {        engineParameters_["FullScreen"] = false;        engineParameters_["WindowWidth"] = 1280;        engineParameters_["WindowHeight"] = 720;    }};
  • Na função Iniciar do CharacterController, configure a forma de colisão do personagem, o corpo rígido e o controlador de personagem cinemático.
class CharacterController : public Component{public:    CharacterController(Context* context) : Component(context)    {    }    void Start() override    {        // Create a capsule collision shape for the character        CollisionShape* shape = node_->CreateComponent<CapsuleCollisionShape>();        shape->SetSize(Vector3(0.5f, 1.0f, 0.5f));        // Create a rigid body for the character        RigidBody* body = node_->CreateComponent<RigidBody>();        body->SetMass(80.0f);        body->SetCollisionShape(shape);        // Create a kinematic character controller        kinematicCharacterController_ = node_->CreateComponent<KinematicCharacterController>();        kinematicCharacterController_->SetRigidBody(body);        kinematicCharacterController_->SetCollisionShape(shape);        kinematicCharacterController_->SetMaxStepHeight(0.5f);    }private:    KinematicCharacterController* kinematicCharacterController_;};

Nesse código, um novo componente CharacterController é criado e adicionado à cena na função Start() da classe Application. Na função Start() do componente, uma forma de colisão de cápsula é criada e definida para o corpo rígido do personagem, e um componente KinematicCharacterController é criado e definido para a forma de colisão do personagem. A altura máxima do degrau, que é a altura máxima que o personagem pode subir, é definida como 0,5f.

Adicione os controles de movimento do personagem

  • Na função Update do CharacterController, obtenha a entrada do jogador e use-a para calcular a direção do movimento do personagem.
  • Use a função Mover do controlador de personagem cinemático para atualizar a posição do personagem com base na direção do movimento e intervalo de tempo.
class CharacterController : public Component{public:    CharacterController(Context* context) : Component(context)    {    }    void Start() override    {        //... previous code for collision shape, rigid body and kinematic character controller    }    void Update(float timeStep) override    {        Input* input = GetSubsystem<Input>();        // Get the move direction from the input        Vector3 moveDirection = Vector3::ZERO;        if (input->GetKeyDown(KEY_W))            moveDirection += Vector3::FORWARD;        if (input->GetKeyDown(KEY_S))            moveDirection += Vector3::BACK;        if (input->GetKeyDown(KEY_A))            moveDirection += Vector3::LEFT;        if (input->GetKeyDown(KEY_D))            moveDirection += Vector3::RIGHT;        // Normalize the move direction        moveDirection.Normalize();        // Use the kinematic character controller's Move function to update the character's position based on the move direction and time step        kinematicCharacterController_->Move(moveDirection * timeStep);    }private:    KinematicCharacterController* kinematicCharacterController_;};

Nesse código, a função Update obtém a direção do movimento da entrada e a normaliza para garantir que o personagem se mova em uma velocidade consistente. A função Mover do controlador de caractere cinemático é chamada e passa a direção do movimento multiplicada pelo intervalo de tempo. Isso move a posição do personagem com base na direção do movimento e no intervalo de tempo.

É importante observar que a função de movimento do controlador de personagem cinemático usa a forma de colisão do personagem e as informações de colisão do mundo da física para mover o personagem. Dessa forma, o personagem responderá corretamente às colisões com o ambiente.

Adicione a câmera em primeira pessoa

  • Crie um novo componente Camera e adicione-o à cena.
  • Posicione a câmera na cabeça do personagem e aponte-a na mesma direção do vetor de avanço do personagem.
  • Defina as distâncias de clipe próximo e clipe distante da câmera para valores apropriados para uma câmera em primeira pessoa.
        // Create a camera component and set it as the viewport's camera        camera_ = GetScene()->CreateChild("Camera")->CreateComponent<Camera>();        GetSubsystem<Renderer>()->SetViewport(0, new Viewport(context_, GetScene(), camera_));        // Position the camera at the character's head        camera_->SetPosition(node_->GetPosition() + Vector3(0.0f, 1.0f, 0.0f));        // Point the camera in the same direction as the character's forward vector        camera_->SetDirection(node_->GetDirection());        // Set the camera's near clip distance        camera_->SetNearClip(0.1f);        // Set the camera's far clip distance        camera_->SetFarClip(100.0f);

Configure o tratamento de entrada para a câmera e o personagem

  • Adicione manipulação de entrada para o movimento do personagem e o movimento da câmera na classe Application.
  • Vincule os eventos de entrada às funções apropriadas nos componentes CharacterController e Camera.
    virtual void Start()    {        //... previous code for creating the scene, physics world, and character controller        // Subscribe to the key down event to handle character movement        SubscribeToEvent(E_KEYDOWN, URHO3D_HANDLER(MyApp, HandleKeyDown));        // Subscribe to the mouse move event to handle camera movement        SubscribeToEvent(E_MOUSEMOVE, URHO3D_HANDLER(MyApp, HandleMouseMove));        // Subscribe to the mouse button down event to handle mouse inputs        SubscribeToEvent(E_MOUSEBUTTONDOWN, URHO3D_HANDLER(MyApp, HandleMouseButtonDown));    }    void HandleKeyDown(StringHash eventType, VariantMap& eventData)    {        using namespace KeyDown;        int key = eventData[P_KEY].GetInt();        // Send the key down event to the character controller        characterController_->HandleKeyDown(key);    }    void HandleMouseMove(StringHash eventType, VariantMap& eventData)    {        using namespace MouseMove;        int dx = eventData[P_DX].GetInt();        int dy = eventData[P_DY].GetInt();        // Send the mouse move event to the camera component        camera_->HandleMouseMove(dx, dy);    }    void HandleMouseButtonDown(StringHash eventType, VariantMap& eventData)    {        using namespace MouseButtonDown;        int button = eventData[P_BUTTON].GetInt();        // Send the mouse button down event to the camera component        camera_->HandleMouseButtonDown(button);    }

Adicione a forma de colisão para o ambiente, se você quiser andar por aí.

  • Crie um componente CollisionShape para o ambiente e anexe-o ao nó raiz da cena.
        // Get the root node of the scene        Node* rootNode = GetScene()->GetChild("Environment", true);        // Create a collision shape for the environment        CollisionShape* environmentShape = rootNode->CreateComponent<CollisionShape>();        //... previous code for setting the shape and size of the collision shape
  • Adicione as propriedades físicas necessárias ao seu ambiente, como fricção, ressalto, etc.
        // Get the rigid body of the environment        RigidBody* environmentBody = rootNode->GetComponent<RigidBody>();        // Set the physics properties of the environment        environmentBody->SetFriction(0.8f);        environmentBody->SetRestitution(0.1f);        environmentBody->SetRollingFriction(0.1f);        environmentBody->SetAnisotropicFriction(Vector3(1.0f, 1.0f, 1.0f));

Com este tutorial, você tem a estrutura básica para um jogo em primeira pessoa com um personagem jogável usando a física do Quake3 em U3D. Você pode adicionar mais recursos, como pular, agachar, atirar e muito mais adicionando mais funcionalidade ao CharacterController e ao ambiente.

Com informações de GameDev.net.