Buscar

Aula 05 - Programação e Interatividade

Prévia do material em texto

Desenvolvimento de Jogos Digitais II
Aula 5: Programação e Interatividade
Apresentação
A maioria das Game Engines permite a personalização de funcionalidades a partir de alguma linguagem de
programação, e no caso da Unreal Engine, a linguagem C++ é utilizada como base para o desenvolvimento. Mesmo os
diversos componentes dos Blueprints foram criados nesse ambiente, fato que justi�ca a plena compatibilidade entre os
ferramentais, o que permite a de�nição da interatividade e regras do jogo de forma �exível e robusta.
Objetivo
Analisar a sintaxe básica da linguagem C++;
Construir componentes para a Unreal Engine utilizando C++;
Demonstrar o uso de C++ para o controle de dispositivos de entrada.
Sintaxe C++
Um elemento essencial em qualquer Game Engine é a possibilidade de expandir e adaptar funcionalidades com base em
alguma linguagem de programação. Considerando-se os dois exemplos mais populares do mercado de jogos, enquanto a
Unity 3D utiliza C#, na Unreal Engine adotamos o C++ como padrão para desenvolvimento.
A linguagem C++ é predecessora do C#, tendo servido como base de sua sintaxe. O uso de uma linguagem clássica e de
grande abrangência na área cientí�ca, como o C++, permite acesso a uma grande base de algoritmos já implementados para
áreas críticas nos jogos, como otimizações grá�cas e sistemas de inteligência arti�cial.
De forma simplista, podemos interpretar o C++ como a linguagem C orientada a objetos, mas existem diversas outras
melhorias, como a sintaxe de ponteiros com o uso de new e delete, no lugar das diversas funções de alocação de memória
do C.
Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online
 
#include <iostream>
using namespace std;
main() {
cout << "Exemplo Simples" << endl;
return 0;
}
 Listagem: Exemplo simples programado em C++. Fonte: O autor.
Nosso primeiro exemplo demonstra algumas características do C++, como o uso de include para a importação de
bibliotecas, o início da execução na função main e a saída texto no vídeo por meio de cout.
Comentário
Uma observação é a de que o uso do namespace std impede que tenhamos de escrever std::cout no lugar de cout.
A linguagem é fortemente tipada, exigindo que a variável seja associada a um tipo especí�co, e temos apenas um pequeno
conjunto de tipos nativos. Também é necessário prestar atenção ao uso de letras maiúsculas e minúsculas, já que a
linguagem é case sensitive.
Tipo Nativo Limites e Observações
Int Variável inteira, variando de -2.147.483.648 até 2.147.483.647
float Variável de ponto flutuante, variando de -3,402E38 até 3,402E38
double Variável de ponto flutuante, variando de -1,797E308 até 1,797E308
char Caractere do padrão ASCII
wchar_t Caractere do padrão UTF-16
bool Variável do tipo lógico, assumindo os valores true ou false
 Tabela: Tipos nativos da linguagem C++. Fonte: O autor.
Vários desses tipos podem ser modi�cados utilizando-se as palavras-chave signed, unsigned, short e long. Quando um
desses modi�cadores é usado sem a de�nição do tipo de dado, o compilador assume o tipo int.
Tipo Nativo Limites e Observações
short int Modificação dos limites de int para -32.768 e 32.767
unsigned short int Modificação dos limites de int para 0 e 65.535
unsigned long int Modificação dos limites de int para 0 e 4.294.967.295
unsigned char Modificação dos limites numéricos de char para 0 e 255
long float Modificação dos limites de float para os de double
 Tabela: Modificadores de tipos na linguagem C++. Fonte: O autor.
A sintaxe do C++ lembra muito a utilizada no C#, até mesmo pela origem comum, mas algumas diferenças podem ser
observadas com relação ao uso de memória, principalmente no que se refere à utilização de ponteiros em C++.
 
#include <iostream>
using namespace std;
main()
{
int a = 5;
int* b = &a; // b aponta para o endereço de a
*b = 10; // posição apontada por b recebe 10
cout << a << endl; // imprime o valor 10
return 0;
}
 Listagem: Utilização básica de ponteiros no C++. Fonte: O autor.
Além dos tipos básicos, é possível criar tipos compostos em C++ com o uso da palavra reservada struct. Alguns livros
de�nem o tipo struct como uma espécie de classe simples, mas isso não é totalmente correto, pois já existia na linguagem C,
que não é orientada a objetos. 
 
Struct Jogador
{
string nome;
int pontos;
}
Jogador j1;
j1.nome = “Luiz”;
j1.pontos = 1320;
 Listagem: Definição e uso de tipos compostos. Fonte: O autor.
Em termos de operadores e controle de �uxo, não existe diferença para as demais linguagens derivadas do C. Podemos
observar, no exemplo seguinte, as estruturas de controle de �uxo for e if sendo utilizadas, além do cin para entrada de dados.
 
#include <iostream>
using namespace std;
main() {
int soma = 0, b;
for (int a = 1; a <= 10; a++) {
cout << “Digite um número:”;
cin >> &b;
if (b%2 == 0) soma += b;
}
cout << “A soma dos pares será “ << soma << endl;
return 0;
}
 Listagem: Exemplo com entrada e saída no C++. Fonte: O autor.
Algo bastante diferente entre o C# e o C++ é a necessidade de arquivos header no C++. Eles guardam apenas as assinaturas
de funções e classes que serão implementadas no arquivo cpp de nome equivalente, permitindo a importação a partir de
outros arquivos de código-fonte.
 
[calculadora.h]
int somar(int a, int b);
[calculadora.cpp]
#include “calculadora.h”
int somar(int a, int b) {
return a + b;
}
 Listagem: Arquivo header e arquivo de implementação. Fonte: O autor.
Você pode observar, nos códigos apresentados, que apesar de trazer todo o ferramental necessário para a implementação
orientada a objetos, o C++ não exige que seja feito dessa forma. De qualquer maneira, como a Unreal Engine trabalha dentro
de um ambiente orientado a objetos, é necessário compreender a sintaxe utilizada pelo C++ na de�nição de classes e objetos.
Inicialmente as classes podem ser prototipadas em arquivos header, com a de�nição de atributos e métodos, sempre
considerando os níveis de acesso private, public e protected.
 
[escritorio.h]
class Pessoa{
private:
int matricula;
string nome;
public:
Pessoa(int matricula, string nome);
~Pessoa();
void exibir();
}
 Listagem: Protótipo da classe Pessoa, criado no arquivo escritorio.h – Fonte: O autor.
Em seguida, as classes são implementadas no arquivo cpp, onde aparece o operador de resolução de escopo (duplo dois
pontos). Esse mesmo operador é utilizado na chamada de métodos estáticos, ou seja, aqueles que não precisam de uma
instância para que sejam executados.
 
[escritorio.cpp]
#include <iostream>
#include "escritorio.h"
using namespace std;
Pessoa::Pessoa(int matricula, string nome){
this -> matricula = matricula;
this -> nome = nome;
}
Pessoa::~Pessoa(){
cout << nome + " removido." << endl;
}
void Pessoa::exibir(){
cout << nome << " tem " << idade << " ano(s)." << endl;
}
 Listagem: Implementação da classe Pessoa, efetuada no arquivo escritorio.cpp – Fonte: O autor.
É interessante observar o uso do ponteiro de autorreferência this no construtor, o que viabiliza a diferenciação entre o atributo
do objeto, precedido do ponteiro, e o argumento que foi recebido no construtor, quando esses dois apresentam o mesmo
nome.
Na linguagem C++ é possível utilizar os objetos como variáveis comuns ou
como ponteiros, mas, de forma diferente do que ocorre em linguagens como
o Java, no C++ não existe um ferramental para coleta de lixo, e todo objeto
alocado dinamicamente deve ser removido de forma explícita na
programação.
A alocação é efetuada com o uso do operador new, sendo acionado o construtor adequado, a partir dos parâmetros
utilizados, e a remoção ocorre com a utilização do operador delete, podendo ser de�nido um método destrutor para que seja
executado algum procedimento imediatamente antes de desalocar o objeto.
 
Pessoa p1("Ana",25);
p1.exibir();
Pessoa* p2 = new Pessoa("Marcos",36);
p2 -> exibir();
delete(p2);
 Listagem: Alocação, utilização e remoção do objeto na linguagem C++. Fonte:O autor.
Na linguagem C++ é possível utilizar os objetos como variáveis comuns ou
como ponteiros, mas, de forma diferente do que ocorre em linguagens como
o Java, no C++ não existe um ferramental para coleta de lixo, e todo objeto
alocado dinamicamente deve ser removido de forma explícita na
programação.
A alocação é efetuada com o uso do operador new, sendo acionado o construtor adequado, a partir dos parâmetros
utilizados, e a remoção ocorre com a utilização do operador delete, podendo ser de�nido um método destrutor para que seja
executado algum procedimento imediatamente antes de desalocar o objeto.
 
Pessoa p1("Ana",25);
p1.exibir();
Pessoa* p2 = new Pessoa("Marcos",36);
p2 -> exibir();
delete(p2);
 Listagem: Alocação, utilização e remoção do objeto na linguagem C++. Fonte: O autor.
Em termos de herança, a linguagem C++ permite diferentes combinações com relação ao nível de acesso dos membros
originais. Uma herança de�nida como pública mantém os níveis originais, enquanto uma herança privada faz com que os
membros herdados nos níveis público e protegido transformem-se em privados na nova classe.
 
Class Funcionario: public Pessoa{
private:
string trabalho;
public:
Funcionario(int matricula, string nome, string trabalho):
base(matricula,nome)
{
this -> trabalho = trabalho;
}
void exibir()
{
Pessoa::exibir();
cout << “ e trabalha como “ < trabalho << endl;
}
}
 Listagem: Definição de uma classe descendente, com implementação direta. Fonte: O autor.
Note que aqui não foi utilizada a prototipação, ocorrendo a implementação direta, o que pode ser feito quando visamos
apenas a utilização local da classe. Vale lembrar que os arquivos header não permitem implementações, o que faz com que
o código nesse estilo deva estar em um arquivo cpp, que não pode ser importado.
Comentário
Também é interessante observar que o construtor de Funcionario inicialmente chama o construtor de Pessoa com o uso da
palavra base, e que um método do pai que tenha sido sobrescrito (polimor�smo) deve ser acessado com o nome da classe
original, seguido do operador de resolução de escopo.
Com relação à de�nição de propriedades, não existe no C++ uma sintaxe voltada para isso, como ocorre no C#, mas é
utilizado o padrão de métodos getters e setters, a exemplo de linguagens como Java.
 
Class Funcionario: public Pessoa{
private:
string trabalho;
public:
/* Métodos anteriores omitidos */
string getTrabalho()
{ return trabalho; }
void setTrabalho(string trabalho)
{ this -> trabalho = trabalho; }
}
 Listagem: Utilização de getters e setters na definição de uma propriedade. Fonte: O autor.
Uso de C++ na Unreal Engine
A forma mais simples de utilizar a linguagem C++ na Unreal Engine é a partir da criação de um projeto apropriado. Você deve
escolher a guia C++, e dentro dela optar pelo tipo Basic Code, digitando o nome do projeto, como Teste001R, e de�nindo o
diretório de base.
 Figura: Criação de projeto simples com base em C++, na Unreal Engine 4.21 – Fonte: O autor.
Em versões mais recentes da Unreal Engine, escolhemos novo projeto de Games, tipo Blank, e apenas na última tela é
escolhido o modelo C++. As outras con�gurações disponíveis incluem qualidade grá�ca e plataforma de execução.
 Figura: Escolha do modelo de projeto com base em C++, na Unreal Engine 4.25 – Fonte: O autor.
Após a criação do projeto, basta acionar a opção Add New no Content Browser e selecionar New C++ Class. Em seguida será
solicitado o tipo da superclasse, que deverá ser Actor para este exemplo. Clicando em Next deverá ser preenchido o nome da
nova classe como Rotacao, tendo também a opção de escolher o diretório ou manter a opção padrão.
 Figura: Seleção do ascendente e nomeação da classe. Fonte: O autor.
A classe Actor serve de base para os componentes que podem ser adicionados às cenas da Unreal Engine, assumindo papel
similar ao do GameObject, presente no ambiente da Unity 3D. As demais opções lidam com elementos mais especializados,
como Pawn, um ator que interage com controladores, e Character, especialização de Pawn que consegue andar pelo
ambiente, entre diversas outras.
Agora você poderá visualizar a classe ARotacao e seu arquivo header no ambiente do Visual Studio, por meio do do Solution
Explorer (Gerenciador de Soluções).
Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online
Inicialmente, você deve observar a de�nição da nova classe, no
header, onde ocorre a especialização pública de AActor, com a
de�nição do construtor, além dos métodos polimór�cos BeginPlay e
Tick, devendo ser acrescentado o atributo público velocidade, do tipo
�oat.
O método BeginPlay é chamado no início do jogo, ou quando o Actor é gerado (spawned), enquanto Tick é chamado a cada
novo frame.
 
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Rotacao.generated.h"
UCLASS()
class TESTE001R_API ARotacao : public AActor
{
GENERATED_BODY()
public:
ARotacao();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
float velocidade = 0.2f;
};
 Listagem: Arquivo header da classe ARotacao. Fonte: O autor.
Nas classes geradas para o ambiente da Unreal Engine, algo muito particular e importante são os metadados de
especi�cação, que funcionam como elementos comportamentais, sendo reconhecidos pela Game Engine e voltados para a
integração com o ambiente. No arquivo de cabeçalho podemos observar o metadado UCLASS, além da macro
GENERATED_BODY.
Metadado Utilização
GENERATED_BODY Macro que define toda a infraestrutura necessária para a comunicação com a Game Engine no protótipo da classe.
UCLASS Define a classe como um elemento interativo da Unreal Engine.
UENUM Define o enumerado como um elemento interativo da Unreal Engine.
UFUNCTION Configura o método como uma função que pode ser reconhecida ao nível dos Blueprints.
UINTERFACE Define a interface como um elemento interativo da Unreal Engine.
UPROPERTY Transforma o atributo em uma propriedade editável, que pode ser modificada no painel Details ou em Blueprints.
USTRUCT Define o registro como um elemento interativo da Unreal Engine.
 Tabela: Metadados e macros comuns da especificação da Unreal Engine. Fonte: O autor.
Agora que temos a classe prototipada adequadamente, devemos codi�car o comportamento desejado no arquivo de
implementação. No caso, será de�nida uma rotina que rotaciona a �gura em torno de um eixo, invertendo o sentido do
movimento entre os limites de 0° e 180°.
 
#include "Rotacao.h"
 
ARotacao::ARotacao()
{
PrimaryActorTick.bCanEverTick = true;
}
void ARotacao::BeginPlay()
{
Super::BeginPlay();
}
void ARotacao::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
FTransform transf1 = GetActorTransform();
FQuat rot1 = transf1.GetRotation();
float angulo = rot1.GetAngle() + DeltaTime * velocidade;
if (angulo > 3.14 || angulo < 0)
velocidade *= -1;
FQuat quat1 = FQuat(FVector::ForwardVector, angulo);
SetActorRotation(quat1);
}
 Listagem: Implementação da classe ARotacao. Fonte: O autor.
Inicialmente é capturado o componente FTransform do Actor e, a partir dele, é obtido o atributo FQuat (Quaternion) referente
à rotação atual. Em seguida é calculado o ângulo de rotação, tendo como base o ângulo atual, acrescido da velocidade
angular em radianos multiplicada pelo DeltaTime. O tempo delta mede o período que decorre entre dois frames
subsequentes e visa manter a velocidade de atualização equivalente entre máquinas distintas.
Atenção
Devido às características do Quaternion, ocorre a inversão do movimento entre os limites de 0° e 180°. Para manter o sentido da
rotação, a velocidade deve ser invertida quando os limites são atingidos.
Ao �nal, o Quaternion contendo o eixo e ângulo de rotação, com o nome quat1, é de�nido, sendo aplicado ao Actor a partir de
SetActorRotation. Note que o eixo de rotação utilizado é FVector::ForwardVector, equivalente ao eixo X, causando o giro no
plano YZ.
Comentário
Como você deve terobservado, o nome da classe, na Unreal Engine, recebe uma letra A no início, constituindo um padrão de
nomenclatura para o ambiente.
Agora que tudo está pronto, podemos compilar a solução no Visual Studio, a partir da opção Compile..Build Solution, ou no
próprio ambiente da Unreal Engine, com a opção Compile.
 Figura: Classe ARotacao, no Content Browser, e objeto Rotacao1, no painel Details. Fonte: O autor.
Com tudo preparado você poderá iniciar o jogo, com a utilização da opção Play, sendo possível observar o cubo rotacionado
no ar enquanto efetua um passeio pelo ambiente 3D.
 Figura: Teste da classe ARotacao, com a execução do projeto. Fonte: O autor.
Controle de Dispositivos de Entrada
Para capturar as entradas efetuadas pelo jogador vamos precisar de uma classe descendente de Pawn, que caracteriza o
tipo de ator mais simples com capacidade de aceitar a interação com o ambiente. A nova classe receberá o nome
Movimento e contará com uma câmera para acompanhamento da malha estática, cujo posicionamento será controlado via
teclado.
Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online
 Figura: Escolha do tipo Pawn na definição da classe. Fonte: O autor.
Inicialmente devemos con�gurar o uso de dispositivos de entrada em nosso projeto, pois, no ambiente da Unreal Engine,
todos os controles utilizados devem ser mapeados. Com o uso do menu Edit..Project Settings, na divisão Engine..Input da
janela de con�gurações, obteremos acesso ao painel de mapeamento de entradas, que podem ser de dois tipos principais:
Action Mappings, voltado para o funcionamento discreto das teclas, e que dão suporte aos eventos IE_Pressed,
IE_Released ou IE_Repeated;
Axis Mappings, utilizado para entradas contínuas, como os eixos de um joystick.
Utilizaremos o controle via teclado e de�niremos o mapeamento Tecla_Z apontando para Z, no grupo key, e Tecla_X,
apontando para X. Ao nível do código C++ teremos a ligação entre cada mapeamento com os eventos IE_Pressed, para tecla
pressionada, e IE_Repeated, quando a tecla é mantida abaixada.
 Figura: Mapeamento de entradas para o exemplo. Fonte: O autor.
Além de viabilizar o uso de diversos tipos de dispositivos, inclusive para
consoles, como Play Station e Xbox, é possível combinar as entradas
selecionadas com um conjunto de teclas de controle, como Shift, Ctrl e Alt.
No código do arquivo header temos a prototipação da classe AMovimento, descendente de Apawn, quando poderemos
observar, além do construtor, BeginPlay e Tick, já utilizados na classe Rotacao, o método SetupPlayerInputComponent, que
será utilizado para efetuar a ligação entre os mapeamentos da entrada e os métodos de reposta interno, no caso
TeclaZ_Mantida e TeclaX_Mantida.
Teremos também duas propriedades, voltadas para a con�guração da velocidade e da malha estática, além de um atributo
interno para o sentido da translação.
 
UCLASS()
class TESTE003R_API Amovimento : public Apawn
{
GENERATED_BODY()
public:
Amovimento();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaSeconds) override;
// Ligação dos mapeamentos com os métodos internos
virtual void SetupPlayerInputComponent(
class UinputComponent* InputComponent) override;
void TeclaZ_Mantida();
void TeclaX_Mantida();
UPROPERTY(EditAnywhere)
UsceneComponent* Malha;
UPROPERTY(EditAnywhere)
float Velocidade = 150.0f;
private:
int multiplica = 0;
};
 Listagem: Arquivo header da classe AMovimento. Fonte: O autor.
Após a de�nição do header, precisamos implementar as funcionalidades de nossa classe no arquivo Movimento.cpp, onde
temos inicialmente o construtor padrão.
 
AMovimento::AMovimento()
{
PrimaryActorTick.bCanEverTick = true;
// Direciona o controle para o primeiro jogador
AutoPossessPlayer = EAutoReceiveInput::Player0;
RootComponent = CreateDefaultSubobject<USceneComponent>(
TEXT("RootComponent"));
UCameraComponent* OurCamera =
CreateDefaultSubobject<UCameraComponent>(TEXT("OurCamera"));
Malha = CreateDefaultSubobject<UStaticMeshComponent>(
TEXT("Malha"));
// A câmera é posicionada para visualização correta da malha
OurCamera->SetupAttachment(RootComponent);
OurCamera->SetRelativeLocation(FVector(-250.0f, 0.0f, 250.0f));
OurCamera->SetRelativeRotation(FRotator(-45.0f, 0.0f, 0.0f));
Malha->SetupAttachment(RootComponent);
 Listagem: Primeiro trecho do arquivo Movimento.cpp – Fonte: O autor.
Analisando o código, ocorre o acionamento dos eventos a cada quadro, como em Rotacao, e a captura da entrada associada
ao primeiro jogador, por meio de AutoPossessPlayer. Temos em seguida a construção dos atores associados, com
RootComponent de�nindo a referência na cena, OurCamera representando a câmera, e Malha de�nindo o objeto visual, o
que é feito a partir do método CreateDefaultSubobject, sendo fornecidos o tipo e o texto de referência.
A câmera deve ser con�gurada, o que é feito com a de�nição da posição em relação à malha e sua inclinação por meio dos
métodos SetRelativeLocation e SetRelativeRotation. Também devemos associar a malha estática e a câmera ao objeto raiz,
com base em SetupAttachment.
 
void AMovimento::BeginPlay()
{
Super::BeginPlay();
}
void AMovimento::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (multiplica != 0) {
FVector NewLocation = GetActorLocation() +
(FVector(0,1,0) * DeltaTime * Velocidade * multiplica);
SetActorLocation(NewLocation);
multiplica = 0;
}
}
 Listagem: Segundo trecho do arquivo Movimento.cpp — Fonte: O autor.
Na segunda parte de Movimento.cpp, temos o evento BeginPlay, que pode ser utilizado para inicializações em tempo de
execução, e Tick, ocorrendo a cada quadro durante o jogo. Para o nosso exemplo temos a alteração da localização do ator,
com base em DeltaTime, Velocidade e sentido da translação (multiplica).
 
void AMovimento::TeclaZ_Mantida()
{
multiplica = -1;
}
void AMovimento::TeclaX_Mantida()
{
multiplica = 1;
}
 Listagem: Terceiro trecho do arquivo Movimento.cpp — Fonte: O autor.
No trecho seguinte de Movimento.cpp temos os métodos de resposta ao pressionamento das teclas Z e X, em que o primeiro
de�ne a translação para a esquerda, com o valor negativo para o multiplicador, e o segundo para a direita, com o
multiplicador positivo. O valor é consumido em Tick, retornando para nulo após mover o objeto.
 
void AMovimento::SetupPlayerInputComponent(
UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
InputComponent->BindAction("Tecla_Z", IE_Pressed, this,
&AMovimento::TeclaZ_Mantida);
InputComponent->BindAction("Tecla_Z", IE_Repeat, this,
&AMovimento::TeclaZ_Mantida);
InputComponent->BindAction("Tecla_X", IE_Pressed, this,
&AMovimento::TeclaX_Mantida);
InputComponent->BindAction("Tecla_X", IE_Repeat, this,
&AMovimento::TeclaX_Mantida);
}
 Listagem: Quarto e último trecho do arquivo Movimento.cpp – Fonte: O autor.
No último trecho do arquivo temos a ligação entre os mapeamentos con�gurados, os eventos e os métodos de resposta
internos. As ligações ocorrem utilizando o método BindAction, onde o primeiro parâmetro refere-se ao nome do
mapeamento, podendo ser Tecla_Z ou Tecla_X; o segundo de�ne o evento utilizado, aqui sendo adotados IE_Pressed e
IE_Repeat, e o terceiro aponta para o método de resposta correto.
Evento Utilização
IE_Pressed Ocorre no momento inicial do pressionamento de uma tecla.
IE_Repeat É repetido durante o período em que a tecla é mantida pressionada.
IE_Released Ocorre no momento em que a tecla é liberada.
 Tabela: Eventos para as ações sobre teclas e outros valores discretos. Fonte: O autor.
Não podemos deixar de mencionar as importações necessárias para lidar com a câmera e os objetos criados via
programação, bem como o controle dos dispositivos de entrada.
 
#include "Movimento.h"
// Controle dos dispositivos de entrada
#include "Components/InputComponent.h"
// Câmera e componentes de cena
#include "Camera/CameraComponent.h"
#include "Components/SceneComponent.h"
 Listagem:Importações utilizadas no arquivo Movimento.cpp – Fonte: O autor.
Após compilar o projeto, a partir do editor da Unreal Engine, adicionamos um objeto do tipo AMovimento à cena,
posicionamos corretamente, e associamos uma malha estática por meio da hierarquia oferecida no painel Details.
 Figura: Escolha da malha estática para o objeto Movimento1. Fonte: O autor.
Afastando a visualização podemos observar tanto a câmera, criada via programação, quanto a malha estática escolhida, e já
estamos em condição de executar o jogo, apertando as teclas Z e X para mover o objeto, com o acompanhamento da
câmera, durante a execução.
 Figura: Instância de AMovimento no ambiente, antes da execução. Fonte: O autor.
Embora existam muitas diferenças entre a Unity 3D e a Unreal Engine, certamente o controle de dispositivos de entrada é um
ponto de grande relevância. Enquanto a Unreal Engine adota o modelo extremamente robusto, demonstrado aqui, com a
necessidade de mapeamentos para todas as entradas adotadas, na Unity 3D temos a possibilidade de veri�car as entradas a
partir de um componente centralizador, sem a necessidade de mapeamentos especí�cos. 
 
using UnityEngine;
 
public class TestaTeclas : MonoBehaviour
{
void Update()
{
if (Input.GetKey(KeyCode.Z))
{
Debug.Log("Tecla Z pressionada");
}
if (Input.GetKey(KeyCode.X))
{
Debug.Log("Tecla X pressionada");
}
}
}
 Listagem: Código C# para teste das teclas Z e X na Unity 3D. Fonte: O autor.
Atividade
1. A linguagem C++ é extremamente robusta, sendo derivada direta do C, mas com o acréscimo de elementos na sintaxe para
dar suporte ao paradigma orientado a objetos. Entre as palavras acrescentadas à sintaxe, qual delas de�ne o ponteiro de
autorreferência?
a) me
b) self
c) base
d) super
e) this
2. Quando criamos um componente para utilização no ambiente da Unreal Engine, devemos derivar a classe de algum dos
modelos básicos contidos nas bibliotecas. Para os objetos que podem ser adicionados como elementos da cena, a classe de
base mais simples seria:
a) Pawn
b) Actor
c) Character
d) PlayerController
e) InterpGroup
3. No ambiente da Unreal Engine, as entradas que serão adotadas devem ser mapeadas de forma a permitir o acionamento de
métodos das classes, relacionados às entradas utilizadas, podendo ocorrer a partir de eventos especí�cos. Qual o método
responsável por efetuar toda a ligação entre mapeamento, evento e método de resposta?
a) BeginPlay
b) Tick
c) SetupAttachment
d) BindAction
e) SetActorLocation
Notas
Bones1
São criadas as chaves de animação, ao longo da linha de tempo, para os diversos componentes da hierarquia, e a malha é
aplicada sobre ela, adequando-se ao movimento esperado — como ocorre para nós, quando nossos esqueletos se movem e a
pele segue o movimento que foi imposto.
Referências
CARNALL, B. Unreal Engine 4.X By Example. Birmingham: Packt Publishing, 2016.
COPLE, D. Desenvolvimento de Jogos II. Rio de Janeiro: SESES, 2019.
DUNN, F. PARBERRY, I. 3D Math Primer for Graphics and Game Development. Texas: Wordware Publishing, Inc, 2002.
MONIEM, M. Mastering Unreal Engine 4.X. Birmingham: Packt Publishing, 2016.
SATHEESH, P. Unreal Engine 4 Game Development Essentials. Birmingham: Packt Publishing, 2016.
Próxima aula
Criação de cenários complexos;
Utilização de narrativa em primeira pessoa;
Utilização de narrativa em terceira pessoa.
Explore mais
No site w3schools.com leia sobre Referência da linguagem C++ tradicional, com diversos exemplos.
Referência  geral da API em C++ para Unreal Engine, disponível no site do fabricante: Unreal Engine.
Também  em Unreal veja a Documentação do fabricante sobre controle de entradas via Blueprints.
javascript:void(0);
javascript:void(0);
javascript:void(0);

Continue navegando