Làm thế nào để thiết kế một hệ thống menu trò chơi nhiều bước?


7

Tôi đang bắt đầu với lập trình trò chơi. Tôi đang thiết kế một trò chơi bắt đầu bằng cách đưa bạn qua một loạt các màn hình menu. Tôi thích tìm hiểu làm thế nào điều này thường được cấu trúc trong phát triển trò chơi chuyên nghiệp.

Hiện tại tôi xử lý các đầu vào của bộ điều khiển từ tệp chính và có các lớp riêng cho từng màn hình menu. Khi người dùng thực hiện lựa chọn, tôi cần chuyển sang màn hình menu tiếp theo. Có vẻ như tôi cần một số "trình quản lý màn hình menu" để theo dõi lựa chọn trước đó và chuyển đổi giữa các màn hình menu và / hoặc tôi cần chuyển xử lý đầu vào của bộ điều khiển xuống các đối tượng menu, vì tôi muốn sử dụng hết / xuống trên một menu và trái / phải trên menu khác.

Làm thế nào một kiến ​​trúc sư lập trình trò chơi chuyên nghiệp / thiết kế này?

require "components/first_menu"
require "components/second_menu"

first_menu = FirstMenu.new
second_menu = SecondMenu.new
menu = first_menu
menu.render

on(controller: "up")   { menu.prev_option }
on(controller: "left") { menu.prev_option }

on(controller: "down")  { menu.next_option }
on(controller: "right") { menu.next_option }

on(controller: "buttonA") do
  if menu.is_a? FirstMenu
    menu.hide
    selected_option = menu.select_option
    menu = second_menu
    menu.show(selected_option)
  else
    selected_option = menu.select_option
    launch_game(selected_option)
  end
end

Vì tò mò, tại sao Ruby? Ruby là một lựa chọn đầu tiên không điển hình để học lập trình trò chơi, bạn có thể tìm thấy nhiều tài nguyên hơn để phát triển trò chơi trong C #, một ngôn ngữ khá thân thiện với người mới bắt đầu với các công cụ miễn phí như Unity để chơi.

@MattJensJensen Đúng. Tôi đang sử dụng Ruby vì tôi là nhà phát triển web Ruby có kinh nghiệm và đang xây dựng một công cụ trò chơi Ruby sử dụng SDL dưới mui xe. Nhưng tôi chưa quen với một số kỹ thuật và mẫu thiết kế trong lập trình trò chơi chuyên nghiệp.
Andrew

1
Đủ công bằng, tôi yêu Ruby vì những gì nó giỏi, nhưng nó có thể thúc đẩy việc bạn học bắn C ++ hoặc C # chỉ vì nhiều tài nguyên tuyệt vời trong thiết kế phần mềm trò chơi chủ yếu nhắm vào các khái niệm trong các ngôn ngữ đó và những ngôn ngữ đó phơi bày về hiệu quả và hiệu suất. Ruby rất đẹp, nhưng thật khó để loại bỏ hiệu năng của nó, ít nhất C ++ được thiết kế để làm cho nó đẹp nhất có thể để loại bỏ hiệu suất.

@Andrew nếu mục tiêu của bạn là xây dựng một công cụ, tôi sẽ không bận tâm đến việc tạo ra một hệ thống menu. Chỉ có khả năng tổ chức các thực thể và vẽ chúng và hệ thống vật lý trong GUI là một nơi tuyệt vời để bắt đầu. Không giống như phần mềm thông thường, các menu không bắt buộc trong trò chơi.
Evorlor

Tạo một công cụ trò chơi không liên quan đến câu hỏi của tôi về việc tạo một hệ thống menu. Nếu bạn biết bất kỳ tài nguyên nào (trong C, C ++, C #, v.v.) bao gồm thiết kế hệ thống menu, vui lòng cho tôi biết. Tôi không tìm kiếm câu trả lời cho Ruby. Chỉ cần cố gắng để hiểu các kỹ thuật và các mẫu thiết kế.
Andrew

Câu trả lời:


3

Nếu bạn có các menu lồng nhau, bạn có thể sử dụng một ngăn xếp. Tôi không quen thuộc với Ruby, tôi nghĩ không có đối tượng 'stack'. Hành vi tương tự có thể được tạo ra bằng cách sử dụng một mảng. Bạn chỉ thêm các mục vào cuối (đẩy), loại bỏ mục cuối cùng (pop) và có thể tương tác với mục cuối cùng (nhìn trộm).

Vì vậy, ý tưởng cơ bản là: bạn định nghĩa một lớp menu với update () và draw (). Đây phải là một thực hiện menu cơ bản. Sau đó, bạn tạo một manumanager để điều khiển menu nào được cập nhật và hiển thị trong gameloop. Điều này thực hiện ngăn xếp: nó có thể thêm hoặc xóa menu nhưng chỉ hiển thị và cập nhật mục trên cùng trong ngăn xếp. Nếu một menuitem lồng nhau sẽ xuất hiện, đẩy lớp menu mới trên Stack. Bộ điều khiển và logic hiển thị của bạn chỉ nên hiển thị menu nằm trên cùng của ngăn xếp.

Thí dụ:

Menu cơ sở:

  • Cài đặt trò chơi -> đẩy menu cài đặt trò chơi lên ngăn xếp
  • Cài đặt đồ họa -> đẩy menu đồ họa trên ngăn xếp
  • Cài đặt âm thanh -> đẩy menu âm thanh trên ngăn xếp
  • Thoát -> thoát menu

Menu cài đặt trò chơi:

  • Số lượng cuộc sống [1 | 3 | 5]
  • Khó khăn [dễ dàng | bình thường | khó khăn]
  • Chọn ngôn ngữ -> menu ngôn ngữ đẩy trên ngăn xếp
  • Thoát -> tự bật khỏi ngăn xếp

Menu ngôn ngữ:

  • Ngôn ngữ [Tiếng Anh | Deutch | Nederlands | Français]
  • Phụ đề [Tắt | Trắng | Vàng]

Bắt đầu với ngăn xếp bằng cách đẩy menu cơ bản lên nó.

Menumanager sẽ chỉ cập nhật và hiển thị đỉnh của ngăn xếp (đây là một 'cái nhìn' ở đầu ngăn xếp).

Nếu người chơi chọn menu cài đặt trò chơi; chúng tôi đẩy menu đó lên ngăn xếp. Vì chúng tôi chỉ cập nhật và hiển thị phần trên cùng của ngăn xếp, menu 'cài đặt trò chơi' được hiển thị và thao tác. Giả sử menu đi sâu hơn; bạn chỉ có thể đẩy menu tiếp theo lên ngăn xếp và cập nhật và hiển thị cái đó.

Thủ thuật gọn gàng là, nếu menu trên cùng bị xóa ("popped") khỏi ngăn xếp, menu bên dưới được hiển thị - bạn chỉ cần đi xuống một cấp. Khi thêm tiền thưởng, menu đó sẽ ở trạng thái người chơi rời khỏi nó!

Bây giờ để mở rộng ý tưởng này; bạn có thể sử dụng một ngăn xếp cho các trạng thái trò chơi của bạn là tốt. Bằng cách này, một menu có thể được đẩy vào trò chơi đang diễn ra và khi nó được bật lên, trò chơi có thể tiếp tục như không có gì xảy ra.


0

Tôi sẽ đưa ra một câu trả lời không phải của Ruby, vì tôi không biết Ruby.

Tôi sẽ có rất nhiều lớp học cho việc này:

MenuOneController
MenuTwoController
MenuOneView
MenuTwoView
InputNames

Các bộ điều khiển điều hướng menu. Nhấn lên và xuống sẽ thay đổi mục đã chọn, nhấn enter chọn mục. Chọn mục sẽ gọi mã ở nơi khác để thực hiện hành động thực tế. Trong khi đó, bất cứ điều gì bộ điều khiển làm là cập nhật các khung nhìn. (Tùy thuộc vào hệ thống menu của bạn, bạn có thể có một bộ điều khiển duy nhất.)

Các khung nhìn vẽ menu thực tế, hiển thị tùy chọn hiện được chọn, cung cấp phản hồi khi tùy chọn được thay đổi, v.v.

Tên đầu vào là một tệp của các chuỗi như:

string up = "Up"

string select = "Enter"

Bằng cách này, nếu bạn quyết định bạn muốn chọn phím cách thay vì nhập, bạn thay đổi chuỗi ở một nơi, thay vì tất cả các bộ điều khiển của bạn. Vì vậy, thay vì on(controller: "buttonA"), bạn sẽ sử dụng on(controller: InputNames.select).

Vì vậy, nếu bạn bắt đầu trong menu một, MenuOneViewsẽ vẽ những gì bạn nhìn thấy. Các MenuOneControllersẽ được kích hoạt. Sau đó, nếu bạn chọn "Menu Two" từ menu một, nó sẽ bắt đầu vẽ MenuTwoViewthay vào đó và lắng nghe MenuOneController.

Đây là một số mã giả:

Class InputNames
{
    string up = "Up";
    string down = "Down";
    string select = "A Button";
}

Class MenuOneController
{
    int selectedMenuOption;

    void GameLoop()
    {
        if(ButtonPressed(InputNames.up)
        {
            selectedMenuOption++;
        }
        if(ButtonPressed(InputNames.down)
        {
            selectedMenuOption--;
        }
        if(ButtonPressed(InputNames.select))
        {
            if(selectedMenuOption == 0)
            {
                MenuOneView.ShowButtonBeingPressed();
                MyCodeElsewhere.DoStuffFromMenuOne();
            }
            if(selectedMenuOption == 1)
            {
                MenuOneView.ShowButtonBeingPressed();
                GameLoop.Remove(this);
                GameLoop.Add(MenuTwoController);
            }
        }
        MenuOneView.DrawUI(selectedMenuOption);
    }
}

Class MenuOneView
{
    void DrawUI(int selectedMenuOption)
    {
        //draw the UI for the currently selected menu option
    }

    void ShowButtonBeingPressed(selectedMenuOption)
    {
        //draw the UI such that the button is pressed
    }
}

Class MenuTwoController
{
    int selectedMenuOption;

    void GameLoop()
    {
        if(ButtonPressed(InputNames.up)
        {
            selectedMenuOption++;
        }
        if(ButtonPressed(InputNames.down)
        {
            selectedMenuOption--;
        }
        if(ButtonPressed(InputNames.select))
        {
            if(selectedMenuOption == 0)
            {
                MenuTwoView.ShowButtonBeingPressed();
                MyCodeElsewhere.DoStuffFromMenuTwo();
            }
            if(selectedMenuOption == 1)
            {
                MenuTwoView.ShowButtonBeingPressed();
                GameLoop.Remove(this);
                GameLoop.Add(MenuOneController);
            }
        }
        MenuTwoView.DrawUI(selectedMenuOption);
    }
}

Class MenuTwoView
{
    void DrawUI(int selectedMenuOption)
    {
        //draw the UI for the currently selected menu option
    }

    void ShowButtonBeingPressed(selectedMenuOption)
    {
        //draw the UI such that the button is pressed
    }
}

"Chọn mục sẽ gọi mã ở nơi khác để thực hiện hành động thực tế." Bạn có thể giải thích thêm một chút về cách bạn thấy điều này hoạt động không? Mã giả cũng sẽ giúp.
Andrew

Bạn đang nói rằng MenuOne sẽ trực tiếp khởi tạo MenuTwo? Hoặc bạn có tưởng tượng một số hệ thống sự kiện trong đó điều khiển được gián tiếp chuyển đến MenuTwo không? Nếu bạn có thể giải thích về điều này quá, điều đó sẽ hữu ích.
Andrew

@Andrew Điều đó phụ thuộc. Nếu tất cả các điều khiển đều giống nhau trên các menu, bạn chỉ có thể sử dụng một bộ điều khiển duy nhất. Nếu chúng khác nhau, bạn có thể yêu cầu bộ điều khiển menu gọi trên bộ điều khiển menu khác để bảo chúng tiếp quản. Hoặc nếu bạn muốn một lớp trừu tượng khác, bạn có thể có MenuControllControll. Cá nhân, tôi nghĩ rằng có một bộ điều khiển cho các bộ điều khiển là quá mức cần thiết, nhưng tôi có thể thấy một đối số cho nó.
Evorlor

@Andrew "Chọn mục sẽ gọi mã ở nơi khác để thực hiện hành động thực tế." Về cơ bản, menu là để chọn những gì bạn muốn làm. Không phải để làm điều đó. Nó nên càng ngu ngốc càng tốt. Vì vậy, chọn nút "Tắt âm lượng" không nên tắt âm lượng. Nó sẽ báo cho người quản lý âm lượng của bạn tắt âm lượng.
Evorlor

Được rồi, nó trở nên rõ ràng hơn một chút với tôi, dựa trên ví dụ mã giả của bạn. Sửa lỗi cho tôi nếu tôi sai, nhưng có vẻ như cách tiếp cận của bạn là có một đối tượng GameLoop toàn cầu (đơn lẻ) có thể được truy cập từ bất cứ đâu và quản lý / điều phối các bộ điều khiển menu riêng lẻ. Đối tượng GameLoop chuyển xử lý đầu vào cho bộ điều khiển menu hoạt động. Các bộ điều khiển riêng lẻ biết bộ điều khiển nào xử lý hành động được chọn trong menu trước. Tôi đã hiểu điều này một cách chính xác?
Andrew
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.