• 沒有找到結果。

Chapter 5 Design of Programming Interface

5.2. DOIT API

NetEngine engine = new TCPNetEngine();

InetSocketAddress sockaddr =

new InetSocketAddress("localhost", 13579);

engine.register(MyMessage.TYPE, new MyMessageFactory(), new MyMessageHandler());

Channel channel = engine.connect(sockaddr);

MyMessage msg = new MyMessage();

channel.send(msg);

//...

5.2. DOIT API

DOIT API provides all the classes and interfaces to develop a game on the DOIT

platform. In this API, developers can totally develop the game in view of game without the complexity of networking, distributed system, and multi-thread issues.

The DOIT API is somewhat similar to NetEngine because it also have the message-oriented property. But the DOIT API is specially designed for game development. It will provide some features aimed at game. The Figure 5-2 is the class diagram of the DOIT API.

Figure 5-2: Class diagram of the DOIT API

5.2.1. Game Protocol and Game Logic

Our platform inherits from NetEngine. So we define the game protocol in the same manner as using NetEngine library, that is, we should define a message class extending the Message class for each type of message. Similarly, we also need to provide a message factory for each message class. To write a game logic, we should provide a message handler extending GameMessageHandler for each type of message. This design is inspired from Java Servlet API [18]. The developers should override the onMessage() method to handle the message. When a message comes, the system will call back the onMessage() method. It will pass in a

GameMessageInfo object. From this object, we can get the message, message type, and game object channel. In particular, the game object channel represents the source of the message to be handled.

The game object channel which is an instance of GameObjChannel class is the similar concept of Channel in NetEngine library. The difference is that the game object channel represents the channel to communicate a game object. In the current version of DOIT API, we provide two kind of GameObjChannel. They are AvatarChannel and NPCChannel respectively. As the name implied, the AvatarChannel is a channel to an avatar. We can send a message to a client indirectly through this class. As for the NPCChannel, it is a channel to a NPC, we can send a message to the NPC bot thought this class.

A game object channel can associate with a game object which extends the GameObject class. The GameObject class is the base class of all game objects.

That is, developers can customize a game object by extending the GameObject class. The GameObjChannel delegate some methods call to his associating game object. They include getX(), getY(), and status() these three methods.

Certainly, the getX() and getY() are the accessor methods to get the location information. As for the status() method, it return a Message instance according to its current state. They will be useful for GameSpace and GameSpaceUtil class.

Therefore, we can conclude the basic flow to design a game.

1. Defines the game protocol.

2. Define the message classes and corresponding message factory classes.

3. Define the game objects.

4. Implements the message handlers.

5.2.2. GameContext and GameSpace

In GameMessageHandler, we can receive a message for a given type, process message, and send updates back to the game object channel. But it is only possible to send updates to original game objects. We need more functionality to deal with game objects. In this subsection, we introduce the two classes, GameContext and GameSpace.

Figure 5-3: GameContext

GameContext represents the context of the game. The concept is similar to ServletContext in the Servet API. But the game context only associates with the current region. We can store and retrieve attributes to and form the context. Besides, we can also obtain some information of the game. The GameContext instance can be obtained from the init() method of MessageHandler, AvatarChannelListner, and AvatarMigrationListener. The Figure 5-3 is the class information of GameContext.

Figure 5-4: GameSpace

GameSpace can be seen as a data structure of the virtual worlds. We can add, remove, move, and find game objects from the GameSpace. The element type of

GameSpace is GameObjChannel. Before adding a GameObjChannel to a GameSpace, we should first associate it with a game object. It is because GameSpace set and retrieve the location information from setX()/getX() and setY()/getY() methods of GameObjChannel. These methods delegate the implementation to the same methods of GameObject associated by the GameObjChannel. Therefore, the GameSpace prohibit a GameObjChannel without GameObject from added to it. The size of GameSpace is specified in the game descriptor (see chapter 5.3). The GameSpace instance can be obtained from the GameContext.

GameSpaceUtil is a class let us use GameSpace more conveniently. We usually need to send a message to surroundings of a game object. We can call the sendMsgToSurroundings() method. It will get the GameObjChannels from the given range and send the message respectively. Likewise, if we need to receive updates from surroundings, we can call the recvUpdtFromSurroundings()

method. It will get the GameObjChannels from the given range, get the updates from status()method of GameObjChannels, and send them to the given channel.

5.2.3. AvatarChannelListener

We can have greater control over the lifecycle of avatar by means of

AvatarChannelListener. A listener implementing AvatarChannelListener can receive the events when an avatar connect or

disconnect. Even though the client disconnected abnormally, the disconnect event also raise correctly.

5.2.4. Avatar Migration

In DOIT API, we use migrate() method of AvatarChannel to migrate a avatar to another. In this method, we should specify the region to migrate, the location, and the migration data. The migration data is type of byte array. We can put arbitrary data in it. Besides, the developers may implement the interface AvatarMigrationListener to get the event about some avatars’ migration.

5.2.5. NPC

NPC (Non Player Character) is also supported in DOIT Platform. In our design, we separate the game logic and AI logic into two parts, NPCBot and GameMessageHandler respectively. They communicate with each other by means of sending messages. The game server is responsible for relaying messages between them (see Figure 5-5). The advantage is that we can process game logic in the same way as processing game logic of avatars. Moreover, it prevents codes of different

purpose from mixing together. To write NPC AI, we should write a class implementing NPCBots. There are three method should be overridden, onInit(), onUpdate(), onTimer(). onInit() is called when a NPC is created.

onUpdate() is called when a message comes. The message is sent from his corresponding NPCChannel. onTimer() is called periodically by GameServer. The timer interval is defined in the description file.

NPCBot GameMessage

5.2.6. Mapping the features to the API

In Chapter 4, we explained the features of the DOIT platform. It is interesting to map these to the API. Table 5-1 lists the features mapping to the API. We can found that the underlying complexity is totally hidden under the easy API.

Features Related API Notes

Customized Protocol

Extends Message, Extends

MessageFactory

Use encode() and decode() callback methods to turn underlying protocol to object form, and vice versa

Customized Game Logic Extends

MessageHandler

Overrides onMessage() method to handle message.

Channel Event

NPC Support extends NPCBot, Use NPCChannel

Overrides onInit()/ onTimeout()/

onUpdate()

Virtual World Uses GameSpace Provides add()/remove()/ find()/move() methods

Game Context Uses

GameContext

Provides put/get attributes

Table 5-1: API for our MMOG Middleware

相關文件