Mudanças entre as edições de "Vetores e Trigonometria"
Linha 1: | Linha 1: | ||
+ | |||
Linha 272: | Linha 273: | ||
Evitar o cálculo do tamanho reduz muito processamento, por isso é bom usar vetores normalizados para representar direções. No C++, o método para o cálculo do produto escalar fica assim: | Evitar o cálculo do tamanho reduz muito processamento, por isso é bom usar vetores normalizados para representar direções. No C++, o método para o cálculo do produto escalar fica assim: | ||
− | <syntaxhighlight lang=c | + | Código em C++: |
+ | |||
+ | <syntaxhighlight lang="c++"> | ||
float Vector2D::dot(const Vector2D& other) const { | float Vector2D::dot(const Vector2D& other) const { | ||
return (x * other.x) + (y * other.y); | return (x * other.x) + (y * other.y); | ||
Linha 278: | Linha 281: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | E o do ângulo entre os dois vetores unitários, assim: | + | Código em Python:<syntaxhighlight lang="python3"> |
+ | def dot(self, other: Vector2D) -> float: | ||
+ | return (self.x * other.x) + (self.y * other.y) | ||
+ | </syntaxhighlight>E o do ângulo entre os dois vetores unitários, assim (C++): | ||
− | <syntaxhighlight lang=c | + | <syntaxhighlight lang="c++"> |
float Vector2D::angleBetween(const Vector2D& other) const { | float Vector2D::angleBetween(const Vector2D& other) const { | ||
float dp = dot(other); | float dp = dot(other); | ||
Linha 292: | Linha 298: | ||
return dot(other) > 0 ? -angPi : angPi; | return dot(other) > 0 ? -angPi : angPi; | ||
} | } | ||
+ | </syntaxhighlight>Código em Python:<syntaxhighlight lang="python3"> | ||
+ | def angle_between(self, other: Vector2D) -> float: | ||
+ | dp = self.dot(other) | ||
+ | |||
+ | # Garantir que o valor do produto escalar esteja entre -1 e 1 | ||
+ | dp = max(-1.0, min(1.0, dp)) | ||
+ | |||
+ | # Calcular o ângulo em radianos | ||
+ | angPi = math.acos(dp) | ||
+ | |||
+ | # Retornar o ângulo positivo ou negativo dependendo do sinal do produto escalar | ||
+ | return -angPi if self.dot(other) > 0 else angPi | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Edição atual tal como às 18h18min de 28 de março de 2025
Links Relacionados: Matemática e Física para Jogos, Jogos Digitais
Descrição
Na Computação Gráfica, e consequentemente nos Games que se utiliza desse recurso para a apresentação e interação visual, são utilizadas algumas grandezas como direção e força do vento, gravidade, direção que um personagem está olhando, etc. Essa é descrita como uma grandeza vetorial.
Essas direções e intensidades são representadas por vetores. Estes possuem informações referentes a distância, sentido e tamanho, geralmente representados graficamente por setas.

Características dos Vetores

- Tamanho: é a intensidade. É também chamado de magnitude;
- Direção: indica a inclinação do vetor no espaço;
- Sentido: mostra para onde o vetor está apontando;
Observação: vetores não possuem como propriedade a posição.
Vetores representam deslocamentos com sinal em cada eixo.
- Em 2 dimensões têm-se um valor para x e y.
- Em 3 dimensões, têm-se x, y e z.
- Em 4 dimensões, têm-se x, y, z e w.
Graficamente, representamos vetores como uma flecha. A posição da flecha não importa, desde que sua direção, tamanho e sentido sejam mantidos.
Representação na Programação
No C++, python ou no Java, esses valores virariam variáveis float:
Código em C++
class Vector2D {
public:
float x;
float y;
Vector2D() : x (0.0f), y (0.0f) {}
Vector2D(float _x, float _y) : x(_x), y(_y) {}
};
Código em Python
class Vector2D:
def __init__(self, x: float, y: float):
self.x: float = x
self.y: float = y
Tamanho
Para encontrarmos o tamanho, utilizamos a fórmula definida na última aula. Transcrevendo-a em C++, temos:
Código em C++
#include <math.h>
float Vector2D::size() {
return sqrt((x * x) + (y * y));
}
Código em Python
def size(self) -> float:
return math.sqrt((self.x * self.x) + (self.y * self.y))
Soma de Vetores
Também podemos utilizar operações de soma de vetores. Por exemplo:

Com o código em C++:
Vector2D Vector2D::operator +(const Vector2D& other) const {
return Vector2D(x + other.x, y + other.y);
}
Vector2D& Vector2D::operator +=(const Vector2D& other) {
x += other.x;
y += other.y;
return *this;
}
Código em Python
def add(self, other: Vector2D) -> None:
self.x += other.x
self.y += other.y
@staticmethod
def sum(a: "Vector2D", b: "Vector2D") -> "Vector2D":
return Vector2D(a.x + b.x, a.y + b.y)
Um exemplo prático pode se ver na figura a seguir. Se quisermos representar a trajetória da bola, podemos somar o vetor gravidade ao vetor da trajetória. É possível também adicionar vetores como vento, por exemplo.

Vetores também podem ser multiplicados por valores. Para tal, o código em C++ efetua essa operação:
Vector2D Vector2D::operator *(float scalar) const {
return Vector2D(x * scalar, y * scalar);
}
Vector2D& Vector2D::operator *=(float scalar) {
x *= scalar;
y *= scalar;
return *this;
}
Código em Python
def multiply(self, other: Vector2D) -> None:
self.x *= other.x
self.y *= other.y
@staticmethod
def multiply_vectors(a: "Vector2D", b: "Vector2D") -> "Vector2D":
return Vector2D(a.x * b.x, a.y * b.y)
Normalização
Para normalizar um vetor, ou seja, impor um tamanho a ele, utilizamos a operação de normalização. Isso reduz o tamanho do vetor para 1 (um). Este vetor norm alizado pode então ser multiplicado por um escalar para obtermos tamanho desejado. Para normalizar um vetor, basta dividirmos x e y pelo tamanho do vetor. Segue o código em C++:
Vector2D& Vector2D::normalize() {
return (*this /= size());
}
Cóidigo em Python:
def normalize(self) -> Vector2D:
s: float = self.size()
return Vector2D(self.x / s, self.y / s)
Vetores e Ângulos
Se quisermos que o nosso atacante chute uma bola baseado no ângulo e na força, podemos criar um vetor com essas informações.
Se for dado um chute de ângulo 50 graus e a uma força 10, poderíamos chamar a função a baixo. Lembrando que em C/C++ o ângulo é em radianos (1 grau = PI/180 radianos).
Código em C++
Vector2D Vector2D::bySizeAndAngle(float size, float angle) {
float radians = angle * M_PI / 180.0f; // Converte graus para radianos
return Vector2D(cos(radians) * size, sin(radians) * size);
}
Código em Python:
@staticmethod
def by_size_and_angle(size: float, angle: float) -> "Vector2D":
radians = math.radians(angle) # Converte graus para radianos
return Vector2D(math.cos(radians) * size, math.sin(radians) * size)
Da mesma forma, podemos retornar qual o ângulo (em radianos) de um vetor por meio do arco-tangente de x e y, conforme o código C++ abaixo:
float Vector2D::angle() const {
return atan2f(y, x);
}
Código em Python:
def angle(self) -> float:
return math.atan2(self.y, self.x) # Retorna o ângulo em radianos
Para facilitar, podemos fazer funções de conversão de radianos para graus e graus para radianos:
#define PI 3.1416
// Converte graus para radianos
float grad2radians(float grad) {
return (grad * PI) / 180; // Correção do fator de conversão
}
// Converte radianos para graus
float radians2grad(float radians) {
return (radians * 180) / PI;
}
Código em Python:
# Converte graus para radianos
def grad2radians(grad: float) -> float:
return (grad * math.pi) / 180
# Converte radianos para graus
def radians2grad(radians: float) -> float:
return (radians * 180) / math.pi
Também podemos rotacionar um vetor, utilizando a operação de rotação vista na última aula. Contudo, nesse caso estamos trabalhando apenas com vetores, em que a posição não importa. Então estamos sempre tendo como base o eixo (0, 0) do vetor, não necessitando das operações de translação.
#define PI 3.1416
Vector2D& Vector2D::rotate(float angle) {
// Assumindo que 'angle' está em radianos. Se estiver em graus, converta para radianos:
// angle = grad2radians(angle); // Se você quiser usar graus como entrada
// Calculando o seno e o cosseno uma única vez para maior eficiência.
float s = sin(angle);
float c = cos(angle);
// Fórmula de rotação
float newX = (x * c) - (y * s);
float newY = (x * s) + (y * c);
// Atualizando as coordenadas do vetor
x = newX;
y = newY;
// Retorna o próprio objeto para permitir encadeamento de métodos
// (por exemplo, v.rotate(...).rotate(...))
return *this;
}
Código em Python:
def rotate(self, angle: float):
# Calculando o seno e o cosseno uma única vez
s = math.sin(angle)
c = math.cos(angle)
# Fórmula de rotação
new_x = (self.x * c) - (self.y * s)
new_y = (self.x * s) + (self.y * c)
# Atualizando as coordenadas do vetor
self.x = new_x
self.y = new_y
return self # Retorna o próprio objeto para encadeamento de métodos
# (ex: v.rotate(...).rotate(...))
Ângulo entre dois vetores
Para encontrar o ângulo entre dois vetores, é utilizado o produto escalar, onde A ⋅ B é o produto escalar entre os pontos A e B:
ou
Assim, podemos dizer que:
Onde |A| e |B| são respectivamente os tamanhos de A e B e α o ângulo que queremos calcular. Agora, note como o cálculo seria simplificado se A e B fossem vetores de tamanho 1:
ou, simplesmente:
Evitar o cálculo do tamanho reduz muito processamento, por isso é bom usar vetores normalizados para representar direções. No C++, o método para o cálculo do produto escalar fica assim:
Código em C++:
float Vector2D::dot(const Vector2D& other) const {
return (x * other.x) + (y * other.y);
}
Código em Python:
def dot(self, other: Vector2D) -> float:
return (self.x * other.x) + (self.y * other.y)
E o do ângulo entre os dois vetores unitários, assim (C++):
float Vector2D::angleBetween(const Vector2D& other) const {
float dp = dot(other);
if (dp >= 1.0) {
dp = 1.0f;
} else if(dp <= -1.0) {
dp = -1.0f;
}
float angPi = (float) acos(dp);
return dot(other) > 0 ? -angPi : angPi;
}
Código em Python:
def angle_between(self, other: Vector2D) -> float:
dp = self.dot(other)
# Garantir que o valor do produto escalar esteja entre -1 e 1
dp = max(-1.0, min(1.0, dp))
# Calcular o ângulo em radianos
angPi = math.acos(dp)
# Retornar o ângulo positivo ou negativo dependendo do sinal do produto escalar
return -angPi if self.dot(other) > 0 else angPi
Exercícios
1. Implemente o header (.h) e o arquivo fonte (.cpp) do vetor 2D para utilizá-lo no resto dos exercícios.
2. Faça um programa com as seguintes características:
- Clique na tela para definir o primeiro ponto (Ponto A)
- Clique na tela para definir o segundo ponto (Ponto B)
- Desenhe uma linha entre o Ponto A e o Ponto B
- Informe na tela, em elementos tipo texto:
- a distância entre os pontos
- o ângulo do Ponto A para o Ponto B
- A cada novo clique, o Ponto B se tornará o Ponto A e o Ponto B será o novo local onde foi dado o clique. Redesenhe a linha entre A e B e refaça os cálculos e apresente-os na tela.
3. Faça um programa com as seguintes características:
- Desenhe do lado esquerdo da tela e abaixo um pequeno canhão.
- A movimentação do mouse para cima e para baixo altera o ângulo de tiro.
- A movimentação do mouse para a esquerda e direita altera a força do tiro.
- O clique do mouse efetua um disparo (represente o disparo com um ponto grande ou com uma imagem)
- Quando a bala do canhão cair, calcule a distância entre o canhão e a bala.
- Considere a gravidade como 9.8 m/s.
- Mostre na tela as informações de:
- Ângulo do tiro
- Força do tiro
- Distância percorrida pela bala do canhão.
4. No programa anterior, acrescente vento. Para isso:
- Crie um vetor de direção e velocidade do vento. Como estamos em um espaço bidimensional, considere apenas contra o canhão ou a favor do tiro do canhão (direita para esquerda ou esquerda para direita).
- Altere a velocidade do vento por meio das setas direcionais ( <- e -> ).
- Acrescente a informação da direção do vento e força.