삼각함수

김민수·2025년 2월 11일
0

게임수학

목록 보기
5/8

1. 삼각함수 기초

1) 직각삼각형과 삼각비

  • 직각삼각형은 한 각이 90°인 삼각형이다.

  • 이 삼각형에서 특정 각도 θ\theta를 기준으로 세 변을 다음과 같이 부른다.

    • 빗변(Hypotenuse): 가장 긴 변
    • 밑변(Adjacent): 기준 각도에 인접한 변
    • 높이(Opposite): 기준 각도에 마주보는 변
  • 삼각비는 이 세 변의 길이 비율로 정의된다.

    • sinθ=높이빗변\sin \theta = \frac{\text{높이}}{\text{빗변}}

    • cosθ=밑변빗변\cos \theta = \frac{\text{밑변}}{\text{빗변}}

    • tanθ=높이밑변\tan \theta = \frac{\text{높이}}{\text{밑변}}

2) 삼각함수의 정의역과 공역

  • sinθ\sin \theta, cosθ\cos \theta, tanθ\tan \theta 등은 실수 전체(각도를 나타내는 θ\theta-\infty부터 \infty까지)에서 정의할 수 있다.
  • 다만, tanθ\tan \theta의 경우 cosθ=0\cos \theta = 0이 되는 θ\theta 값(예: 9090^\circ, π2\frac{\pi}{2} 등)에서는 정의되지 않으므로 주의가 필요하다.
  • 공역:
    • sinθ,cosθ\sin \theta, \cos \theta의 값 범위는 [1,1][-1, 1]
    • tanθ\tan \theta는 이론적으로 (,)(-\infty, \infty)

3) 단위 원(Unit Circle)과 삼각함수

  • 단위 원은 반지름이 1인 원으로, 원의 방정식은 x2+y2=1x^2 + y^2 = 1이다.
  • 이 원 위의 임의의 점 (x,y)(x, y)가 각도 θ\theta를 기준으로 움직인다고 할 때,
    x=cosθ,y=sinθx = \cos \theta,\quad y = \sin \theta
    로 표현된다.
  • 즉, 각 θ\theta에 대해 단위 원 위의 좌표가 (cosθ,sinθ)\left(\cos\theta, \sin\theta\right)가 되며, 이를 통해 삼각함수를 시각화하기 쉽다.

4) 삼각함수 주요 공식

  • sin2θ+cos2θ=1\sin^2 \theta + \cos^2 \theta = 1
  • tanθ=sinθcosθ\tan \theta = \frac{\sin \theta}{\cos \theta}
  • 합각 공식
    cos(A+B)=cosAcosBsinAsinB\cos(A+B) = \cos A \cos B - \sin A \sin B
    sin(A+B)=sinAcosB+cosAsinB\sin(A+B) = \sin A \cos B + \cos A \sin B

2. 각도법과 호도법

1) 각도법(도, Degree)

  • 원을 360등분하여 만든 각 단위다.
  • 예: 180180^\circ, 9090^\circ, 3030^\circ

2) 호도법(래디안, Radian)

  • 원의 반지름 길이와 같은 길이의 호(원호)가 만드는 각을 1rad1 \,\text{rad}로 정의한다.
  • 한 바퀴(360360^\circ)가 2πrad2\pi \,\text{rad}에 해당한다.
  • 주요 관계식
    • 180=π(rad)180^\circ = \pi\,(\text{rad})
    • 1=π180rad1^\circ = \frac{\pi}{180}\,\text{rad}
    • 1rad=180π1\,\text{rad} = \frac{180}{\pi}^\circ

3. 삼각함수의 게임 활용 예시

1) 캐릭터 이동 예시

아래 조건을 가정해 캐릭터를 움직이는 간단한 예제를 살펴봅니다.

변수설명
초기 위치(0.0, 0.0)시작점
이동 각도30도오른쪽을 0도로 했을 때의 방향
이동 속도200.0초당 200 유닛 이동
총 이동 시간1.0초1초 동안 이동
프레임 속도(FPS)60 FPSΔt=160\Delta t = \frac{1}{60}
이동 반복 횟수60회매 프레임마다 이동(총 60프레임)

2) 예시

#include <iostream>
#include <cmath>

#define PI 3.14159265358979323846

struct Vector2 {
    float x, y;

    void Print() const {
        std::cout << "Position: (" << x << ", " << y << ")\n";
    }
};

// 삼각함수를 이용한 이동 함수
Vector2 MoveCharacter(Vector2 position, float angleDegrees, float speed, float deltaTime) {
    float angleRadians = angleDegrees * (PI / 180.0f); // 도 -> 라디안 변환
    float dx = cos(angleRadians) * speed * deltaTime;
    float dy = sin(angleRadians) * speed * deltaTime;

    return { position.x + dx, position.y + dy };
}

int main() {
    Vector2 playerPosition = { 0.0f, 0.0f };
    float playerAngle = 30.0f;  
    float playerSpeed = 200.0f;
    float deltaTime = 1.0f / 60.0f;

    for (int i = 0; i < 60; ++i) {
        playerPosition = MoveCharacter(playerPosition, playerAngle, playerSpeed, deltaTime);
        playerPosition.Print();
    }

    return 0;
}
  • 각도를 라디안으로 변환한 뒤, cos, sin 함수를 사용해 한 프레임마다 이동량(dxdx, dydy)을 구한다.
  • 누적된 위치를 출력해 보면, 1초간 (200×cos30,200×sin30)(200 \times \cos 30^\circ, 200 \times \sin 30^\circ)만큼 이동했음을 확인할 수 있다.

4. 좌표계의 이해

1) 직교좌표계(Cartesian Coordinate System)

  • 2D에서 (x,y)(x, y), 3D에서 (x,y,z)(x, y, z)로 표현된다.
  • 대부분의 게임 엔진은 물체의 위치, 이동, 충돌 등을 직교좌표계로 계산한다.

2) 극좌표계(Polar Coordinate System)

  • 원점으로부터의 거리(rr)와 회전 각도(θ\theta)로 위치를 표현한다.
  • 회전하는 물체원형 패턴을 구현할 때 직관적이다.
  • 좌표 변환
    • 극좌표 (r,θ)(r,\theta) → 직교좌표 (x,y)(x,y)
      x=rcosθ,y=rsinθx = r \cos\theta,\quad y = r \sin\theta
    • 직교좌표 (x,y)(x,y)$ → 극좌표 (r,θ)(r,\theta)
      r=x2+y2,θ=tan1(yx)r = \sqrt{x^2 + y^2},\quad \theta = \tan^{-1}\left(\frac{y}{x}\right)

5. 극좌표계 게임 내에서의 예시

1) 레이더(원형 범위) 시스템

  • 예: 배틀로얄 게임의 원형 안전 구역(Safe Zone)
  • 플레이어와 구역 중심 간의 거리 rr를 구해, rRsafer \leq R_{\text{safe}}이면 안전, 초과하면 위험 지역으로 판정 가능
  • 중심을 기준으로 거리 하나만 비교하므로, 많은 오브젝트를 효율적으로 판별할 수 있다.
#include <iostream>
#include <cmath>
using namespace std;

// 플레이어가 안전 구역 안에 있는지 확인
bool isInSafeZone(double player_x, double player_y, 
                  double zone_center_x, double zone_center_y, 
                  double safe_radius) {
    double dx = player_x - zone_center_x;
    double dy = player_y - zone_center_y;
    double r = sqrt(dx*dx + dy*dy);
    return (r <= safe_radius);
}

int main() {
    double zone_x = 50, zone_y = 50, safe_radius = 30;
    
    double player1_x = 60, player1_y = 60; // 안전 구역 근처
    double player2_x = 90, player2_y = 90; // 훨씬 멀리 있음

    cout << (isInSafeZone(player1_x, player1_y, zone_x, zone_y, safe_radius)
             ? "Player 1 Safe\n" : "Player 1 Not Safe\n");

    cout << (isInSafeZone(player2_x, player2_y, zone_x, zone_y, safe_radius)
             ? "Player 2 Safe\n" : "Player 2 Not Safe\n");

    return 0;
}

2) 원형 패턴의 공격(Bullet Hell)

  • 슈팅 게임에서 적이 방사형으로 총알을 발사할 때, 각도 θ\theta만 적절히 늘려주면 손쉽게 여러 총알의 위치를 계산할 수 있다.
  • 예: 8개 총알을 등간격(각도 45° 간격)으로 배치
    θi=3608×i,i=0,1,,7\theta_i = \frac{360^\circ}{8} \times i,\quad i = 0,1,\dots,7
    (xi,yi)=(rcosθi, rsinθi)(x_i, y_i) = \bigl(r \cos \theta_i,\ r \sin \theta_i\bigr)
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;

struct Bullet {
    double x, y;
};

// 총알 위치를 극좌표계를 이용해 계산
vector<Bullet> generateBullets(int n, double radius) {
    vector<Bullet> bullets;
    for (int i = 0; i < n; i++) {
        double theta_deg = (360.0 / n) * i; 
        double theta_rad = theta_deg * M_PI / 180.0; 
        
        double x = radius * cos(theta_rad);
        double y = radius * sin(theta_rad);
        
        bullets.push_back({x, y});
    }
    return bullets;
}

int main() {
    int bullet_count = 8;
    double radius = 10.0;
    
    vector<Bullet> bullets = generateBullets(bullet_count, radius);

    for (int i = 0; i < bullets.size(); i++) {
        cout << "Bullet " << i + 1 
             << ": (" << bullets[i].x << ", " 
             << bullets[i].y << ")\n";
    }

    return 0;
}
profile
안녕하세요

0개의 댓글