В настоящее время я пытаюсь создать систему меню для игры и не могу найти какой-либо действительно надежный способ сделать это. Есть несколько экранов меню, каждый из которых нетривиальный, поэтому я хотел бы сохранить их как отдельные классы. Основная проблема, с которой я столкнулся, - это передача управления между этими экранами меню.
Я попытался построить каждый из экранов как синглтон и вызывать один экран напрямую с другого, т.е. что-то вроде [[MainMenu instance] display] в Objective C. Это немного беспорядочно, потому что (1) мне нужно написать шаблонный одноэлементный код для каждого из экранов меню и (2) классы становятся зависимыми друг от друга, иногда мне приходится кодировать по кругу зависимости и т. д.
Я подумал о том, чтобы сделать классы полностью статичными, чтобы обойти управление экземплярами (что в данном случае немного лишнее, поскольку на самом деле существует только один экземпляр каждого экрана). Но это также выглядит довольно некрасиво, особенно с учетом того, что Objective C вынужден «подделывать» переменные класса, объявляя их static.
Затем я подумал о каком-то классе «менеджера», который будет создавать экземпляры и передавать управление, но я не уверен, что введение дополнительного класса решит проблему, особенно если этот класс будет называться Manager :-)
Должен заметить, что у меня делать есть работающая система, просто не очень приятно. Под этим я подразумеваю, что происходит небольшое дублирование кода, если я не буду осторожен, вещь может зависнуть и так далее. Есть идеи? Я понимаю, что это недостаточно определено, так что обсуждение, вероятно, будет скорее мозговым штурмом, но меня все равно интересуют идеи, даже если они не решают полностью мою проблему.
Обновление: Спасибо всем за идеи. Что я в итоге сделал:
Я переработал содержимое меню (кнопки, графику и т. д.), Чтобы оно соответствовало одному интерфейсу под названием ScreenView. Это общий интерфейс, который выглядит так:
@protocol ScreenView
- (void) draw;
- (BOOL) handlesPoint: (CGPoint) p;
- (void) appearWithAnimation;
- (void) disappearWithAnimation;
- (BOOL) hasFinishedAnimating;
@optional
- (void) fingerDown;
- (void) fingerUp;
@end
Благодаря этому протоколу я смог отбросить все определенные экраны меню и создать общий экран меню, который принимает список подвидов для отображения и обрабатывает всю презентацию, такую как рисование, переходы, события и т. д. Этот общий экран меню не подвергается частым подклассам, потому что большинство экранов меню просто отображают список подпредставлений. Это будет V в MVC.
Затем я также создал класс контроллера, который обрабатывает все события для определенного экрана меню. (Очевидно, C в MVC.) Класс корневого контроллера обрабатывает управление экземпляром, переходы между меню и некоторые другие мелочи. Большинство экранов меню получают настраиваемый подкласс контроллера, который обрабатывает события от кнопок и других подпредставлений.
Количество классов увеличилось, но код намного чище, не повторяется и менее подвержен ошибкам. Управление экземплярами все еще не идеально, но дизайн меня вполне устраивает. Еще раз спасибо всем, кто ответил.





Я думаю, что класс MenuManager был бы подходящим вариантом. У вас будет один базовый класс Menu, от которого происходят все экраны меню, и у менеджера будет указатель на текущий активный экран меню. Он также может, например, отслеживать предыдущие экраны меню для удобного использования кнопок возврата на экранах меню при вызовах произвольных экранов меню. Возможно, просто используйте для этого std :: vector, чтобы вам не приходилось воссоздавать предыдущие экраны меню при возврате (это также предотвратит потерю введенной информации, как в меню параметров с подменю Advanced).
Помещение всего содержимого меню в словарь, сброс в список и чтение каждого по мере необходимости с экранов меню, вероятно, самый простой путь, но, честно говоря, вам следует подумать о более ориентированном на MVC подходе к решению проблемы. Экраны должны быть для представления данных, а не для их хранения. Если вы обеспечите четкое разделение данных и представлений, проблема решится сама собой.
Один из приемов, которым я научился для создания достойного дизайна, - всегда отделять данные от кода. Это сделает ЧУДЕСА для вашей конкретной проблемы.
Под этим я подразумеваю, что элементы меню (строки) и отношения между меню должны храниться где-то либо в массиве, либо в отдельном файле (и считываться в массив).
Затем вы используете этот массив для создания экземпляров всех классов меню.
Как только вы перекодируете его так, чтобы он работал таким образом (я сделал это с меню), весь ваш код встанет на свои места, вы также исключите - 90% вашего кода меню (каждое меню больше не будет собственным классом , точно такой же класс, созданный с его собственными уникальными данными.
Цели пунктов меню также хранятся в «данных» (как указатели на методы или экземпляры классов).