Thay thế cho hệ thống nhà nước trò chơi?


30

Theo như tôi có thể nói, hầu hết các trò chơi đều có một số "hệ thống trạng thái trò chơi" chuyển đổi giữa các trạng thái trò chơi khác nhau; đó có thể là những thứ như "Giới thiệu", "MainMothy", "Chọn nhân vật", "Đang tải" và "Trò chơi".

Một mặt, hoàn toàn hợp lý khi tách chúng thành một hệ thống nhà nước. Rốt cuộc, chúng khác nhau và nếu không cần phải ở trong một tuyên bố chuyển đổi lớn, rõ ràng là lộn xộn; và họ chắc chắn được đại diện bởi một hệ thống nhà nước. Nhưng đồng thời, tôi nhìn vào trạng thái "Trò chơi" và tự hỏi liệu có điều gì sai về cách tiếp cận hệ thống nhà nước này. Bởi vì nó giống như con voi trong phòng; đó là LỚN và hiển nhiên nhưng không ai thắc mắc về cách tiếp cận hệ thống trạng thái trò chơi.

Có vẻ ngớ ngẩn với tôi rằng "Trò chơi" được đặt ngang hàng với "Menu chính". Tuy nhiên, không có cách nào để phá vỡ trạng thái "Trò chơi".

Là một hệ thống nhà nước trò chơi là cách tốt nhất để đi? Có một số kỹ thuật khác nhau, tốt hơn để quản lý, tốt, "trạng thái trò chơi"? Có ổn không khi có trạng thái giới thiệu vẽ một bộ phim và lắng nghe, sau đó là trạng thái tải vòng lặp trên trình quản lý tài nguyên, và sau đó là trạng thái trò chơi thực tế mọi thứ ? Điều này dường như không cân bằng với bạn quá? Tui bỏ lỡ điều gì vậy?

Câu trả lời:


30

Tôi nghĩ rằng bạn chỉ đang tranh luận ngữ nghĩa ở đây. Nó được gọi là Trạng thái trò chơi vì nó hoạt động giống như một Máy trạng thái hữu hạn, với số lượng trạng thái và chuyển tiếp hữu hạn giữa chúng. 'Trò chơi' trong 'Hệ thống trạng thái trò chơi' đề cập đến toàn bộ hệ thống, với 'Đang tải', 'MainMothy', v.v. là các trạng thái của trò chơi. Chúng có thể dễ dàng được gọi là 'cảnh' hoặc 'màn hình' hoặc 'cấp độ'. Nó chỉ là ngữ nghĩa.

Tôi không chắc chắn rằng một FSM nghiêm ngặt sẽ áp dụng nữa. Trong phần triển khai của mình, tôi gọi các trạng thái 'Màn hình' và cho phép chúng có thể xếp chồng lên nhau - tức là. màn hình có thể được vẽ trên đầu các màn hình khác, kiểm soát xem màn hình bên dưới chúng có được cập nhật hay vẽ hay không. Bằng cách này, tôi có thể có nhiều màn hình hoạt động cùng một lúc với logic và mã độc lập dành riêng cho màn hình đó mà không phải lo lắng về bất kỳ màn hình nào khác.

Ví dụ, màn hình Tạm dừng có thể được mở ở phía trên màn hình chơi trò chơi chính của tôi không cho phép cập nhật, nhưng cho phép vẽ bên dưới chính nó. Một màn hình kiểm kê nhân vật có thể cho phép cả bản vẽ và cập nhật - vì vậy trò chơi tiếp tục chơi trong khi bạn làm việc trong kho của mình.


đây chính xác là cách nó nên được thực hiện. Màn hình có thể chứa nhiều màn hình khác trong kiến ​​trúc giống như cây. Vì vậy, chương trình của bạn chứa màn hình trò chơi chứa màn hình menu tạm dừng chứa màn hình cài đặt âm thanh và màn hình cài đặt trò chơi. vv
Iain

1
Tôi rất thích xem mã nguồn ví dụ cho điều này! (Ưu tiên trong C ++ / C # / Java)
Zolomon

1
Thật không may, hiện tại tôi chỉ có mã sản xuất, nhưng có một khái niệm tương tự trong mẫu Trạng thái trò chơi XNA: creators.xna.com/en-GB/samples/gamestHRan Quản lý
DrDeth

7

Chắc chắn trạng thái Trò chơi sẽ rất lớn, nhưng không có lý do gì mà chính trạng thái Trò chơi không thể chứa một máy trạng thái để quản lý dữ liệu của nó. Máy trạng thái phân cấp là hữu ích.


4

Tôi luôn thích nghĩ mỗi "trạng thái" là một "cảnh". Vì vậy, video mở đầu là một cảnh, chỉ là một tĩnh. Các khoản tín dụng là một cảnh. Thực đơn là một cảnh. Sự khác biệt duy nhất giữa tất cả chúng là mức độ tương tác và logic trò chơi.


3

Tôi có vấn đề với điều đó quá, thực sự.

Giả sử bạn có một Trò chơi.

Thay vì biến 'Trò chơi' thành trạng thái như 'Đang tải', 'Menu chính', v.v. - IMO tốt hơn là để Game một số trạng thái:

"Đang tải" - "hiển thị menu" - "tạm dừng" , v.v.

Trò chơi vẫn đang chạy, nhưng khi nó hiển thị menu chính, nó sẽ ở chế độ 'hiển thị menu'.

Và khi Game không ở bất kỳ trạng thái cụ thể nào, nó chỉ chạy.

Nó có ý nghĩa hơn nhiều, ít nhất là với tôi. :)


Tôi đồng ý. Không ai muốn thoát khỏi Trạng thái trò chơi chỉ để vào Trạng thái tạm dừng . Mặt khác: Nó vẫn là một hệ thống nhà nước .. chỉ được lồng vào nhau :)
bummzack

2

Một chương trình trực tuyến (theo nghĩa truyền thống của trực tuyến, nghĩa là liên tục chạy và phản hồi đầu vào, thay vì ý nghĩa được kết nối với internet) thường bao gồm 3 điều:

  • thu thập và xử lý đầu vào
  • cập nhật logic
  • đầu ra

Nói chung, 3 cái này có liên quan và thay đổi cùng một lúc. Ví dụ: khi hiển thị màn hình giật gân, bạn có thể ánh xạ tất cả các phím của mình sang lệnh 'đóng màn hình' và bản cập nhật có thể làm mờ hình ảnh một cách chậm chạp với đầu ra chỉ hiển thị đồ họa đó. Nhưng khi chơi trò chơi, các phím có thể ánh xạ tới các lệnh khác nhau và bản cập nhật đang thay đổi thuộc tính của nhiều đối tượng trong trò chơi.

Khi bạn xem theo cách này, sẽ rất hợp lý khi tách Giới thiệu khỏi Tạo nhân vật và khỏi Trò chơi: mỗi trò chơi có một bộ quy tắc nhập, cập nhật và đầu ra riêng. Chúng gần giống như các chương trình độc lập tình cờ chia sẻ một số dữ liệu và mã thư viện. Và, với suy nghĩ này, thường có ý nghĩa khi chỉ có một trạng thái Trò chơi, vì lối chơi khá đồng nhất trong suốt.

Tất nhiên, nếu bạn thực sự có các loại trò chơi riêng biệt (ví dụ: ví dụ về RPG - Bản đồ thế giới, Bản đồ thị trấn, Cutscene, Chiến đấu), với các đầu vào, cập nhật và đầu ra khác nhau, không có lý do gì bạn không thể có nhiều trạng thái ở đó quá thay vì chỉ 1 trạng thái Trò chơi. Nhưng nó phụ thuộc vào trò chơi của bạn.


1

Tôi nhìn nó theo cách khác. 'Menu', 'HighScores', "credit" hoặc whathaveyou, có thể được coi là một cấp độ khác, và khi đó trạng thái đó không nhất thiết phải nhẹ hơn trạng thái 'trò chơi' của bạn (trạng thái trò chơi nói chung có nhiều thực thể hơn, và những cái khác nhau, nhưng cuối cùng, nó chỉ là một cấp độ khác, nơi các thực thể tình cờ thể hiện hành vi dự đoán nhiều hơn và 'bản đồ' thường ít phức tạp hơn).
Làm cho chuyển đổi trong suy nghĩ của bạn chắc chắn kéo bạn ra khỏi hội chứng "menu nhàm chán".


Tôi cũng sẽ nói như vậy ... Tất cả các menu, màn hình của tôi, bất cứ thứ gì, chỉ là một cấp độ khác.
tốc

1

Trong trò chơi của tôi, tôi có:

Trình quản lý thực thi , giúp kích hoạt ứng dụng (trò chơi), tải tài nguyên, giải phóng tài nguyên khi thoát ứng dụng, v.v ... Nó kích hoạt ứng dụng Engine, GameViewEngine, GameLogicEngine.

Trình quản lý trạng thái trò chơi , nằm trong GameLogicEngine, và chịu trách nhiệm kiểm soát những thứ liên quan đến vòng lặp chính của trò chơi: phát hiện va chạm, tính toán vật lý, đọc bàn phím, thao tác toán học, v.v ...

Ban đầu, tôi có xu hướng chỉ có một Trình quản lý trạng thái trò chơi là một phần của GameLogicEngine. Tuy nhiên, tôi đã gặp một số khó khăn với các trình điều khiển về việc thâm nhập vào các hệ thống con chính (GameLogic, ApplicationEngine, ...). Nó có thể đã được thực hiện, nhưng nó lộn xộn hơn, imo.

Bây giờ mọi thứ trông trong suốt hơn đối với tôi, và tôi hài lòng với thiết kế.


0

Đổi tên trạng thái 'Trò chơi' thành một cái gì đó như 'Trò chơi'. Sau đó, logic của bạn có vẻ tốt hơn; Bạn dừng chơi để chuyển đến menu thứ: bạn thoát khỏi trạng thái Gameplay để chuyển sang trạng thái MainMothy.

Ngoài ra, tôi nghĩ những thứ như tạm dừng, sẽ yêu cầu trò chơi ở trạng thái giống như khi bạn tạm dừng trò chơi, không nên ở trạng thái riêng biệt. Con nhà nước và làm tổ, có lẽ? Gameplay có một menu tạm dừng.


0

Tôi nghĩ rằng có một phương pháp tốt gọi là ngăn xếp trạng thái trò chơi. Tôi chưa thấy bất kỳ bài báo hay bài báo nào về nó nhưng nó được lan truyền một chút bằng giọng nói. Về cơ bản, trạng thái trò chơi trên cùng trên ngăn xếp được gọi đầu tiên và được thực hiện bất cứ điều gì nó muốn với đầu vào / kết xuất, v.v. Trạng thái trò chơi trên cùng là trạng thái duy nhất được phép đẩy hoặc bật trạng thái.

Trong công cụ của tôi, trạng thái trò chơi thực sự chỉ là danh sách các thực thể trò chơi. Sau đó tôi có các thực thể làm việc như các menu. Các trạng thái menu của tôi tạm dừng trò chơi (bằng cách không cập nhật mục tiếp theo trên ngăn xếp) nhưng để (các) trạng thái khác đẩy mô hình của chúng sang trình kết xuất để menu tạm dừng của tôi (không bao phủ toàn bộ màn hình) có kết xuất trò chơi ở phía sau.

Tôi hy vọng điều đó đưa ra ý tưởng về một hệ thống hơi khác một chút không dựa trên một máy trạng thái.


0

Có ổn không khi có trạng thái giới thiệu vẽ một bộ phim và lắng nghe, sau đó là trạng thái tải vòng lặp trên trình quản lý tài nguyên, và sau đó là trạng thái trò chơi thực tế mọi thứ? Điều này dường như không cân bằng với bạn quá? Tui bỏ lỡ điều gì vậy?

Điều này là hoàn toàn tốt. Hoặc ít nhất, đó là một cải tiến so với việc "có một công tắc lớn xấu xí tùy thuộc vào trạng thái của trò chơi".

Tôi muốn chỉ ra rằng trong hầu hết các trò chơi, bạn sẽ cần một bộ máy trạng thái hữu hạn để đối phó với AI thực thể đơn giản. Ví dụ điển hình là những kẻ thù ở trạng thái Iddle, Tấn công hoặc Chết.

Nếu bạn có một Máy trạng thái hữu hạn đủ trừu tượng, thì bạn có thể sử dụng lại nó cho cả đối tượng Trò chơi và AI của bạn; đột nhiên bạn không "đầu tư" nhiều nỗ lực vào trạng thái Trò chơi - thay vào đó bạn đang sử dụng lại mã mà bạn đã sử dụng.

Tự cắm không biết xấu hổ xảy ra: Tôi đã triển khai Máy trạng thái hữu hạn như vậy trên thư viện trò chơi Lua của mình, MiddleClass (cụ thể là, tiện ích bổ sung có tên MindState). Đây là cách bạn làm một điều Game State với nó .


0

Một cách tiếp cận khác cho vấn đề này là sử dụng một khái niệm từ thế giới lập trình chức năng gọi là Liên minh phân biệt đối xử . Trong khi những thứ này thường được tìm thấy trong các ngôn ngữ FP, bạn có thể mô phỏng chúng bằng các lớp .

Về cơ bản, Liên minh phân biệt đối xử là một loại luôn là một trong những ntrường hợp và dữ liệu được lưu trữ có thể thay đổi theo từng trường hợp.

Ví dụ:

type GameState =
  | Menu of MenuState
  | Playing of SimulationState

Ở đây, GameStateloại của chúng tôi có thể là Menuhoặc Playing. Nếu có Menu, thì nó sẽ chứa một MenuStateđối tượng. Nếu có Playing, thì nó sẽ chứa một SimulationStateđối tượng.

Để cập nhật, chúng tôi sẽ matchở trạng thái và gọi một chức năng khác cho phù hợp:

let update gameTime = 
  let nextState = 
    match gameState with
    | Menu menuState -> updateMenu gameTime menuState
    | Playing simulationState -> updateSimulation gameTime simulationState

  // Mutate the current state
  gameState <- nextState

Và tương tự để kết xuất:

let render gameTime = 
  let nextState = 
    match gameState with
    | Menu menuState -> renderMenu menuState
    | Playing simulationState -> renderSimulation simulationState

Một lợi thế của phương pháp này là bạn có thể xử lý mọi thứ trên các trạng thái (như tài nguyên) dễ dàng hơn mà không cần toàn cầu hoặc chuyển qua các đối tượng "dịch vụ".

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.