|
|
@ -2,17 +2,18 @@ package core |
|
|
|
|
|
|
|
import ( |
|
|
|
"fmt" |
|
|
|
"github.com/aceld/zinx/ziface" |
|
|
|
"github.com/aceld/zinx/zinx_app_demo/mmo_game/pb" |
|
|
|
"github.com/golang/protobuf/proto" |
|
|
|
"math/rand" |
|
|
|
"sync" |
|
|
|
"time" |
|
|
|
|
|
|
|
"github.com/aceld/zinx/ziface" |
|
|
|
"github.com/aceld/zinx/zinx_app_demo/mmo_game/pb" |
|
|
|
"github.com/golang/protobuf/proto" |
|
|
|
) |
|
|
|
|
|
|
|
//玩家对象
|
|
|
|
type Player struct { |
|
|
|
Pid int32 //玩家ID
|
|
|
|
PID int32 //玩家ID
|
|
|
|
Conn ziface.IConnection //当前玩家的连接
|
|
|
|
X float32 //平面x坐标
|
|
|
|
Y float32 //高度
|
|
|
@ -23,19 +24,19 @@ type Player struct { |
|
|
|
/* |
|
|
|
Player ID 生成器 |
|
|
|
*/ |
|
|
|
var PidGen int32 = 1 //用来生成玩家ID的计数器
|
|
|
|
var IdLock sync.Mutex //保护PidGen的互斥机制
|
|
|
|
var PIDGen int32 = 1 //用来生成玩家ID的计数器
|
|
|
|
var IDLock sync.Mutex //保护PIDGen的互斥机制
|
|
|
|
|
|
|
|
//创建一个玩家对象
|
|
|
|
func NewPlayer(conn ziface.IConnection) *Player { |
|
|
|
//生成一个PID
|
|
|
|
IdLock.Lock() |
|
|
|
id := PidGen |
|
|
|
PidGen++ |
|
|
|
IdLock.Unlock() |
|
|
|
IDLock.Lock() |
|
|
|
ID := PIDGen |
|
|
|
PIDGen++ |
|
|
|
IDLock.Unlock() |
|
|
|
|
|
|
|
p := &Player{ |
|
|
|
Pid: id, |
|
|
|
PID: ID, |
|
|
|
Conn: conn, |
|
|
|
X: float32(160 + rand.Intn(50)), //随机在160坐标点 基于X轴偏移若干坐标
|
|
|
|
Y: 0, //高度为0
|
|
|
@ -46,11 +47,11 @@ func NewPlayer(conn ziface.IConnection) *Player { |
|
|
|
return p |
|
|
|
} |
|
|
|
|
|
|
|
//告知客户端pid,同步已经生成的玩家ID给客户端
|
|
|
|
func (p *Player) SyncPid() { |
|
|
|
//组建MsgId0 proto数据
|
|
|
|
data := &pb.SyncPid{ |
|
|
|
Pid: p.Pid, |
|
|
|
//告知客户端pID,同步已经生成的玩家ID给客户端
|
|
|
|
func (p *Player) SyncPID() { |
|
|
|
//组建MsgID0 proto数据
|
|
|
|
data := &pb.SyncPID{ |
|
|
|
PID: p.PID, |
|
|
|
} |
|
|
|
|
|
|
|
//发送数据给客户端
|
|
|
@ -60,9 +61,9 @@ func (p *Player) SyncPid() { |
|
|
|
//广播玩家自己的出生地点
|
|
|
|
func (p *Player) BroadCastStartPosition() { |
|
|
|
|
|
|
|
//组建MsgId200 proto数据
|
|
|
|
//组建MsgID200 proto数据
|
|
|
|
msg := &pb.BroadCast{ |
|
|
|
Pid: p.Pid, |
|
|
|
PID: p.PID, |
|
|
|
Tp: 2, //TP2 代表广播坐标
|
|
|
|
Data: &pb.BroadCast_P{ |
|
|
|
P: &pb.Position{ |
|
|
@ -80,17 +81,17 @@ func (p *Player) BroadCastStartPosition() { |
|
|
|
|
|
|
|
//给当前玩家周边的(九宫格内)玩家广播自己的位置,让他们显示自己
|
|
|
|
func (p *Player) SyncSurrounding() { |
|
|
|
//1 根据自己的位置,获取周围九宫格内的玩家pid
|
|
|
|
pids := WorldMgrObj.AoiMgr.GetPidsByPos(p.X, p.Z) |
|
|
|
//2 根据pid得到所有玩家对象
|
|
|
|
players := make([]*Player, 0, len(pids)) |
|
|
|
//1 根据自己的位置,获取周围九宫格内的玩家pID
|
|
|
|
pIDs := WorldMgrObj.AoiMgr.GetPIDsByPos(p.X, p.Z) |
|
|
|
//2 根据pID得到所有玩家对象
|
|
|
|
players := make([]*Player, 0, len(pIDs)) |
|
|
|
//3 给这些玩家发送MsgID:200消息,让自己出现在对方视野中
|
|
|
|
for _, pid := range pids { |
|
|
|
players = append(players, WorldMgrObj.GetPlayerByPid(int32(pid))) |
|
|
|
for _, pID := range pIDs { |
|
|
|
players = append(players, WorldMgrObj.GetPlayerByPID(int32(pID))) |
|
|
|
} |
|
|
|
//3.1 组建MsgId200 proto数据
|
|
|
|
//3.1 组建MsgID200 proto数据
|
|
|
|
msg := &pb.BroadCast{ |
|
|
|
Pid: p.Pid, |
|
|
|
PID: p.PID, |
|
|
|
Tp: 2, //TP2 代表广播坐标
|
|
|
|
Data: &pb.BroadCast_P{ |
|
|
|
P: &pb.Position{ |
|
|
@ -110,7 +111,7 @@ func (p *Player) SyncSurrounding() { |
|
|
|
playersData := make([]*pb.Player, 0, len(players)) |
|
|
|
for _, player := range players { |
|
|
|
p := &pb.Player{ |
|
|
|
Pid: player.Pid, |
|
|
|
PID: player.PID, |
|
|
|
P: &pb.Position{ |
|
|
|
X: player.X, |
|
|
|
Y: player.Y, |
|
|
@ -132,9 +133,9 @@ func (p *Player) SyncSurrounding() { |
|
|
|
|
|
|
|
//广播玩家聊天
|
|
|
|
func (p *Player) Talk(content string) { |
|
|
|
//1. 组建MsgId200 proto数据
|
|
|
|
//1. 组建MsgID200 proto数据
|
|
|
|
msg := &pb.BroadCast{ |
|
|
|
Pid: p.Pid, |
|
|
|
PID: p.PID, |
|
|
|
Tp: 1, //TP 1 代表聊天广播
|
|
|
|
Data: &pb.BroadCast_Content{ |
|
|
|
Content: content, |
|
|
@ -144,7 +145,7 @@ func (p *Player) Talk(content string) { |
|
|
|
//2. 得到当前世界所有的在线玩家
|
|
|
|
players := WorldMgrObj.GetAllPlayers() |
|
|
|
|
|
|
|
//3. 向所有的玩家发送MsgId:200消息
|
|
|
|
//3. 向所有的玩家发送MsgID:200消息
|
|
|
|
for _, player := range players { |
|
|
|
player.SendMsg(200, msg) |
|
|
|
} |
|
|
@ -154,10 +155,10 @@ func (p *Player) Talk(content string) { |
|
|
|
func (p *Player) UpdatePos(x float32, y float32, z float32, v float32) { |
|
|
|
|
|
|
|
//触发消失视野和添加视野业务
|
|
|
|
//计算旧格子gid
|
|
|
|
oldGid := WorldMgrObj.AoiMgr.GetGidByPos(p.X, p.Z) |
|
|
|
//计算新格子gid
|
|
|
|
newGid := WorldMgrObj.AoiMgr.GetGidByPos(x, z) |
|
|
|
//计算旧格子gID
|
|
|
|
oldGID := WorldMgrObj.AoiMgr.GetGIDByPos(p.X, p.Z) |
|
|
|
//计算新格子gID
|
|
|
|
newGID := WorldMgrObj.AoiMgr.GetGIDByPos(x, z) |
|
|
|
|
|
|
|
//更新玩家的位置信息
|
|
|
|
p.X = x |
|
|
@ -165,19 +166,19 @@ func (p *Player) UpdatePos(x float32, y float32, z float32, v float32) { |
|
|
|
p.Z = z |
|
|
|
p.V = v |
|
|
|
|
|
|
|
if oldGid != newGid { |
|
|
|
if oldGID != newGID { |
|
|
|
//触发gird切换
|
|
|
|
//把pid从就的aoi格子中删除
|
|
|
|
WorldMgrObj.AoiMgr.RemovePidFromGrid(int(p.Pid), oldGid) |
|
|
|
//把pid添加到新的aoi格子中去
|
|
|
|
WorldMgrObj.AoiMgr.AddPidToGrid(int(p.Pid), newGid) |
|
|
|
//把pID从就的aoi格子中删除
|
|
|
|
WorldMgrObj.AoiMgr.RemovePIDFromGrID(int(p.PID), oldGID) |
|
|
|
//把pID添加到新的aoi格子中去
|
|
|
|
WorldMgrObj.AoiMgr.AddPIDToGrID(int(p.PID), newGID) |
|
|
|
|
|
|
|
_ = p.OnExchangeAoiGrid(oldGid, newGid) |
|
|
|
_ = p.OnExchangeAoiGrID(oldGID, newGID) |
|
|
|
} |
|
|
|
|
|
|
|
//组装protobuf协议,发送位置给周围玩家
|
|
|
|
msg := &pb.BroadCast{ |
|
|
|
Pid: p.Pid, |
|
|
|
PID: p.PID, |
|
|
|
Tp: 4, //4- 移动之后的坐标信息
|
|
|
|
Data: &pb.BroadCast_P{ |
|
|
|
P: &pb.Position{ |
|
|
@ -197,47 +198,47 @@ func (p *Player) UpdatePos(x float32, y float32, z float32, v float32) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func (p *Player) OnExchangeAoiGrid(oldGid, newGid int) error { |
|
|
|
func (p *Player) OnExchangeAoiGrID(oldGID, newGID int) error { |
|
|
|
//获取就的九宫格成员
|
|
|
|
oldGrids := WorldMgrObj.AoiMgr.GetSurroundGridsByGid(oldGid) |
|
|
|
oldGrIDs := WorldMgrObj.AoiMgr.GetSurroundGrIDsByGID(oldGID) |
|
|
|
|
|
|
|
//为旧的九宫格成员建立哈希表,用来快速查找
|
|
|
|
oldGridsMap := make(map[int]bool, len(oldGrids)) |
|
|
|
for _, grid := range oldGrids { |
|
|
|
oldGridsMap[grid.GID] = true |
|
|
|
oldGrIDsMap := make(map[int]bool, len(oldGrIDs)) |
|
|
|
for _, grID := range oldGrIDs { |
|
|
|
oldGrIDsMap[grID.GID] = true |
|
|
|
} |
|
|
|
|
|
|
|
//获取新的九宫格成员
|
|
|
|
newGrids := WorldMgrObj.AoiMgr.GetSurroundGridsByGid(newGid) |
|
|
|
newGrIDs := WorldMgrObj.AoiMgr.GetSurroundGrIDsByGID(newGID) |
|
|
|
//为新的九宫格成员建立哈希表,用来快速查找
|
|
|
|
newGridsMap := make(map[int]bool, len(newGrids)) |
|
|
|
for _, grid := range newGrids { |
|
|
|
newGridsMap[grid.GID] = true |
|
|
|
newGrIDsMap := make(map[int]bool, len(newGrIDs)) |
|
|
|
for _, grID := range newGrIDs { |
|
|
|
newGrIDsMap[grID.GID] = true |
|
|
|
} |
|
|
|
|
|
|
|
//------ > 处理视野消失 <-------
|
|
|
|
offlineMsg := &pb.SyncPid{ |
|
|
|
Pid: p.Pid, |
|
|
|
offlineMsg := &pb.SyncPID{ |
|
|
|
PID: p.PID, |
|
|
|
} |
|
|
|
|
|
|
|
//找到在旧的九宫格中出现,但是在新的九宫格中没有出现的格子
|
|
|
|
leavingGrids := make([]*Grid, 0) |
|
|
|
for _, grid := range oldGrids { |
|
|
|
if _, ok := newGridsMap[grid.GID]; !ok { |
|
|
|
leavingGrids = append(leavingGrids, grid) |
|
|
|
leavingGrIDs := make([]*GrID, 0) |
|
|
|
for _, grID := range oldGrIDs { |
|
|
|
if _, ok := newGrIDsMap[grID.GID]; !ok { |
|
|
|
leavingGrIDs = append(leavingGrIDs, grID) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//获取需要消失的格子中的全部玩家
|
|
|
|
for _, grid := range leavingGrids { |
|
|
|
players := WorldMgrObj.GetPlayersByGid(grid.GID) |
|
|
|
for _, grID := range leavingGrIDs { |
|
|
|
players := WorldMgrObj.GetPlayersByGID(grID.GID) |
|
|
|
for _, player := range players { |
|
|
|
//让自己在其他玩家的客户端中消失
|
|
|
|
player.SendMsg(201, offlineMsg) |
|
|
|
|
|
|
|
//将其他玩家信息 在自己的客户端中消失
|
|
|
|
anotherOfflineMsg := &pb.SyncPid{ |
|
|
|
Pid: player.Pid, |
|
|
|
anotherOfflineMsg := &pb.SyncPID{ |
|
|
|
PID: player.PID, |
|
|
|
} |
|
|
|
p.SendMsg(201, anotherOfflineMsg) |
|
|
|
time.Sleep(200 * time.Millisecond) |
|
|
@ -247,15 +248,15 @@ func (p *Player) OnExchangeAoiGrid(oldGid, newGid int) error { |
|
|
|
//------ > 处理视野出现 <-------
|
|
|
|
|
|
|
|
//找到在新的九宫格内出现,但是没有在就的九宫格内出现的格子
|
|
|
|
enteringGrids := make([]*Grid, 0) |
|
|
|
for _, grid := range newGrids { |
|
|
|
if _, ok := oldGridsMap[grid.GID]; !ok { |
|
|
|
enteringGrids = append(enteringGrids, grid) |
|
|
|
enteringGrIDs := make([]*GrID, 0) |
|
|
|
for _, grID := range newGrIDs { |
|
|
|
if _, ok := oldGrIDsMap[grID.GID]; !ok { |
|
|
|
enteringGrIDs = append(enteringGrIDs, grID) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
onlineMsg := &pb.BroadCast{ |
|
|
|
Pid: p.Pid, |
|
|
|
PID: p.PID, |
|
|
|
Tp: 2, |
|
|
|
Data: &pb.BroadCast_P{ |
|
|
|
P: &pb.Position{ |
|
|
@ -268,8 +269,8 @@ func (p *Player) OnExchangeAoiGrid(oldGid, newGid int) error { |
|
|
|
} |
|
|
|
|
|
|
|
//获取需要显示格子的全部玩家
|
|
|
|
for _, grid := range enteringGrids { |
|
|
|
players := WorldMgrObj.GetPlayersByGid(grid.GID) |
|
|
|
for _, grID := range enteringGrIDs { |
|
|
|
players := WorldMgrObj.GetPlayersByGID(grID.GID) |
|
|
|
|
|
|
|
for _, player := range players { |
|
|
|
//让自己出现在其他人视野中
|
|
|
@ -277,7 +278,7 @@ func (p *Player) OnExchangeAoiGrid(oldGid, newGid int) error { |
|
|
|
|
|
|
|
//让其他人出现在自己的视野中
|
|
|
|
anotherOnlineMsg := &pb.BroadCast{ |
|
|
|
Pid: player.Pid, |
|
|
|
PID: player.PID, |
|
|
|
Tp: 2, |
|
|
|
Data: &pb.BroadCast_P{ |
|
|
|
P: &pb.Position{ |
|
|
@ -299,13 +300,13 @@ func (p *Player) OnExchangeAoiGrid(oldGid, newGid int) error { |
|
|
|
|
|
|
|
//获得当前玩家的AOI周边玩家信息
|
|
|
|
func (p *Player) GetSurroundingPlayers() []*Player { |
|
|
|
//得到当前AOI区域的所有pid
|
|
|
|
pids := WorldMgrObj.AoiMgr.GetPidsByPos(p.X, p.Z) |
|
|
|
//得到当前AOI区域的所有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))) |
|
|
|
//将所有pID对应的Player放到Player切片中
|
|
|
|
players := make([]*Player, 0, len(pIDs)) |
|
|
|
for _, pID := range pIDs { |
|
|
|
players = append(players, WorldMgrObj.GetPlayerByPID(int32(pID))) |
|
|
|
} |
|
|
|
|
|
|
|
return players |
|
|
@ -317,8 +318,8 @@ func (p *Player) LostConnection() { |
|
|
|
players := p.GetSurroundingPlayers() |
|
|
|
|
|
|
|
//2 封装MsgID:201消息
|
|
|
|
msg := &pb.SyncPid{ |
|
|
|
Pid: p.Pid, |
|
|
|
msg := &pb.SyncPID{ |
|
|
|
PID: p.PID, |
|
|
|
} |
|
|
|
|
|
|
|
//3 向周围玩家发送消息
|
|
|
@ -327,15 +328,15 @@ func (p *Player) LostConnection() { |
|
|
|
} |
|
|
|
|
|
|
|
//4 世界管理器将当前玩家从AOI中摘除
|
|
|
|
WorldMgrObj.AoiMgr.RemoveFromGridByPos(int(p.Pid), p.X, p.Z) |
|
|
|
WorldMgrObj.RemovePlayerByPid(p.Pid) |
|
|
|
WorldMgrObj.AoiMgr.RemoveFromGrIDByPos(int(p.PID), p.X, p.Z) |
|
|
|
WorldMgrObj.RemovePlayerByPID(p.PID) |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
发送消息给客户端, |
|
|
|
主要是将pb的protobuf数据序列化之后发送 |
|
|
|
*/ |
|
|
|
func (p *Player) SendMsg(msgId uint32, data proto.Message) { |
|
|
|
func (p *Player) SendMsg(msgID uint32, data proto.Message) { |
|
|
|
//fmt.Printf("before Marshal data = %+v\n", data)
|
|
|
|
//将proto Message结构体序列化
|
|
|
|
msg, err := proto.Marshal(data) |
|
|
@ -351,7 +352,7 @@ func (p *Player) SendMsg(msgId uint32, data proto.Message) { |
|
|
|
} |
|
|
|
|
|
|
|
//调用Zinx框架的SendMsg发包
|
|
|
|
if err := p.Conn.SendMsg(msgId, msg); err != nil { |
|
|
|
if err := p.Conn.SendMsg(msgID, msg); err != nil { |
|
|
|
fmt.Println("Player SendMsg error !") |
|
|
|
return |
|
|
|
} |
|
|
|