日誌:
a) 移動的碰撞只用了左上角,忘記了要用四個角
b) 跨越地圖的玩家移動被重複計算,爲此在VM中發現預先循環將所有跨越地圖的玩家放新地圖,接下來的兩次循環才進行移動
地圖服務器初始化地圖信息
4月18--20日服務器協同調試,不過經常被各種事情打斷
只發現以下錯誤:
1、 在testlogin中登錄第二個玩家,mapserver便退出
原因:在onread中多了一個對singal的判斷,以致線程在玩家1時沒有退出臨界區
當收到玩家2的消息,進入臨界區中會出錯
2、 消息會發生重疊,可能是Edit的顯示問題
3、 有時調試出錯退出,下一次調試會出錯,直到再下一次再正確
4、 第一個玩家登陸時,消息正確,但後面的玩家消息錯誤越來越多
原因:makemsg()中用於產生消息的buf太小了
5、直接運行exe,當兩個玩家登陸時,第一玩家收不到otherIn消息,而第二個卻收到兩條;於是mapserver調試運行,消息卻正確
原因:在檢查中
開始測試定時運行地圖狀態機,處理玩家移動
1、上述問題又出現,在從黃良毅更新了新的MsgLog後才正常,看來buf太小隻是一方面原因,另一方面是消息的追加方式。
2、Socket的OnRead線程在處理完msgBuf中所有的消息後才返回。如在處理某一消息處理時就到了狀態機運行的間隔時間,只能處理完該消息纔將控制權交給狀態機,當然狀態機會有所延遲。原來的OnRead沒有體現這些,而是默認消息處理不會超過間隔時間, 爲此進行了修改。
發現錯誤:
1、當兩個玩家登陸之後,玩家1和2都無法開始移動
原因:測試時玩家登陸都是在默認座標,將會互相阻擋,進港或出建築物也會有問題。
修改:根據玩家的移動方向不同選擇踫撞點。另外爲了測試方便,在些臨時文件保存玩家的登陸座標,測試時玩家從中讀出登陸時座標。
2、當移動起點和終點相同時,在計算移動參數會出現除零錯誤,加入判斷避免錯誤
測試進入建築物,選擇交易所,玩家進入交易所,邏輯服務器發回交易所和玩家自身的貨物信息。
測試出建築物,但是從gameserver收到msgQuitRequest後的處理未發消息給mapServer。
測試補給,將地圖和玩家屬性改成海上,補給會定時改變,好像沒什麼問題。
在客戶端加入MapMoveMsg和MapEventMsg消息的處理
1、測試跨越地圖移動,從地圖1移動至地圖2,
發現錯誤:當玩家準備跨越至地圖2時會出現訪問異常。
原因:在預先跨越地圖(PreBlock)在遍歷玩家list時發現有人跨越就將其刪除,即在遍歷容器時將修改容器,使容器失效。
修改:將所有跨越者保存在臨時表中,在遍歷結束後一併刪除。
2、對服務器地圖信息類和地圖玩家信息類重新命名,分別爲CMapInfo和CMapPlayer
1、 測試進港,從海上地圖2移動至港口,經邏輯服務器確認,進入地市地圖1。不過邏輯服務器的進港確認處理還未加入,只好以後再測
2、 測試出港,從地市地圖1移動至碼頭,客戶端發出港請求,邏輯服務器確認後,進入海上地圖2。
改正了碼頭、港口的觸發點錯誤、邏輯服務器對補給和水手判斷的錯誤,可以按以下過程出港。
玩家進入碼頭,邏輯服務器發回補給價格
玩家發出港請求,邏輯服務器將請求通知地圖服務器,地圖服務器發回海上地圖的信息
3、 將msgMoveBegin, msgPutOff, msgPutIn等消息實體是發送給地圖或邏輯服務器,其msgHead.userID就是要處理的玩家playerID,於是把原定義重複中的playerID都去掉了
對mapserver的代碼進行整理,改了TestLogin的菜單
重新測試出建築物,gameserver收到msgQuitRequest後,發msgQuitConfirm消息給mapServer。mapServer再發返回城市消息給客戶端。
重新確定了進港和進建築物的消息,在地圖服務器、客戶端重新進行處理
重新測試進港,gameserver收到msgPutInRequest後,發msgPutInConfirm消息給客戶端。客戶端模擬發msgMapInfoRequest,地圖服務器返回msgDisplaceMap
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破壞有關。只有在重啓或註銷之後才能正常運行一次
1、 加入玩家移動到鼠標點擊處,運行卻無法移動
原因:鼠標點擊座標是相對於鏡頭左上角的偏移,忘記將其轉成全局座標
2、 客戶端能自主移動進入港口並消失,在消息框卻沒有加移動驗證、進港等消息
原因:可能是客戶端狀態機的間隔0.1秒太小了(5 月3日又改回0.1秒,運行正常,可見不是間隔的問題,另有原因)
修改:將客戶端狀態機的間隔改成0.2秒,相應的地圖服務器的改成1秒
3、 客戶端接收到DisplaceMap便不響應,調試時異常斷點在list的empty()
原因:客戶端的各種list初始化時忘記Clear()
4、收到DisplaceMap便不響應,調試時在mapPlayer的getState()提示訪問衝突
原因:一開始從playerList獲得迭代器指針,在調用一個函數時容器被修改了,以致迭代器指針也失效,再使用就會提示訪問衝突
修改:在容器修改後重新獲得迭代器指針
1、 想在OnMapInitConfirm()中將獲得的一個玩家信息的內存釋放,提示在dbgheap中出現未處理異常:用戶斷點
原因:該內存在靜態消息buf,不是動態的。
2、 客戶端能自主移動進入港口並消失,在消息框卻沒有加移動驗證、進港等消息,如昨天一樣
原因:不明,但重啓後調試又正常
3、 客戶端接收到DisplaceMap便不響應,調試時異常斷點在list的end()
原因:客戶端的在初始化新地圖已經舊地圖全部刪除了,在後來的一個操作卻試圖獲得舊地圖的指針
修改:調整了初始化新地圖各項操作的順序
4、切換至新地圖後卻沒有顯示Sprite
原因: 新地圖playerList在添加與玩家是出錯
修改:
5、出現在地市地圖中時忘記重新SetCamera
6、切換地圖之後在碼頭門口,一移動又不響應,程序還是不穩定
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.
以後改進
1、跨越地圖的算法目前侷限在一個區域中移動,以後再實現類似環球航行的繞地球一圈的算法
2、在Cscene中加入成員函數AddSprite()用於加入一個精靈指針
在CMap中加入id,用於以後改進跨越地圖算法
3、跨越地圖時提示在CMapPlayer的GetMapID()訪問衝突,退出
原因:跨越時的算法有錯。
4、玩家移動到地圖邊界時靜止等待服務器確認跨越,確認後又開始運動,但是跨越後精靈會消失,要用鼠標點擊一下窗體精靈纔會出現
原因:跨越後忘記設置精靈和鏡頭的座標
5、跨越時,切換地圖後跳躍較大。雖然將在服務器確認後玩家狀態設爲運行,但似乎並沒開始運動,於是每次MoveCheck或是MoveOver消息到來後都跳躍一下
原因:不明
6、跨越地圖不等待服務器確認,但是鏡頭與移動方向反向移動
原因:跨越後忘記設置精靈和鏡頭的座標有錯
7、加入玩家退出遊戲的消息處理,但是在保存信息時ini.WriteInt("global", "x", global.x)之類的語句時MapServer中會不響應,而ini會出現重複的鍵值和鍵名。
1、玩家1從TradeAge中登陸,之後玩家1從TestLog中登陸,在玩家1中可以看見玩家1。如果玩家2退出,其精靈也消失。如果玩家1退出,玩家2收到消息。
2、進入建築物時玩家就不能再移動
3、從地圖服務器和客戶端的地圖移動所需玩家信息中提取出了公共類CMapPlayer
派生出CServerMapPlayer和CClientMapPlayer。客戶端地圖移動所需玩家信息從圖服務器傳來,先轉成CMapPlayer,再轉成CClientMapPlayer。
下午更改了玩家移動的時間間隔和速度等參數,
晚上爲解決客戶端無法顯示其他玩家的移動,調試MapServer,發現要地圖中添加新的玩家的方法有錯,改正即可
1、 手動修改城市1觸發點,每個建築物門口有四個觸發圖元
2、 在互聯網上進行連接在,登陸遠程服務器成功。
3、 當玩家跨越地圖後,和原地圖中的玩家互相看不見
原因:在跨越地圖時只是重設了當前玩家精靈的偏移,沒有重設其他的
修改:重設區域內所有的精靈
3、在地圖中加入阻擋,但是沒有起作用,也許地圖文件中未編輯阻擋關係
4、用加了阻擋關係的地圖,似乎阻擋的太多了,無法靠近建築物,
而且進入建築物更加容易消失。
1、 客戶端進入建築物由地圖服務器確認解決了消失問題
2、 在海上地圖4的的港口進入城市後,又出海,被顯示在海上地圖2的的港口
修改:邏輯服務器進行了修改
3、 在刪除精靈指針的同時釋放內存
在海上和城市中使用不同的精靈:
服務器收到MapInfoRequest時重新設置精靈類型,以便於廣播給區域其他玩家
客戶端收到DisplaceMap時重新設置精靈類型,產生新的精靈
但是只是在登陸時可以從船隻變成人物,以後再進出港一直是人物,無法重新設置精靈類型, 而且精靈背景爲黑
原因:調試時很奇怪,玩家的狀態總是與實際相反,而且只要一做pCurrent->f()
pSprite的屬性值就混亂。
不理會以上,又可能是因爲原有的精靈未釋放,在顯示兩個精靈時精靈背景也會是黑的
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; , 問題解決
1、 重新編輯了城市地圖使玩家的移動更加流暢
2、 修改了地圖編輯器顯示地圖的一些錯誤之後,在海洋地圖邊界加了了阻擋用於測試
1、上午服務器的第0.5秒週期的移動偏移用0.1秒內偏移的5倍表示,而不是直接算0.5秒內偏移,使服務器和客戶端的移動儘量一致。但是效果不明顯,移動結束還是會被往前拉一些
2、客戶端改成每0.5秒驗證一次玩家的移動,這使服務器和客戶端的移動儘量一致。但是爲了使顯示流暢,每0.1秒改變一下精靈的位置,並不改變玩家座標。當至0.5秒驗證玩家的移動時,如果移動阻擋將被拉回。移動有些不流暢。
3、下午原來狀態機遍歷每張地圖的玩家列表,驗證玩家的移動,由於玩家可能跨越地圖,於是玩家的移動可能被計算兩次,當初爲了避免加了個預先跨越。
現在狀態機遍歷玩家列表,不用預先跨越,簡化了程序,跨越地圖不需服務器確認。
1、 晚上發現第一個玩家進入建築物後,第二個玩家進入城市時在其客戶端仍然顯示第一個玩家,未隱藏。
原因:第二個玩家客戶端收到第一個玩家OtheIn消息時,產生精靈時未判斷其處於建築物中而將其隱藏。
2、 改人物相互阻擋的算法
將玩家重疊定義爲:玩家A的精靈中心座標處於玩家B的精靈區域中。由於玩家精靈的大小一樣,其實玩家B的精靈中心座標處於玩家A的精靈區域中。
人物相互阻擋並不要求十分精確,有時會出現玩家重疊的情況。
多個玩家從建築物中出來,均被顯示在門口是,會重疊
多個玩家同時移向同,均被顯示在門口是,會重疊
爲此,將人物相互阻擋的算法改爲:玩家A移動時
1如果玩家A和B在嘗試移動前已經互相重疊,A嘗試移動後不改變玩家的相對方向,而且A將遠離B,則不阻擋,否則阻擋
2如果玩家A和B在嘗試移動未互相重疊,A嘗試移動後玩家B的中心不處於A移動掃過的區域中,則不阻擋,否則阻擋
改後,多個玩家從建築物中出來可以移動,移動速度較快時也不出現穿過對方的現象
下午和黃良毅一起修改了CInitSet
晚由於客戶端CSuperScene基本上只在mapManager中使用,於是將封裝在CMapManager中。
將set目錄下的精靈ini文件中的[up]fsp=*改成[up]fps=*
上午加入補給用完和水手死光後,玩家回到城市,完善了補給和水手同步
晚上加入一張海上地圖,使之成爲一個區域
注意:
1、 有些消息(OtherMove、OtherIn、OtherOut)是用於發送給其他玩家的,但由於在廣播消息時沒有考慮這一點,而是把消息發送給當前區域所有在地圖中的人(建築物中的玩家認爲不在地圖中),這樣也會發送給自己。客戶端收到自己的消息不進行處理,其他人的才處理。
2、 地圖服務器通過OtherIn消息廣播自己的進入之前,要把玩家的地圖設爲新地圖。而客戶端收到之後,要重新設置移動玩家的MoveOffset。
3、 地圖服務器的ChangeMap已經沒用到了,客戶端的ChangeMap也只在OnAcrossMap中用一下,好像作用不大了
還有客戶端的InitNewMap只是在登陸和進出港切換地圖時用一下,InitNewAdjMap只是OnAcrossMap中與ChangeMap配合使用