zl程序教程

您现在的位置是:首页 >  其他

当前栏目

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

同步服务器源码 分析 第二 人生 人物 二十五
2023-09-14 09:10:40 时间
在网络游戏里,玩家的行走与平时单机版的游戏有着很大的差别,当你按下键盘时,人物角色并不能立即就向前行走,而是需要把它移动的请求发送到服务器,让服务器来作出判断是否可以行走,然后把行走位置通知视野里所有其它玩家,第二人生的客户端就会把这个人物按位置信息显示出来。下面就来分析怎么样发送玩家状态信息给服务器。
 
#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 深圳