Đồng bộ hóa nhiều lớp dựa trên gạch


8

Tôi phải đồng bộ hóa chuyển động của nhiều người chơi qua Internet và tôi đang cố gắng tìm ra cách an toàn nhất để làm điều đó.

Trò chơi dựa trên ô xếp, bạn chỉ có thể di chuyển theo 4 hướng và mỗi lần di chuyển sẽ di chuyển sprite 32px (tất nhiên theo thời gian). Bây giờ, nếu tôi chỉ đơn giản gửi hành động di chuyển này đến máy chủ, nó sẽ phát nó cho tất cả người chơi, trong khi phím đi bộ được nhấn xuống, để tiếp tục đi bộ, tôi phải thực hiện lệnh tiếp theo này, gửi nó đến máy chủ, và cho tất cả khách hàng, theo thời gian, hoặc phong trào sẽ không còn suôn sẻ nữa. Tôi đã thấy điều này trong các trò chơi khác, và nó có thể trở nên xấu xí khá nhanh, thậm chí không bị lag. Vì vậy, tôi tự hỏi nếu điều này thậm chí là một lựa chọn khả thi. Đây có vẻ là một phương pháp rất tốt cho người chơi đơn, vì nó dễ dàng, thẳng tiến (chỉ cần thực hiện hành động di chuyển tiếp theo kịp thời và thêm nó vào danh sách), và bạn có thể dễ dàng thêm chuyển động chuột (nhấp vào một số ô), để thêm một đường dẫn đến hàng đợi, đó là đi dọc.

Một điều khác xuất hiện trong đầu tôi là gửi thông tin rằng ai đó bắt đầu di chuyển theo hướng nào đó, và một lần nữa khi anh ta dừng lại hoặc thay đổi hướng, cùng với vị trí, để sprite xuất hiện ở đúng vị trí, hoặc đúng hơn là vị trí có thể được cố định nếu nó sai. Điều này sẽ (hy vọng) chỉ gây ra vấn đề nếu ai đó thực sự bị tụt lại, trong trường hợp đó là điều được mong đợi. Để giải quyết vấn đề này, tôi cần một số loại hàng đợi, nơi lưu trữ thay đổi hướng đến và công cụ, vì vậy sprite biết nơi để đi, sau khi chuyển động hiện tại sang lát tiếp theo kết thúc. Điều này thực sự có thể làm việc, nhưng âm thanh quá phức tạp. Mặc dù nó có thể là cách duy nhất để làm điều này, mà không có nguy cơ nói lắp. Nếu một điểm dừng hoặc thay đổi hướng được nhận ở phía máy khách, nó ' s được lưu trong hàng đợi và char tiếp tục di chuyển đến tọa độ đã chỉ định, trước khi dừng hoặc thay đổi hướng. Nếu lệnh mới đến quá muộn, dĩ nhiên sẽ có nói lắp ...

Tôi đang gặp khó khăn khi quyết định phương pháp và tôi thực sự không thể tìm thấy bất kỳ ví dụ nào cho việc này. Vấn đề chính của tôi là giữ cho chuyển động của gạch trơn tru, đó là lý do tại sao các chủ đề khác liên quan đến đồng bộ hóa chuyển động dựa trên pixel không giúp ích quá nhiều.

Cách "tiêu chuẩn" để làm điều này là gì?

Câu trả lời:


4

Tôi giả sử bạn đang nói về việc di chuyển trong thời gian thực. Cố gắng nội suy vị trí có lẽ là một nguyên nhân bị mất; qua kết nối chậm, trạng thái trò chơi của bạn có thể giảm hơn nữa và xa hơn trạng thái trò chơi thực tế. Không giống như các bình luận khác, tôi sẽ khuyên không nên đưa nhiều logic trò chơi vào phía máy chủ. Khi tôi triển khai các loại giải pháp này, máy khách có một ổ cắm TCP đến máy chủ liên tục. Khi trạng thái trò chơi thay đổi, nó sẽ gửi một thông báo tới máy chủ, như 'máy khách ở x = 10, y = 20'. Máy chủ đẩy tin nhắn đến các máy khách khác, những người cố gắng xử lý nó dựa trên logic bên trong của chính họ. Sử dụng TCP đảm bảo tin nhắn của bạn đến theo thứ tự.

Thật không may, ngay cả các trò chơi AAA không thể xử lý độ trễ cực cao; Người chơi đôi khi sẽ di chuyển rất nhanh, bởi vì trạng thái mạng và địa phương của họ ở rất xa. Theo dõi ping người đi khứ hồi và đá người dùng quá xa / chậm sẽ giúp ích cho việc này.


1
+1 cho 'ngay cả các trò chơi AAA cũng không thể xử lý độ trễ cực cao;' Trên thực tế Không ai có thể xử lý ngay cả độ trễ nhỏ một cách hoàn hảo. Chúng tôi có thể làm cho nó trông giống như chúng ta có thể mặc dù.
Valmond

3

Về cơ bản đây là cách bạn có thể làm điều đó một cách đơn giản và an toàn (cảnh báo, mã giả cực cao):

A) Máy khách (playerid = 5) yêu cầu máy chủ di chuyển 'phải' (hoặc tốt hơn, sang ô 73,18)

B) Máy chủ kiểm tra bản đồ 2D lớn của anh ấy có chứa người chơi (hoặc ID người chơi chẳng hạn):

 if(map[73][18] == occupied)
     Send back ('Not OK') to client (the case is blocked by another player)
else
    Set the new position as blocked: map[73][18]=5
    Release the old position: map[72][18]=0;
    Send a 'new position: 5, 73,18' message to all players who are nearby (moving client included)

C) Khách hàng nhận được thông báo 'vị trí mới' (tốt, hoặc người chơi 5 nhận được thông báo 'Không ổn')

D) khách hàng di chuyển từ từ vật phẩm có playerid = 5 về vị trí mới (hoặc tạo vật phẩm nếu nó không có một vật phẩm với playerid = 5)


Vâng, cảm ơn, nhưng vấn đề của tôi là giữ cho nó trơn tru trên các khách hàng khác qua nhiều chuyển động gạch tiếp tục, không phải là chuyển động của gạch nói chung ^^
Mars

Đặt tốc độ chính xác và bù cho độ trễ, ví dụ như tính toán chết hoặc chỉ là 'ngu ngốc' 'tiến tới mục tiêu ở tốc độ không đổi' (hoặc tốc độ tỷ lệ trên một kho bạc nhất định nếu bạn gửi dấu thời gian dọc theo các vị trí) và bạn sẽ ổn.
Valmond

1

Tôi nghĩ rằng phương pháp bạn mô tả là khá tốt, đặc biệt là trong một trò chơi đơn giản chỉ cho phép 4 động tác. Đây là cách tôi thực hiện nó.

Tôi không biết về bất kỳ tiêu chuẩn nào, nhưng điều đầu tiên tôi nghĩ đến là chỉ phát "thay đổi đầu vào", thay đổi trong đầu vào của người chơi, từ người chơi sang người khác. Ví dụ: bạn chỉ có thể phát các tin nhắn dọc theo dòng [phím được nhấn, ID khóa, thời gian] hoặc [phím được phát hành, ID khóa, thời gian] và để trò chơi của người chơi hành động theo những thay đổi đầu vào này. Bao gồm thời gian sẽ giúp điều chỉnh đường dẫn (nếu người chơi đã thay đổi hướng tại thời điểm t, thì "tiến về phía trước" tại thời điểm t + 1 sẽ cần phải được sửa).

Tuy nhiên, với giải pháp này, bạn có thể gặp phải vấn đề mất tin nhắn; giả sử tin nhắn "chìa khóa phát hành" không bao giờ được gửi? Một cái gì đó có thể giúp điều này là định kỳ thăm dò trạng thái trò chơi của người chơi và trả lại vị trí hiện tại của người chơi, cũng như bất kỳ phím nào được nhấn, hoặc thậm chí trả lại toàn bộ trạng thái trò chơi. Tùy thuộc vào số lượng người chơi và lệnh, bạn có thể điều chỉnh điều này để cân bằng thông điệp truyền giữa các máy khách / máy chủ để có sự cân bằng tốt.

Một điều khác bạn có thể nhìn vào là lập kế hoạch đường dẫn. Ví dụ: nếu người chơi đã di chuyển về phía trước trong 5 giây, thì trong một phần nghìn giây tiếp theo, người chơi vẫn sẽ di chuyển về phía trước. Trong trường hợp đó, bạn có thể tạo một giao dịch dự đoán đường dẫn để tránh độ trễ. Đây thực chất là những gì phương pháp trên đang làm, mặc dù điều này có thể tính đến các đường dẫn tròn.

Tôi hy vọng điều này sẽ giúp!


1
Vấn đề với việc chỉ gửi đầu vào là nếu bạn bỏ lỡ một cái nào đó hoặc đôi khi chỉ hiểu sai thứ tự thì trò chơi của bạn sẽ không còn ổn nữa, tức là. hai khách hàng sẽ hiển thị 'màn hình' khác nhau.
Valmond

@Valmond điểm rất tốt ... trên thực tế, tôi cảm thấy muốn xóa câu trả lời của mình, vì trong ánh sáng đó, nó cảm thấy không chính xác.
Jonathan Pitre

1
Bạn có thể gửi đầu vào đến máy chủ (cho đến khi nó ổn) nhưng máy chủ nên (IMO) gửi dữ liệu chính xác hoặc ít nhất là xác minh dữ liệu hoặc có thể gửi toàn bộ trò chơi (điều này đã được thực hiện trong các trò chơi thực tế, ví dụ như Blood Bowl ), có lẽ bạn có thể điều chỉnh câu trả lời của mình thay vì xóa nó :-)
Valmond
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.