貿易時代開發文檔(四)--地圖服務器開發日誌【鄒志兵】

日誌:

310開始………………………………………………………

325發現地圖移動的兩個錯誤,並進行修正: 

a)         移動的碰撞只用了左上角,忘記了要用四個角

b)        跨越地圖的玩家移動被重複計算,爲此在VM中發現預先循環將所有跨越地圖的玩家放新地圖,接下來的兩次循環才進行移動

326完成地圖消息的消息處理,其中對地圖相關消息進行了重新定義

327開始客戶端的地圖移動,並嘗試用STL改造代碼

328完成客戶端的地圖移動,由於對STL理解不夠,只在少部分使用了STL函數

329完善客戶端地圖相關消息處理和發送

330完成客戶端地圖功能

331加入將地圖服務器涉及的消息重新分成兩類:地圖移動消息和地圖事件消息

地圖服務器初始化地圖信息

41登陸時地圖服務器初始化玩家信息

42玩家改變地圖時讀出將區域中新的地圖,並將新增地圖中的鄰居信息入通過MsgOtherIn傳入給他,同時將玩家信息傳給他的鄰居們

43根據統一後的消息加入了補給的計算

44加入VM的定時器,重載mapSocketOnRead函數

45加入數據臨界區

46停電

47上午開會,下午將全局函數整合進其他類,沒有成功

48加入MapManager類,將mapListplayer的相互操作作爲其成員函數,使CMapListSessionCMapPlayerSession完全獨立。

49MsgLog中加入地圖服務器相關消息,開始調試

410將繼續調試地圖服務器,同時將客戶端改成九張地圖

411將繼續調試地圖服務器

412在認真考慮客戶端與服務器的同步,進行修改

413地圖編輯器的打開文件和保存文件的方法

414停電

415上午開會,下午加入針對IN_BUILDING玩家的處理

416完善開題報告,在移動過程中添加、刪除精靈

417完善地圖服務器文檔

418--20日服務器協同調試,不過經常被各種事情打斷

   只發現以下錯誤:

1、  testlogin中登錄第二個玩家,mapserver便退出

原因:在onread中多了一個對singal的判斷,以致線程在玩家1時沒有退出臨界區

當收到玩家2的消息,進入臨界區中會出錯

2、  消息會發生重疊,可能是Edit的顯示問題

3、  有時調試出錯退出,下一次調試會出錯,直到再下一次再正確

4、  第一個玩家登陸時,消息正確,但後面的玩家消息錯誤越來越多

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

5、直接運行exe,當兩個玩家登陸時,第一玩家收不到otherIn消息,而第二個卻收到兩條;於是mapserver調試運行,消息卻正確

原因:在檢查中

 

421解決了地圖編輯器的保存問題

422發現上述問題5是因爲Editbuf太小,以致消息發送正常,只是顯示異常

開始測試定時運行地圖狀態機,處理玩家移動

423

1、上述問題又出現,在從黃良毅更新了新的MsgLog後才正常,看來buf太小隻是一方面原因,另一方面是消息的追加方式。

2SocketOnRead線程在處理完msgBuf中所有的消息後才返回。如在處理某一消息處理時就到了狀態機運行的間隔時間,只能處理完該消息纔將控制權交給狀態機,當然狀態機會有所延遲。原來的OnRead沒有體現這些,而是默認消息處理不會超過間隔時間, 爲此進行了修改。

424

發現錯誤:

1、當兩個玩家登陸之後,玩家12都無法開始移動

原因:測試時玩家登陸都是在默認座標,將會互相阻擋,進港或出建築物也會有問題。

修改:根據玩家的移動方向不同選擇踫撞點。另外爲了測試方便,在些臨時文件保存玩家的登陸座標,測試時玩家從中讀出登陸時座標。

2、當移動起點和終點相同時,在計算移動參數會出現除零錯誤,加入判斷避免錯誤

425

測試進入建築物,選擇交易所,玩家進入交易所,邏輯服務器發回交易所和玩家自身的貨物信息。

測試出建築物,但是從gameserver收到msgQuitRequest後的處理未發消息給mapServer

測試補給,將地圖和玩家屬性改成海上,補給會定時改變,像沒什麼問題。

在客戶端加入MapMoveMsgMapEventMsg消息的處理

426

       1、測試跨越地圖移動,從地圖1移動至地圖2

發現錯誤:當玩家準備跨越至地圖2時會出現訪問異常。

原因:在預先跨越地圖(PreBlock)在遍歷玩家list時發現有人跨越就將其刪除,即在遍歷容器時將修改容器,使容器失效。

修改:將所有跨越者保存在臨時表中,在遍歷結束後一併刪除。

2、對服務器地圖信息類和地圖玩家信息類重新命名,分別爲CMapInfoCMapPlayer

427

1、  測試進港,從海上地圖2移動至港口,經邏輯服務器確認,進入地市地圖1。不過邏輯服務器的進港確認處理還未加入,只好以後再測

2、  測試出港,從地市地圖1移動至碼頭,客戶端發出港請求,邏輯服務器確認後,進入海上地圖2

改正了碼頭、港口的觸發點錯誤、邏輯服務器對補給和水手判斷的錯誤,可以按以下過程出港。

玩家進入碼頭,邏輯服務器發回補給價格

玩家發出港請求,邏輯服務器將請求通知地圖服務器,地圖服務器發回海上地圖的信息

3、  msgMoveBegin, msgPutOff, msgPutIn等消息實體是發送給地圖或邏輯服務器,其msgHead.userID就是要處理的玩家playerID,於是把原定義重複中的playerID都去掉了

428(上午開會)

    mapserver的代碼進行整理,改了TestLogin的菜單

重新測試出建築物,gameserver收到msgQuitRequest後,發msgQuitConfirm消息給mapServermapServer再發返回城市消息給客戶端。

429(上午開會)

重新確定了進港和進建築物的消息,在地圖服務器、客戶端重新進行處理

重新測試進港,gameserver收到msgPutInRequest後,發msgPutInConfirm消息給客戶端。客戶端模擬發msgMapInfoRequest,地圖服務器返回msgDisplaceMap

430

    1、在TradeAge加入了狀態機,結果一運行就退出

   原因:MapServerTradeAge 都使用編號爲1的定時器,引起衝突

   修改:TradeAge 改用編號爲2的定時器

  2、玩家登陸時TradeAge異常退出,調試時在訪問玩家屬性提示訪問衝突

   原因: TradeAgeOnMapInit中先添加登陸的玩家,再初始化玩家當前區域的地圖。

在初始化當前地圖時有一個清空地圖中玩家的操作,把登陸的玩家也誤刪了

   修改:初始化當前地圖時只清空其他的玩家

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破壞有關。只有在重啓或註銷之後才能正常運行一次

51

1、  加入玩家移動到鼠標點擊處,運行卻無法移動

原因:鼠標點擊座標是相對於鏡頭左上角的偏移,忘記將其轉成全局座標

2、  客戶端能自主移動進入港口並消失,在消息框卻沒有加移動驗證、進港等消息

原因:可能是客戶端狀態機的間隔0.1秒太小了(5 3日又改回0.1秒,運行正常,可見不是間隔的問題,另有原因)

修改:將客戶端狀態機的間隔改成0.2秒,相應的地圖服務器的改成1

3、  客戶端接收到DisplaceMap便不響應,調試時異常斷點在listempty()

原因:客戶端的各種list初始化時忘記Clear()

  4、收到DisplaceMap便不響應,調試時在mapPlayergetState()提示訪問衝突

原因:一開始從playerList獲得迭代器指針,在調用一個函數時容器被修改了,以致迭代器指針也失效,再使用就會提示訪問衝突

修改:在容器修改後重新獲得迭代器指針

52

1、  想在OnMapInitConfirm()中將獲得的一個玩家信息的內存釋放,提示在dbgheap中出現未處理異常:用戶斷點

原因:該內存在靜態消息buf,不是動態的。

2、  客戶端能自主移動進入港口並消失,在消息框卻沒有加移動驗證、進港等消息,如昨天一樣

原因:不明,但重啓後調試又正常

3、  客戶端接收到DisplaceMap便不響應,調試時異常斷點在listend()

原因:客戶端的在初始化新地圖已經舊地圖全部刪除了,在後來的一個操作卻試圖獲得舊地圖的指針

修改:調整了初始化新地圖各項操作的順序

   4、切換至新地圖後卻沒有顯示Sprite

原因: 新地圖playerList在添加與玩家是出錯

修改:

      5、出現在地市地圖中時忘記重新SetCamera

    6、切換地圖之後在碼頭門口,一移動又不響應,程序還是不穩定

53繼續通過進入港口、在城市中移動,出港來測試

1、  玩家進入港口後出現在碼頭門口,但是無法移動

原因:GetGlobalByCompare在轉換方法不對,修改。

2、  移動時在y方向經常到不了鼠標點擊的終點

原因:移動時只以x座標判斷是否到終點,改成以xy一起判斷

3、移動至終點後不停止

原因: 上一步修改後判斷到終點的函數有問題

4、  鼠標點擊的終點後,要走的移動路徑貼近地圖左、上邊緣時,無法移動

原因:地圖的InMap()少了=,將左上邊緣的認爲不在地圖中

  

      5、在城市中移動,進入碼頭隱藏精靈, 點“出建築物”菜單又顯示精靈,正常

6、將地圖服務器的狀態週期改回0.5秒,客戶端爲0.1

地圖服務器移動驗證改成每10個週期一次,但是發現這樣玩家走的是折線

原因:因爲計算用乘100100來近似兩位精度的浮點計算,當玩家要走的移動路徑斜率較小或較大時,方向1上有偏移(方向12x y方向),方向2的偏移會近似成0。當前一方向移動移動至與終點時,才重設偏移,這下又方向2上有偏移,方向1的爲0.

以後改進

54

1、跨越地圖的算法目前侷限在一個區域中移動,以後再實現類似環球航行的繞地球一圈的算法

2、在Cscene中加入成員函數AddSprite()用於加入一個精靈指針

CMap中加入id,用於以後改進跨越地圖算法

3、跨越地圖時提示在CMapPlayerGetMapID()訪問衝突,退出

原因:跨越時的算法有錯。

4、玩家移動到地圖邊界時靜止等待服務器確認跨越,確認後又開始運動,但是跨越後精靈會消失,要用鼠標點擊一下窗體精靈纔會出現

原因:跨越後忘記設置精靈和鏡頭的座標

       5、跨越時,切換地圖後跳躍較大。雖然將在服務器確認後玩家狀態設爲運行,但似乎並沒開始運動,於是每次MoveCheck或是MoveOver消息到來後都跳躍一下

       原因:不明

6、跨越地圖不等待服務器確認,但是鏡頭與移動方向反向移動

原因:跨越後忘記設置精靈和鏡頭的座標有錯

7、加入玩家退出遊戲的消息處理,但是在保存信息時ini.WriteInt("global", "x", global.x)之類的語句時MapServer中會不響應,而ini會出現重複的鍵值和鍵名。

55

1、玩家1TradeAge中登陸,之後玩家1TestLog中登陸,在玩家1中可以看見玩家1。如果玩家2退出,其精靈也消失。如果玩家1退出,玩家2收到消息。

2、進入建築物時玩家就不能再移動

3、從地圖服務器和客戶端的地圖移動所需玩家信息中提取出了公共類CMapPlayer

派生出CServerMapPlayerCClientMapPlayer。客戶端地圖移動所需玩家信息從圖服務器傳來,先轉成CMapPlayer,再轉成CClientMapPlayer

56整理文檔

5715日回家

516整理文檔

517上午去找老師沒找到,

下午更改了玩家移動的時間間隔和速度等參數,

晚上爲解決客戶端無法顯示其他玩家的移動,調試MapServer,發現要地圖中添加新的玩家的方法有錯,改正即可

518

1、  手動修改城市1觸發點,每個建築物門口有四個觸發圖元

2、  在互聯網上進行連接在,登陸遠程服務器成功。

3、  當玩家跨越地圖後,和原地圖中的玩家互相看不見

原因:在跨越地圖時只是重設了當前玩家精靈的偏移,沒有重設其他的

修改:重設區域內所有的精靈

   3、在地圖中加入阻擋,但是沒有起作用,也許地圖文件中未編輯阻擋關係

   4、用加了阻擋關係的地圖,似乎阻擋的太多了,無法靠近建築物,

而且進入建築物更加容易消失。

519寫論文

520

1、  客戶端進入建築物由地圖服務器確認解決了消失問題

2、  在海上地圖4的的港口進入城市後,又出海,被顯示在海上地圖2的的港口

修改:邏輯服務器進行了修改

3、  在刪除精靈指針的同時釋放內存

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

服務器收到MapInfoRequest時重新設置精靈類型,以便於廣播給區域其他玩家

客戶端收到DisplaceMap時重新設置精靈類型,產生新的精靈

但是只是在登陸時可以從船隻變成人物,以後再進出港一直是人物,無法重新設置精靈類型, 而且精靈背景爲黑

原因:調試時很奇怪,玩家的狀態總是與實際相反,而且只要一做pCurrent->f()

pSprite的屬性值就混亂。

不理會以上,又可能是因爲原有的精靈未釋放,在顯示兩個精靈時精靈背景也會是黑的

521

   1、客戶端在每次運行狀態機、切換地圖、跨越地圖後都用CMapManager::SetCamera()重新設置鏡頭和精靈座標

   2、客戶端在InitNewMap()刪除原有玩家前先釋放其精靈內存

   3、地圖服務器和客戶端在改變精靈類型時同時改變踫撞點

   4、出港是時玩家精靈是在OnDisplaceMap()中改變,可是這段單步調試時並不按語句執行,而且監視值有錯(以前也碰到很多次這的情況,執行exe時沒錯,可能編譯器有問題),甚至於無法單步執行至出港改變精靈類型的那一句。

其他客戶端也需要顯示這個玩家出港後的精靈,不同的是其他客戶端在OnOtherIn()中從地圖服務器獲得這個玩家的信息,併產生精靈。雖然OnOtherIn()單步調試時並不按語句執行,但恰好可以在獲得的信息看到玩家精靈類型值是2(正確值應爲3)

1) 追蹤至地圖服務器在OnMapInfoRequestGetShipType=0, 精靈類型=ShipType+2=2

2) 追蹤至SeverMapPlayerInit()中有ship[0].Init(),Tship.Init()的定義在gameserver

3) 追蹤至gameserverTship.Init()

    int type = ini.ReadInt(ca, "船隻類型");

    identifier.ID = type;

this->baseInfo = g_ship.GetBaseShip(type);執行後baseInfo.type.ID仍爲0,爲加了一句   baseInfo.type.ID = type; , 問題解決

522

1、  重新編輯了城市地圖使玩家的移動更加流暢

2、  修改了地圖編輯器顯示地圖的一些錯誤之後,在海洋地圖邊界加了了阻擋用於測試

52328日改論文

529軟件水平考試

530論文,下午修改了對地圖移動的觸發點的判斷,當玩家的中心進入觸發點時才觸發事件

531

1、上午服務器的第0.5秒週期的移動偏移用0.1秒內偏移的5倍表示,而不是直接算0.5秒內偏移,使服務器和客戶端的移動儘量一致。但是效果不明顯,移動結束還是會被往前拉一些

2客戶端改成每0.5秒驗證一次玩家的移動,這使服務器和客戶端的移動儘量一致。但是爲了使顯示流暢,每0.1秒改變一下精靈的位置,並不改變玩家座標。當至0.5秒驗證玩家的移動時,如果移動阻擋將被拉回。移動有些不流暢。

3、下午原來狀態機遍歷每張地圖的玩家列表,驗證玩家的移動,由於玩家可能跨越地圖,於是玩家的移動可能被計算兩次,當初爲了避免加了個預先跨越。

現在狀態機遍歷玩家列表,不用預先跨越,簡化了程序,跨越地圖不需服務器確認。

61客戶端在狀態機在判斷是否到05秒時出錯,計數器從05,算成了0.6秒,以致移動不流暢。將計數器改成從15。以前的服務器的移動和補給驗證存在同樣的問題也糾正了。

62白天停電,

1、  晚上發現第一個玩家進入建築物後,第二個玩家進入城市時在其客戶端仍然顯示第一個玩家,未隱藏。

原因:第二個玩家客戶端收到第一個玩家OtheIn消息時,產生精靈時未判斷其處於建築物中而將其隱藏。

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

將玩家重疊定義爲:玩家A的精靈中心座標處於玩家B的精靈區域中。由於玩家精靈的大小一樣,其實玩家B的精靈中心座標處於玩家A的精靈區域中。

人物相互阻擋並不要求十分精確,有時會出現玩家重疊的情況。

多個玩家從建築物中出來,均被顯示在門口是,會重疊

多個玩家同時移向同,均被顯示在門口是,會重疊

爲此,將人物相互阻擋的算法改爲:玩家A移動時

1如果玩家AB在嘗試移動前已經互相重疊,A嘗試移動後不改變玩家的相對方向,而且A將遠離B,則不阻擋,否則阻擋

2如果玩家AB在嘗試移動未互相重疊,A嘗試移動後玩家B的中心不處於A移動掃過的區域中,則不阻擋,否則阻擋

改後,多個玩家從建築物中出來可以移動,移動速度較快時也不出現穿過對方的現象

63

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

晚由於客戶端CSuperScene基本上只在mapManager中使用,於是將封裝在CMapManager中。

  將set目錄下的精靈ini文件中的[up]fsp=*改成[up]fps=*

610

上午加入補給用完和水手死光後,玩家回到城市,完善了補給和水手同步

         

晚上加入一張海上地圖,使之成爲一個區域

 

 

 

 

 

 

 

注意:

1、  有些消息(OtherMoveOtherInOtherOut)是用於發送給其他玩家的,但由於在廣播消息時沒有考慮這一點,而是把消息發送給當前區域所有在地圖中的人(建築物中的玩家認爲不在地圖中),這樣也會發送給自己。客戶端收到自己的消息不進行處理,其他人的才處理。

2、  地圖服務器通過OtherIn消息廣播自己的進入之前,要把玩家的地圖設爲新地圖。而客戶端收到之後,要重新設置移動玩家的MoveOffset

3、  地圖服務器的ChangeMap已經沒用到了,客戶端的ChangeMap也只在OnAcrossMap中用一下,好像作用不大了

還有客戶端的InitNewMap只是在登陸和進出港切換地圖時用一下,InitNewAdjMap只是OnAcrossMap中與ChangeMap配合使用

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章