Billiard Game

 DirectX를 이용하여 당구 게임을 제작해보았다. 주어진 에셋에는 당구대와 벽, 공 4개와 흰 공을 움직이는 space바 명령어 뿐이다.

따라서 공의 움직임 (공 끼리의 충돌과 공과 벽 사이 충돌 등)을 모두 구현해야 한다. 공의 충돌은 운동량과 충격량을 이용하여 쉽게 계산할 수 있다. 

충격량은 운동량의 변화량이고, 해당 값을 구해서 속도를 업데이트 하는 식으로 하면 자연스러운 공의 움직임을 만들 수 있다. 따라서 해당 값을 구하기 위해 각 공의 상대속도를 구하고, 각 공 사이의 중심의 거리 벡터를 normalize 한 것과 dot product를 하면 상대속도의 변화량을 구할 수 있다. 속도의 변화량은 운동량의 변화량과 같기 때문에 이를 통해 바로 공의 속도 변화를 바로 계산할 수 있다. 


void hitBy(CSphere& ball)
    {
        if (hasIntersected(ball))
        {
            // Calculate relative velocity
            float relVelX = ball.getVelocity_X() - getVelocity_X();
            float relVelZ = ball.getVelocity_Z() - getVelocity_Z();
            // Calculate the normal vector at the collision point
            D3DXVECTOR3 normal = ball.getCenter() - getCenter();
            D3DXVec3Normalize(&normal, &normal);
            // Calculate impulse based on the normal and relative velocity
            float impulse = 2.0f * (relVelX * normal.x + relVelZ * normal.z) /(1.0f + 1.0f); // Assuming equal masses
            // Update velocities
            setPower(getVelocity_X() + impulse * normal.x, getVelocity_Z() + impulse * normal.z);
            ball.setPower(ball.getVelocity_X() - impulse * normal.x, ball.getVelocity_Z() - impulse * normal.z);
        }
    }


벽과의 충돌은 훨씬 더 간단하다. 벽과의 충돌할 때 입사각을 알면, 동일한 반사각으로 나가게 하면 된다. 이 때, 벽이 상하좌우 네 개가 존재하므로 어느 벽에 충돌하는 지 알아야 어느 방향의 속도를 반대로 뒤집고, 나머지 하나는 그대로 유지하는지를 결정할 수 있다.

 

 void hitBy(CSphere& ball)
    {
        if (hasIntersected(ball)) {
            if (m_width > m_depth) {       // 가로방향 벽일 때
                if (ball.getVelocity_Z() * (m_z - ball.getCenter().z) > 0) {        

                // 공이 벽을 향해 움직이고 있을 때만 충돌 판정
                    ball.setPower(0.7*ball.getVelocity_X(), -0.7*ball.getVelocity_Z());        

                // 공의 속도의 z성분 부호 반전
                }
            }
            else {                                   // 세로방향 벽일 때
                if (ball.getVelocity_X() * (m_x - ball.getCenter().x) > 0) {       

                 // 공이 벽을 향해 움직이고 있을 때만 충돌 판정
                    ball.setPower(-0.7*ball.getVelocity_X(), 0.7*ball.getVelocity_Z());       

                 // 공의 속도의 x성분 부호 반전
                }
            }
        }
    } 


*전체 코드

https://raw.githubusercontent.com/gaenyangi/mydb/main/OOP23_proj3/virtualLego.cpp?token=GHSAT0AAAAAACJU45JBSUFT23BRRKYTMIVKZKXAYTQ

댓글

이 블로그의 인기 게시물

IIKH Class from Timothy Budd's introduction to OOP

Compiler 9 - Efficient Code generation

Software Engineering 10 - V&V, SOLID principle