Nền tảng 2D: tại sao làm cho vật lý phụ thuộc vào tốc độ khung hình?


12

"Super Meat Boy" là một nền tảng khó khăn mới xuất hiện cho PC, đòi hỏi khả năng kiểm soát đặc biệt và nhảy hoàn hảo pixel. Mã vật lý trong trò chơi phụ thuộc vào tốc độ khung hình, được khóa ở mức 60fps; điều này có nghĩa là nếu máy tính của bạn không thể chạy trò chơi ở tốc độ tối đa, vật lý sẽ phát điên, khiến (trong số những thứ khác) nhân vật của bạn chạy chậm hơn và rơi xuống đất. Hơn nữa, nếu vsync tắt, trò chơi chạy cực nhanh.

Những người có kinh nghiệm với lập trình trò chơi 2D có thể giải thích lý do tại sao trò chơi được mã hóa theo cách này? Không phải một vòng lặp vật lý chạy ở tốc độ không đổi sẽ là một giải pháp tốt hơn? (Trên thực tế, tôi nghĩ rằng một vòng lặp vật lý được sử dụng cho các phần của trò chơi, vì một số thực thể tiếp tục di chuyển bình thường bất kể tốc độ khung hình. Nhân vật của bạn, mặt khác, chạy chính xác [fps / 60] nhanh như vậy.)

Điều làm tôi băn khoăn về việc triển khai này là sự mất đi tính trừu tượng giữa công cụ trò chơi và kết xuất đồ họa, điều này phụ thuộc vào những thứ cụ thể của hệ thống như màn hình, card đồ họa và CPU. Nếu vì bất kỳ lý do gì, máy tính của bạn không thể xử lý vsync hoặc không thể chạy trò chơi với tốc độ chính xác 60fps, nó sẽ bị hỏng một cách ngoạn mục. Tại sao bước kết xuất theo bất kỳ cách nào ảnh hưởng đến các tính toán vật lý? (Hầu hết các trò chơi hiện nay sẽ làm chậm trò chơi hoặc bỏ qua các khung.) Mặt khác, tôi hiểu rằng các nền tảng trường học cũ trên NES và SNES phụ thuộc vào tốc độ khung hình cố định cho phần lớn sự kiểm soát và vật lý của chúng. Tại sao lại như vậy, và liệu có thể tạo ra một patformer trong tĩnh mạch đó mà không có sự phụ thuộc khung hình? Có nhất thiết phải mất độ chính xác nếu bạn tách kết xuất đồ họa khỏi phần còn lại của động cơ không?

Cảm ơn bạn, và xin lỗi nếu câu hỏi khó hiểu.


Tiếp tuyến cho câu hỏi của bạn. Đây là một bài viết tuyệt vời bao gồm chính xác các vấn đề bạn đang mô tả và cách "đúng" để xử lý dấu thời gian và tốc độ khung hình. gafferongames.com/game-physics/fix-your-timestep
num1

Nó thực sự làm tôi ngạc nhiên rằng họ sẽ làm theo cách này. Tôi cho rằng nó phải là bởi vì nó được xây dựng chủ yếu cho giao diện điều khiển, nơi tốc độ khung hình có thể dựa vào. Thất vọng!
Iain

Câu trả lời:


7

Tại sao?

Rất nhiều lý do, hãy lựa chọn: Họ không biết gì hơn. Nó nhanh hơn và dễ thực hiện hơn. Họ đã tập trung nhiều hơn vào lối chơi và ít hơn vào các trường hợp cạnh có thể không mọc lên trong hầu hết các trường hợp.

Bạn đã làm một công việc khá tốt để giải thích tại sao không. Tôi chắc rằng bạn đã nhận thấy có rất nhiều chủ đề bao gồm chủ đề này . Tôi không chắc chắn bạn sẽ tìm thấy một câu trả lời thỏa đáng ngoài những câu tôi đã liệt kê.


"Họ không biết gì hơn" mô tả lý do tại sao tôi thực hiện phương pháp đó với "Jack là một kẻ ngốc". Nhưng - tôi đã phụ thuộc rất nhiều vào việc gọi dt kể từ khung cuối cùng với tất cả logic của tôi. Nhưng - với tọa độ điểm nổi, nó có thể dẫn đến một số lỗi kỳ lạ, khó lặp lại
lochok

4

SMB ban đầu là một trò chơi trên console, nơi an toàn khi cho rằng nó có thể chạy ở tốc độ 60fps trên tất cả Xbox360 (có thể là 50 đối với một số người chơi PAL). Giả sử một dấu thời gian cố định đơn giản hóa mã một chút công bằng.

Mặc dù dễ dàng điều chỉnh nhiều thứ theo một dấu thời gian thay đổi - 'pos + = velocity * timestep', sẽ khá khó để thực hiện chính xác khi bạn xử lý gia tốc và tốc độ thay đổi gia tốc, v.v.

Phân tách trò chơi và kết xuất là một giải pháp tốt trong lý thuyết , nhưng thực hiện nó tốt (với phép nội suy tốt) khá khó khăn và mọi thứ có thể dễ dàng trở nên lộn xộn. Kỹ thuật này được sử dụng trong các trò chơi thực tế khá phổ biến (mặc dù một số trò chơi lớn làm điều đó, đặc biệt là các trò chơi RTS, nhưng nhiều hơn cho đồng bộ hóa trò chơi mạng).

Khi cũng thiết kế cho độ phân giải màn hình cố định cũng như tốc độ khung hình cố định, có một điều khác bạn có thể làm để làm cho việc cuộn thêm mượt mà. Bạn có thể đảm bảo rằng trò chơi cuộn ở toàn bộ số pixel trên mỗi khung hình - tránh bất kỳ 'pixel phụ nào bạn có thể nhận được bằng cách cuộn một số pixel một phần cho mỗi khung hình.


1

Giải pháp rõ ràng là có 2 vòng lặp chạy song song - kết xuất cứ sau 1/60 giây và vòng lặp trò chơi cứ sau 1/60 giây.

Nhưng với kinh nghiệm của tôi về Flash (AS3, mà tôi khá chắc chắn Super Meat Boy đã được tạo ra), bộ lập lịch không phải lúc nào cũng rất chính xác. Độ chính xác cũng phụ thuộc nhiều vào môi trường. Trong trình phát flash độc lập, nó có thể có độ phân giải dưới một phần nghìn giây. Nhưng khi chạy trong một số trình duyệt web, độ chính xác của nó trở thành tốc độ khung hình.

Vì vậy, cách gần nhất để bạn có thể tách rời các vòng lặp kết xuất và logic trò chơi là để tất cả các chuyển động được dựa trên thời gian (và chạy từng khung dựa trên thời gian đã trôi qua kể từ khung cuối cùng). Điều đó có thể giới thiệu một số toán học phức tạp hơn (như có lực hấp dẫn được áp dụng liên tục, thay vì thêm vào vận tốc của một vật trong các khoảng thời gian đã định). Bởi vì trò chơi có thể bị trễ trong một giây và sau đó người chơi của bạn sẽ di chuyển 200 pixel trong một bước, việc phát hiện và phản ứng va chạm có thể trở nên phức tạp hơn nữa. Nếu lập trình viên đang thực hiện phát hiện va chạm dựa trên khung (kiểm tra va chạm mỗi dấu thời gian), họ cũng sẽ phải chuyển sang phát hiện va chạm dựa trên thời gian. Và nếu họ muốn nó cảm thấy tự nhiên, họ sẽ phải sử dụng phương pháp trọng lực được mô tả ở trên, điều này khiến cho chuyển động của vật thể là một đường cong (trái ngược với đường thẳng),


2
Meat Boy ban đầu là một trò chơi Flash. Super Meat Boy là một trò chơi C ++.
Archagon

0

Tôi không nghĩ sẽ yêu cầu nhiều game 2D PC chơi ở tốc độ 60fps nữa. Ngay cả hầu hết các trò chơi 2D đều được tăng tốc phần cứng nên cá nhân tôi sẽ không lo lắng về yêu cầu fps.

Câu hỏi thực sự là tại sao bạn không sử dụng pixel dựa trên, các trò chơi có rất nhiều mánh gian lận và lối tắt.

Nếu bạn đang làm một trò chơi dựa trên vật lý (có lẽ là ném chim?) Thì câu trả lời là hiển nhiên, nhưng một bản sao siêu mario? chuyển động dựa trên thời gian có thể là một chút nhiều.


Không khó để chơi chúng ở tốc độ 60fps, nhưng màn hình có tốc độ làm mới riêng là 50Hz, 70-85Hz và 120Hz vẫn có thể dễ dàng tìm thấy.

0

Để tránh hành vi lạ trong vật lý 2d họ đang sử dụng?

Thành thật tôi chỉ có thể đoán. Tôi sẽ thử một lời giải thích:

Trung tâm của trò chơi là vòng lặp trò chơi chính. Về cơ bản trông như thế này:

while(gameRunning)
{
  updateGame(timestep);
  renderGame(timestep);
}

updateGame cập nhật gameState: kiểm tra đầu vào của người chơi, áp dụng đầu vào của người chơi vào thế giới trò chơi và chạy mô phỏng vật lý, v.v.

renderGame vẽ và hoạt hình trò chơi.

Điều này cặp vợ chồng cập nhật vật lý để kết xuất. Nếu bạn muốn tách rời nó, bạn sẽ cần sử dụng các luồng và đồng bộ hóa chính xác từng truy cập dữ liệu của kết xuất và luồng gameUpdate với dữ liệu được chia sẻ, ví dụ như vị trí của người chơi. Điều này có thể thực hiện được.

Một vấn đề khác có thể là mô phỏng vật lý đòi hỏi một dấu thời gian liên tục để chạy ổn định. Điều này phụ thuộc vào cách siêu mẫu tính toán chuyển động (Một lần nữa chúng ta có thể đoán họ đã thực hiện nó như thế nào;)).

Một cách tiếp cận ngây thơ sẽ là (mà tôi đang sử dụng trong trò chơi của mình * thở dài *):

position=position+speed*timestep;
speed=speed+acceleration*timestep;

Đây được gọi là Tích hợp Euler và thường được coi là một ý tưởng tồi. Nếu dấu thời gian là không có lỗi tính toán không đổi xảy ra sẽ làm cho mô phỏng kém ổn định hơn. Vật thể có thể di chuyển với tốc độ quá cao hoặc không phải tất cả hoặc bay qua các bức tường khỏi màn hình. Ngay cả khi dấu thời gian là Tích hợp Euler không đổi gây ra các lỗi tính toán nhỏ. Tốt hơn nên sử dụng phương pháp tích hợp khác như RK4 hoặc sử dụng động cơ vật lý.

Ngoài ra, có thể có vấn đề khi phát hiện va chạm nếu dấu thời gian quá lớn. Vì các va chạm không được kiểm tra giữa hai gameUpdates, các đối tượng có thể vượt qua chướng ngại vật.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.