К событиям не должна быть привязана какая-либо логика;они являются просто сообщением, техникой, чтобы сообщить заинтересованным компонентам , что произошло , но как иметь дело с событием является ответственностью указанных компонентов (иначе слушателей).В вашем случае, это ваши NPC (ы).
Но я не понимаю ваш аргумент в пользу "событий, не являющихся ОО", что заставляет вас в это верить?Что это за события, которые не могут быть объектно-ориентированными?
Теперь о том, как обрабатывать события и процесс в целом, у меня нет опыта работы с C #, но я сделал свой вклад в C ++, ивот подход, который я неоднократно использовал, который был достаточно гибким для моих нужд:
У меня был мета-класс Event, из которого каждое определенное событие могло бы быть подклассом (то есть события пользовательского интерфейса, события NPC,так далее).Был также EventManager, который создает и уничтожает все события («Emitters», компоненты, которые должны инициировать события, вызывал бы диспетчер для экземпляра, то есть GameObjects) и, что наиболее важно, имеет очередь обработки.
Объекты-эмиттеры «привязывают» событие к очереди, а EventManager отправляет их «слушателям».Теперь слушатель интересуется событиями и, таким образом, может регистрироваться для определенных событий или их типов.Как только менеджер отправляет событие этим слушателям, от них зависит выполнение логики, связанной с этим событием, начиная с этого момента.
В конце концов, дизайн мета-класса события, из которого я должен сохранять подклассыэто было не очень гибко для меня, и это была утомительная работа, поэтому я выбрал другой подход, в котором я могу произвольно прикреплять свойства к объекту события, и компонент обработки должен был бы знать, как с ним обращаться.Конечно, это влияет на производительность, но это было необходимо для меня, поскольку я запускаю и обрабатываю логику событий в Lua, а не в C ++.
Если вы создаете RPG-игру, события и сценарии довольно хороши.большая часть вашей игры, и вам действительно понадобится чистый дизайн этих двух аспектов, прежде чем вы начнете кодировать вещи.Я предлагаю для начала прочитать статьи по обработке событий на Gamedev.net .
Наконец, я не уверен, будет ли это полезно для вас, но я однажды писал о событиях, покаЯ создавал сетевую игру на C ++ / Lua, дизайн, вероятно, более сложный, чем нужно, учитывая природу сетевых игр, но вы можете проверить это здесь в любом случае.
Обновление : я покажу вам пример того, как я буду использовать свою систему, но сначала я должен прояснить ситуацию: вы используете C # и XNA по какой-то причине, и я не могу ошибаться, что XNA обеспечивает именно то, чтовам нужно, поэтому я бы не советовал использовать мою систему управления событиями или чью-либо еще в этом отношении, так как моя тесно связана с C ++ и ее шаблонными механизмами и может быть вам не полезна.Фреймворк должен дать вам то, что вам нужно, поэтому сначала проверьте это.
// singleton
class EventManager {
public:
Event* createEvt<EventType*>();
void subscribe(Event*, Listener*);
void hook(Event*);
void update();
}
class Listener {
// tells evt manager we want to listen to these events
void register(Event* someEvtType, Handler* myMethod);
// adds event to the queue (called by the EventManager)
void enqueue(Event* someEvt);
// processes events in the queue
void process();
protected:
// calls every subscribed handler to process the event
// a handler is only a functor that is bound to an event
// when calling "register()"
void dispatch(Event*);
map<Event*, list<Handler*>> myHandlers; // an event could have multiple handlers (methods)
}
class GameObject : public Listener {
}
class NPC : public GameObject {
protected:
void walkTo(NPCEvent_Walk* evt);
void talk(NPCEvent_Talk* evt);
}
// inside wherever you're gonna trigger the event, i presumed on mouseclick here
void InputManager::mouseClicked(MouseEvent* evt) {
// we want the NPC to move
NPCEvent_Walk* evtWalk = EventManager->createEvt<NPCEvent_Walk>();
evtWalk->setX(...);
evtWalk->setY(...);
// and talk
NPCEvent_Talk* evtTalk = EventManager->createEvt<NPCEvent_Talk>();
evtTalk->setText(...);
// when the master queue is empty, these events will be
// dispatched to their registered Listeners which will
// process them on their own terms
EventManager->hook(evtWalk);
EventManager->hook(evtTalk);
}
// as an NPC, i'd like to be notified of NPCEvents
NPC::NPC() {
register(NPCEvent_Walk*, &NPC::walkTo);
register(NPCEvent_Talk*, &NPC::talk);
}
void NPC::walkTo(NPCEvent_Walk*) {
// move it
// ...
// are we done?
// return true;
// if we need more updates, return false and we will be called again
// return false;
}
void NPC::talk(NPCEvent_Talk*) {
// update UI components or whatever
// ...
return true;
}
Ясно, что этот код не будет работать, поскольку в нем отсутствуют все детали реализации и он даже синтаксически не корректен, но он должен дать вамидея.Однако, как я сказал выше, вам не нужно делать это, если вы используете XNA.