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

天行健 君子當自強而不息

Getting Online with Multiplayer Gaming(14)

 

Updating Players

In order to synchronize itself with clients, the server needs to maintain a simplified
version of the game running internally. This version of the game doesn’t include
graphics, sound, or any other fancy features; it only needs to track player’s actions.

The server tracks those actions by updating the player’s actions every 33ms (just as
the client application will do). Those actions include walking and waiting for other
specific states to clear (such as sword swinging and being hurt).

The cApp::update_players function is responsible for updating all players:

void cApp::update_players()
{
    sStateChangeMsg change_msg;

    
// loop through all players
    for(int i = 0; i < MAX_PLAYERS; i++)
    {
        
// only update connected players
        if(! m_players[i].connected)
            
continue;

        
long elapsed = timeGetTime() - m_players[i].last_update_time;

        
if(m_players[i].last_state == STATE_MOVE)
        {
            
// calculate amount of movement by time passed
            float speed  = elapsed / 1000.0f * m_players[i].speed;
            
float x_move = sin(m_players[i].direction) * speed;
            
float z_move = cos(m_players[i].direction) * speed;

            
// check for movement collision - can not walk past anything blocking path
            if(check_intersect(&m_level_mesh,
                m_players[i].x_pos,          m_players[i].y_pos + 16.0f, m_players[i].z_pos,
                m_players[i].x_pos + x_move, m_players[i].y_pos + 16.0f, m_players[i].z_pos + z_move))
            {
                x_move = z_move = 0.0f;
            }

            
// update player coordinates
            m_players[i].x_pos += x_move;
            m_players[i].y_pos  = 0.0f;     
// stay on ground
            m_players[i].z_pos += z_move;

            m_players[i].last_update_time = timeGetTime();
        }
        
else if(m_players[i].last_state == STATE_SWING && elapsed > 1000)   // clear swing status after 1 second
        {
            m_players[i].last_state = STATE_IDLE;

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

            send_network_msg(&change_msg, DPNSEND_NOLOOPBACK, ALL_CLIENT_PLAYERS);
        }
        
else if(m_players[i].last_state == STATE_HURT && elapsed > 1000)    // clear hurt status after 1 second
        {
            m_players[i].last_state = STATE_IDLE;

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

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

As the server scans the list of players, it determines which players are connected
and calculates the time since the last server update for all connected players. Next,
if a player’s state is set to STATE_MOVE, the elapsed time is used to move the player.

Next, the server deals with the STATE_SWING and STATE_HURT states. Those states are
cleared only after one second has passed (as determined by the elapsed time).

Surprisingly, that’s it for cApp::update_players! Remember that the update_players function
is called every 33ms, so keeping the function quick and to the point is crucial.
Once all players are updated, you need to notify other players.

 

Updating the Network Clients

Throughout earlier sections in this chapter, I mentioned periodic server updates
that are sent to the client in order to synchronize game-play. That’s the purpose of
the cApp::update_network function. The update_network function is quick and to the
point, sending out the current state of all connected clients every 100ms.

void cApp::update_network()
{
    
// send all player updates
    for(long i = 0; i < MAX_PLAYERS; i++)
    {
        
if(m_players[i].connected)  // only send data about connected players
        {
            sStateChangeMsg change_msg;

            change_msg.header.type      = MSG_STATE_CHANGE;
            change_msg.header.size      = 
sizeof(sStateChangeMsg);
            change_msg.header.player_id = m_players[i].player_id;
            change_msg.x_pos            = m_players[i].x_pos;
            change_msg.y_pos            = m_players[i].y_pos;
            change_msg.z_pos            = m_players[i].z_pos;
            change_msg.direction        = m_players[i].direction;
            change_msg.speed            = m_players[i].speed;
            change_msg.state            = m_players[i].last_state;
            change_msg.latency          = m_players[i].latency;

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

 

Calculating Latency

The server periodically calculates the time it takes a message to be received from a
client and uses the latency in the timed calculations to update clients, all of which
is crucial to maintaining the synchronization of the game. The function that calculates
the latency is update_latency, and it is called every 10 seconds from the main
application loop (cApp::frame).

void cApp::update_latency()
{
    
// go through all players
    for(long i = 0; i < MAX_PLAYERS; i++)
    {
        
if(m_players[i].connected)  // only process connected players
        {
            DPN_CONNECTION_INFO connect_info;

            
// request player connection settings
            if(SUCCEEDED(m_server.get_server()->GetConnectionInfo(m_players[i].player_id, &connect_info, 0)))
            {
                m_players[i].latency = connect_info.dwRoundTripLatencyMS / 2;

                
// bounds latency to 1 second
                if(m_players[i].latency > 1000)
                    m_players[i].latency = 1000;
            }
            
else
                m_players[i].latency = 0;
        }
    }
}

To calculate the latency, the server queries DirectPlay for the connection statistics
via the IDirectPlay8Server::GetConnectInfo function. That function call takes a structure
(DPN_CONNECTION_INFO) as an argument, and inside the structure is a variable that
represents the roundtrip latency time in milliseconds. The server divides that
latency value in half and stores it in each player’s data structure.

 

Other function:

int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{
    
const char* class_name = "ServerClass";

    WNDCLASSEX win_class;

    
// create window class and register it

    win_class.cbSize        = 
sizeof(win_class);
    win_class.style         = CS_CLASSDC;
    win_class.lpfnWndProc   = window_proc;
    win_class.cbClsExtra    = 0;
    win_class.cbWndExtra    = 0;
    win_class.hInstance     = inst;
    win_class.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    win_class.hCursor       = LoadCursor(NULL, IDC_ARROW);
    win_class.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);;
    win_class.lpszMenuName  = NULL;
    win_class.lpszClassName = class_name;
    win_class.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    
if(! RegisterClassEx(&win_class))
        
return false;

    DWORD style = WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;

    DWORD pos_x = (get_screen_width()  - CLIENT_WIDTH) / 2;
    DWORD pos_y = (get_screen_height() - CLIENT_HEIGHT) / 4;
    
    g_hwnd = CreateWindow(class_name, "Network Server Demo", style, pos_x, pos_y, 
                          CLIENT_WIDTH, CLIENT_HEIGHT, NULL, NULL, inst, NULL);

    
if(g_hwnd == NULL)
        
return -1;

    ShowWindow(g_hwnd, SW_NORMAL);
    UpdateWindow(g_hwnd);

    resize_window(g_hwnd, CLIENT_WIDTH, CLIENT_HEIGHT);

    cApp app;
    app.run();

    
return 0;
}

///////////////////////////////////////////////////////////////////////////////////////

BOOL CALLBACK config_dlg_proc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
    
static HWND adapter_wnd;

    
switch(msg)
    {
    
case WM_INITDIALOG:
        adapter_wnd = GetDlgItem(dlg, IDC_ADAPTERS);

        
// add adapter names to list
        for(long i = 0; i < g_adapter->get_num_adapters(); i++)
        {
            
char text[256];
            g_adapter->get_name(i, text);

            insert_string_to_combo(adapter_wnd, i, text);
        }

        
// select first adapter in list
        set_combo_cur_sel(adapter_wnd, 0);

        
return TRUE;

    
case WM_COMMAND:
        
switch(LOWORD(wParam))
        {
        
case IDC_OK:
            {
            
int sel = (int) get_combo_cur_sel(adapter_wnd);  

            
// make sure an adapter was selected
            if(sel == LB_ERR)
                
break;

            g_app->set_adapter_guid(g_adapter->get_guid(sel));

            EndDialog(dlg, TRUE);
            
return TRUE;
            }

        
case IDC_CANCEL:
            EndDialog(dlg, FALSE);
            
return TRUE;
        }
    }

    
return FALSE;
}

///////////////////////////////////////////////////////////////////////////////////////

bool cApp::init()
{
    
// select a network adapter to use (or quit if selected)
    if(! select_adapter())
        
return false;

    setup_app_window();

    
// intialize the game, set display mode, load level mesh.
    if(! init_game())
    {
        show_error_msg(
false, "Unable to initialize game.");
        
return false;
    }

    
// begin hosting the game session
    if(! host_game())
    {
        show_error_msg(
false, "Unable to host network server.");
        
return false;
    }

    
return true;
}

///////////////////////////////////////////////////////////////////////////////////////

bool cApp::frame()
{
    
static DWORD player_counter  = timeGetTime();
    
static DWORD network_counter = timeGetTime();
    
static DWORD latency_counter = timeGetTime();

    process_queue_msg();

    
// update players every 33ms (30 times a second)
    if(timeGetTime() > player_counter + 33)
    {
        update_players();
        player_counter = timeGetTime();
    }
    
    
// send out network update every 100ms (10 times a second)
    if(timeGetTime() > network_counter + 100)
    {
        update_network();
        network_counter = timeGetTime();
    }

    
// update player latency values every 10 seconds
    if(timeGetTime() > latency_counter + 10000)
    {
        update_latency();
        latency_counter = timeGetTime();
    }

    
return true;
}

///////////////////////////////////////////////////////////////////////////////////////

void cApp::shutdown()
{
    delete[] m_msgs;
    m_msgs = NULL;

    delete[] m_players;
    m_players = NULL;

    DeleteCriticalSection(&m_msg_cs);
}
    
///////////////////////////////////////////////////////////////////////////////////////

bool cApp::select_adapter()
{
    ShowWindow(g_hwnd, SW_HIDE);    
// hide main window
    m_adapter.init();

    
return (bool) DialogBox(get_window_inst(), MAKEINTRESOURCE(IDD_CONFIG), g_hwnd, config_dlg_proc);
}

///////////////////////////////////////////////////////////////////////////////////////

void cApp::setup_app_window()
{
    
// window to hold host IP address
    m_controls[CONTROL_SERVER_IP] = CreateWindow("STATIC", "", WS_CHILD | WS_VISIBLE, 4, 4, 312, 18,
                                                 g_hwnd, NULL, get_window_inst(), NULL);

    
// window to hold number of connected players
    m_controls[CONTROL_PLAYER_NUM] = CreateWindow("STATIC", "No Connected Players",  WS_CHILD | WS_VISIBLE,
                                                  4, 26, 312, 18, g_hwnd, NULL, get_window_inst(), NULL);

    
// list box to display connect player's names
    m_controls[CONTROL_PLAYER_LIST] = CreateWindow("LISTBOX", "", WS_CHILD | WS_BORDER | WS_VSCROLL | WS_VISIBLE,
                                                   4, 48, 312, 154, g_hwnd, NULL, get_window_inst(), NULL);

    
// show main window
    ShowWindow(g_hwnd, SW_SHOW);
}

///////////////////////////////////////////////////////////////////////////////////////

bool cApp::init_game()
{
    create_display(g_hwnd, CLIENT_WIDTH, CLIENT_HEIGHT, 16, 
truetrue);

    
// load the level mesh for collision checking
    if(! m_level_mesh.load("..\\Data\\ArenaCM.x", "..\\Data\\"))
        
return false;

    m_msgs = 
new sMsg[MAX_MESSAGES];
    m_msg_head = m_msg_tail = 0;

    m_players = 
new sPlayer[MAX_PLAYERS];
    m_connected_player_num = 0;

    
return true;
}

///////////////////////////////////////////////////////////////////////////////////////

bool cApp::host_game()
{
    
// configure server and begin hosting

    m_server.init();

    
if(! m_server.host(m_adapter_guid, 9123, "RPGGAME", NULL, MAX_PLAYERS))
        
return false;

    
char text[33], ip[16];

    
// get server ip address and display in application window
    m_server.get_ip(ip, 0);
    sprintf(text, "Host IP Address: %s", ip);
    SetWindowText(m_controls[CONTROL_SERVER_IP], text);

    
return true;
}

download source and solution

posted on 2007-12-18 23:20 lovedday 閱讀(217) 評論(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>
            亚洲久久一区| 欧美激情中文字幕在线| 欧美伊人久久久久久午夜久久久久 | 国产精品福利影院| 国产亚洲欧美激情| 国产精品综合| 91久久精品国产91性色| 麻豆久久精品| 99视频一区二区三区| 91久久国产综合久久| 噜噜噜噜噜久久久久久91 | 欧美日韩亚洲一区三区| 欧美黄色一区| 欧美亚男人的天堂| 国产免费成人av| 免费成人毛片| 久热精品在线视频| 亚洲精品少妇| 欧美一区影院| 欧美欧美午夜aⅴ在线观看| 欧美日韩精品欧美日韩精品| 国产精品久久久免费| 激情亚洲成人| 亚洲黄色性网站| 另类亚洲自拍| 美女网站久久| 一区二区三区日韩欧美精品| 欧美日本三级| 亚洲字幕一区二区| 欧美第一黄色网| 韩国一区电影| 欧美久久久久久久| 国产乱码精品一区二区三区忘忧草 | 精久久久久久久久久久| 狠狠色综合一区二区| 亚洲免费人成在线视频观看| 久久精品国产清高在天天线 | 亚洲精品久久久蜜桃| 一本久久a久久免费精品不卡| 欧美中文字幕在线播放| 亚洲黄色成人网| 久久亚洲一区二区三区四区| 国产精品视频福利| 中文av字幕一区| 亚洲三级毛片| 欧美日韩国产成人| 亚洲天堂免费观看| 亚洲欧洲在线视频| 欧美日韩国产一区二区三区地区| 国产亚洲一区二区精品| 久久成人一区二区| 午夜在线视频一区二区区别| 国产精品久久99| 久久动漫亚洲| 久久免费观看视频| 好看的av在线不卡观看| 久久成人18免费网站| 亚洲精品三级| 欧美在线观看视频在线| 亚洲精品1区2区| 欧美国产精品日韩| 亚洲电影欧美电影有声小说| 久久精品国产亚洲精品 | 激情久久久久| 亚洲国产日韩在线一区模特| 欧美va天堂va视频va在线| 亚洲日本中文| 一个色综合导航| 国产美女精品| 欧美高清视频免费观看| 欧美高清视频在线| 亚洲免费激情| 亚洲欧美成人一区二区三区| 国内外成人免费激情在线视频网站| 欧美一区二区三区四区在线观看 | 欧美日韩一视频区二区| 亚洲免费视频网站| 久久成人资源| 99精品免费视频| 久久精品国产欧美亚洲人人爽 | 老鸭窝亚洲一区二区三区| 久久久综合网站| 亚洲精品一区二区在线观看| 一区二区三区视频在线看| 禁久久精品乱码| 久久爱www久久做| 亚洲在线中文字幕| 欧美人与性动交α欧美精品济南到| 欧美日韩精品在线| 久久一区亚洲| 国产综合视频在线观看| 亚洲无亚洲人成网站77777| 1769国内精品视频在线播放| 欧美/亚洲一区| 欧美一级久久| 在线观看日韩| 欧美激情久久久| 午夜伦理片一区| 国产在线麻豆精品观看| 欧美三级午夜理伦三级中文幕 | 国产精品高精视频免费| 午夜精品福利视频| 久久先锋影音| 亚洲色图自拍| 亚洲国产美国国产综合一区二区| 亚洲欧美经典视频| 亚洲精品中文字| 国产精品影片在线观看| 久久国产精品99久久久久久老狼| 亚洲激情婷婷| 99综合精品| 国产视频在线一区二区| 国产精品久久久久91| 欧美日韩 国产精品| 欧美精品麻豆| 亚洲人www| 亚洲精品四区| 亚洲免费成人av电影| 日韩一级免费观看| 亚洲天堂激情| 久久亚洲影院| 亚洲国产婷婷综合在线精品| 亚洲电影毛片| 欧美综合激情网| 一区二区日韩伦理片| 中国av一区| 在线亚洲电影| 亚洲午夜三级在线| 欧美在线播放高清精品| 亚洲宅男天堂在线观看无病毒| 日韩一级不卡| 午夜欧美不卡精品aaaaa| 尤物99国产成人精品视频| 国产亚洲福利一区| 精品999日本| 亚洲天堂成人| 欧美诱惑福利视频| 猛男gaygay欧美视频| 中文日韩在线视频| 亚洲精品国产精品国自产观看浪潮 | 在线观看视频欧美| 在线成人h网| 一本大道av伊人久久综合| 在线免费观看日本一区| 99精品黄色片免费大全| 日韩视频中文| 亚洲免费一区二区| 欧美福利视频在线| 欧美网站在线观看| 欧美日韩福利| 国产丝袜美腿一区二区三区| 亚洲一区二区三区精品在线| 久久亚洲精选| 亚洲综合精品| 免费日韩av电影| 韩日欧美一区| 黑人中文字幕一区二区三区| 亚洲一本视频| 亚洲国产aⅴ天堂久久| 亚洲无限av看| 国产乱码精品一区二区三区av| 亚洲一区二区在线免费观看视频| 99天天综合性| 在线观看的日韩av| 一区二区三区蜜桃网| 精品999久久久| 亚洲自拍偷拍一区| 欧美成人精品在线观看| 亚洲欧洲日韩女同| 亚洲国产合集| 欧美色另类天堂2015| 91久久久久久| 欧美亚洲一区二区在线| 久久天天躁狠狠躁夜夜爽蜜月| 国产综合久久| 亚洲国产精品一区二区www| 中日韩高清电影网| 在线视频欧美日韩| 国产精品电影在线观看| 久久这里有精品15一区二区三区| 91久久久久久久久| 欧美激情五月| 小处雏高清一区二区三区| 亚洲自拍偷拍麻豆| 日韩视频在线一区二区三区| 亚洲国产精品视频| 亚洲电影免费| 91久久精品视频| 亚洲乱码国产乱码精品精天堂| 欧美视频精品在线| 亚洲一区二区三区久久| 欧美成人性生活| 美乳少妇欧美精品| 黑人巨大精品欧美黑白配亚洲 | 欧美激情亚洲视频| 欧美激情一区二区三区全黄 | 亚洲欧洲视频| 亚洲深夜福利视频| 一区二区三区四区五区精品| 欧美在线播放一区|