Zinx源代碼
github
https://github.com/aceld/zinx
gitee碼云
https://gitee.com/Aceld/zinx
在線開發(fā)教程
【B站】
zinx視頻教程-Golang輕量級TCP服務器框架-適合自學者
【YouTube】
zinx開發(fā)YouTube中國版
微信端文檔
【Zinx教程目錄】
完整教程電子版(在線高清)-下載
Zinx框架視頻教程(框架篇)(完整版下載)鏈接在下面正文
Zinx框架視頻教程(應用篇)(完整版下載)鏈接在下面正文
Zinx開發(fā)API文檔
Zinx第一章-引言
Zinx第二章-初識Zinx框架
Zinx第三章-基礎路由模塊
Zinx第四章-全局配置
Zinx第五章-消息封裝
Zinx第六章-多路由模式
Zinx第七章-讀寫分離模型
Zinx第八章-消息隊列及多任務
Zinx第九章-鏈接管理
Zinx第十章-連接屬性設置
【Zinx應用案例-MMO多人在線游戲】
(1)案例介紹
(2)AOI興趣點算法
(3)數(shù)據(jù)傳輸協(xié)議protocol buffer
(4)Proto3協(xié)議定義
(5)構(gòu)建項目及用戶上線
(6)世界聊天
(7)上線位置信息同步
(8)移動位置與AOI廣播
(9)玩家下線
(10)模擬客戶端AI模塊
現(xiàn)在我們來添加玩家移動的時候辣垒,周邊玩家顯示同步位置躺苦,具體流程圖张症,如下:
這里面涉及到兩個消息MsgID:3和 MsgID200九杂,Tp=4。當玩家移動的時候脚线,客戶端會主動給服務端發(fā)送MsgID:3
的消息. 所以首先搁胆,我們應該給服務端注冊MsgID:3
的路由處理業(yè)務
mmo_game/ server.go
func main() {
//創(chuàng)建服務器句柄
s := znet.NewServer()
//注冊客戶端連接建立和丟失函數(shù)
s.SetOnConnStart(OnConnecionAdd)
//注冊路由
s.AddRouter(2, &api.WorldChatApi{}) //聊天
s.AddRouter(3, &api.MoveApi{}) //移動
//啟動服務
s.Serve()
}
接下來,我們需要創(chuàng)建一個api接口,實現(xiàn)MoveApi{}
模塊.
mmo_game/api/move.go
package api
import (
"fmt"
"github.com/golang/protobuf/proto"
"zinx/ziface"
"zinx/zinx_app_demo/mmo_game/core"
"zinx/zinx_app_demo/mmo_game/pb"
"zinx/znet"
)
//玩家移動
type MoveApi struct {
znet.BaseRouter
}
func (*MoveApi) Handle(request ziface.IRequest) {
//1. 將客戶端傳來的proto協(xié)議解碼
msg := &pb.Position{}
err := proto.Unmarshal(request.GetData(), msg)
if err != nil {
fmt.Println("Move: Position Unmarshal error ", err)
return
}
//2. 得知當前的消息是從哪個玩家傳遞來的,從連接屬性pid中獲取
pid, err := request.GetConnection().GetProperty("pid")
if err != nil {
fmt.Println("GetProperty pid error", err)
request.GetConnection().Stop()
return
}
fmt.Printf("user pid = %d , move(%f,%f,%f,%f)", pid, msg.X, msg.Y, msg.Z, msg.V)
//3. 根據(jù)pid得到player對象
player := core.WorldMgrObj.GetPlayerByPid(pid.(int32))
//4. 讓player對象發(fā)起移動位置信息廣播
player.UpdatePos(msg.X, msg.Y, msg.Z, msg.V)
}
? move.go
的業(yè)務和我們之前的world_chat.go
的業(yè)務很像丰涉。最后調(diào)用了Player.UpdatPos()
方法拓巧,該方法是主要處理及發(fā)送同步消息的方法。我們接下來一起實現(xiàn)這個方法.
mmo_game/core/player.go
//廣播玩家位置移動
func (p *Player) UpdatePos(x float32, y float32, z float32, v float32) {
//更新玩家的位置信息
p.X = x
p.Y = y
p.Z = z
p.V = v
//組裝protobuf協(xié)議一死,發(fā)送位置給周圍玩家
msg := &pb.BroadCast{
Pid:p.Pid,
Tp:4, //4 - 移動之后的坐標信息
Data: &pb.BroadCast_P{
P:&pb.Position{
X:p.X,
Y:p.Y,
Z:p.Z,
V:p.V,
},
},
}
//獲取當前玩家周邊全部玩家
players := p.GetSurroundingPlayers()
//向周邊的每個玩家發(fā)送MsgID:200消息肛度,移動位置更新消息
for _, player := range players {
player.SendMsg(200, msg)
}
}
//獲得當前玩家的AOI周邊玩家信息
func (p *Player) GetSurroundingPlayers() []*Player {
//得到當前AOI區(qū)域的所有pid
pids := WorldMgrObj.AoiMgr.GetPidsByPos(p.X, p.Z)
//將所有pid對應的Player放到Player切片中
players := make([]*Player, 0, len(pids))
for _, pid := range pids {
players = append(players, WorldMgrObj.GetPlayerByPid(int32(pid)))
}
return players
}
? 其中GetSurroundingPlayers()
是獲取當前玩家AOI周邊的玩家Player對象有哪些。
該方法的整體思路是獲取周邊的所有玩家投慈,發(fā)送位置更新信息承耿。
下面我們再次啟動服務器,同時開3個客戶端伪煤,看看最后的效果加袋。
顯示證明,3個客戶端已經(jīng)可以實現(xiàn)移動同步的過程抱既,那么實際上职烧,我們基本的MMO大型網(wǎng)游在線游戲的基礎模型已經(jīng)搭建完成了,接下來至于添加一些其他的游戲機制防泵,比如對戰(zhàn)蚀之,積分等。實際上可以基于這個開發(fā)架構(gòu)和流程繼續(xù)迭代開發(fā)了捷泞。
關(guān)于作者:
作者:Aceld(劉丹冰)
簡書號:IT無崖子
mail: danbing.at@gmail.com
github: https://github.com/aceld
原創(chuàng)書籍gitbook: http://legacy.gitbook.com/@aceld
原創(chuàng)聲明:未經(jīng)作者允許請勿轉(zhuǎn)載, 如果轉(zhuǎn)載請注明出處