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

天行健 君子當(dāng)自強(qiáng)而不息

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 閱讀(274) 評(píng)論(0)  編輯 收藏 引用


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


公告

導(dǎo)航

統(tǒng)計(jì)

常用鏈接

隨筆分類(178)

3D游戲編程相關(guān)鏈接

搜索

最新評(píng)論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产精品一区二区久久国产| 久久精品九九| 亚洲高清久久| 久久久视频精品| 亚洲福利小视频| 亚洲第一精品影视| 99一区二区| 亚洲精品字幕| 欧美日韩精品久久| 欧美激情国产日韩| 亚洲欧美精品一区| 在线一区二区三区做爰视频网站| 亚洲裸体俱乐部裸体舞表演av| 亚洲欧洲视频在线| 亚洲综合清纯丝袜自拍| 午夜精品网站| 性色av一区二区三区红粉影视| 亚洲二区免费| 亚洲图片在区色| 亚洲一区二区三区四区五区黄| 裸体丰满少妇做受久久99精品| 欧美在线视频观看| 亚洲先锋成人| 欧美日韩亚洲另类| 国产一区日韩一区| 中文av字幕一区| 久久久久一区二区三区四区| 亚洲综合好骚| 欧美日韩一区二区三区四区五区| 伊人久久大香线蕉综合热线| 在线观看一区视频| 在线一区二区三区四区| 亚洲成色精品| 裸体一区二区| 国产欧美日韩视频一区二区三区| 亚洲综合国产| 亚洲国产日韩在线一区模特| 欧美激情视频一区二区三区在线播放| 国产一区亚洲一区| 欧美一区二区视频在线| 亚洲欧美日韩专区| 韩国成人福利片在线播放| 久久国产精品一区二区| 亚洲午夜一区| 欧美三级网址| 99天天综合性| 国产一区二区三区无遮挡| 亚洲精品视频一区二区三区| 亚洲国产经典视频| 久久久久久色| 在线日韩一区二区| 欧美激情亚洲一区| 欧美少妇一区二区| 99精品视频一区| 欧美一区二区三区久久精品茉莉花 | 欧美激情亚洲综合一区| 国产精品啊v在线| 亚洲欧美中文日韩在线| 午夜一区不卡| 国产日韩一区欧美| 亚洲国产三级在线| 国产精品一区免费视频| 亚洲一区二区日本| 欧美一级一区| 亚洲欧洲精品一区二区三区波多野1战4| 欧美二区不卡| 国产一级一区二区| 午夜精品在线| 亚洲一区二区精品在线| 久久精品中文字幕免费mv| 红桃视频国产精品| 亚洲女人av| 亚洲精品久久久久久久久| 久久久精品国产免费观看同学| 亚洲日本一区二区三区| 国产一区二区三区四区三区四 | 久久久久看片| 在线观看91精品国产入口| 亚洲精品小视频| 伊人精品久久久久7777| 亚洲专区国产精品| 日韩一区二区免费高清| 狂野欧美激情性xxxx| 久久精品卡一| 国产日产欧美精品| 久久久美女艺术照精彩视频福利播放| 亚洲欧美日本在线| 好吊成人免视频| 欧美福利在线观看| 午夜日韩av| 亚洲三级影片| 91久久线看在观草草青青| 久久蜜桃av一区精品变态类天堂| 久久人人爽人人爽爽久久| 国产精品影音先锋| 免费不卡在线观看| 在线亚洲免费| 亚洲人成网站精品片在线观看 | 亚洲电影免费观看高清完整版| 国产精品久久久久久av下载红粉 | 久久久999国产| 欧美日韩99| 亚洲欧美日韩中文视频| 欧美系列精品| 91久久久久| 在线亚洲免费视频| 国产在线观看91精品一区| 久久男人资源视频| 日韩小视频在线观看| 免费观看在线综合| 一区二区三区回区在观看免费视频| 久久久亚洲国产天美传媒修理工| 一本色道久久加勒比88综合| 你懂的亚洲视频| 欧美一区二区三区视频在线 | 蜜乳av另类精品一区二区| 久久国产主播精品| 亚洲一本大道在线| 在线综合亚洲欧美在线视频| 国产日韩在线不卡| 国产精品国产三级欧美二区 | 国产亚洲在线| 欧美.www| 久久精品在线观看| 男女精品视频| 国产精品久久久久91| 欧美日韩午夜在线| 欧美日韩精品免费观看视频完整| 亚洲欧美在线网| 午夜精品网站| 久久婷婷久久| 久久久水蜜桃av免费网站| 久久国产精品一区二区| 午夜精品久久久久久| 一区二区三区精品在线| 亚洲国产精品一区制服丝袜 | 亚洲国产另类精品专区| 国产专区欧美专区| 激情欧美一区二区三区在线观看| 国产精品一二| 影音先锋久久久| 亚洲资源av| 久久精品国产清自在天天线| 欧美一区二区视频在线| 先锋a资源在线看亚洲| 久久成人亚洲| 亚洲国产婷婷香蕉久久久久久99| 一本色道久久综合亚洲精品小说 | 免费观看日韩| 久久久久国色av免费看影院| 午夜电影亚洲| 欧美aa国产视频| 在线亚洲高清视频| 久久国产色av| 免费成人性网站| 日韩视频免费大全中文字幕| 欧美在线免费视频| 国产精品天天看| 亚洲国产精品一区二区尤物区| 日韩天天综合| 亚洲欧洲一区二区在线播放| 欧美诱惑福利视频| 国产日韩av高清| 性视频1819p久久| 欧美国产日本高清在线| 欧美一区精品| 国产日韩三区| 亚洲黄网站在线观看| 久久精品久久99精品久久| 日韩一级精品| 欧美一级日韩一级| 久久九九久久九九| 香蕉久久国产| 国产女人水真多18毛片18精品视频| 亚洲第一天堂av| 小嫩嫩精品导航| 欧美亚洲午夜视频在线观看| 国产精品swag| 久久视频这里只有精品| 亚洲欧美综合v| 国产亚洲欧美另类中文| 另类av导航| 狼人社综合社区| 亚洲综合精品四区| 欧美一区二区视频免费观看| 精品不卡一区二区三区| 欧美激情在线免费观看| 久久影院午夜论| 亚洲私人影院| 麻豆视频一区二区| 亚洲制服少妇| 久久亚洲春色中文字幕| 亚洲国内高清视频| 亚洲欧美国产另类| 一区二区日韩| 欧美不卡高清| 欧美成人激情视频| 欧美三级第一页| 亚洲欧洲精品一区二区| 国产精品一区二区久久精品|