The object-oriented programming model is undoubtedly successful, and the virtual function mechanism is undoubtedly very useful for constructing complex systems. But in the face of complex enough problems, we often need more powerful mechanisms. The construction of the physical layer of the game is one possible situation.
Some people may be surprised: Which one, the legendary XXL software can be perfectly implemented with OO, a game logic will be more complicated? Don't worry, wait for me to begin. Once upon a time, a program has many possible events that need to be customized by sub-classes. Therefore, it defines many virtual functions, but each sub-class usually only cares about the processing of a small number of events, as a result, most of the time is wasted on calling empty virtual functions that cannot be inline. Its life is very empty, so it is defeated in the competition with other programs. This is one of the least important reasons: Empty virtual function overhead.
The biggest problem with using the virtual function mechanism is coupling, because virtual functions must be defined for all possible events in the base class, this means that the basic class that is the least ignorant of the specific logic of the game must be related to the specific design of the game. In contrast, the message mechanism is more flexible. The base class only needs a virtual function to process a message without knowing the specific message, it can also be easily broadcast and distributed to multiple entities. Readers who have written windows or XWindow programs in C will immediately feel familiar with it. However, for advanced languages and application development frameworks, such as MFC, winform, and WPF, these Apis seem to be a standard way of using a virtual function for an event? This is the difference between the mechanism and representation. At the underlying layer, it is a set of messaging mechanisms. At the high-level level, it can be encapsulated into a form that is easy to understand in OO mode. MFC maps messages to member functions using macros. Winform is a virtual function that triggers events based on messages. The base class control maps only common event virtual functions, and the subclass maps its own event virtual functions. WPF does not use the message mechanism of the operating system, but has its own message system. Its core component is the dispatcher class. Its message definition is very similar to that of a function call, message data is a function and call parameter.
Similarly, there are different message mechanisms in the design of the game entity layer. Some people like simple switch enumeration (messages are used as data), while others like to wrap them like function calls (messages are used as operations ). The most primitive way to define a message is:
Struct message
{
Msgcode MSG;
Int param1;
Int param2;
}
Disadvantage: the number of parameters is limited and type conversion is required. The more OO method is to define a message type inheritance system:
Class message
{
Public:
Virtual msgcode getmsgcode () const = 0;
Virtual ~ Message (){}
}
Class updatemessage: public message
{
Public:
Msgcode getmsgcode () {return msg_update ;}
Float timeinterval;
}
Of course, the C ++ stream method is also used, saving the trouble of defining the type for each message, but also losing the type check:
Message MSG;
MSG <msg_update <timeinterval;
Sendmessage (MSG );
The managed language can simply use an object array to pass parameters, map messages to class member functions, and enjoy runtime parameter type check:
Messagequeue. sendmessage (msgcode. Update, timeinterval );
The script language can dynamically DISPATCH:
Messagequeue. sendmessage ("Update", timeinterval );
Although there are different methods, message queues are mandatory, because another important advantage of the message mechanism is that it supports asynchronous processing and priority. The ultimate advantage of Asynchronization is that the game logic can be allocated to multiple threads in parallel, or even multiple servers in parallel, and the task allocation can be dynamically adjusted according to the load. Asynchronization not only means parallel, but also concurrent ). In game logic, concurrency is often required. For example, role a goes to Role B and talks to Role B. Then, he goes to the table to get a book and the rest of the game runs as usual, this can be achieved through the state machine that responds to the message, or a more intuitive coroutine. Supports message priority and can be extended to the specified message to be sent after n seconds to implement delayed operation.
At this point, we recall several basic elements of objects in the basic object-oriented concepts: property, method, and message ). Message ?! Yes. We are so familiar with mainstream programming languages such as C ++ that we forget the original appearance of OO. If you look at Pure oo languages such as Objective C or smalltalk, you will find that the proportion of messages in them is very large.