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

天行健 君子當自強而不息

Getting Online with Multiplayer Gaming(13)

 

cApp::remove_player

Just as players join the game, so do players quit, and that’s the purpose of the
remove_player function. In the remove_player function, the server will scan the list of
connected players for a match of a DirectPlay identification number (from the disconnecting
player) and remove that player from the list. After the scan is complete
and the appropriate player is removed from the list, all clients are notified of the
disconnecting player, and the server rebuilds a list of existing players.

void cApp::remove_player(const sMsg* msg)
{
    
// search for player in list
    for(long i = 0; i < MAX_PLAYERS; i++)
    {
        
if(m_players[i].player_id == msg->header.player_id && m_players[i].connected)
        {
            m_players[i].connected = 
false;

            
// send remove player message to all players

            sDestroyPlayerMsg destroy_msg;

            destroy_msg.header.type      = MSG_DESTROY_PLAYER;
            destroy_msg.header.size      = 
sizeof(sDestroyPlayerMsg);
            destroy_msg.header.player_id = msg->header.player_id;

            send_network_msg(&destroy_msg, DPNSEND_NOLOOPBACK, ALL_CLIENT_PLAYERS);

            m_connected_player_num--;
            list_players();

            
break;
        }
    }
}
 

cApp::send_player_info

Unfortunately, in network gaming, game messages sometimes get lost along the
way. What if one of those lost messages intended to inform the client application
that a player had joined the game? Furthermore, what if the client started receiving
messages related to a player that the client didn’t know existed (because of a lost
message)?

In cases where the client has no knowledge of a player and is receiving messages
related to that player, the client will request the appropriate player’s data from the
server in order to continue. The server, in turn, will send the requested player’s
information to the client using the send_player_info function:

bool cApp::send_player_info(const sMsg* msg, DPNID to)
{
    sRequestPlayerInfoMsg* request_msg = (sRequestPlayerInfoMsg*) msg;

    
for(long i = 0; i < MAX_PLAYERS; i++)
    {
        
// only send if found in list
        if(m_players[i].player_id == request_msg->request_player_id && m_players[i].connected)
        {
            
// send player infomation to requesting player

            sCreatePlayerMsg create_msg;

            create_msg.header.type      = MSG_SEND_PLAYER_INFO;
            create_msg.header.size      = 
sizeof(sCreatePlayerMsg);
            create_msg.header.player_id = request_msg->request_player_id;
            create_msg.x_pos            = m_players[i].x_pos;
            create_msg.y_pos            = m_players[i].y_pos;
            create_msg.z_pos            = m_players[i].z_pos;
            create_msg.direction        = m_players[i].direction;

            send_network_msg(&create_msg, DPNSEND_NOLOOPBACK, to);

            
break;
        }
    }

    
return true;
}
 

cApp::player_state_change

The major message-processing function in the server must be player_state_change,
which takes incoming actions from the clients and updates the internal player data.

bool cApp::player_state_change(const sMsg* msg)
{
    
// get player index in list
    long player_index = -1;
    
    
for(long i = 0; i < MAX_PLAYERS; i++)
    {
        
if(m_players[i].player_id == msg->header.player_id && m_players[i].connected)
        {
            player_index = i;
            
break;
        }
    }

    
if(player_index == -1)
        
return false;

    sPlayer* player = &m_players[player_index];

    
bool allow_change = true;
    
    
// refuse to update player if swinging sword or hurt
    if(player->last_state == STATE_SWING || player->last_state == STATE_HURT)
        allow_change = 
false;    

    
// only change state if allowed
    if(! allow_change)
        
return false;

    sStateChangeMsg* change_msg = (sStateChangeMsg*) msg;

    
// update selected player
    player->last_update_time = timeGetTime();
    player->last_state       = change_msg->state;
    player->direction        = change_msg->direction;

    
// adjust action time based on latency
    player->last_update_time -= player->latency;

    sStateChangeMsg state_msg;

    
// send player data to all clients
    state_msg.header.type      = MSG_STATE_CHANGE;
    state_msg.header.size      = 
sizeof(sStateChangeMsg);
    state_msg.header.player_id = change_msg->header.player_id;
    state_msg.state            = player->last_state;
    state_msg.x_pos            = player->x_pos;
    state_msg.y_pos            = player->y_pos;
    state_msg.z_pos            = player->z_pos;
    state_msg.direction        = player->direction;
    state_msg.speed            = player->speed;

    send_network_msg(&state_msg, DPNSEND_NOLOOPBACK, ALL_CLIENT_PLAYERS);

    
if(change_msg->state != STATE_SWING)
        
return true;

    
// If swinging sword, determing who is hurt, check all players.
    for(long i = 0; i < MAX_PLAYERS; i++)
    {
        
// only check against other players that are connected
        if(i == player_index || !m_players[i].connected)
            
continue;

        
// get distance to player
        float x_diff = fabs(player->x_pos - m_players[i].x_pos);
        
float z_diff = fabs(player->z_pos - m_players[i].z_pos);
        
float dist   = x_diff * x_diff + z_diff * z_diff;

        
// continue if distance between players acceptable
        if(dist >= 10000.0f)
            
continue;

        
// get angle between players
        float angle = -atan2(m_players[i].z_pos - player->z_pos, m_players[i].x_pos - player->x_pos) + 1.570796f;

        angle -= player->direction;     
// adjust for attacker's direction
        angle += 0.785f;                // adjust for FOV

        // bounds angle value
        if(angle < 0.0f)        angle += 6.28f;
        
if(angle >= 6.28f)      angle -= 6.28f;

        
// player hit if in front of attacker (90 FOV)
        if(angle >= 0.0f && angle <= 1.570796f && m_players[i].last_state != STATE_HURT)
        {
            m_players[i].last_state = STATE_HURT;
            m_players[i].last_update_time = timeGetTime();

            
// send network message
            state_msg.header.type      = MSG_STATE_CHANGE;
            state_msg.header.size      = 
sizeof(sStateChangeMsg);
            state_msg.header.player_id = m_players[i].player_id;
            state_msg.state            = m_players[i].last_state;
            state_msg.x_pos            = m_players[i].x_pos;
            state_msg.y_pos            = m_players[i].y_pos;
            state_msg.z_pos            = m_players[i].z_pos;
            state_msg.direction        = m_players[i].direction;
            state_msg.speed            = m_players[i].speed;

            send_network_msg(&state_msg, DPNSEND_NOLOOPBACK, ALL_CLIENT_PLAYERS);
        }
    }

    
return true;
}

Up to this point, the server has looked for the player that uses the state-change
message. If a message is coming from a player who is not connected, the message
is ignored. From now on, the game’s logic takes over.

Players are allowed to walk, stand still, or swing their weapons. Players whose states
are already set as swinging their weapons or being hurt are not allowed to update
their states (until those states are cleared).

Now the player’s state is updated (if allowed) and sent out to all other connected
players. Next, if the player has swung his weapon, all players are scanned to see
whether the attacker hit them. If so, the states of those hurt are changed to HURT.

Also, notice that I offset the state’s time variable (sPlayer::last_update_time) by the player’s
latency value (sPlayer::latency). This adjusts for network transmission delays and
improves synchronization. If you remove the latency offset, you’ll see a jumping
effect when players are moving around the level.

Note that players who are swinging their swords have a chance to hit the players in
front of them. To check whether another player was hit during an attack, you first
perform a distance calculation, and if any characters are considered close enough,
the angles between the players are checked. If the players being attacked are within
a 90-degree field of view in front of the attackers (as illustrated in Figure 19.14),
they are considered hit, at which point, those victims’ states are changed to HURT.

And that’s it for dealing with the game messages and state changes in players.
Although the player_state_change function is responsible for parsing the queued game
messages, it’s really up to another function to move players and clear their swinging
or hurt states, as you see in the following section.

posted on 2007-12-18 22:39 lovedday 閱讀(241) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導航

統計

常用鏈接

隨筆分類(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>
            国产手机视频精品| 久久亚洲欧美| 国产精品久久久久aaaa九色| 欧美3dxxxxhd| 欧美黄色影院| 欧美剧在线免费观看网站| 欧美精品黄色| 欧美日韩喷水| 国产精品网站视频| 黑人巨大精品欧美一区二区小视频 | 国产精品99一区| 国产精品v欧美精品v日韩 | 欧美日韩精品免费观看视频完整| 欧美日韩在线亚洲一区蜜芽| 国产精品视频成人| 亚洲福利视频一区| 亚洲视频精选| 久久精品盗摄| 亚洲高清视频的网址| 一区二区三区久久| 久久久久久国产精品mv| 欧美日韩成人在线视频| 国产视频欧美视频| 99视频日韩| 久久青青草原一区二区| 亚洲精品乱码久久久久久日本蜜臀| 亚洲一区二区三区乱码aⅴ蜜桃女| 久久精品99国产精品| 欧美另类videos死尸| 国产一区二区三区在线观看免费视频| 在线国产精品一区| 亚洲综合色噜噜狠狠| 欧美jizzhd精品欧美巨大免费| 99国产一区| 久久综合伊人77777蜜臀| 国产精品sm| 亚洲精品网站在线播放gif| 亚洲欧美日本在线| 91久久精品日日躁夜夜躁国产| 亚洲欧美日韩成人| 欧美日韩成人精品| 亚洲精品1区2区| 亚洲激情第一页| 久久九九国产精品怡红院| 亚洲乱码国产乱码精品精98午夜| 久久久av水蜜桃| 国产精品羞羞答答xxdd| 夜夜夜久久久| 最新国产成人在线观看| 久久伊人亚洲| 国产一区二区日韩| 欧美高清免费| 久久久久**毛片大全| 一区电影在线观看| 欧美人在线观看| 亚洲精品国偷自产在线99热| 久热国产精品| 久久久国产精品一区二区中文 | 亚洲最新中文字幕| 欧美gay视频激情| 久久久久久久一区| 国产在线拍偷自揄拍精品| 午夜精品成人在线视频| 日韩亚洲欧美成人一区| 欧美日韩国产色站一区二区三区| 亚洲日本免费| 亚洲国产精品一区制服丝袜| 久久天天躁狠狠躁夜夜爽蜜月| 国产在线一区二区三区四区 | 国产欧美日本在线| 午夜精品影院| 午夜日韩激情| 国产自产高清不卡| 欧美jizzhd精品欧美巨大免费| 久久国产精品网站| 在线日韩中文字幕| 欧美国产日韩精品免费观看| 亚洲欧美日韩在线高清直播| 欧美一区二区黄色| 一色屋精品视频在线看| 久久人人爽人人爽| 久久久综合网站| 久久午夜影视| 欧美在线视频一区二区三区| 国产午夜精品视频| 欧美在线综合视频| 午夜一区二区三区在线观看| 国产美女精品一区二区三区 | 国产伦精品一区二区三区视频孕妇 | 夜夜嗨av一区二区三区四季av | 国产一区二区三区久久悠悠色av | 欧美一区二区精美| 国产伦精品一区二区三区照片91| 亚洲男女自偷自拍| 在线性视频日韩欧美| 欧美影院在线| 狂野欧美一区| 国产欧美日韩在线| 嫩草成人www欧美| 久久最新视频| 99视频精品| 亚洲综合精品四区| 狠狠色丁香婷婷综合| 亚洲福利专区| 国产精品久久久久免费a∨ | 在线成人激情黄色| 亚洲精品欧美日韩| 欧美日韩综合精品| 亚洲看片免费| 欧美中文在线观看| 亚洲精品午夜| 亚洲永久字幕| 亚洲国产精品一区二区第四页av| 亚洲欧洲日夜超级视频| 国产精品视频午夜| 欧美/亚洲一区| 国产精品观看| 欧美激情精品久久久| 欧美日韩国产美女| 久热精品视频在线| 欧美系列精品| 欧美sm视频| 国产乱子伦一区二区三区国色天香| 亚洲日本中文| 国产一区二区黄色| 亚洲国产精品久久久久婷婷884| 国产精品午夜春色av| 欧美国产日韩一区二区| 国产欧美日韩三区| 日韩午夜电影在线观看| 国产精品xxxav免费视频| 欧美一区三区二区在线观看| 你懂的视频一区二区| 欧美一区二区三区免费观看 | 亚洲欧美在线网| 欧美va亚洲va香蕉在线| 亚洲免费在线观看| 欧美国产一区视频在线观看| 亚洲精品麻豆| 久久精品国产免费看久久精品| 国产日韩欧美| 韩日欧美一区| 99re6这里只有精品视频在线观看| 国产九区一区在线| 最新亚洲一区| 亚洲国产精品久久久久婷婷884| 亚洲视频一二| 亚洲国产成人av| 欧美激情亚洲一区| 欧美激情一区二区三区蜜桃视频 | 亚洲大片在线观看| 午夜日本精品| 久久亚洲精品一区| 午夜精品久久久久久久久久久久| 欧美在线地址| 亚洲精品网站在线播放gif| 美女精品网站| 麻豆精品网站| 国内偷自视频区视频综合| 亚洲影院免费| 久久精品91| 狠狠色丁香久久综合频道 | 国产欧美精品一区二区三区介绍 | 亚洲一二区在线| 国产精品女人久久久久久| 欧美成人在线免费观看| 国产精品成人va在线观看| 亚洲激情小视频| 国产精品久久久久久久久久久久久久| 亚洲精品欧美激情| 99v久久综合狠狠综合久久| 欧美精品在线极品| 99精品欧美一区二区蜜桃免费| 99视频精品在线| 欧美午夜精品久久久久久孕妇| 中文av字幕一区| 久久精品国产亚洲一区二区| 亚洲精品一区二区三区四区高清 | 狼人社综合社区| 国产精品福利网站| 欧美中文字幕第一页| 欧美成人精品1314www| 99国内精品久久久久久久软件| 欧美日韩视频在线观看一区二区三区| 一区二区欧美在线| 久久国产手机看片| 一色屋精品视频在线看| 欧美大胆a视频| 一本色道久久综合狠狠躁篇的优点 | 久久精品午夜| 亚洲精品麻豆| 欧美一区二区三区在线播放| 日韩视频永久免费观看| 亚洲一级在线观看| 国产女主播一区二区三区| 欧美一级专区| 亚洲乱码日产精品bd| 日韩午夜高潮| 91久久久久| 国产一区二区三区久久悠悠色av |