Làm cách nào để cập nhật cài đặt Hiển thị từ màn hình Tùy chọn mà không cần khởi động lại?


9

Tôi hiện đang tạo một game nhập vai 2D trong C ++ 11 với Allegro 5 và boost.

Mục tiêu của tôi là bằng cách nào đó cập nhật cài đặt trò chơi của mình khi một tùy chọn được thay đổi trong Menu Tùy chọn. Tôi không muốn buộc người dùng khởi động lại trò chơi của mình. Các trò chơi khác không yêu cầu khởi động lại khi thay đổi độ phân giải hoặc chuyển từ toàn màn hình sang cửa sổ, vì vậy trò chơi của tôi không nên. Xin vui lòng xem một cái nhìn đơn giản của hệ thống dưới đây.

Xin lưu ý rằng tôi không nhất thiết muốn gọi trực tiếp đối tượng Trò chơi của mình từ OptionsScreen. Đường đứt nét chỉ đơn thuần là để minh họa cho hiệu ứng tôi đang cố gắng đạt được; để bằng cách nào đó gây ra một bản cập nhật của trò chơi khi một tùy chọn được thay đổi trong một phần khác của hệ thống.

Giải thích chi tiết

Trình quản lý màn hình chứa danh sách tất cả GameScreencác đối tượng hiện đang tồn tại. Đây sẽ là các màn hình khác nhau trong trò chơi bao gồm cả cửa sổ bật lên. Thiết kế này tuân thủ ít nhiều với mẫu Quản lý trạng thái trò chơi trong C # / XNA .

ScreenManagerchứa một tham chiếu đến Gameđối tượng của tôi . Đối Gametượng khởi tạo và sửa đổi cài đặt của trò chơi. Nếu tôi muốn thay đổi độ phân giải, hãy chuyển sang toàn màn hình hoặc tắt tiếng âm lượng tôi sẽ làm trong Gamelớp.

Tuy nhiên, OptionsScreen hiện không thể truy cập lớp Trò chơi. Xem sơ đồ dưới đây:

Một GameScreen có thể báo hiệu ba sự kiện onFinished, onTransitionStartonTransitionEnd. Không có onOptionsChangedbởi vì chỉ có một màn hình làm điều đó. Trình quản lý màn hình không thể thiết lập xử lý sự kiện cho việc đó vì nó xử lý tất cả các màn hình dưới dạng GameScreens.

Câu hỏi của tôi là, làm thế nào tôi có thể thay đổi thiết kế của mình để thay đổi trong OptionsMothy không yêu cầu khởi động lại, nhưng được thay đổi ngay lập tức? Tôi tốt nhất nên yêu cầu Gameđối tượng của mình cập nhật sau khi nhấn nút áp dụng.


Câu hỏi này (mặc dù có liên quan đến trò chơi) có vẻ phù hợp với các lập trình
viên.stackexchange.com

Nơi nào bạn có được một biểu đồ tìm kiếm tuyệt vời như vậy?
joltmode

@psycketom: Đầu tiên là từ Visio 2013 và lần thứ hai được tạo từ mã bởi VS2012. Mong rằng sẽ giúp!
IAE

Câu trả lời:


1

Từ những gì tôi đã thấy, cách tiếp cận dễ nhất là đọc tệp tùy chọn khi khởi động để xác định cài đặt hiển thị hiện tại; sau đó, khi màn hình tùy chọn của bạn được hiển thị, tải tất cả các tùy chọn hiện tại từ một tệp.

Khi các thay đổi được hoàn thành thông qua một nút applyhoặc ok, chúng sẽ được lưu lại vào một tệp. Nếu bất kỳ thay đổi nào ảnh hưởng đến màn hình, thông báo cho người dùng rằng trò chơi phải được khởi động lại để chúng có hiệu lực.

Khi trò chơi được khởi động lại, cài đặt hiển thị (bây giờ mới) sẽ được đọc lại từ tệp.

--BIÊN TẬP--

Annd ... nó sẽ có ích nếu tôi nhận thấy câu cuối cùng đó. Bạn không muốn phải khởi động lại. Làm cho mọi thứ khó khăn hơn một chút tùy thuộc vào việc triển khai và Thư viện đồ họa phụ trợ của bạn.

IIRC, Allegro có chức năng gọi cho phép bạn thay đổi cài đặt hiển thị khi đang di chuyển. Tôi chưa kịp cập nhật Allegro 5, nhưng tôi biết bạn có thể làm được 4.


Tôi không nghĩ vấn đề này liên quan đến Allegro và khả năng của nó. "Câu hỏi của tôi là, làm cách nào tôi có thể thay đổi thiết kế của mình để thay đổi trong OptionsMothy không yêu cầu khởi động lại, nhưng được thay đổi ngay lập tức?" Việc khởi động lại là do "OptionsScreen hiện không thể truy cập lớp Trò chơi" và phải tải chúng từ tệp cài đặt nếu tôi hiểu chính xác.
ClassicThunder

@Casey: Xin chào Casey! :) Có, tôi đang sử dụng tệp cấu hình để lưu trữ dữ liệu hiển thị có liên quan, nhưng tôi muốn có thể tránh khởi động lại. Đây là một trò chơi nhỏ và các trò chơi khác có thể thay đổi độ phân giải mà không phải khởi động lại, vì vậy tôi không hiểu tại sao tôi nên buộc người dùng khởi động lại với tôi. Đây là một vấn đề về khả năng sử dụng. Mặc dù tôi chỉ có thể gọi các chức năng phân tán allegro, tôi đang cố gắng duy trì OOP và không trộn lẫn các cuộc gọi đồ họa của mình chỉ vì tôi có thể; Tôi không xem xét thiết kế tốt.
IAE

Tôi đã nhấn mạnh bit "không khởi động lại" để những người khác không gặp phải câu cuối cùng. Một sự thật quan trọng như vậy không nên đến vào cuối, tôi xin lỗi):
IAE

@SoulBeaver Ai nói bạn phải làm điều đó để bạn không khởi động lại? Đó là một điều khả thi để yêu cầu điều đó, trên thực tế, nó trở nên phổ biến hơn bây giờ. Một số bản phát hành gần đây (XCOM: Enemy Unknown, Skyrim, v.v.) của các trò chơi có ngân sách lớn yêu cầu khởi động lại. (thực tế là họ đang ở trên Steam có thể là thủ phạm do đồng bộ hóa các tùy chọn phía máy chủ của nó nhưng chúng ta đừng đến đó ...)
Casey

1
@Casey: Đúng, và đối với một số tùy chọn nhất định, tôi có thể thấy lý do tại sao điều đó thậm chí cần thiết, nhưng đối với những thứ như toàn màn hình / cửa sổ hoặc độ phân giải màn hình? Tôi chưa bao giờ thấy một trò chơi yêu cầu khởi động lại cho các cài đặt đó. Câu hỏi cơ bản của tôi là: tại sao tôi phải buộc người dùng của mình khởi động lại khi trò chơi có thể tự động thay đổi cài đặt?
IAE

1

Đây là những gì tôi làm cho trò chơi của tôi. Tôi có 2 chức năng riêng biệt để khởi tạo công cụ, 'init' và 'reset'. Ban đầu chỉ được gọi một lần khi khởi động và thực hiện những việc không dựa vào bất kỳ cài đặt nào, chẳng hạn như tải tài sản chính. Đặt lại thực hiện những việc như đặt giao diện người dùng dựa trên độ phân giải màn hình, do đó được gọi mỗi khi thay đổi cài đặt.

init();
bool quit = false;
while( !quit )
{
    createWindow();
    reset();

    bool settings_changed = false;
    while( !quit && !settings_changed )
    {
        ... main loop
        // set quit=true if user clicks 'quit' in main menu
        // set settings_changed=true if user clicks 'apply' in options
    }

    destroyCurrentWindow();
}

Tôi không quen thuộc với Allegro, nhưng câu trả lời của tôi khá chung chung, vì vậy tôi hy vọng nó sẽ giúp bạn hoặc bất kỳ ai khác có vấn đề tương tự.


Đó là một giải pháp thú vị. Tôi đã cố gắng kiểm soát chặt chẽ bất cứ khi nào thiết lập lại được gọi, nhưng bạn làm điều đó bất kể thay đổi. Đó chắc chắn là điều tôi có thể thực hiện, và tôi sẽ xem xét nó, cảm ơn!
IAE

1

Không làm rối kiến ​​trúc hiện tại của bạn, tôi thấy hai cách. Đầu tiên, bạn có thể lưu trữ một con trỏ tới Gamethể hiện trong OptionsScreenlớp. Thứ hai, bạn có thể Gamelớp tìm nạp các cài đặt hiện tại trong một khoảng nhất định, giả sử mỗi giây.

Để thực sự thích ứng với các cài đặt mới, Gamelớp phải thực hiện một số loại chức năng thiết lập lại tìm nạp các cài đặt hiện tại và khởi tạo lại dựa trên các cài đặt đó.

Đối với một giải pháp sạch, bạn cần một người quản lý toàn cầu thuộc loại nào đó, do đó cần nỗ lực hơn để thực hiện. Ví dụ một hệ thống sự kiện hoặc hệ thống nhắn tin. Nó rất hữu ích để cho các lớp giao tiếp mà không có sự ràng buộc mạnh mẽ như tổng hợp hoặc thành phần, v.v.

Với một người quản lý sự kiện toàn cầu, OptionsScreenđơn giản là có thể bắn toàn cầu một sự kiện vẽ lại Gameđã đăng ký để nghe trước đó.

Nói chung, bạn có thể triển khai lớp quản lý lưu trữ các sự kiện và gọi lại nghe chúng trong bản đồ băm. Sau đó, bạn có thể tạo một phiên bản duy nhất của trình quản lý đó và chuyển con trỏ tới nó cho các thành phần của bạn. Sử dụng C ++ mới hơn khá dễ dàng vì bạn có thể sử dụng std::unordered_maplàm bản đồ băm và std::functionlưu trữ các cuộc gọi lại. Có nhiều cách tiếp cận khác nhau mà bạn có thể sử dụng làm chìa khóa. Ví dụ: bạn có thể tạo chuỗi trình quản lý sự kiện dựa trên đó làm cho các thành phần thậm chí độc lập hơn. Trong trường hợp đó, bạn sẽ sử dụng std::stringlàm khóa trong bản đồ băm. Cá nhân tôi thích điều này và nó chắc chắn không có vấn đề về hiệu năng, nhưng hầu hết các hệ thống sự kiện truyền thống đều hoạt động với các sự kiện như các lớp.


Xin chào danijar. Tôi đã sử dụng các tín hiệu boost :: để thiết lập sơ đồ xử lý sự kiện thô sơ. Dòng mạnh mẽ từ GameScreen đến ScreenManager thực sự là xử lý sự kiện. Bạn có bất kỳ tài nguyên chi tiết kiến ​​trúc của một người quản lý sự kiện toàn cầu? Nhiều việc hơn hay không, điều này nghe có vẻ như có thể dẫn đến việc thực hiện sạch sẽ.
IAE

Mặc dù tôi chưa đọc bất kỳ nghiên cứu nào về việc này, tôi đã triển khai một trình quản lý sự kiện toàn cầu cho công cụ nhỏ của riêng mình. Nếu bạn quan tâm đến việc thực hiện, tôi sẽ gửi cho bạn một liên kết. Tôi cập nhật câu trả lời của tôi để bao gồm chi tiết hơn.
danijar

1

Vâng, đây là một số trường hợp cụ thể của mẫu Observer.

Có một giải pháp liên quan đến cuộc gọi lại. Đây là cách tốt nhất để làm điều này nếu bạn muốn khớp nối lỏng lẻo và tôi nghĩ đó cũng là cách sạch nhất. Điều này sẽ không liên quan đến bất kỳ nhà quản lý toàn cầu hoặc singletons.

Về cơ bản, bạn sẽ cần phải có một số loại SettingsStore. Ở đó bạn lưu trữ các cài đặt. Khi bạn tạo một màn hình mới, họ sẽ cần một con trỏ tới cửa hàng. Trong trường hợp OptionsScreennó sẽ tự sửa đổi một số giá trị cài đặt. Trong trường hợp của GameScreennó sẽ chỉ đọc chúng. Vì vậy, trong trò chơi của bạn, bạn sẽ chỉ tạo một phiên bản, sẽ được chuyển qua tất cả các màn hình yêu cầu một màn hình.

Bây giờ, SettingsStorelớp đó sẽ có một danh sách notifiables. Chúng là các lớp thực hiện một ISettingChangedgiao diện nhất định . Giao diện sẽ là một giao diện đơn giản chứa phương thức sau:

void settingChanged(std::string setting);

Sau đó, trong màn hình của bạn, bạn sẽ triển khai logic cho từng cài đặt bạn quan tâm. Sau đó, thêm chính bạn vào cửa hàng để được thông báo : store->notifyOnChange(this);. Khi một cài đặt được thay đổi, cuộc gọi lại được gọi với tên cài đặt. Giá trị cài đặt mới sau đó có thể được lấy từ SettingsStore.

Bây giờ, điều này có thể được tăng cường hơn nữa với các ý tưởng sau:

  • Sử dụng một lớp lưu trữ các chuỗi cài đặt - thậm chí có thể là SettingsStore(các chuỗi const) để ngăn chặn các chuỗi sao chép xung quanh.
  • Thậm chí tốt hơn, thay vì một chuỗi, sử dụng enum để chỉ định cài đặt bạn có
  • Bạn thậm chí có thể chỉ định các giá trị cũ và mới làm đối số trong cuộc gọi lại, nhưng điều đó sẽ phức tạp hơn, vì bạn có thể có các giá trị chuỗi hoặc int hoặc không có gì. Tuỳ bạn.

0

Đọc cài đặt của bạn từ một tệp thành các biến. Theo dõi Trình quản lý màn hình nếu màn hình mà nó vừa xuất hiện là màn hình Tùy chọn và nếu có, hãy tải lại cài đặt của bạn từ các biến. Khi người dùng thoát khỏi trò chơi của bạn, hãy viết các cài đặt trong các biến trở lại tệp.

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.