728x90
반응형
- 개요

임의의 벡터가 각 θ만큼 회전한 결과로 생성되는 벡터는 위와 같다
위의 식을 사용하여 하트를 회전시키는 예제를 작성한다
- 예제
// 모든 스코프가 공유하는 변수
// 최종 위치 벡터 / 최종 하트 크기 / 최종 회전각(각도법)
Vector2 currentPosition;
float currentScale = 10.f;
float currentDegree = 0.f;
// 매 프레임마다 호출하는 함수
void SoftRenderer::Update2D(float InDeltaSeconds)
{
// 사용자로부터 입력을 받기 위한 레퍼런스
auto& g = Get2DGameEngine();
const InputManager& input = g.GetInputManager();
// 로컬 변수
// 하트 이동 속도 / 하트 최소 크기 / 하트 최대 크기 / 하트 크기를 조절하는 속도 / 하트를 회전하는 속도(각속도)
static float moveSpeed = 100.f;
static float scaleMin = 5.f;
static float scaleMax = 20.f;
static float scaleSpeed = 20.f;
static float rotateSpeed = 180.f;
// 사용자로부터 입력값을 받아와 변경할 하트의 위치 벡터 / 하트의 크기 / 하트의 각도 생성
Vector2 inputVector = Vector2(input.GetAxis(InputAxis::XAxis), input.GetAxis(InputAxis::YAxis)).GetNormalize();
Vector2 deltaPosition = inputVector * moveSpeed * InDeltaSeconds;
float deltaScale = input.GetAxis(InputAxis::ZAxis) * scaleSpeed * InDeltaSeconds;
float deltaDegree = input.GetAxis(InputAxis::WAxis) * rotateSpeed * InDeltaSeconds;
// 하트의 최종 위치 / 최종 크기 / 최종 각도 설정
currentPosition += deltaPosition;
currentScale = Math::Clamp(currentScale + deltaScale, scaleMin, scaleMax);
currentDegree += deltaDegree;
}
// 화면에 렌더링하는 함수
void SoftRenderer::Render2D()
{
// 화면에 렌더하기 위해 가져올 레퍼런스
auto& r = GetRenderer();
const auto& g = Get2DGameEngine();
// 배경에 격자 그리기
DrawGizmo2D();
// 로컬 변수
// 현재 각도 / 각도를 서서히 증가시킬 값 / 하트를 구성하는 점을 저장할 컨테이너 / 현재 각도에 대응하는 색
float rad = 0.f;
static float increment = 0.001f;
static std::vector<Vector2> hearts;
HSVColor hsv(0.f, 1.f, 0.85f);
// 컨테이너에 하트를 구성하는 점들을 저장하는 로직
if (hearts.empty())
{
// sin 함수와 cos 함수의 정의역인 0과 2π의 범위만을 순회
for (rad = 0.f; rad < Math::TwoPI; rad += increment)
{
float sin = sinf(rad);
float cos = cosf(rad);
float cos2 = cosf(2 * rad);
float cos3 = cosf(3 * rad);
float cos4 = cosf(4 * rad);
// 하트 방정식 사용
float x = 16.f * sin * sin * sin;
float y = 13 * cos - 5 * cos2 - 2 * cos3 - cos4;
hearts.push_back(Vector2(x, y));
}
}
// 최종 각도에 대응하는 사인과 코사인 값 얻기
float sin = 0.f, cos = 0.f;
Math::GetSinCos(sin, cos, currentDegree);
// 현재 각도를 초기화한 후 색상을 증가시키면서 점에 대응
rad = 0.f;
for (auto const& v : hearts)
{
// 1) 점(위치벡터)에 크기를 적용
Vector2 scaledV = v * currentScale;
// 2) 벡터의 회전을 구하는 식을 사용하여 점을 회전
Vector2 rotatedV = Vector2(scaledV.X * cos - scaledV.Y * sin, scaledV.X * sin + scaledV.Y * cos);
// 3) 회전시킨 점을 이동
Vector2 translatedV = rotatedV + currentPosition;
hsv.H = rad / Math::TwoPI;
r.DrawPoint(translatedV, hsv.ToLinearColor());
rad += increment;
}
// 현재 하트의 위치 / 크기 / 각도를 화면에 출력
r.PushStatisticText(std::string("Position : ") + currentPosition.ToString());
r.PushStatisticText(std::string("Scale : ") + std::to_string(currentScale));
r.PushStatisticText(std::string("Degree : ") + std::to_string(currentDegree));
}
Update2D 함수에서 설정한 최종 각도에 대응하는 sin 함수와 cos 함수의 값을 가져와서
각 점(위치벡터)을 최종 각도만큼 회전시킨 결과를 얻어오고 Render2D 함수에서 렌더링을 진행한다
- 최종 실행 결과

728x90
반응형
'수학 > 이득우의 게임 수학 - 실습 예제' 카테고리의 다른 글
| 행렬을 사용하여 하트의 크기 변환 & 회전 변환 구현 (0) | 2025.09.10 |
|---|---|
| 극좌표계를 활용한 소용돌이 효과 구현 (0) | 2025.08.27 |
| sin 함수를 사용한 하트의 박동 표현 (0) | 2025.08.27 |
| 하트에 무지개 색상 입히기 (0) | 2025.08.27 |
| 삼각함수로 하트 그리기 (0) | 2025.08.24 |