Tôi đang cố gắng tạo ra một trò chơi platformer 2D (loại Mario) và tôi gặp một số vấn đề với việc xử lý va chạm đúng cách. Tôi đang viết trò chơi này bằng C ++, sử dụng SDL cho đầu vào, tải hình ảnh, tải phông chữ, vân vân. Tôi cũng đang sử dụng OpenGL thông qua thư viện FreeGLUT kết hợp với SDL để hiển thị đồ họa.
Phương pháp phát hiện va chạm của tôi là AABB (Hộp giới hạn theo trục), đây thực sự là tất cả những gì tôi cần để bắt đầu. Những gì tôi cần là một cách dễ dàng để cả hai phát hiện va chạm xảy ra ở phía nào và xử lý các va chạm đúng cách. Vì vậy, về cơ bản, nếu người chơi va chạm với đỉnh của nền tảng, hãy định vị lại anh ta lên đỉnh; nếu có va chạm sang hai bên, hãy định vị lại người chơi quay lại phía bên của vật thể; nếu có va chạm xuống đáy, hãy định vị lại người chơi dưới nền tảng.
Tôi đã thử nhiều cách khác nhau để làm điều này, chẳng hạn như cố gắng tìm độ sâu thâm nhập và định vị lại người chơi bằng độ sâu thâm nhập. Đáng buồn thay, không có gì tôi đã cố gắng dường như hoạt động chính xác. Chuyển động của người chơi cuối cùng rất rối mắt và định vị lại người chơi khi tôi không muốn. Một phần lý do có lẽ là vì tôi cảm thấy đây là một việc quá đơn giản nhưng tôi lại nghĩ quá nhiều.
Nếu bất cứ ai nghĩ rằng họ có thể giúp đỡ, xin vui lòng xem mã dưới đây và giúp tôi cố gắng cải thiện điều này nếu bạn có thể. Tôi muốn không sử dụng thư viện để xử lý việc này (vì tôi muốn tự học) hoặc một cái gì đó giống như SAT (Định lý trục tách) nếu có thể. Cảm ơn rất nhiều về sự trợ giúp của bạn!
void world1Level1CollisionDetection()
{
for(int i; i < blocks; i++)
{
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==true)
{
de2dObj ballPrev;
ballPrev.coords[0] = ball.coords[0];
ballPrev.coords[1] = ball.coords[1];
ballPrev.coords[2] = ball.coords[2];
ballPrev.coords[3] = ball.coords[3];
ballPrev.coords[0] -= ball.xspeed;
ballPrev.coords[1] -= ball.yspeed;
ballPrev.coords[2] -= ball.xspeed;
ballPrev.coords[3] -= ball.yspeed;
int up = 0;
int left = 0;
int right = 0;
int down = 0;
if (ballPrev.coords[0] < block[i].coords[0] && ballPrev.coords[2] < block[i].coords[0] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || ball.coords[3] < block[i].coords[3])))
{
left = 1;
}
if (ballPrev.coords[0] > block[i].coords[2] && ballPrev.coords[2] > block[i].coords[2] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || (ball.coords[3] < block[i].coords[3]))))
{
right = 1;
}
if(ballPrev.coords[1] < block[i].coords[1] && block[i].coords[1] < ballPrev.coords[3] && ballPrev.coords[3] < block[i].coords[3])
{
up = 1;
}
if(block[i].coords[1] < ballPrev.coords[1] && ball
{
down = 1;
}
cout << left << ", " << right << ", " << up << ", " << down << ", " << endl;
if (left == 1)
{
ball.coords[0] = block[i].coords[0] - 18.0f;
ball.coords[2] = block[i].coords[0] - 2.0f;
}
else if (right == 1)
{
ball.coords[0] = block[i].coords[2] + 2.0f;
ball.coords[2] = block[i].coords[2] + 18.0f;
}
else if (down == 1)
{
ball.coords[1] = block[i].coords[3] + 4.0f;
ball.coords[3] = block[i].coords[3] + 20.0f;
}
else if (up == 1)
{
ball.yspeed = 0.0f;
ball.gravity = 0.0f;
ball.coords[1] = block[i].coords[1] - 17.0f;
ball.coords[3] = block[i].coords[1] - 1.0f;
}
}
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==false)
{
ball.gravity = -0.5f;
}
}
}
Để giải thích ý nghĩa của một số mã này:
Biến khối về cơ bản là một số nguyên đang lưu trữ số lượng khối hoặc nền tảng. Tôi đang kiểm tra tất cả các khối bằng vòng lặp for và số vòng lặp hiện đang được đại diện bởi số nguyên i. Hệ thống tọa độ có vẻ hơi lạ, vì vậy điều đó đáng để giải thích. coords [0] đại diện cho vị trí x (trái) của đối tượng (nơi nó bắt đầu trên trục x). coords [1] đại diện cho vị trí y (trên cùng) của đối tượng (nơi nó bắt đầu trên trục y). coords [2] đại diện cho chiều rộng của đối tượng cộng với coords [0] (phải). coords [3] đại diện cho chiều cao của đối tượng cộng với coords [1] (dưới cùng). de2dCheckCollision thực hiện phát hiện va chạm AABB. Lên là âm y và xuống là dương y, vì nó có trong hầu hết các trò chơi.
Hy vọng tôi đã cung cấp đủ thông tin cho ai đó để giúp tôi thành công. Nếu có điều gì đó tôi bỏ qua có thể rất quan trọng, hãy cho tôi biết và tôi sẽ cung cấp thông tin cần thiết. Cuối cùng, đối với bất kỳ ai có thể giúp đỡ, việc cung cấp mã sẽ rất hữu ích và được đánh giá cao.
Cảm ơn lần nữa vì sự giúp đỡ của bạn!
Chỉnh sửa : Tôi đã cập nhật mã của mình bằng một thuật toán mới để kiểm tra vị trí của quả bóng trước đó trước khi va chạm. Các trường hợp góc hoạt động chính xác trên nền tảng duy nhất đó, nhưng khi tôi có một bức tường của các vật thể, tôi giữ nó thực sự có thể trượt vào nó, nhưng nếu tôi di chuyển về phía bức tường trong khi trượt, tôi đi qua nó và về cơ bản là đứng trên đỉnh của một khối bên trong bức tường. Ngoài ra, có một hiệu ứng giật hình xảy ra khi tôi ở trên mặt đất, nơi bóng liên tục lên xuống.
TheirPos-ourSize +- 1
xóa 1, nếu đó là những gì bạn đang làm. Nếu bạn không chắc chắn làm thế nào để tìm ra thuật toán đó, tôi sẵn sàng giúp đỡ, thì hiện tại tôi đang hoàn hảo =] (bạn cũng đang kiểm tra các đối tượng theo thứ tự nào?)