Vòng lặp vật lý trong môi trường NodeJS / Socket.IO


8

Tôi đang phát triển Trò chơi Canvas HTML5 2D và tôi đang cố gắng nghĩ ra cách hiệu quả nhất để triển khai Vòng lặp Vật lý ở cuối máy chủ, chạy NodeJS và Socket.IO.

Phương pháp duy nhất tôi nghĩ đến là sử dụng setTimeout/Interval, có cách nào tốt hơn không? Bất kỳ ví dụ sẽ được đánh giá cao.

EDIT: The Game là một trò chơi từ trên xuống, như Zelda và các trò chơi Pokemon cũ hơn. Hầu hết các vật lý được thực hiện trong vòng lặp sẽ là các giao điểm đơn giản.


Bạn có thể nên chỉ định loại trò chơi bạn đang lên kế hoạch, cụ thể là khó có thể nói bất cứ điều gì về thời gian máy chủ mà không biết thời gian trò chơi của bạn sẽ quan trọng như thế nào.
aaaaaaaaaaaa

Zelda rất quan trọng về thời gian hơn Pokemon. Thành phần nhiều người chơi là gì? Tại sao trò chơi cần phải chạy trên máy chủ?
aaaaaaaaaaaa

@eBusiness Đó là chế độ nhiều người chơi, hãy nghĩ MMORPG, nơi có nhiều người chơi ở các khu vực khác nhau của Bản đồ tại bất kỳ thời điểm nào, cập nhật bằng máy chủ.
Oyed

Tôi gặp vấn đề tương tự. vòng lặp trò chơi có thể được thực hiện bằng cách sử dụng liên kết dưới đây: npmjs.com/package/gameupdate-loop
Phòng thí nghiệm phi thực tế

Câu trả lời:


5

Tôi tin setTimeoutlà đủ tốt cho nhu cầu của bạn. Tôi, chính tôi, đối mặt với một tình huống tương tự và tôi đang đi với setTimeout. Bài viết tuyệt vời này về BNG đã giúp tôi hiểu rõ hơn những gì tôi phải làm (hoặc ít nhất là thử): Nhiều người chơi trong thời gian thực trong HTML5 .

Về liên kết: Nó chủ yếu nói về nhiều vòng lặp trò chơi và kết nối chúng. Nó thật tuyệt Dưới đây, một đoạn trích.

Khi nói đến một trò chơi thời gian thực, chúng tôi muốn tự chạy logic trò chơi trên máy chủ VÀ máy khách. Điều này là do thực tế rằng máy chủ cần phải là người có thẩm quyền về trạng thái của trò chơi mọi lúc, nhưng khách hàng cũng cần phải chạy trò chơi cục bộ. Mỗi khung hình trên máy chủ, đầu vào từ mạng sẽ được xử lý và áp dụng cho người chơi và thay đổi đó được gửi cho những người chơi khác theo tỷ lệ cố định. Trên máy khách, đầu vào sẽ được thu thập và gửi đến máy chủ và các vị trí có thể được cập nhật trong khi chờ tin nhắn quay lại từ máy chủ (dự đoán của máy khách).

Đó là một bài đọc rất khuyến khích. Ít nhất là bởi tôi. = P


1
Bạn nên thêm nhiều hơn vào câu trả lời của mình để người dùng trong tương lai biết bạn đang nói về điều gì, trong trường hợp liên kết bị chết.

@AlexM. Liên kết giống như một bổ sung và không liên quan ngay đến câu hỏi ... Nhưng bạn đã đúng. Dù sao thì tốt hơn hết là tôi đã quyết định đặt nó ở đó. =)
slacktracer

1
Cũng có thể đáng được đề cập trong câu trả lời về cách bài viết đề xuất có các vòng lặp riêng biệt để cập nhật vật lý (~ 60fps) và máy chủ -> cập nhật máy khách (~ 20fps) trên máy chủ, cũng như các vòng lặp riêng cho vật lý (~ 60fps) và máy khách -> máy chủ (nhanh nhất có thể) cập nhật trên máy khách. Sự tách biệt giữa các vòng lặp io và chủ đề vật lý là điểm đặc biệt nhất của bài viết đó so với một vài bài khác mà tôi đã xem.
tối đa

2

Đối với công cụ phía máy chủ, bạn có một vài tùy chọn. Đầu tiên là ngoại suy hoàn toàn tất cả các va chạm của bạn khi giả định rằng bạn sẽ có các tin nhắn thường xuyên từ khách hàng, truyền đạt tất cả các thay đổi trạng thái có ý nghĩa thông qua máy chủ, sau đó sẽ chạy xác thực trên các sự kiện trò chơi khi nó nhận được các cuộc gọi lại IO từ kết nối khách hàng.

Cách thứ hai, mà bạn có vẻ thích hơn, là chạy vòng lặp của riêng bạn trong khi bạn xử lý các cuộc gọi lại IO. Mặc dù setInterval và setTimeout sẽ thực hiện điều này, nhưng bạn có một bộ công cụ chi tiết hơn nhiều để kiểm soát điều này: setImmediate(callbacks, [[arg], ...])process.nextTick(callback).

Process.nextTick sẽ chạy cuộc gọi lại của bạn trước các sự kiện IO khác, miễn là bạn chưa xếp chồng một ngăn gọi vô hạn đệ quy (nếu vượt quá một số nhất định, process.maxTickDepth, thì nó sẽ mang lại các cuộc gọi lại IO).

SetImmediateCallback tương tự như process.nextTick ở chỗ nó hoạt động mọi tick, nhưng chỉ một trong số các cuộc gọi lại được xếp hàng được thực thi trên mỗi tick, thay vì tất cả các cuộc gọi lại được xếp hàng.

Sử dụng chúng sẽ trông tương tự như setTimeout hoặc requestAnimationFrame.

function gameLoop() {
  updateCollisions();
  process.nextTick(gameLoop);
}

process.nextTick(gameLoop);

Ưu điểm của những điều này là bạn không phụ thuộc vào việc triển khai setTimeout và setInterval của V8. Đây là nhiều hơn một dòng trực tiếp đến vòng lặp sự kiện của Node. Chỉ cần chắc chắn rằng bạn không bỏ đói IO nếu bạn đang sử dụng process.nextTick. updateCollutions nên được đảm bảo để không mất nhiều thời gian.


-1 requestAnimationFrame móc vào tốc độ làm mới màn hình, nó chỉ liên quan đến máy tính người dùng. Và đối với một trò chơi nối mạng, bạn thực sự sẽ không muốn thử bất cứ thứ gì ngoại trừ vật lý độc lập với màn hình tốc độ cố định.
aaaaaaaaaaaa

Kinh doanh điện tử là đúng, requestAnimationFrame dựa trên màn hình trong khi Vòng lặp tôi đang cố gắng đạt được là phía máy chủ trong NodeJS.
Oyed

@eBusiness Hình như tôi đã đọc sai câu hỏi, được cập nhật với các tài liệu liên quan đến mã máy chủ và nodejs.
michael.bartnett

@ michael.bartnett Liên quan đến việc ngoại suy tất cả các va chạm dựa trên các gói thường xuyên từ người dùng, đây là điều tôi đã triển khai trước đó, nhưng trên Máy 60FPS, nhiều gói được gửi hơn, trong khi 30FPS là một nửa nhiều gói, v.v. bạn muốn giới thiệu cái này chứ? Tôi khá cởi mở để đề xuất ngay bây giờ. Ví dụ bạn cung cấp có vẻ khá chắc chắn, nhưng như bạn đã nói, phụ thuộc vào Kiểm tra va chạm / Vật lý khác khá nhanh. Điều này là tốt, nhưng nếu có một lựa chọn tốt hơn mà bạn biết, xin vui lòng chia sẻ!
Oyed

@ThomasMosey Đó là một câu hỏi rộng và khó trả lời, và khá phụ thuộc vào chi tiết cụ thể của trò chơi của bạn. Đặc biệt là phương thức mà máy chủ không chạy vòng logic của riêng nó. Một nơi tốt để bắt đầu suy nghĩ là trả lời: ai sở hữu từng đối tượng tại mọi thời điểm trong trò chơi, điều gì khiến những đối tượng đó thay đổi chủ sở hữu và điều gì phải được theo dõi và phân xử một cách khách quan - đó là do máy chủ sở hữu.
michael.bartnett
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.