Tôi đã thực hiện một công cụ vật lý tùy chỉnh và tôi khá gần để nó hoạt động như tôi muốn. Có một lực hấp dẫn, va chạm và phản ứng va chạm. Thật không may, dường như có một số jitter trong số các đối tượng gần đứng yên, rất có thể là do các dấu hiệu vật lý thấp không thể thay đổi.
Tôi đã xem trực tuyến và đã thử một số triển khai tôi đã tìm thấy, bao gồm một số nỗ lực của riêng tôi. Dưới đây là các giải pháp tôi đã thử:
- Chuyển động giảm xóc khi tốc độ / động lượng / năng lượng tiềm năng dưới một ngưỡng.
- Chỉ áp dụng trọng lực khi tốc độ / động lượng / năng lượng tiềm năng vượt quá ngưỡng.
- Thực hiện chức năng ngủ. kiểm tra vị trí của đối tượng trong 60 khung hình cuối cùng và ngủ nếu nó không di chuyển ra ngoài hộp giới hạn ngưỡng.
- Lặp lại qua các đối tượng từ trên xuống dưới khi áp dụng thử nghiệm và giải quyết va chạm.
Đây là mã của tôi:
for each (auto ball in m_Balls)
{
ball->Update(t);
ball->Accelerate(m_Gravity);
}
// This disgusting hack sorts the balls by height. In a more complete physics
// implementation, I guess I could change the sorting based on the direction of
// gravitational force. This hack is necessary to prevent balls being pulled downwards
// into other balls by gravity; by calculating from the bottom of the pile of
// objects, we avoid issues that occur when adjustments push the object towards gravity.
m_Balls.sort([](const CSprite* a, const CSprite* b)
{return a->m_pos.m_y < b->m_pos.m_y; });
static float cor = 0.8f;
for each (auto ball in m_Balls)
{
for each (auto collider in m_Walls)
{
if (collider->HitTest(ball, 1))
{
float offset = 0;
auto n = Helper::GetNormal(ball, collider, offset);
ball->SetPosition(ball->GetPosition() + (n * offset));
auto r = ball->GetVelocity() - ((1 + cor) * Dot(ball->GetVelocity(), n) * n);
ball->SetVelocity(r);
ball->SetPosition(ball->GetPosition() + ball->GetVelocity() * DeltaTime());
}
}
CVector adjustment;
for each (auto collider in m_Balls)
{
if (ball == collider)
{
break;
}
auto diff = collider->GetPosition() - ball->GetPosition();
float distance = diff.Length();
if (distance <= (ball->GetWidth() / 2) + (collider->GetWidth() / 2))
{
auto midPoint = (ball->GetPosition() + collider->GetPosition()) * 0.5f;
adjustment = diff.Normalise() * (ball->GetWidth() / 2
- Distance(ball->GetPosition(), midPoint));
ball->SetPosition(ball->GetPosition() - adjustment);
diff = collider->GetPosition() - ball->GetPosition();
if (Dot(ball->GetVelocity() - collider->GetVelocity(), diff) > 0)
{
auto n = diff.Normalise();
auto u = Dot(cor * ball->GetVelocity() - collider->GetVelocity(), n) * n;
ball->Accelerate(-u);
collider->Accelerate(u);
}
}
}
if (ball->GetSpeed() > MAX_SPEED)
{
ball->SetSpeed(MAX_SPEED);
}
}
Làm thế nào để tôi ngăn ngừa jitter giữa các đối tượng vật lý gần như đứng yên?