• <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游戲編程相關鏈接

            搜索

            最新評論

            久久亚洲高清综合| 亚洲v国产v天堂a无码久久| 久久人与动人物a级毛片| 久久夜色精品国产噜噜亚洲a| 国产精品99久久久精品无码| 人妻丰满AV无码久久不卡| 国产韩国精品一区二区三区久久 | 久久精品免费全国观看国产| 久久无码AV中文出轨人妻| 2021久久精品国产99国产精品 | 99久久www免费人成精品| 久久人人爽人人精品视频| 久久精品亚洲精品国产色婷| 精品无码久久久久久久动漫| 久久人人爽爽爽人久久久| 蜜桃麻豆www久久国产精品| 国产精品美女久久久m| 久久久久人妻一区精品| 久久天天躁狠狠躁夜夜avapp| 香蕉99久久国产综合精品宅男自 | 欧美精品丝袜久久久中文字幕| 久久婷婷国产剧情内射白浆 | 无码人妻精品一区二区三区久久久 | 久久久精品人妻无码专区不卡| 97视频久久久| 久久亚洲欧洲国产综合| 精品精品国产自在久久高清 | 中文字幕热久久久久久久| 国产精品一区二区久久精品无码| 久久人妻AV中文字幕| 久久久久久久亚洲精品| 亚洲精品高清久久| www.久久99| 国产99精品久久| 久久99国产综合精品女同| 亚洲中文字幕无码久久精品1 | 国产99久久精品一区二区| 久久久久亚洲AV片无码下载蜜桃 | 日本强好片久久久久久AAA| 伊人久久亚洲综合影院| 久久91精品国产91|