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

天行健 君子當自強而不息

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>
            亚洲一区尤物| 久久电影一区| 国产精品久久国产精品99gif| 夜夜狂射影院欧美极品| 亚洲精品国产系列| 欧美另类变人与禽xxxxx| 在线综合欧美| 香蕉久久夜色精品国产使用方法| 国产欧美日韩麻豆91| 美女精品网站| 欧美精品三级| 午夜精品久久久久影视| 久久狠狠亚洲综合| 亚洲欧洲精品一区二区三区波多野1战4 | 欧美影院一区| 亚洲国产成人在线视频| 亚洲精品久久久一区二区三区| 欧美香蕉视频| 免播放器亚洲一区| 欧美三级日本三级少妇99| 欧美一区二区三区啪啪| 裸体女人亚洲精品一区| 亚洲自啪免费| 久久亚洲春色中文字幕| 亚洲一区二区免费在线| 久久久久久久尹人综合网亚洲 | 黄色亚洲免费| 亚洲精品影视| 狠狠色狠狠色综合日日小说| 亚洲日本激情| 一区免费在线| 午夜精品福利在线| 日韩午夜激情电影| 久久精品亚洲精品| 亚洲欧美国产精品va在线观看| 久久久欧美一区二区| 亚洲自拍三区| 欧美啪啪一区| 欧美成人a∨高清免费观看| 国产精品日韩| 亚洲精品午夜| 亚洲欧洲在线看| 久久经典综合| 久久激情综合网| 国产精品国产| 99亚洲一区二区| 亚洲免费观看| 欧美顶级少妇做爰| 欧美国产三级| 在线成人中文字幕| 久久久国产91| 久久噜噜噜精品国产亚洲综合| 欧美偷拍一区二区| 99视频在线精品国自产拍免费观看| 亚洲高清在线观看| 久久亚洲不卡| 欧美大片免费观看| 亚洲电影网站| 麻豆精品视频在线| 欧美成人一区二区在线| 一区二区三区在线视频观看| 亚洲欧美久久| 久久精品人人做人人爽电影蜜月| 国产精品你懂的| 亚洲一区二区三区视频| 性欧美大战久久久久久久免费观看 | 午夜精品视频在线| 亚欧成人精品| 国产日本亚洲高清| 性欧美超级视频| 久久婷婷久久| 亚洲高清不卡av| 欧美高清视频免费观看| 亚洲国产成人高清精品| 日韩视频在线观看国产| 欧美三级乱码| 亚洲欧美日韩精品久久| 久久精品噜噜噜成人av农村| 国内揄拍国内精品少妇国语| 久久精品欧美日韩| 欧美电影打屁股sp| 国产精品99久久99久久久二8| 欧美日韩高清在线| 亚洲一区二区三区久久| 久久久av网站| 亚洲精品一区二区三| 欧美视频在线免费| 午夜日韩在线| 亚洲福利一区| 亚洲一区二区三区在线看| 国产毛片精品国产一区二区三区| 欧美在线日韩在线| 亚洲国产精品精华液网站| 亚洲一区二区欧美日韩| 国产亚洲精品久久久久婷婷瑜伽| 久久久久久97三级| 亚洲美女色禁图| 久久久久九九视频| 一区二区欧美在线观看| 国产亚洲精品一区二555| 欧美成人一区二区在线| 亚洲永久免费av| 亚洲成色777777在线观看影院| 久久久夜精品| 日韩视频在线一区| 免费久久99精品国产自| 亚洲香蕉视频| 亚洲国产成人精品女人久久久| 欧美三级电影一区| 蜜臀91精品一区二区三区| 亚洲色图在线视频| 亚洲第一精品电影| 欧美中文字幕不卡| 日韩网站在线观看| 黄色精品一区二区| 国产精品亚洲视频| 欧美日韩二区三区| 免费日本视频一区| 久久久九九九九| 亚洲欧美日韩专区| 亚洲美女在线国产| 欧美成人午夜激情| 久久久国产视频91| 亚洲综合色在线| 一区二区三区日韩欧美| 亚洲二区在线视频| 国产亚洲高清视频| 国产精品婷婷午夜在线观看| 欧美日韩99| 欧美精品一区二区三区一线天视频| 久久精品国产久精国产爱| 亚洲午夜一级| 中文日韩在线视频| 日韩网站免费观看| 亚洲欧洲日韩综合二区| 亚洲高清资源| 欧美激情免费在线| 欧美激情亚洲另类| 欧美激情亚洲自拍| 亚洲国产成人午夜在线一区| 欧美成人精品在线播放| 久久亚洲综合色一区二区三区| 欧美在线视频免费播放| 欧美一区二区三区免费观看视频 | 亚洲精品专区| 亚洲精品欧美一区二区三区| 最新中文字幕亚洲| 9人人澡人人爽人人精品| 亚洲欧洲三级| 在线亚洲观看| 亚洲欧美日韩在线高清直播| 亚洲欧美日本国产专区一区| 亚洲免费视频网站| 久久av红桃一区二区小说| 欧美一区午夜视频在线观看| 久久精品亚洲精品| 美国成人直播| 亚洲激情av| 亚洲夜间福利| 久久精品国产第一区二区三区最新章节| 欧美在线一二三| 欧美成人国产va精品日本一级| 欧美成人一二三| 国产精品久久久久久久app| 国产欧美一区二区精品性色| 国语自产精品视频在线看一大j8| 亚洲高清视频在线| 一区二区激情小说| 欧美一区二区视频在线观看| 麻豆成人在线播放| 亚洲日本激情| 午夜久久久久久| 蜜桃视频一区| 国产精品久久久久婷婷| 激情欧美亚洲| 亚洲一区三区在线观看| 久久精品亚洲一区二区| 亚洲国产成人91精品| 亚洲一区激情| 欧美成年人在线观看| 国产精品青草综合久久久久99| 激情婷婷欧美| 亚洲综合999| 欧美电影专区| 亚洲欧美综合另类中字| 欧美精品1区2区| 黄色成人在线网址| 亚洲视频国产视频| 欧美成人精品h版在线观看| 正在播放欧美视频| 欧美成人一品| 激情91久久| 欧美一区三区二区在线观看| 亚洲高清av| 久久久久久久网站| 国产日韩亚洲欧美综合| 一区二区黄色| 亚洲黄色片网站| 久久久亚洲国产美女国产盗摄| 国产精品mv在线观看|