Оригинальный вопрос
Я прочитал, по крайней мере, дюжину статей и ТАКИХ событий, и озадачил основные идеи, но я немного запутался в том, как это сделать. Правильный путь ™.Кажется, что есть по крайней мере два общих подхода к написанию событий, и один рекомендуется больше, чем другой.
Я вижу много материала, в котором автор пропускает части процесса, предполагая для некоторыхпричина того, что вы просто знаете это.Есть также много туториалов, таких как «MyEventExample» и «SomeProcessGoesHere», которые усложняют работу с примером в целом.Многие примеры приводят к тому, что вы учитесь тому, как что-то делать, только в конце заявляете, что вы, конечно, никогда не сделаете этого на самом деле - но тогда они не дадут того, как вы могли бы сделайте это.
Наконец, соглашения о присвоении имен для каждого из компонентов сценария, использующего события, по всей видимости, присутствуют на всей карте.У меня много проблем с выяснением того, где применяются определенные концепции, потому что каждый называет каждую его часть по-своему.
Итак, вот что я преследую: у меня есть простая ситуация в игре, которая использует события.Я бы хотел, чтобы кто-то пришел и написал о событиях, демонстрируя рекомендуемый подход и наиболее распространенные соглашения об именах и структурах.Я знаю, что это плохая форма, чтобы просить написать код для меня, но я действительно ищу способ , чтобы написать это, чтобы я мог начать уверенно делать это для себя.
Пожалуйстане обращайте внимания, является ли это хорошим игровым дизайном , или даже является ли это подходящей ситуацией для событий.Мне просто интересно, как правильно написать материал для события, и это мой пример.
//In my game I have a number of entities which can 'talk' to the player.
//An NPC can greet them, a zone might 'greet' them by displaying "Cityville"
//when they enter it, their inventory might tell them they're out of space,
//and so on. Everything would pass a Message object to a Messenger object,
//which would then deliver the messages as it saw fit.
public class Messenger
{
private Queue<Message> _messages = new Queue<Message>();;
private Stack<Message> _archive = new Stack<Message>();;
public IEnumerable<Message> Messages { get { return _messages.AsEnumerable(); } }
public IEnumerable<Message> Archive { get { return _archive.AsEnumerable(); } }
public void Add(Message message)
{
_messages.Enqueue(message);
}
public void Deliver()
{
Message msg = _messages.Dequeue();
_archive.Push(msg);
//Here's where I'd broadcast to any subsystem listening
//that the message was delivered
//Event args should be (_archive.Peek(), DateTime.Now);
}
public event MessageDeliveryEvent Delivery;
protected virtual void OnDelivery(MessageHandlerDeliveryEventArgs e)
{
if (this.Delivery != null) { this.Delivery(this, e); }
}
}
//Okay, here's my delegate declared outside any class. One tutorial suggested
//putting it in the same file as the event arguments class so it would be
//easier to find, which sounds reasonable to me, but I dunno.
public delegate void MessageDeliveryEvent(object sender, MessageHandlerDeliveryEventArgs e);
//I've seen examples where they don't even write an event arguments class.
//I think you could probably just pass the same stuff directly, but the
//separate class sounds like a good idea, more flexible if things change.
public class MessageHandlerDeliveryEventArgs : EventArgs
{
private readonly Message _message;
private readonly DateTime _delivered;
public MessageHandlerDeliveryEventArgs(Message message, DateTime delivered)
{
_message = message;
_delivered = delivered;
}
public Message Message { get { return _message; } }
public DateTime DeliveryDateTime { get { return _delivered; } }
}
//So in the UI layer I'd have things like a ChatBox which would be a
//scrolling list of everything said to the player. There would also be a
//GeneralInfoBox control that displayed things like what zone you just
//entered, or that your inventory is full. Both would listen to the
//Messenger object for a delivery event, and then check the Message object
//associated with that event to see if they needed to handle the display
//of that message.
public class ChatBox
{
//OMG there's a new message, lemme see if I should display it
private void TheThingThatListensToMessengerEvents(Message message, DateTime datetime)
{
if Message.Type == MessageType.Chat { Print(datetime.ToString() + ": " + message.Text); }
}
public string Print(string text) {}
}
public class GeneralInfoBox
{
//OMG there's a new message, lemme see if I should display it
private void TheThingThatListensToMessengerEvents(Message message)
{
if Message.Type == MessageType.General { Print(message.Text); }
}
public string Print(string text) {}
}
Если я смогу что-то уточнить, дайте мне знать.Если есть действительно хороший урок, который я явно пропустил, пожалуйста, не стесняйтесь, просто укажите мне на это.Заранее спасибо.
Что я взял из ветки
Итак, вот мой пример с событиями, связанными с ним.Может быть, это поможет кому-то, кто думает как я (помоги им Бог), визуализировать это.
public class MessageHandler
{
private Queue<Message> _messages = new Queue<Message>();
private Stack<Message> _archive = new Stack<Message>();
public MessageHandler() { }
public IEnumerable<Message> Messages { get { return _messages.AsEnumerable(); } }
public IEnumerable<Message> Archive { get { return _archive.AsEnumerable(); } }
public void Add(Message message)
{
_messages.Enqueue(message);
}
public void Deliver()
{
Message msg = _messages.Dequeue();
_archive.Push(msg);
//Call the method which broadcasts the event
OnDelivery(new MessageDeliveryEventArgs(_archive.Peek(), DateTime.Now));
}
//The event
public event EventHandler<MessageDeliveryEventArgs> Delivery;
//The method which broadcasts the event
protected virtual void OnDelivery(MessageDeliveryEventArgs messageDeliveryEventArgs)
{
EventHandler<MessageDeliveryEventArgs> handler = Delivery;
if (handler != null) { handler(this, messageDeliveryEventArgs); }
}
}
//The event arguments class for the event of interest. Carries information about this kind of event
public class MessageDeliveryEventArgs : EventArgs
{
private readonly Message _message;
private readonly DateTime _delivered;
public MessageDeliveryEventArgs(Message message, DateTime delivered)
{
_message = message;
_delivered = delivered;
}
public Message Message { get { return _message; } }
public DateTime DeliveryDateTime { get { return _delivered; } }
}
//A UI control which listens for an event in a Messenger object
public class ChatBox
{
//Specify the instance of the Messenger class to whose event(s) we plan to subscribe
public ChatBox(MessageHandler messenger)
{
//Subscribe this control's OnDelivery method to the Delivery event of the specified instance of Messenger
messenger.Delivery += this.OnDelivery;
}
//The method which we intend to subscribe to the Delivery event of an instance of Messenger
private void OnDelivery(object sender, MessageDeliveryEventArgs e)
{
if (e.Message.Format == MessageFormat.Local)
{
Print(String.Format("{0}: {1}", e.DeliveryDateTime, e.Message.Text));
}
}
private void Print(string text) { }
}