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

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            色婷婷狠狠久久综合五月| 国内精品久久久久国产盗摄| 精品久久久久成人码免费动漫| 久久人人爽人人爽人人片AV不 | 婷婷久久五月天| 麻豆亚洲AV永久无码精品久久| 亚洲国产精品久久久久婷婷老年| 久久毛片免费看一区二区三区| 久久婷婷五月综合色奶水99啪| 久久精品中文字幕有码| 久久精品无码专区免费东京热| 精品久久综合1区2区3区激情| 日韩乱码人妻无码中文字幕久久| 久久狠狠一本精品综合网| 77777亚洲午夜久久多喷| 亚洲欧美成人久久综合中文网| 久久这里只精品国产99热| 亚洲精品高清国产一线久久| 久久综合视频网站| 亚洲综合精品香蕉久久网97| 久久亚洲中文字幕精品有坂深雪 | 国产成人久久精品麻豆一区| 亚洲国产精品久久久天堂| 日韩亚洲国产综合久久久| 美女写真久久影院| 2021久久国自产拍精品| 午夜精品久久久久久久| 思思久久精品在热线热| 久久亚洲国产成人影院| 亚洲精品乱码久久久久久蜜桃| 国产免费福利体检区久久| 国产福利电影一区二区三区,免费久久久久久久精 | 久久午夜无码鲁丝片秋霞 | 97精品国产91久久久久久| 久久精品国产99国产精品亚洲| 久久精品一区二区影院| 久久久精品日本一区二区三区| 日韩欧美亚洲国产精品字幕久久久| 色婷婷综合久久久久中文字幕| 亚洲а∨天堂久久精品| 亚洲色婷婷综合久久|