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.