现在的位置: 首页 > 综合 > 正文

第二人生的源码分析(二十五)人物行走与服务器同步

2013年10月09日 ⁄ 综合 ⁄ 共 4269字 ⁄ 字号 评论关闭
在网络游戏里,玩家的行走与平时单机版的游戏有着很大的差别,当你按下键盘时,人物角色并不能立即就向前行走,而是需要把它移动的请求发送到服务器,让服务器来作出判断是否可以行走,然后把行走位置通知视野里所有其它玩家,第二人生的客户端就会把这个人物按位置信息显示出来。下面就来分析怎么样发送玩家状态信息给服务器。
 
#001 void LLAppViewer::idle()
#002 {
#003      // Update frame timers
#004      static LLTimer idle_timer;
#005 
#006      LLControlBase::updateAllListeners();
#007 
#008      LLFrameTimer::updateFrameTime();
#009      LLEventTimer::updateClass();
#010      LLCriticalDamp::updateInterpolants();
#011      LLMortician::updateClass();
#012       F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
#013 
……
#077     
#078          static LLFrameTimer agent_update_timer;
#079          static U32                          last_control_flags;
#080     
#081          //     When appropriate, update agent location to the simulator.
#082          F32 agent_update_time = agent_update_timer.getElapsedTimeF32();
#083          BOOL flags_changed = gAgent.controlFlagsDirty() || (last_control_flags != gAgent.getControlFlags());
#084     
#085          if (flags_changed || (agent_update_time > (1.0f / (F32) AGENT_UPDATES_PER_SECOND)))
#086          {
#087                 // Send avatar and camera info
#088                 last_control_flags = gAgent.getControlFlags();
#089                 send_agent_update(TRUE);
#090                 agent_update_timer.reset();
#091          }
#092      }
#093 ......
#094 }
 
上面第83行获取当前角色的状态是否发生变化,然后通过send_agent_update函数不断地发送状态消息给服务器。接着下来就去分析这个函数,它的代码如下:
#001 void send_agent_update(BOOL force_send, BOOL send_reliable)
#002 {
#003      if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE)
#004      {
#005             // We don't care if they want to send an agent update, they're not allowed to until the simulator
……
#147 
#148      if (duplicate_count < DUP_MSGS && !gDisconnected)
#149      {
#150             // Build the message
#151             msg->newMessageFast(_PREHASH_AgentUpdate);
#152             msg->nextBlockFast(_PREHASH_AgentData);
#153             msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
#154             msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
#155             msg->addQuatFast(_PREHASH_BodyRotation, body_rotation);
#156             msg->addQuatFast(_PREHASH_HeadRotation, head_rotation);
#157             msg->addU8Fast(_PREHASH_State, render_state);
#158             msg->addU8Fast(_PREHASH_Flags, flags);
#159 
#160 //          if (camera_pos_agent.mV[VY] > 255.f)
#161 //          {
#162 //                 llinfos << "Sending camera center " << camera_pos_agent << llendl;
#163 //          }
#164            
#165             msg->addVector3Fast(_PREHASH_CameraCenter, camera_pos_agent);
#166             msg->addVector3Fast(_PREHASH_CameraAtAxis, gCamera->getAtAxis());
#167             msg->addVector3Fast(_PREHASH_CameraLeftAxis, gCamera->getLeftAxis());
#168             msg->addVector3Fast(_PREHASH_CameraUpAxis, gCamera->getUpAxis());
#169             msg->addF32Fast(_PREHASH_Far, gAgent.mDrawDistance);
#170            
#171             msg->addU32Fast(_PREHASH_ControlFlags, control_flags);
#172 
#173             if (gDebugClicks)
#174             {
#175                    if (control_flags & AGENT_CONTROL_LBUTTON_DOWN)
#176                    {
#177                           llinfos << "AgentUpdate left button down" << llendl;
#178                    }
#179 
#180                    if (control_flags & AGENT_CONTROL_LBUTTON_UP)
#181                    {
#182                           llinfos << "AgentUpdate left button up" << llendl;
#183                    }
#184             }
#185 
#186             gAgent.enableControlFlagReset();
#187 
#188             if (!send_reliable)
#189             {
#190                    gAgent.sendMessage();
#191             }
#192             else
#193             {
#194                    gAgent.sendReliableMessage();
#195             }
#196 
#197             //llinfos << "agent " << avatar_pos_agent << " cam " << camera_pos_agent << llendl;
#198 
#199             // Copy the old data
#200             last_head_rot = head_rotation;
#201             last_render_state = render_state;
#202             last_camera_pos_agent = camera_pos_agent;
#203             last_camera_at = gCamera->getAtAxis();
#204             last_camera_left = gCamera->getLeftAxis();
#205             last_camera_up = gCamera->getUpAxis();
#206             last_control_flags = control_flags;
#207             last_flags = flags;
#208      }
#209 }
#210 
 
在上面的代码里,就调用msg消息对象创建状态消息,然后通过sendMessage和sendReliableMessage函数发送给服务器,这样在服务器的玩家角色就会更新状态,如果行走的话,也会得到更新的。第二人生里的消息结构是根据XML模板来构造的,这个部分的功能也比较复杂。

 

蔡军生 2008/3/14 QQ:9073204 深圳

抱歉!评论已关闭.