상당히 좋은 자동차 운동을 만드는 것은 어렵지 않습니다 (그러나이 게시물은 꽤 길 것입니다). 자동차가 물리적으로 그럴듯 해지려면 몇 가지 기본 힘을 "시뮬레이션"해야합니다.
(모든 코드 샘플은 의사 코드입니다.)
가속
먼저 가속이 필요합니다. 다음 줄처럼 간단한 것 :
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))