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

天行健 君子當自強而不息

Getting Online with Multiplayer Gaming(19)

 

Updating All Players

Whereas the local player’s input is processed in the cApp::frame function, the
update_players (which you saw in the code in the previous section) processes the
players according to their respective states.

Unlike the server's update_players function, the client's update_players function is simple.
The client is allowed to move players based only on their last known positions,
directions, and elapsed time since their last update.

Remember, only the server can clear the weapon-swinging and being-hurt states, so
the client has nothing to do at this point except update the various animations to
show the player what is going on:

void cApp::update_players()
{
    
// process all active player movements
    for(long i = 0; i < MAX_PLAYERS; i++)
    {
        
if(! m_players[i].connected)
            
continue;

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

        
if(m_players[i].last_state == STATE_MOVE)
        {
            
// process player movement state

            
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 collisions - can not walk past anything blocking path
            if(m_nodetree_mesh.is_ray_intersect(
                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,
                NULL))
            {
                x_move = z_move = 0.0f;
            }

            
// update coordinates

            EnterCriticalSection(&m_update_cs);

            m_players[i].x_pos += x_move;
            m_players[i].y_pos  = 0.0f;
            m_players[i].z_pos += z_move;

            m_players[i].last_update_time = timeGetTime();  
// reset time

            
if(m_players[i].last_anim != ANIM_WALK)
            {
                m_players[i].last_anim = ANIM_WALK;
                m_players[i].body.set_anim_set(&m_char_anim, "Walk", timeGetTime()/32);
            }

            LeaveCriticalSection(&m_update_cs);
        }
        
else if(m_players[i].last_state == STATE_IDLE)
        {
            
// set new animations as needed

            
if(m_players[i].last_anim != ANIM_IDLE)
            {
                EnterCriticalSection(&m_update_cs);

                m_players[i].last_anim = ANIM_IDLE;
                m_players[i].body.set_anim_set(&m_char_anim, "Idle", timeGetTime()/32);

                LeaveCriticalSection(&m_update_cs);
            }
        }
        
else if(m_players[i].last_state == STATE_SWING)
        {
            
if(m_players[i].last_anim != ANIM_SWING)
            {
                EnterCriticalSection(&m_update_cs);

                m_players[i].last_anim = ANIM_SWING;
                m_players[i].body.set_anim_set(&m_char_anim, "Swing", timeGetTime()/32);

                LeaveCriticalSection(&m_update_cs);
            }
        }
        
else if(m_players[i].last_state == STATE_HURT)
        {
            
if(m_players[i].last_anim != ANIM_HURT)
            {
                EnterCriticalSection(&m_update_cs);

                m_players[i].last_anim = ANIM_HURT;
                m_players[i].body.set_anim_set(&m_char_anim, "Hurt", timeGetTime()/32);

                LeaveCriticalSection(&m_update_cs);
            }
        }
    }
}

Character animations are updated only if they differ from the last known animation.
The sPlayer::last_anim variable tracks the last known animation, although the
various ANIM_* macros define which animations to play.

 

Other Function:

int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{        
    DWORD pos_x = (get_screen_width()  - CLIENT_WIDTH) / 2;
    DWORD pos_y = (get_screen_height() - CLIENT_HEIGHT) / 4;

    build_window(inst, "ClientClass", "Network Client Demo", 
                 WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
                 pos_x, pos_y, CLIENT_WIDTH, CLIENT_HEIGHT);
    
    cApp app;
    app.run();

    
return 0;
}

/****************************************************************************************************/

cApp::cApp()
{
    
// clear class data           
    m_adapter_guid   = NULL;    
    m_host_ip[0]     = '\0';
    m_player_name[0] = '\0';    
    m_players        = NULL;
    m_num_players    = 0;   
    m_cam_angle      = 0.0f;
    m_font           = NULL;

    
// set global pointer
    g_app     = this;
    g_adapter = &m_adapter;

    InitializeCriticalSection(&m_update_cs);
}

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

bool cApp::init()
{
    
if(! select_adapter())
        
return false;

    
if(! init_game())
    {
        show_error_msg(
false, "Unable to initialize game.");
        
return false;
    }

    
if(! join_game())
    {
        show_error_msg(
false, "Unable to connect to server.");
        
return false;
    }

    
return true;
}

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

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

    DeleteCriticalSection(&m_update_cs);
}

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

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

    m_adapter.init();

    
// do not continue if quit selected
    if(! DialogBox(get_window_inst(), MAKEINTRESOURCE(IDD_CONNECT), g_hwnd, connect_dialog_proc))
        
return false;

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

    
return true;
}

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

BOOL CALLBACK connect_dialog_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);

        
// clear fields
        SetWindowText(GetDlgItem(dlg, IDC_HOSTIP), "192.168.0.100");
        SetWindowText(GetDlgItem(dlg, IDC_NAME), "");

        
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;

            
char name[32], ip[16];

            
// make sure there is an ip entered
            GetWindowText(GetDlgItem(dlg, IDC_HOSTIP), ip, sizeof(ip));

            
if(ip[0] == '\0')   // ip is NULL
                break;

            
// make sure there is a name entered
            GetWindowText(GetDlgItem(dlg, IDC_NAME), name, sizeof(name));

            
if(name[0] == '\0') // name is NULL
                break;

            g_app->set_info(g_adapter->get_guid(sel), ip, name);

            EndDialog(dlg, TRUE);
            
return TRUE;
            }

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

    
return FALSE;
}

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

void cApp::set_info(GUID* adapter_guid, const char* host_ip, const char* player_name)
{
    m_adapter_guid = adapter_guid;

    strcpy(m_host_ip, host_ip);
    strcpy(m_player_name, player_name);
}

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

bool cApp::init_game()
{
    create_display(g_hwnd, CLIENT_WIDTH, CLIENT_HEIGHT, 16, 
truetrue);
    set_perspective(D3DX_PI/4, 1.3333f, 1.0f, 10000.0f);

    ShowCursor(FALSE);

    create_font(&m_font, "Arial", 16, 
truefalse);

    m_input.create(g_hwnd, get_window_inst());
    m_keyboard.create_keyboard(&m_input);
    m_mouse.create_mouse(&m_input, 
true);

    
if(! m_terrain_mesh.load("..\\Data\\Arena.x", "..\\Data\\"))
        
return false;

    m_nodetree_mesh.create(&m_terrain_mesh, QUADTREE, 256, 32);

    
// load the meshes and animations

    
if(! m_char_mesh.load("..\\Data\\Warrior.x", "..\\Data\\"))
        
return false;

    
if(! m_weapon_mesh.load("..\\Data\\Sword.x", "..\\Data\\"))
        
return false;

    
if(! m_char_anim.load("..\\Data\\Warrior.x", &m_char_mesh))
        
return false;

    m_char_anim.set_loop(
true,  "Walk");
    m_char_anim.set_loop(
true,  "Idle");
    m_char_anim.set_loop(
false, "Swing");
    m_char_anim.set_loop(
false, "Hurt");

    m_cam_angle = 0.0f;

    m_players = 
new sPlayer[MAX_PLAYERS];

    
// setup player data
    for(long i = 0; i < MAX_PLAYERS; i++)
    {
        m_players[i].body.create(&m_char_mesh);
        m_players[i].weapon.create(&m_weapon_mesh);
        m_players[i].weapon.attach_to_object(&m_players[i].body, "Bip01_R_Finger11");
        m_players[i].weapon.rotate(1.57f, 0.0f, 0.0f);
    }

    m_num_players = 1;

    
// setup local player structure
    m_players[0].connected  = true;
    m_players[0].direction  = 0.0f;
    m_players[0].x_pos      = 0.0f;
    m_players[0].y_pos      = 0.0f;
    m_players[0].z_pos      = 0.0f;
    m_players[0].speed      = 0.0f;
    m_players[0].last_state = STATE_IDLE;

    
return true;
}

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

bool cApp::join_game()
{
    
// initialize network and try to connect to host

    m_client.init();

    
return m_client.connect(m_adapter_guid, m_host_ip, 9123, m_player_name, "RPGGAME", NULL);
}

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

void cApp::render_scene()
{
    
// center camera on player using camera angle
    float x_eye = m_players[0].x_pos + cos(m_cam_angle) * 300.0f;
    
float y_eye = m_players[0].y_pos + 100.0f;
    
float z_eye = m_players[0].z_pos + sin(m_cam_angle) * 300.0f;

    m_camera.point(x_eye, y_eye, z_eye, m_players[0].x_pos, m_players[0].y_pos, m_players[0].z_pos);
    set_display_camera(&m_camera);

    cFrustum frustum;
    frustum.create(0.0f);

    clear_display(0, 1.0f);

    
if(begin_display_scene())
    {
        
// draw the terrain
        enable_zbuffer();
        m_nodetree_mesh.render(&frustum, 0.0f);

        
// draw all actiive and in view characters
        for(long i = 0; i < MAX_PLAYERS; i++)
        {
            
if(! m_players[i].connected)
                
continue;

            
float radius;
            m_players[i].body.get_bounds(NULL, NULL, NULL, NULL, NULL, NULL, &radius);

            
// bounds check if player in view
            if(frustum.is_sphere_in(m_players[i].x_pos, m_players[i].y_pos, m_players[i].z_pos, radius))
            {
                
// position character and rotate
                m_players[i].body.move(m_players[i].x_pos, m_players[i].y_pos, m_players[i].z_pos);
                m_players[i].body.rotate(0.0f, m_players[i].direction, 0.0f);

                
// render body and weapon
                m_players[i].body.update_anim(timeGetTime()/32, true);
                m_players[i].body.render();
                m_players[i].weapon.render();
            }
        }

        end_display_scene();
    }

    present_display();
}
 

The Client’s Full Glory

The hard work is over! The only requirements for running the client are processing
the local player’s input and updating the players. Now, all you have to do is
spruce up your project with some 3-D graphics, and you’ll almost have a game.

The graphics portion of the client application uses the Graphics Core to draw the
various connected players in the game. You use a NodeTree object to render the
game’s level. The client loads all meshes when the application class is initialized. As
previously mentioned, all players receive an assigned mesh to represent their characters
and weapons. Animations are also used and are set by the various update messages.

You limit rendering of a scene to 30 times a second, and to ensure that everything
runs as quickly as possible, you use a viewing frustum to render the level and to clip
unseen characters out of the rendering loop.

To wrap up the Client application, you deal with the different kinds of application
code, such as selecting an adapter and connecting to the server.

 

Download source and solution
 

posted on 2007-12-19 17:53 lovedday 閱讀(311) 評論(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>
            一区二区三区色| 性欧美超级视频| 欧美精品一区三区| 一二三四社区欧美黄| 亚洲精一区二区三区| 欧美日本国产一区| 亚洲中字在线| 欧美伊人久久| 亚洲激情精品| 亚洲天堂免费在线观看视频| 久久综合九色99| 久久精品国产免费| 亚洲人成在线观看| 一本久久综合亚洲鲁鲁五月天| 欧美三级韩国三级日本三斤| 欧美一级电影久久| 久久夜色精品| 亚洲在线视频网站| 久久国产欧美| 中文av一区特黄| 欧美伊人久久大香线蕉综合69| 亚洲国产日日夜夜| 亚洲影院免费观看| 在线免费不卡视频| 亚洲午夜小视频| 91久久精品日日躁夜夜躁欧美| 中日韩高清电影网| 亚洲国产91色在线| 亚洲欧美日本在线| 亚洲精品一区二区三区在线观看| 亚洲一区欧美一区| 亚洲精品精选| 久久av一区二区| 亚洲一区二区精品| 久久综合九色欧美综合狠狠| 亚洲欧美国产另类| 欧美国产综合视频| 久久伊人免费视频| 国产精品私拍pans大尺度在线 | 欧美日本中文字幕| 久久久久久国产精品mv| 欧美午夜视频| 亚洲国产小视频在线观看| 国产日韩欧美不卡| 在线观看91精品国产入口| 日韩视频亚洲视频| 亚洲国产欧美一区| 性高湖久久久久久久久| 亚洲午夜久久久久久久久电影网| 免费中文日韩| 免费视频一区| 一区二区三区我不卡| 午夜精品久久久久久久久| 亚洲一区不卡| 欧美日韩精品免费| 亚洲人久久久| 亚洲精品欧美| 欧美成人免费大片| 嫩草成人www欧美| 一区二区三区在线不卡| 久久精品官网| 久久久久久97三级| 国产亚洲在线| 久久不射中文字幕| 久久免费高清视频| 99国产精品久久久| 99日韩精品| 欧美日韩在线观看一区二区三区| 亚洲激情国产精品| 一区二区电影免费观看| 欧美精品在线播放| 日韩一级精品视频在线观看| 中日韩在线视频| 国产精品高清网站| 香蕉av福利精品导航| 久久手机免费观看| 尤物yw午夜国产精品视频| 久久久久国产精品午夜一区| 免费观看国产成人| 亚洲精品一区二区三| 欧美日韩爆操| 亚洲欧美久久久久一区二区三区| 久久爱91午夜羞羞| 在线日韩中文| 欧美精品二区| 亚洲天堂免费观看| 久久久噜噜噜久久中文字免| 亚洲国产精品电影| 欧美三级免费| 性xx色xx综合久久久xx| 女同性一区二区三区人了人一 | 国产亚洲一二三区| 免费成人性网站| 中文在线资源观看网站视频免费不卡 | 久久青草久久| 亚洲精品1区| 国产精品国产三级国产普通话99 | 国产伦精品一区二区三区免费迷 | 欧美日韩国产色综合一二三四 | 一区二区三区国产在线观看| 小黄鸭精品密入口导航| 一区免费观看视频| 欧美日韩综合网| 欧美在线观看视频在线| 亚洲黄一区二区三区| 欧美一区二区三区在线观看| 亚洲国产精品t66y| 国产精品私人影院| 欧美黄色成人网| 午夜亚洲福利| 亚洲精品影院| 毛片av中文字幕一区二区| 99精品欧美一区| 国产日韩欧美自拍| 欧美日韩精品久久久| 久久久噜噜噜久久中文字幕色伊伊 | 亚洲欧美日韩精品一区二区| 怡红院精品视频| 国产精品久久久久影院色老大| 午夜日韩av| 亚洲激情午夜| 好看的亚洲午夜视频在线| 欧美三区在线观看| 另类专区欧美制服同性| 先锋影音国产精品| 在线一区二区视频| 亚洲日韩视频| 麻豆精品精华液| 久久精品综合一区| 午夜欧美不卡精品aaaaa| 亚洲伦理自拍| 亚洲国产午夜| 亚洲国产成人精品女人久久久| 国产亚洲一区在线| 国产欧美一区二区三区国产幕精品| 欧美人与性动交α欧美精品济南到 | 久久久夜夜夜| 午夜一区不卡| 午夜久久久久| 午夜精品久久久久久久蜜桃app| 亚洲人成网站色ww在线 | 欧美日韩国产高清视频| 狂野欧美激情性xxxx| 久久亚洲精品一区二区| 久久久久久久999精品视频| 亚洲一级影院| 亚洲一区欧美激情| 亚洲欧美日韩国产另类专区| 亚洲在线第一页| 性欧美大战久久久久久久久| 欧美在线1区| 久久久噜噜噜久久| 老司机精品视频网站| 免费毛片一区二区三区久久久| 噜噜噜在线观看免费视频日韩| 久久久亚洲一区| 久久综合伊人77777蜜臀| 鲁大师影院一区二区三区| 美女日韩欧美| 欧美高清影院| 国产精品九九| 国一区二区在线观看| 91久久精品一区二区别| 中文久久乱码一区二区| 亚洲自拍啪啪| 欧美日韩午夜激情| 国产精品每日更新| 精品1区2区3区4区| 日韩视频二区| 销魂美女一区二区三区视频在线| 久久精品首页| 亚洲国产精品电影在线观看| 一区二区三区视频观看| 久久国产精品色婷婷| 欧美肥婆bbw| 国产精品一区在线播放| 亚洲第一搞黄网站| 亚洲制服av| 欧美大片在线影院| 一区二区不卡在线视频 午夜欧美不卡' | 亚洲在线一区二区三区| 久久久久综合一区二区三区| 91久久精品久久国产性色也91| 亚洲神马久久| 久久夜色精品国产| 国产精品午夜久久| 亚洲精品久久久久久久久久久久 | 久久久久一本一区二区青青蜜月| 欧美国产三区| 亚洲在线视频网站| 欧美国产精品va在线观看| 国产欧美日韩精品丝袜高跟鞋| 亚洲人人精品| 快射av在线播放一区| 亚洲午夜精品国产| 欧美日韩国产bt| 亚洲人成网在线播放| 久久人人爽人人| 亚洲女人小视频在线观看| 欧美日韩精品久久|