青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

Getting Online with Multiplayer Gaming(9)

 

Storing Player Information

Players in the game are only allowed to move around and swing their weapons (hitting
other players). The server will want to track every player’s current state (walking,
standing still, swinging their weapons, or being hurt), the coordinates in the world,
the direction they are facing, and the speed they are walking (if they are walking).

This player data is stored inside a structure called sPlayer. Because all connected
players in the game need their own set of unique data, an array of sPlayer structures
are allocated to store the information. Both the number of player structures
to allocate and the number of players to allow to join the game session are stored
in the macro MAX_PLAYERS, which is currently set to 8.

The sPlayer structure is as follows (with supporting state definition macros):

#define MAX_PLAYERS           8     // Maximum number of players allowed to be connected at once

#define STATE_IDLE            1 
#define STATE_MOVE            2
#define STATE_SWING           3
#define STATE_HURT            4

typedef 
struct sPlayer
{
    
bool    connected;

    
char    name[256];
    DPNID   player_id;

    
long    last_state;      
    
long    last_update_time;
    
long    latency;

    
float   x_pos, y_pos, z_pos;
    
float   direction;
    
float   speed;

    
///////////////////////////////////////////////////////////////
    
    sPlayer()
    {
        ZeroMemory(
thissizeof(*this));
    }
} *sPlayerPtr;

There’s not much to the sPlayer structure; you have a flag if the player is connected,
the name of the player, the player’s DirectPlay identification number, the
player’s current state (as defined by the state macros), time of last state change,
network latency value, the player’s coordinates, direction, and walking speed.

The variables in sPlayer are self-explanatory, except for latency. Remember that
latency is the delay resulting from network transmission. By storing the time it takes
for a message to go from the server to the client (and vice versa), time-based calculations
become more synchronized between the server and client.

Speaking of time-based calculations, that's the purpose of the last_update_time variable. Whenever
the server updates all players, it needs to know the time that has elapsed between
updates. Every time a player state is changed (from the client), the last_update_time variable is set
to the current time (minus the latency time).

Time is also used to control actions. If a player swings a weapon, the server refuses
to accept further state changes from the client until the swing weapon state is
cleared. How does the state clear? After a set amount of time, that’s how! After one
second passes, the update player cycle clears the player’s state back to idle, allowing
the client to begin sending new state-change messages.

On the subject of sending messages, take a look at how the server deals with the
incoming network messages.

 

Handling Messages

You’ve already seen DirectPlay messages in action, but now you focus on the game
action messages (state changes). Because DirectPlay has only three functions of
interest when handling incoming network messages (create_player, destroy_player, and
receive), the server will need to convert the incoming networking message to messages
more suited to game-play.

The server receives messages from clients via the DirectPlay network’s receive function.
Those messages are stored in the pReceiveData buffer contained within the
DPNMSG_RECEIVE structure passed to the receive function. That buffer is cast into a
more usable game message, which is stuffed into the game message queue.

The server game code doesn’t deal directly with network messages. Those are handled
by a small subset of functions that take the incoming messages and convert
them into game messages (which are entered into the message queue). The server
game code works with those game messages.

Because there can be many different types of game messages, a generic message
container structure is needed. Each message starts with a header that stores
the type of message, the total size of the message data (in bytes) including the
header, and a DirectPlay player identification number that is usually set to the
player sending the message.

I’ve taken the liberty of separating the header into another structure, making
it possible to reuse the header in every game message:

#define MESSAGES_PER_FRAME 64 // number of messages to process per frame
#define MAX_MESSAGES 1024 // number of message to allocate for message queue

typedef struct sMsgHeader
{
  long type; // type of message (MSG_*)
  long size; // size of data to send
  DPNID player_id; // player performing action
} *sMsgHeaderPtr;

Because there can be many different game messages, you first need a generic message
container capable of holding all the different game messages. This generic
message container is a structure as follows:

typedef struct sMsg // the message queue message structure
{
  sMsgHeader header;
  char data[512];
} *sMsgPtr;

Pretty basic, isn’t it? The sMsg structure needs to contain only the message header
and an array of chars used to store the specific message data. To use a specific message,
you can cast the sMsg structure into another structure to access the data.

For example, here is a structure that represents a state-change message:

typedef struct sStateChangeMsg
{
  sMsgHeader header;

  long state; // State message (STATE_*)
  float x_pos, y_pos, z_pos;
  float direction;
  float speed;
  long latency;
} *sStateChangeMsgPtr;

 

To cast the sMsg structure that contains a state-change message into a usable
sStateChangeMsg structure, you can use this code bit:

sMsg Msg; // Assuming message contains data
sStateChangeMsg *scm = (sStateChangeMsg*) Msg;

// Access state-change message data
scm->state = STATE_IDLE;
scm->direction = 1.57f;

In addition to the state-change message, the following message structures are used
in the network game:

typedef struct sCreatePlayerMsg
{
  sMsgHeader header;
  float x_pos, y_pos, z_pos; // create player coordinates
  float direction;
} *sCreatePlayerMsgPtr;

typedef struct sRequestPlayerInfoMsg
{
  sMsgHeader header;
  DPNID request_player_id; // which player to request
} *sRequestPlayerInfoMsgPtr;

typedef struct sDestroyPlayerMsg
{
  sMsgHeader header;
} *sDestroyPlayerMsgPtr;

Each message also has a related macro that both the server and client use. Those
message macros are the values store in the sMsgHeader::type variable. Those message
type macros are as follows:

#define MSG_CREATE_PLAYER    1
#define MSG_SEND_PLAYER_INFO 2
#define MSG_DESTROY_PLAYER   3
#define MSG_STATE_CHANGE     4

You see each message in action in the sections “Processing Game Messages” and
“Working with Game Clients,” later in this chapter, but for now, check out how the
server maintains these game-related messages.

posted on 2007-12-18 19:52 lovedday 閱讀(271) 評論(0)  編輯 收藏 引用

公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲人成在线播放| 国产精品入口夜色视频大尺度 | 一区二区不卡在线视频 午夜欧美不卡在| 国产精品最新自拍| 国产精品一级在线| 国产日韩精品一区观看| 国产农村妇女毛片精品久久麻豆 | 国产欧美日韩综合一区在线播放| 国产精品人人做人人爽人人添| 国产精品免费区二区三区观看| 国产精品私房写真福利视频| 国产一区美女| 亚洲三级国产| 亚洲欧美日韩精品久久奇米色影视 | 久久青青草原一区二区| 欧美 日韩 国产精品免费观看| 牛人盗摄一区二区三区视频| 欧美日在线观看| 狠狠久久五月精品中文字幕| 欧美一区2区三区4区公司二百| 国产日韩欧美在线观看| 亚洲国产精品日韩| 亚洲一级黄色av| 久久精品五月婷婷| 亚洲激情一区二区| 中文国产成人精品| 久久亚洲图片| 欧美午夜在线| 亚洲国产精品热久久| 午夜一区不卡| 亚洲经典三级| 久久久国际精品| 午夜精品成人在线| 久久久久久黄| 99国产精品自拍| 久久久亚洲人| 久久成人av少妇免费| 欧美电影免费观看网站| 国产午夜一区二区三区| 一区二区激情| 欧美国产在线观看| 午夜免费日韩视频| 欧美色区777第一页| 亚洲高清视频一区二区| 欧美一区成人| 亚洲视频一区在线| 欧美日韩国产综合视频在线观看中文| 国产一区二区三区的电影| 亚洲免费福利视频| 欧美mv日韩mv亚洲| 欧美一区午夜视频在线观看| 国产精品家教| 亚洲视频在线观看网站| 亚洲区免费影片| 欧美激情国产日韩精品一区18| 精品999在线观看| 久久久久久久国产| 欧美一区二区在线观看| 国产欧美日韩综合精品二区| 亚洲欧美日韩中文播放| 一区二区三区黄色| 欧美视频你懂的| 亚洲制服丝袜在线| 一区二区三区**美女毛片| 欧美日韩免费看| 亚洲视频一区二区| 亚洲视屏一区| 国产日韩欧美二区| 久久久久久久成人| 久久精品日韩欧美| 亚洲第一在线视频| 亚洲高清久久| 欧美日韩天堂| 欧美在线观看一二区| 久久www免费人成看片高清| 好吊色欧美一区二区三区视频| 久久影音先锋| 牛牛影视久久网| 欧美一区二区三区在线观看| 欧美国产在线电影| 99re热这里只有精品免费视频| 亚洲国产精品久久久久秋霞影院| 欧美黑人一区二区三区| 久久久蜜桃精品| 日韩亚洲欧美一区二区三区| 99日韩精品| 国产欧美va欧美va香蕉在| 久久综合久色欧美综合狠狠| 麻豆精品在线播放| 亚洲一区二区三区在线| 午夜精品久久| 亚洲国产免费看| 在线亚洲欧美专区二区| 国产一区成人| 91久久夜色精品国产网站| 欧美日韩精品一区二区| 欧美亚洲视频一区二区| 巨乳诱惑日韩免费av| 国产精品99久久久久久久女警 | 一区二区三区毛片| 国产日韩综合| 亚洲欧洲日本一区二区三区| 国产精品一二三| 欧美激情黄色片| 国产九区一区在线| 亚洲国产日韩欧美一区二区三区| 国产精品成人国产乱一区| 老司机久久99久久精品播放免费| 欧美日韩国产不卡| 久久综合伊人77777麻豆| 欧美日韩视频在线一区二区观看视频 | 老司机精品视频一区二区三区| 在线视频精品一区| 久久久久国产精品一区二区| 亚洲在线一区二区| 免费亚洲电影在线| 久久久精彩视频| 欧美视频你懂的| 亚洲国产成人不卡| 娇妻被交换粗又大又硬视频欧美| 正在播放亚洲一区| 日韩手机在线导航| 久久久久中文| 久久国产精品网站| 国产精品久久久一本精品| 亚洲人成7777| 亚洲精品美女久久久久| 久久理论片午夜琪琪电影网| 欧美在线综合视频| 国产精品美腿一区在线看| 亚洲精品中文字幕女同| 亚洲黄色尤物视频| 久热国产精品视频| 麻豆精品91| 免费看成人av| 在线欧美视频| 久久国产成人| 久久精品夜色噜噜亚洲a∨| 国产精品你懂的| 亚洲一区二区三区在线视频| 亚洲综合欧美| 国产精品v欧美精品v日韩精品| 亚洲精品乱码久久久久| 99国产精品视频免费观看一公开| 免费观看成人| 亚洲片区在线| 亚洲视频在线观看视频| 国产精品久久一区主播| 亚洲影视在线播放| 久久久久成人精品| 精品成人国产| 欧美国产日韩精品| 亚洲看片免费| 欧美亚洲日本网站| 国产一区二区三区在线观看精品| 欧美亚洲一区| 美女视频网站黄色亚洲| 亚洲国产欧美一区二区三区丁香婷| 久久尤物视频| 亚洲精选一区| 欧美在线观看视频一区二区| 精品动漫3d一区二区三区| 老鸭窝亚洲一区二区三区| 亚洲国产日韩在线| 亚洲欧美国产日韩中文字幕| 国产一区二区三区不卡在线观看| 久色成人在线| 一本一本a久久| 久久久xxx| 亚洲精品在线视频| 国产精品区一区二区三| 久久久噜噜噜久久中文字免| 99xxxx成人网| 美女福利精品视频| 亚洲色在线视频| 狠狠色丁香婷综合久久| 欧美理论电影在线播放| 亚洲免费人成在线视频观看| 欧美肥婆在线| 亚欧成人精品| 99国内精品| 国产午夜精品在线| 欧美伦理影院| 久久久久国内| 亚洲一区二区三区免费视频| 欧美成年网站| 久久99在线观看| 亚洲精品视频免费在线观看| 国产乱子伦一区二区三区国色天香| 玖玖在线精品| 欧美一区二区三区婷婷月色| 亚洲精品在线观| 欧美成人免费va影院高清| 亚洲一区久久久| 1000部精品久久久久久久久| 欧美视频一区二区三区四区| 免费成人高清| 久久精品av麻豆的观看方式| 亚洲夜晚福利在线观看| 亚洲精品国久久99热|