• <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>

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

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


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


            公告

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            隨筆分類(178)

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

            搜索

            最新評論

            久久人人爽人人爽人人爽| 久久天天躁狠狠躁夜夜网站 | 国产亚洲美女精品久久久2020| 久久亚洲国产中v天仙www| 91精品国产91久久久久福利| 无码人妻精品一区二区三区久久| 久久精品卫校国产小美女| 人妻丰满?V无码久久不卡| 亚洲精品无码久久久久AV麻豆| 亚洲欧洲中文日韩久久AV乱码| 色婷婷噜噜久久国产精品12p| 色婷婷久久综合中文久久一本| 伊人久久大香线蕉综合5g| 久久青青色综合| 亚洲国产精品无码久久久秋霞2| 久久国产精品无码HDAV| 久久综合九色综合精品| 久久最新免费视频| 国产精品乱码久久久久久软件 | 国产女人aaa级久久久级| 久久av高潮av无码av喷吹| 亚洲国产天堂久久久久久| 久久人人爽人人人人爽AV| 久久精品无码专区免费东京热 | 久久亚洲精品国产亚洲老地址| 国内精品人妻无码久久久影院导航 | 久久99精品国产麻豆| 伊人久久免费视频| 久久夜色精品国产亚洲| …久久精品99久久香蕉国产| 欧洲国产伦久久久久久久| 色欲久久久天天天综合网| 亚洲综合精品香蕉久久网97| 国产精品乱码久久久久久软件| 高清免费久久午夜精品| 中文字幕无码久久精品青草 | 久久久久精品国产亚洲AV无码| 久久99国产精品一区二区| 国内精品伊人久久久久妇| 国产精品九九久久免费视频 | 日本久久久久久中文字幕|