您的位置:首页 > 其它

贸易时代开发文档(四)--地图服务器开发日志【邹志兵】

2006-01-31 19:03 337 查看
日志:

3月10日开始………………………………………………………

3月25日发现地图移动的两个错误,并进行修正: 

a)         移动的碰撞只用了左上角,忘记了要用四个角

b)        跨越地图的玩家移动被重复计算,为此在VM中发现预先循环将所有跨越地图的玩家放新地图,接下来的两次循环才进行移动

3月26日完成地图消息的消息处理,其中对地图相关消息进行了重新定义

3月27日开始客户端的地图移动,并尝试用STL改造代码

3月28日完成客户端的地图移动,由于对STL理解不够,只在少部分使用了STL函数

3月29日完善客户端地图相关消息处理和发送

3月30日完成客户端地图功能

3月31日加入将地图服务器涉及的消息重新分成两类:地图移动消息和地图事件消息

地图服务器初始化地图信息

4月1日登陆时地图服务器初始化玩家信息

4月2日玩家改变地图时读出将区域中新的地图,并将新增地图中的邻居信息入通过MsgOtherIn传入给他,同时将玩家信息传给他的邻居们

4月3日根据统一后的消息加入了补给的计算

4月4日加入VM的定时器,重载mapSocket的OnRead函数

4月5日加入数据临界区

4月6日停电

4月7日上午开会,下午将全局函数整合进其他类,没有成功

4月8日加入MapManager类,将mapList和player的相互操作作为其成员函数,使CMapListSession和CMapPlayerSession完全独立。

4月9日在MsgLog中加入地图服务器相关消息,开始调试

4月10日将继续调试地图服务器,同时将客户端改成九张地图

4月11日将继续调试地图服务器

4月12日在认真考虑客户端与服务器的同步,进行修改

4月13日地图编辑器的打开文件和保存文件的方法

4月14日停电

4月15日上午开会,下午加入针对IN_BUILDING玩家的处理

4月16日完善开题报告,在移动过程中添加、删除精灵

4月17日完善地图服务器文档

4月18--20日服务器协同调试,不过经常被各种事情打断

   只发现以下错误:

1、  在testlogin中登录第二个玩家,mapserver便退出

原因:在onread中多了一个对singal的判断,以致线程在玩家1时没有退出临界区

当收到玩家2的消息,进入临界区中会出错

2、  消息会发生重叠,可能是Edit的显示问题

3、  有时调试出错退出,下一次调试会出错,直到再下一次再正确

4、  第一个玩家登陆时,消息正确,但后面的玩家消息错误越来越多

原因:makemsg()中用于产生消息的buf太小了

5、直接运行exe,当两个玩家登陆时,第一玩家收不到otherIn消息,而第二个却收到两条;于是mapserver调试运行,消息却正确

原因:在检查中

 

4月21日解决了地图编辑器的保存问题

4月22日发现上述问题5是因为Edit的buf太小,以致消息发送正常,只是显示异常

开始测试定时运行地图状态机,处理玩家移动

4月23日

1、上述问题又出现,在从黄良毅更新了新的MsgLog后才正常,看来buf太小只是一方面原因,另一方面是消息的追加方式。

2、Socket的OnRead线程在处理完msgBuf中所有的消息后才返回。如在处理某一消息处理时就到了状态机运行的间隔时间,只能处理完该消息才将控制权交给状态机,当然状态机会有所延迟。原来的OnRead没有体现这些,而是默认消息处理不会超过间隔时间, 为此进行了修改。

4月24日

发现错误:

1、当两个玩家登陆之后,玩家1和2都无法开始移动

原因:测试时玩家登陆都是在默认坐标,将会互相阻挡,进港或出建筑物也会有问题。

修改:根据玩家的移动方向不同选择踫撞点。另外为了测试方便,在些临时文件保存玩家的登陆坐标,测试时玩家从中读出登陆时坐标。

2、当移动起点和终点相同时,在计算移动参数会出现除零错误,加入判断避免错误

4月25日

测试进入建筑物,选择交易所,玩家进入交易所,逻辑服务器发回交易所和玩家自身的货物信息。

测试出建筑物,但是从gameserver收到msgQuitRequest后的处理未发消息给mapServer。

测试补给,将地图和玩家属性改成海上,补给会定时改变,好像没什么问题。

在客户端加入MapMoveMsg和MapEventMsg消息的处理

4月26日

       1、测试跨越地图移动,从地图1移动至地图2,

发现错误:当玩家准备跨越至地图2时会出现访问异常。

原因:在预先跨越地图(PreBlock)在遍历玩家list时发现有人跨越就将其删除,即在遍历容器时将修改容器,使容器失效。

修改:将所有跨越者保存在临时表中,在遍历结束后一并删除。

2、对服务器地图信息类和地图玩家信息类重新命名,分别为CMapInfo和CMapPlayer

4月27日

1、  测试进港,从海上地图2移动至港口,经逻辑服务器确认,进入地市地图1。不过逻辑服务器的进港确认处理还未加入,只好以后再测

2、  测试出港,从地市地图1移动至码头,客户端发出港请求,逻辑服务器确认后,进入海上地图2。

改正了码头、港口的触发点错误、逻辑服务器对补给和水手判断的错误,可以按以下过程出港。

玩家进入码头,逻辑服务器发回补给价格

玩家发出港请求,逻辑服务器将请求通知地图服务器,地图服务器发回海上地图的信息

3、  将msgMoveBegin, msgPutOff, msgPutIn等消息实体是发送给地图或逻辑服务器,其msgHead.userID就是要处理的玩家playerID,于是把原定义重复中的playerID都去掉了

4月28日(上午开会)

    对mapserver的代码进行整理,改了TestLogin的菜单

重新测试出建筑物,gameserver收到msgQuitRequest后,发msgQuitConfirm消息给mapServer。mapServer再发返回城市消息给客户端。

4月29日(上午开会)

重新确定了进港和进建筑物的消息,在地图服务器、客户端重新进行处理

重新测试进港,gameserver收到msgPutInRequest后,发msgPutInConfirm消息给客户端。客户端模拟发msgMapInfoRequest,地图服务器返回msgDisplaceMap

4月30日

    1、在TradeAge加入了状态机,结果一运行就退出

   原因:MapServer和TradeAge 都使用编号为1的定时器,引起冲突

   修改:TradeAge 改用编号为2的定时器

  2、玩家登陆时TradeAge异常退出,调试时在访问玩家属性提示访问冲突

   原因: TradeAge在OnMapInit中先添加登陆的玩家,再初始化玩家当前区域的地图。

在初始化当前地图时有一个清空地图中玩家的操作,把登陆的玩家也误删了

   修改:初始化当前地图时只清空其他的玩家

3、玩家移动之后,重新SetSprite()提示访问冲突?????????????

 原因:在WinMain的系统消息循环中有Display()定时刷新时会用到sprite,引起冲突

   修改:在WinMain的系统消息循环中注释掉Display()

    4、为了使客户端MapPlayer中的便于计算0.1秒, 客户端的MapPlayer不用地图服务器的,暂时从地图服务器进行修改,以后应该把两边的共同部分抽象成基类,分别根据需要派生。目前的移动同步正常

5、测试进出交易所,结果正常

6、测试进港,玩家登陆地图2(海上地图),移动进入港口,再进入地市1(在地图1)。

第一次运行玩家登陆成功,直到地图服务器发DisplaceMap到客户端,客户端初始化玩家新区域的地图,提示“变量id致使stack破坏”,id好像是指定义的一个临时数组char id[10];

调试又没问题。而以后每次运行时,地图服务器发出MapInitConfirm,登陆服务器转发了,但是TradeAge的消息中无法添加,甚至不响应,可能stack破坏有关。只有在重启或注销之后才能正常运行一次

5月1日

1、  加入玩家移动到鼠标点击处,运行却无法移动

原因:鼠标点击坐标是相对于镜头左上角的偏移,忘记将其转成全局坐标

2、  客户端能自主移动进入港口并消失,在消息框却没有加移动验证、进港等消息

原因:可能是客户端状态机的间隔0.1秒太小了(5 月3日又改回0.1秒,运行正常,可见不是间隔的问题,另有原因)

修改:将客户端状态机的间隔改成0.2秒,相应的地图服务器的改成1秒

3、  客户端接收到DisplaceMap便不响应,调试时异常断点在list的empty()

原因:客户端的各种list初始化时忘记Clear()

  4、收到DisplaceMap便不响应,调试时在mapPlayer的getState()提示访问冲突

原因:一开始从playerList获得迭代器指针,在调用一个函数时容器被修改了,以致迭代器指针也失效,再使用就会提示访问冲突

修改:在容器修改后重新获得迭代器指针

5月2日

1、  想在OnMapInitConfirm()中将获得的一个玩家信息的内存释放,提示在dbgheap中出现未处理异常:用户断点

原因:该内存在静态消息buf,不是动态的。

2、  客户端能自主移动进入港口并消失,在消息框却没有加移动验证、进港等消息,如昨天一样

原因:不明,但重启后调试又正常

3、  客户端接收到DisplaceMap便不响应,调试时异常断点在list的end()

原因:客户端的在初始化新地图已经旧地图全部删除了,在后来的一个操作却试图获得旧地图的指针

修改:调整了初始化新地图各项操作的顺序

   4、切换至新地图后却没有显示Sprite

原因: 新地图playerList在添加与玩家是出错

修改:

      5、出现在地市地图中时忘记重新SetCamera

    6、切换地图之后在码头门口,一移动又不响应,程序还是不稳定

5月3日继续通过进入港口、在城市中移动,出港来测试

1、  玩家进入港口后出现在码头门口,但是无法移动

原因:GetGlobalByCompare在转换方法不对,修改。

2、  移动时在y方向经常到不了鼠标点击的终点

原因:移动时只以x坐标判断是否到终点,改成以x和y一起判断

3、移动至终点后不停止

原因: 上一步修改后判断到终点的函数有问题

4、  鼠标点击的终点后,要走的移动路径贴近地图左、上边缘时,无法移动

原因:地图的InMap()少了=,将左上边缘的认为不在地图中

  

      5、在城市中移动,进入码头隐藏精灵, 点“出建筑物”菜单又显示精灵,正常

6、将地图服务器的状态周期改回0.5秒,客户端为0.1

地图服务器移动验证改成每10个周期一次,但是发现这样玩家走的是折线

原因:因为计算用乘100除100来近似两位精度的浮点计算,当玩家要走的移动路径斜率较小或较大时,方向1上有偏移(方向1或2指x 或y方向),方向2的偏移会近似成0。当前一方向移动移动至与终点时,才重设偏移,这下又方向2上有偏移,方向1的为0.

以后改进

5月4日

1、跨越地图的算法目前局限在一个区域中移动,以后再实现类似环球航行的绕地球一圈的算法

2、在Cscene中加入成员函数AddSprite()用于加入一个精灵指针

在CMap中加入id,用于以后改进跨越地图算法

3、跨越地图时提示在CMapPlayer的GetMapID()访问冲突,退出

原因:跨越时的算法有错。

4、玩家移动到地图边界时静止等待服务器确认跨越,确认后又开始运动,但是跨越后精灵会消失,要用鼠标点击一下窗体精灵才会出现

原因:跨越后忘记设置精灵和镜头的坐标

       5、跨越时,切换地图后跳跃较大。虽然将在服务器确认后玩家状态设为运行,但似乎并没开始运动,于是每次MoveCheck或是MoveOver消息到来后都跳跃一下

       原因:不明

6、跨越地图不等待服务器确认,但是镜头与移动方向反向移动

原因:跨越后忘记设置精灵和镜头的坐标有错

7、加入玩家退出游戏的消息处理,但是在保存信息时ini.WriteInt("global", "x", global.x)之类的语句时MapServer中会不响应,而ini会出现重复的键值和键名。

5月5日

1、玩家1从TradeAge中登陆,之后玩家1从TestLog中登陆,在玩家1中可以看见玩家1。如果玩家2退出,其精灵也消失。如果玩家1退出,玩家2收到消息。

2、进入建筑物时玩家就不能再移动

3、从地图服务器和客户端的地图移动所需玩家信息中提取出了公共类CMapPlayer

派生出CServerMapPlayer和CClientMapPlayer。客户端地图移动所需玩家信息从图服务器传来,先转成CMapPlayer,再转成CClientMapPlayer。

5月6日整理文档

5月7日-15日回家

5月16日整理文档

5月17日上午去找老师没找到,

下午更改了玩家移动的时间间隔和速度等参数,

晚上为解决客户端无法显示其他玩家的移动,调试MapServer,发现要地图中添加新的玩家的方法有错,改正即可

5月18日

1、  手动修改城市1触发点,每个建筑物门口有四个触发图元

2、  在互联网上进行连接在,登陆远程服务器成功。

3、  当玩家跨越地图后,和原地图中的玩家互相看不见

原因:在跨越地图时只是重设了当前玩家精灵的偏移,没有重设其他的

修改:重设区域内所有的精灵

   3、在地图中加入阻挡,但是没有起作用,也许地图文件中未编辑阻挡关系

   4、用加了阻挡关系的地图,似乎阻挡的太多了,无法靠近建筑物,

而且进入建筑物更加容易消失。

5月19日写论文

5月20日

1、  客户端进入建筑物由地图服务器确认解决了消失问题

2、  在海上地图4的的港口进入城市后,又出海,被显示在海上地图2的的港口

修改:逻辑服务器进行了修改

3、  在删除精灵指针的同时释放内存

在海上和城市中使用不同的精灵:

服务器收到MapInfoRequest时重新设置精灵类型,以便于广播给区域其他玩家
客户端收到DisplaceMap时重新设置精灵类型,产生新的精灵
但是只是在登陆时可以从船只变成人物,以后再进出港一直是人物,无法重新设置精灵类型, 而且精灵背景为黑
原因:调试时很奇怪,玩家的状态总是与实际相反,而且只要一做pCurrent->f()

pSprite的属性值就混乱。
不理会以上,又可能是因为原有的精灵未释放,在显示两个精灵时精灵背景也会是黑的

5月21日

   1、客户端在每次运行状态机、切换地图、跨越地图后都用CMapManager::SetCamera()重新设置镜头和精灵坐标

   2、客户端在InitNewMap()删除原有玩家前先释放其精灵内存

   3、地图服务器和客户端在改变精灵类型时同时改变踫撞点

   4、出港是时玩家精灵是在OnDisplaceMap()中改变,可是这段单步调试时并不按语句执行,而且监视值有错(以前也碰到很多次这的情况,执行exe时没错,可能编译器有问题),甚至于无法单步执行至出港改变精灵类型的那一句。

其他客户端也需要显示这个玩家出港后的精灵,不同的是其他客户端在OnOtherIn()中从地图服务器获得这个玩家的信息,并产生精灵。虽然OnOtherIn()单步调试时并不按语句执行,但恰好可以在获得的信息看到玩家精灵类型值是2(正确值应为3)。

1) 追踪至地图服务器在OnMapInfoRequest中GetShipType=0, 精灵类型=ShipType+2=2

2) 追踪至SeverMapPlayer的Init()中有ship[0].Init(),而Tship.Init()的定义在gameserver

3) 追踪至gameserver的Tship.Init()中

    int type = ini.ReadInt(ca, "船只类型");

    identifier.ID = type;

this->baseInfo = g_ship.GetBaseShip(type);执行后baseInfo.type.ID仍为0,为加了一句   baseInfo.type.ID = type; , 问题解决

5月22日

1、  重新编辑了城市地图使玩家的移动更加流畅

2、  修改了地图编辑器显示地图的一些错误之后,在海洋地图边界加了了阻挡用于测试

5月23日-28日改论文

5月29日软件水平考试

5月30日论文,下午修改了对地图移动的触发点的判断,当玩家的中心进入触发点时才触发事件

5月31日

1、上午服务器的第0.5秒周期的移动偏移用0.1秒内偏移的5倍表示,而不是直接算0.5秒内偏移,使服务器和客户端的移动尽量一致。但是效果不明显,移动结束还是会被往前拉一些

2、客户端改成每0.5秒验证一次玩家的移动,这使服务器和客户端的移动尽量一致。但是为了使显示流畅,每0.1秒改变一下精灵的位置,并不改变玩家坐标。当至0.5秒验证玩家的移动时,如果移动阻挡将被拉回。移动有些不流畅。

3、下午原来状态机遍历每张地图的玩家列表,验证玩家的移动,由于玩家可能跨越地图,于是玩家的移动可能被计算两次,当初为了避免加了个预先跨越。

现在状态机遍历玩家列表,不用预先跨越,简化了程序,跨越地图不需服务器确认。

6月1日客户端在状态机在判断是否到0。5秒时出错,计数器从0到5,算成了0.6秒,以致移动不流畅。将计数器改成从1到5。以前的服务器的移动和补给验证存在同样的问题也纠正了。

6月2日白天停电,

1、  晚上发现第一个玩家进入建筑物后,第二个玩家进入城市时在其客户端仍然显示第一个玩家,未隐藏。

原因:第二个玩家客户端收到第一个玩家OtheIn消息时,产生精灵时未判断其处于建筑物中而将其隐藏。

2、  改人物相互阻挡的算法

将玩家重叠定义为:玩家A的精灵中心坐标处于玩家B的精灵区域中。由于玩家精灵的大小一样,其实玩家B的精灵中心坐标处于玩家A的精灵区域中。

人物相互阻挡并不要求十分精确,有时会出现玩家重叠的情况。

多个玩家从建筑物中出来,均被显示在门口是,会重叠

多个玩家同时移向同,均被显示在门口是,会重叠

为此,将人物相互阻挡的算法改为:玩家A移动时

1如果玩家A和B在尝试移动前已经互相重叠,A尝试移动后不改变玩家的相对方向,而且A将远离B,则不阻挡,否则阻挡

2如果玩家A和B在尝试移动未互相重叠,A尝试移动后玩家B的中心不处于A移动扫过的区域中,则不阻挡,否则阻挡

改后,多个玩家从建筑物中出来可以移动,移动速度较快时也不出现穿过对方的现象

6月3日

下午和黄良毅一起修改了CInitSet

晚由于客户端CSuperScene基本上只在mapManager中使用,于是将封装在CMapManager中。

  将set目录下的精灵ini文件中的[up]fsp=*改成[up]fps=*

6月10日

上午加入补给用完和水手死光后,玩家回到城市,完善了补给和水手同步

         

晚上加入一张海上地图,使之成为一个区域

 

 

 

 

 

 

 

注意:

1、  有些消息(OtherMove、OtherIn、OtherOut)是用于发送给其他玩家的,但由于在广播消息时没有考虑这一点,而是把消息发送给当前区域所有在地图中的人(建筑物中的玩家认为不在地图中),这样也会发送给自己。客户端收到自己的消息不进行处理,其他人的才处理。

2、  地图服务器通过OtherIn消息广播自己的进入之前,要把玩家的地图设为新地图。而客户端收到之后,要重新设置移动玩家的MoveOffset。

3、  地图服务器的ChangeMap已经没用到了,客户端的ChangeMap也只在OnAcrossMap中用一下,好像作用不大了

还有客户端的InitNewMap只是在登陆和进出港切换地图时用一下,InitNewAdjMap只是OnAcrossMap中与ChangeMap配合使用

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息