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

            搜索

            最新評論

            99久久综合国产精品二区| MM131亚洲国产美女久久| 韩国三级中文字幕hd久久精品| 久久亚洲天堂| 久久综合久久自在自线精品自 | 国产精品18久久久久久vr| 亚洲精品高清国产一久久| 久久人人爽人人爽人人片AV高清 | 久久综合欧美成人| 亚洲精品国产自在久久| 99久久无码一区人妻| 久久青青草原亚洲av无码app| 久久人人青草97香蕉| 一级A毛片免费观看久久精品| 中文精品久久久久国产网址| 浪潮AV色综合久久天堂| 久久久久久曰本AV免费免费| 999久久久国产精品| 性高朝久久久久久久久久| 久久国产福利免费| 久久se精品一区二区影院| 中文字幕精品无码久久久久久3D日动漫 | 国产精品免费看久久久香蕉| 国产免费福利体检区久久| 久久国产乱子伦精品免费午夜| 国产精品久久久久久久午夜片| 国产精品内射久久久久欢欢 | 欧美黑人又粗又大久久久| 久久超乳爆乳中文字幕| 久久九九久精品国产免费直播| 免费精品久久天干天干| 99久久精品费精品国产| 久久久久99精品成人片直播| 久久成人国产精品| 久久精品成人欧美大片| 久久亚洲国产精品123区| 久久精品水蜜桃av综合天堂| 欧美性大战久久久久久| 精品国产福利久久久| 伊人久久综合成人网| 久久天天躁狠狠躁夜夜avapp|