벡터를 사용하여 현실적인 자동차 움직임을 만들려고합니다.


12

나는 이것을하는 방법을 고글하고 이것을 http://www.helixsoft.nl/articles/circle/sincos.htm 발견 했다. 존재하지 않았기 때문입니다. 나는 cos와 sin 함수를 보았지만 사용법과 벡터를 사용하여 자동차 운동이 올바르게 작동하는 방법을 이해하지 못합니다. 무엇을해야할지 잘 모르겠 기 때문에 코드가 없습니다.

도움을 주시면 감사하겠습니다.

편집하다:

게임에 TL 엔진을 사용해야한다는 제한이 있습니다. 물리 엔진을 추가 할 수 없습니다. C ++로 프로그래밍해야합니다. 다음은 내가 제공 한 링크에서 수행 한 내용을 따르려고 시도한 결과입니다.

if(myEngine->KeyHeld(Key_W))
    {
        length += carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_S))
    {
        length -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_A))
    {
        angle -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_D))
    {
        angle += carSpeedIncrement;
    }

    carVolocityX = cos(angle);
    carVolocityZ = cos(angle);

    car->MoveX(carVolocityX * frameTime);
    car->MoveZ(carVolocityZ * frameTime);

이 사이트에서 스티어링 동작을 확인하십시오 : red3d.com/cwr/steer
MichaelHouse

"현실적인 자동차 움직임"을 정의해야합니다
Maik Semder

1
아마도 당신의 각도는 스티어링 휠에서 나온 것으로 가정합니다. 길이는 속도의 크기 여야합니다. 마지막 코드 조각의 라인에 뭔가가 될 수 있도록 : carVecloityX = length* cos(angle);, carVelocityZ = length *sin(angle);, 그 외에도, 귀하의 의견이 무엇인지 말해 차는 행동하는 방법을하시기 바랍니다. 지금은지면에서 조종해야하지만 다시 한 번 이것은 일반적인 것이 아닙니다. 거기에서 우리는 조잡한 오일러 통합 단계를 만들었습니다 ..
teodron

답변:


23

상당히 좋은 자동차 운동을 만드는 것은 어렵지 않습니다 (그러나이 게시물은 꽤 길 것입니다). 자동차가 물리적으로 그럴듯 해지려면 몇 가지 기본 힘을 "시뮬레이션"해야합니다.

(모든 코드 샘플은 의사 코드입니다.)

가속

먼저 가속이 필요합니다. 다음 줄처럼 간단한 것 :

acceleration_vector = forward_vector * acceleration_input * acceleration_factor
  • forward_vector — 자동차와 같은 방향을 가리키는 벡터입니다.
  • acceleration_input — 입력은 [-1, 1] 간격이어야합니다.
  • acceleration_factor — 가속 값 (픽셀 / 초 ^ 2 또는 단위).

조타

조향도 상당히 간단합니다. 원칙적으로 자동차의 전방 벡터 를 회전시켜 다른 방향으로 향하게하는 것입니다.

steer_angle = steer_input * steer_factor
new_forward_vector = rotate_around_axis(forward_vector, up_vector, steer_angle)

그러나 여기서 합병증이 발생할 수 있습니다. 입력 값이 키보드를 통해 입력 된 경우 그 값은 -1 또는 1이되므로 자동차가 즉시 회전합니다. 매우 간단한 선형 보간 (lerping)을 사용하여이 문제를 해결할 수 있습니다.

 amount = time_since_last_frame * steer_lerp_factor
 forward_vector = lerp(forward_vector, new_forward_vector, amount)

양은 움직임이 프레임 속도에 의존하지 않도록 시간에 따라 달라집니다. 양은 [0, 1] 사이 여야하고 더 작을수록 기존 벡터와 새 벡터 사이의 전환이 더 매끄러 워집니다.

(이 시점에서이 차가 아직도 서있는 경우에도 조종 것을 발견 할 것이다. 곱셈, 그것을 방지하기 위해 steer_angle에 의해 current_speed / max_speed, 어디 max_speed당신에 의해 정의 된 상수입니다.)

움직이는

이제 가속도를 적용하고 속도, 가속도 및 조향에 따라 특정 수의 픽셀을 이동시킵니다. 또한 자동차 속도가 제한되어 무한히 빠르게 움직이지 않도록해야합니다.

current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

차가 미끄러 져

내가 옳다면, 마치 차가 얼음 위에있는 것처럼 돌 때마다 차가 미끄러 져있는 것처럼 보일 것입니다. 마찰이 없기 때문입니다. 실제 자동차의 경우 측면 마찰이 적습니다 (바퀴가 옆으로 회전 할 수 없기 때문에 : P).

측면 속도를 줄여야합니다. 완전히 줄이지 않으면 자동차가 표류하는 것처럼 보일 수도 있습니다.

 lateral_velocity = right_vector * dot(velocity_vector, right_vector)
 lateral_friction = -lateral_velocity * lateral_friction_factor 

우리가 마찰에 대해 이야기하고 있기 때문에 가속을 멈 추면 차가 결국 멈추도록 속도를 줄이는 힘 (마찰력)을 원할 수도 있습니다.

 backwards_friction = -velocity_vector * backwards_friction_factor

자동차 이동 코드는 이제 다음과 같아야합니다.

// Friction should be calculated before you apply the acceleration
lateral_velocity = right_vector * dot(velocity_vector, right_vector)
lateral_friction = -lateral_velocity * lateral_friction_factor
backwards_friction = -velocity_vector * backwards_friction_factor
velocity_vector += (backwards_friction + lateral_friction) * time_since_last_frame


current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{ 
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

결산 메모

스티어링에 lerping을 어떻게 적용해야하는지 언급했습니다. 가속과 조향 각도에 대해서도 동일한 작업을 수행해야 할 수도 있습니다 (이전 프레임의 값을 저장하고 그로부터 뛰어 넘어야합니다). 또한 자동차와 관련된 모든 벡터 (앞, 오른쪽, 위)는 길이가 1이어야합니다.

또한 마찰은 여기에 표시된 것보다 약간 더 복잡합니다. 자동차의 정지에 필요한 가속 길이보다 길지 않아야합니다. 그렇지 않으면 마찰로 인해 자동차가 반대 방향으로 움직입니다. 따라서 다음과 같은 것이 있어야합니다.

dt = time_since_last_frame
backwards_friction.resize(min(backwards_friction.norm(), velocity_vector.norm() / dt))
lateral_friction.resize(min(lateral_friction.norm(), lateral_velocity.norm() / dt))

와우, 이것은 훌륭한 답변입니다!
ezolotko

0

귀하의 질문으로 판단하면, 나는 당신이 프로그래밍에 익숙하지 않다고 가정 할 것입니다 (a-ok btw!). 현실적인 자동차 시뮬레이션은 물리학에서 가장 어려운 측면 중 하나이므로 기존 프레임 워크를 사용하는 것이 좋습니다.

2D / 3D 제한 사항에 대해서는 언급하지 않았으므로 계속해서 Havok SDK (비상업적 용도로는 무료)를 다운로드하고 간단한 데모를 시작하여 실행하십시오 (실제로 데모가 있음) 시스템에 컴파일되면 모든 코드가 있습니다.] 컴파일하기 위해 아무것도 할 필요가 없습니다 ... 프로젝트를 열고 빌드를 누르십시오).

자동차 물리학의 비하인드 씬에 대한 아이디어가 생기면 (실제로는 실제 물리 구현이 보이지 않지만 숨겨져 있지만 인터페이스를 보게 될 것입니다.) 더 나은 위치에 있다고 생각합니다. 스스로 시작할 때 바로 얻을 수 있습니다.

나는 얼마 전 비슷한 질문을 했다. 링크가 도움이 될 수도 있습니다. 그리고 여기 또 다른 링크가 있습니다.


편집 결과를 본 후에는 계산 된 각도에 따라 자동차의 속도를 단순히 변경하려고하는 것 같습니다 (현실적이지 않기 때문에 원래 질문을 변경하여 반영해야 함). 각도가 질문의 일부이고 (변경할 수 없음) 새 속도를 계산하기 위해 각도를 사용해야하는 경우 @teodron이 주석에 넣은 내용으로 이동하십시오.

다른 방법은 벡터 만 사용하는 것입니다. 벡터를 사용하는 여러 가지 접근법이 있습니다.

속도는 방향 * 크기입니다 (여기서 크기는 속도이고 방향은 정규화 된 벡터입니다). 자동차의 현재 속도와 방향을 계산하십시오. 방향을 취하고 벡터 D'에 직교 하는 벡터를 추가 하십시오. 이것은 자동차의 속도를 변화시킵니다. 주위를 엉망으로 어떤 각도 (당신이 있지만 수 있습니다 당신이 할 수있는 수직 벡터의 길이를 결정하는 각도를 사용하여 요소를 설정을 [아래 참조하지])

계산 방법D' : 수직 벡터를 찾으려면 원래 속도의 방향을 취하고 벡터를 교차하는 순서가 수직 벡터의 방향을 결정하는 화면을 향한 방향 벡터와 교차시킵니다. 그런 다음이 페페 추라 팩터와 회전 계수 를 곱 하면 회전 속도가 결정됩니다.


물리 엔진을 사용할 수는 없지만 게임은 3D이며 변경해야 할 것은 X와 Z 벡터만으로 실제 상태를 해결하는 데 필요합니다.
bobthemac

@bobthemac : 이것은 숙제 질문입니까? 그렇다면 질문을 수정하여 현재 가지고있는 제한 사항을 지적하고 관련 코드를 게시하여 작성해야 할 내용을 만드십시오. Btw, 마지막 링크는 기능 이해 측면에서 찾고있는 것일 수 있습니다.
Samaursa

요청하신 정보를 추가하고 제공된 링크를 보았지만 여전히 이해하지 못합니다.
bobthemac

@bobthemac : 내 편집 참조
Samaursa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.