Я начинаю свой первый «правильный» игровой проект, и я неизбежно попадаю в блок, пытаясь решить, как должны взаимодействовать игровые компоненты в XNA.
Из предыдущих (Java) событий программирования GUI, обработчики и слушатели выглядели как путь вперед. Таким образом, у меня была бы какая-то шина событий, которая принимает регистрации событий и классы, подписанные на эти события, с обработчиками для их обработки. Например (псевдокод):
class SpriteManager
Update(){
if(player.collidesWith(enemy)
// create new 'PlayerCollisionEvent'
}
class HUDManager
onPlayerCollisionEvent(){
// Update the HUD (reduce lives etc)
}
Однако я не уверен в настройке кода (в C #), которая потребовалась бы для полного выполнения этого. Что отслеживает события (какой-то автобус?) И как оно структурировано?
Похоже, что в Game Services также много говорится о том, что вы можете зарегистрировать GameComponent в своем основном классе Game.cs, а затем извлечь его из любого места в вашем коде, который имеет ссылку на основной объект «Game». Я пробовал это с моим объектом SpriteBatch, и это кажется очень легким ... однако я не вижу такой гибкости, как у модели событий.
Взять, к примеру, когда враг умирает. Мы хотим обновить счет игры. Используя службы, я могу получить ссылку на мой объект StateManager, созданный в Game1 и добавленный в качестве службы, а затем установить для «показателя» новое значение. Я бы подумал, что событие «onEnemyDeath», которое может обрабатываться множеством классов по-разному, но инициируется 1 строкой кода в соответствующем разделе «Обнаружение смерти противника», было бы лучше, чем индивидуальное приведение каждого требуемого GameComponent, а затем вызов любого методы требуются.
Или эти стратегии уступают чему-то другому?
Я понимаю, что это отчасти мое плохое знание C # и парадигм игрового общения, но я бы очень хотел понять эту фундаментальную вещь правильно.
Обновить
Посмотрев на сервисы более подробно, я менее убежден - это, в основном, передача глобальной переменной (насколько я понимаю).
Обновление 2
Изучив этот базовый учебник по обработке событий и тестированию примера кода, кажется, что события будут логичным выбором для того, что я обсуждаю. Но я не могу использовать его в примерах, которые я видел. Есть ли какая-то очевидная причина, почему нельзя?
источник
Ответы:
Причина, по которой вы не найдете много информации о шинах событий в C #, заключается в том, что я не думаю, что кто-то за пределами Java называет такую вещь «шиной», по моему опыту. Более распространенными терминами могут быть очередь сообщений, менеджер событий, сигналы / слоты, публикация / подписка и т. Д.
Вам не нужен ни один из них, чтобы сделать рабочую игру, но если вам удобна такая система, то и здесь она вам пригодится. К сожалению, никто не может сказать вам точно, как его сделать, потому что каждый катит их немного по-другому, даже если они вообще их используют. (Не знаю, например.) Вы можете начать с простого
System.Collections.Generic.List<Event>
для очереди, где ваши различные события являются подклассами события, и список подписчиков для каждого типа события. Для каждого события в очереди получите список подписчиков, а для каждого подписчика вызовитеhandle(this_event)
его. Затем удалите его из очереди. Повторение.Возможно, он не такой гибкий, но его легче отлаживать. События и сообщения являются хитрыми, потому что они отделяют вызывающую функцию от вызываемой функции, что означает, что ваши стеки вызовов не очень полезны при отладке, промежуточные действия могут привести к тому, что что-то сломается, что обычно работает, вещи могут молча потерпеть неудачу, если не подключены должным образом , и так далее. Явный метод «захватить компонент и вызвать то, что вам нужно» работает хорошо, когда речь идет о раннем обнаружении ошибок и наличии ясного и явного кода. Это просто приводит к тесно связанному коду и множеству сложных зависимостей.
C # в значительной степени идентичен языку Java. Все, что вы делали в Java, может быть сделано в C #, только с другим синтаксисом. Если у вас возникли проблемы с переводом концепции, это, вероятно, просто потому, что вы знаете только специфичное для Java имя.
источник
Вы пробовали просто использовать простые статические события? Например, если вы хотите, чтобы ваш класс оценки знал о том, когда умер враг, вы бы сделали что-то вроде этого:
Score.cs
EnemySpaceship.cs
SpaceshipDeathEventArgs.cs
источник
Если вам неудобно использовать подход, основанный на событиях, попробуйте Artemis C #, это среда Entity System, основанная на http://t-machine.org/index.php/2007/09/03/entity-systems-are. -The-будущее из-MMOG-развитие-часть-1 /
Источник: https://github.com/thelinuxlich/artemis_CSharp Пример игры: https://github.com/thelinuxlich/starwarrior_CSharp
источник
попробуйте использовать агрегатор событий, как этот
источник