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

            天行健 君子當自強而不息

            Getting Online with Multiplayer Gaming(18)

             

            Updating the Local Player

            Between updates from the server, the clients need to update all players to keep the
            game running smoothly. The client application limits updates to every 33ms (30 times
            a second), which matches the server update rate. Between these player updates, the
            client is allowed to collect input from the player who is used to change their actions.

            The cApp::frame function is generally used to update the local player. The players
            use the keyboard and mouse to control their characters, so I included a few Input
            Core objects (m_keyboard and m_mouse):

            bool cApp::frame()
            {
                
            // get local input every frame
                m_keyboard.acquire();
                m_mouse.acquire();
                m_keyboard.read();
                m_mouse.read();

                
            // handle connection screen
                if(!g_connected || m_players[0].player_id == 0)
                {
                    
            // display connection message

                    clear_display(0, 1.0f);

                    
            if(begin_display_scene())
                    {
                        draw_font(m_font, "Connecting to server ", 0, 0, 0, 0, COLOR_WHITE, DT_LEFT);
                        end_display_scene();
                    }

                    present_display();
                    
            return true;
                }

                
            // store movements every frame

                
            static long move_action = 0, last_move = 0;

                
            if(m_keyboard.get_key_state(KEY_UP) || m_keyboard.get_key_state(KEY_W))
                    move_action |= ACTION_MOVE_UP;

                
            if(m_keyboard.get_key_state(KEY_RIGHT)  || m_keyboard.get_key_state(KEY_D))
                    move_action |= ACTION_MOVE_RIGHT;

                
            if(m_keyboard.get_key_state(KEY_DOWN)  || m_keyboard.get_key_state(KEY_S))
                    move_action |= ACTION_MOVE_DOWN;

                
            if(m_keyboard.get_key_state(KEY_LEFT)  || m_keyboard.get_key_state(KEY_A))
                    move_action |= ACTION_MOVE_LEFT;

                
            // store attack action
                if(m_keyboard.get_key_state(KEY_SPACE) || m_mouse.get_button_state(MOUSE_LBUTTON))
                    move_action |= ACTION_ATTACK;

                
            // rotate camera

                
            static bool cam_moved = false;

                
            if(m_mouse.get_x_delta() > 0)
                {
                    m_cam_angle -= 0.1f;
                    cam_moved = 
            true;
                }

                
            if(m_mouse.get_x_delta() < 0)
                {
                    m_cam_angle += 0.1f;
                    cam_moved = 
            true;
                }

                
            static DWORD update_counter = timeGetTime();

                
            // only update players every 33ms (30 times a second)
                if(timeGetTime() < update_counter + 33)
                    
            return true;

                
            // set flag to allow player movement
                bool allow_move = true;

                
            // do not allow movement if still swinging weapon or being hurt
                if(m_players[0].last_state == STATE_SWING || m_players[0].last_state == STATE_HURT)
                    allow_move = 
            false;

                
            // handle movements if allowed
                if(allow_move)
                {
                    
            // process attack
                    if(move_action & ACTION_ATTACK)
                    {
                        move_action = 0;    
            // clear movement
                        last_move   = 0;    // clear last movement

                        // send attack message - let server signal swing

                        sStateChangeMsg change_msg;

                        change_msg.header.type      = MSG_STATE_CHANGE;
                        change_msg.header.size      = 
            sizeof(sStateChangeMsg);
                        change_msg.header.player_id = m_players[0].player_id;
                        change_msg.state            = STATE_SWING;
                        change_msg.direction        = m_players[0].direction;

                        send_network_msg(&change_msg, DPNSEND_NOLOOPBACK);
                    }

                    
            // process local player movements
                    if(move_action > 0 && move_action < 13)
                    {
                        
            // set new player state
                        
                        EnterCriticalSection(&m_update_cs);

                        m_players[0].last_state = STATE_MOVE;
                        m_players[0].direction  = g_angles[move_action] - m_cam_angle + 4.71f;

                        LeaveCriticalSection(&m_update_cs);

                        
            // reset last move if camera moved since last update
                        if(cam_moved)
                        {
                            cam_moved = 
            false;
                            last_move = 0;
                        }

                        
            // send actions to server if changed from last move
                        if(move_action != last_move)
                        {
                            last_move = move_action;    
            // store last action

                            m_players[0].last_update_time = timeGetTime();

                            sStateChangeMsg change_msg;

                            
            // construct message
                            change_msg.header.type      = MSG_STATE_CHANGE;
                            change_msg.header.size      = 
            sizeof(sStateChangeMsg);
                            change_msg.header.player_id = m_players[0].player_id;
                            change_msg.state            = STATE_MOVE;
                            change_msg.direction        = m_players[0].direction;

                            send_network_msg(&change_msg, DPNSEND_NOLOOPBACK);
                        }
                    }
                    
            else
                    {
                        
            // change to idle state
                        EnterCriticalSection(&m_update_cs);
                        m_players[0].last_state = STATE_IDLE;
                        LeaveCriticalSection(&m_update_cs);

                        
            // send update only if player moved last update
                        if(last_move)
                        {
                            last_move = 0;

                            sStateChangeMsg change_msg;

                            change_msg.header.type      = MSG_STATE_CHANGE;
                            change_msg.header.size      = 
            sizeof(sStateChangeMsg);
                            change_msg.header.player_id = m_players[0].player_id;
                            change_msg.state            = STATE_IDLE;
                            change_msg.direction        = m_players[0].direction;

                            send_network_msg(&change_msg, DPNSEND_NOLOOPBACK);
                        }
                    }
                }

                update_all_players();
                render_scene();

                move_action = 0;                    
            // clear action data for next frame
                update_counter = timeGetTime();     // reset update counter

                
            return true;
            }

            At every frame, the input devices are restored (in case a device’s focus has been
            lost), and input is read in. If the user presses Esc, the game-play quits by returning
            a value of false from the frame function.

            From here, game-play may only continue if the client is connected to the server.
            If no such connection exists, a message displays to that effect. Also, if a player is
            still waiting for a DirectPlay identification number from the server, a message displays,
            and a request is periodically sent to the server for the correct identification
            number.

            From here on, player input is parsed. A single variable tracks player actions (move_action),
            and each bit in the variable represents a specific action (as shown in Figure 19.17). The
            user’s actions are move up, move down, move left, move right, and attack. Also, camera
            angle changes are recorded (and flagged for later updating).

            Normally, players are allowed to move around the world, but if a player is currently
            swinging his weapon or being hurt, that player is not allowed to move. You use the
            allow_move flag to signify when a player’s actions can be processed, as shown here:

            If a player chooses to attack, you need to construct a state-change message and
            send that message to the server. After you send the state-change message, clear the
            player’s movement actions. Notice that the client does not change its own state at
            this point; the server determines when to change the player’s state.

            If the player did not attack, his actions are checked to see whether the player is
            moving.

            After the player’s state and movement direction is set, the Frame function continues
            by resetting the camera’s movements (by setting the cam_move flag to false). The
            player’s controls are relative to the camera-viewing angle (if the player is pressing
            the up arrow key, he is walking away from the camera). If you change the camera’s
            angle while the player is walking, you force the player’s direction to change as well.
            The client takes this change of the player’s direction into consideration when the
            camera is rotated.

            Once a player has moved, the client sends a state-change message to the server.
            Notice that the state-change message is sent only if the player’s movement is different
            from the last move he performed (as recorded in the last_move variable).

            If the player hasn’t moved, his state is changed to standing still (STATE_IDLE), and a
            state-change message is sent to the server.

            At this point, the local player’s actions have been recorded and sent to the server.
            Next, all players are updated, the scene is rendered, and the movement actions are
            reset for the next frame.

            posted on 2007-12-19 17:22 lovedday 閱讀(221) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            久久久91人妻无码精品蜜桃HD| 日韩精品国产自在久久现线拍| 亚洲成av人片不卡无码久久| 久久夜色撩人精品国产小说| 欧美国产成人久久精品| 久久精品国产亚洲网站| 久久久国产99久久国产一| 91视频国产91久久久| 久久影院午夜理论片无码| 国产成年无码久久久免费| 久久久久国产精品| 亚洲午夜福利精品久久| 久久美女人爽女人爽| 亚洲午夜久久久久久久久久| 99精品久久久久久久婷婷| 色综合久久综合中文综合网| 国产综合免费精品久久久| 欧美噜噜久久久XXX| 一本久久免费视频| 国产精品成人99久久久久 | 亚洲国产小视频精品久久久三级| 一本久久免费视频| 伊人色综合久久| 久久精品人人做人人爽电影| 亚洲精品高清国产一线久久| 亚洲乱码日产精品a级毛片久久| 国产精品18久久久久久vr| 午夜精品久久久久久久| 久久精品成人欧美大片| 伊人久久一区二区三区无码| 激情综合色综合久久综合| 免费国产99久久久香蕉| 久久香蕉国产线看观看99| 狠狠狠色丁香婷婷综合久久五月| 久久国产免费观看精品3| 午夜精品久久久久久毛片| 亚洲欧美伊人久久综合一区二区 | 亚洲午夜久久久久久噜噜噜| 精品国产青草久久久久福利| 久久精品国产精品亚洲精品 | 久久er国产精品免费观看2|