Все статьи Векторная алгебра в SFML
В sf::Vector2f и sf::Vector2i удобно хранить двумерные физические величины
- положение, расстояние или перемещение (т.е. точку или вектор перемещения)
- скорость (вместе с направлением движения)
- ускорение (вместе с направлением движения)
- размеры ограничивающего прямоугольника (a.k.a. bounding box)
Некоторые полезные возможности уже поддерживаются в SFML. Другие придётся разработать самостоятельно.
Идиома «статический класс»
Для математики стоило бы завести отдельную пару файлов GameMath.h
и GameMath.cpp
. Но тут есть грабли. Объясним на примере:
- GameMath.h (обратите внимание, в названиях функций нет глаголов — такое исключение делается для математических функций) ```cpp #pragma once
sf::Vector2f Normalized(sf::Vector2f value); sf::Vector2f Cartesian(float radius, float angle);
- GameMath.cpp
```cpp
#include "GameMath.h"
sf::Vector2f Normalized(sf::Vector2f value)
{
// ...
}
sf::Vector2f Cartesian(float radius, int angle)
{
// ...
}
Код нормально скомпилируется, но при попытке использовать Cartesian компоновщик (linker) выдаст ошибку категории ‘unresolved symbol’. Причина проста: в заголовке функция Cartesian описана как принимающая 2 числа float, а в cpp как принимающая float и int. Для компилятора это разные функции из-за перегрузки функций.
Для защиты от этих ошибок есть простое решение: структура со статическими методами:
- GameMath.h ```cpp #pragma once
struct Math() { // protect from suspicious creation. Math() = delete;
static sf::Vector2f Normalized(sf::Vector2f value);
static sf::Vector2f Cartesian(float radius, float angle); ``` - GameMath.cpp ```cpp #include "GameMath.h"
sf::Vector2f Math::Normalized(sf::Vector2f value) { // … }
sf::Vector2f Math::Cartesian(float radius, float value) { // … }
- как использовать:
```cpp
sf::Vector2f normal = Math::Normalized(unit.distance);
Часто употребляемые функции
- функция Cartesian для перевода из полярной системы координат в прямоугольную (декартову). Эта функция, например, позволяет получить двумерную скорость движения из модуля скорости в виде числа и направления движения в виде угла.
sf::Vector2f Math::Cartesian(float radius, float angle) { float radians = ToRadian(angle); // SFML allows to multiply sf::Vector2f on float. return sf::Vector2f{cosf(radians), sinf(radians)} * radius; }
- функция
float ToRadian(float angle)
для перевода величины угла из градусов в радианы - функция
float ToDegree(float angle)
для перевода величины угла из радианов в градусы - функция
float Sign(float value)
, возвращающая -1 для отрицательных чисел, 0 для нуля и 1 для положительных - функция
int Random(int max)
, возвращающая случайное число от 0 до max (включая либо не включая max) - функция
float Distance(sf::Vector2f from, sf::Vector2f to)
для определения расстояния между двумя точками - функция
sf::Vector2f Normalized(sf::Vector2f vec)
для получения вектора с тем же направлением и единичной длиной. Такой вектор называется нормаль (орт), при умножении его на абсолютную скорость юнита и на время мы получим перемещение юнита за данный промежуток времени. - функция
float PolarAngle(sf::Vector2f vec)
, которая превращает вектор направления в угол в градусах (или радианах).
Читать далее
- контракты функций
- линейная алгебра для программистов (habrahabr.ru)
- механизм перегрузки функций (cplusplus.com)