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

            搜索

            最新評論

            久久这里只精品国产99热| 日本久久中文字幕| av午夜福利一片免费看久久| 久久久久久精品成人免费图片| 99精品国产综合久久久久五月天| 亚洲精品无码久久千人斩| 久久精品aⅴ无码中文字字幕重口 久久精品a亚洲国产v高清不卡 | 亚洲日本久久久午夜精品| 看久久久久久a级毛片| 成人免费网站久久久| 人妻中文久久久久| 久久九九全国免费| 亚洲日韩欧美一区久久久久我 | 久久国产精品一区二区| 久久久久一级精品亚洲国产成人综合AV区| 大香伊人久久精品一区二区| 国产精品久久久久影院色 | 久久婷婷国产综合精品 | 麻豆AV一区二区三区久久| 国产精品永久久久久久久久久| 伊人久久无码中文字幕| 久久婷婷五月综合色99啪ak| 久久不射电影网| 久久99精品久久久久婷婷| 久久久久国产精品嫩草影院| 久久e热在这里只有国产中文精品99 | 亚洲国产精品久久久久婷婷软件 | 日韩一区二区久久久久久| 久久精品人人做人人爽电影| 久久国产乱子伦精品免费午夜| 久久精品国产亚洲AV电影| 天天躁日日躁狠狠久久| 麻豆国内精品久久久久久| 青青草原综合久久| 久久国产高清字幕中文| 97热久久免费频精品99| 777米奇久久最新地址| 97久久综合精品久久久综合| 91视频国产91久久久| 91精品婷婷国产综合久久| 色综合久久综精品|