diff --git a/zinx_app_demo/mmo_game/conf/zinx.json b/zinx_app_demo/mmo_game/conf/zinx.json new file mode 100644 index 0000000..4ebe2cd --- /dev/null +++ b/zinx_app_demo/mmo_game/conf/zinx.json @@ -0,0 +1,7 @@ +{ + "Name":"Zinx Game", + "Host":"0.0.0.0", + "TcpPort":8999, + "MaxConn":3000, + "WorkerPoolSize":10 +} diff --git a/zinx_app_demo/mmo_game/core/player.go b/zinx_app_demo/mmo_game/core/player.go new file mode 100644 index 0000000..315aea2 --- /dev/null +++ b/zinx_app_demo/mmo_game/core/player.go @@ -0,0 +1,103 @@ +package core + +import ( + "fmt" + "github.com/golang/protobuf/proto" + "math/rand" + "zinx/ziface" + "zinx/zinx_app_demo/mmo_game/pb" +) + +//玩家对象 +type Player struct { + Pid int32 //玩家ID + Conn ziface.IConnection //当前玩家的连接 + X float32 //平面x坐标 + Y float32 //高度 + Z float32 //平面y坐标 (注意不是Y) + V float32 //旋转0-360度 +} + +//创建一个玩家对象 +func NewPlayer(conn ziface.IConnection, pid int32) *Player { + p := &Player{ + Pid : pid, + Conn:conn, + X:float32(160 + rand.Intn(10)),//随机在160坐标点 基于X轴偏移若干坐标 + Y:0, //高度为0 + Z:float32(134 + rand.Intn(17)), //随机在134坐标点 基于Y轴偏移若干坐标 + V:0, //角度为0,尚未实现 + } + + return p +} + +//告知客户端pid,同步已经生成的玩家ID给客户端 +func (p *Player) SyncPid() { + //组建MsgId0 proto数据 + data := &pb.SyncPid{ + Pid:p.Pid, + } + + //发送数据给客户端 + p.SendMsg(1, data) +} + +//广播玩家自己的出生地点 +func (p *Player) BroadCastStartPosition() { + + msg := &pb.BroadCast{ + Pid:p.Pid, + Tp:2,//TP2 代表广播坐标 + Data: &pb.BroadCast_P{ + &pb.Position{ + X:p.X, + Y:p.Y, + Z:p.Z, + V:p.V, + }, + }, + } + + p.SendMsg(200, msg) +} + +//广播玩家的自身地理位置信息 +func (p *Player) SyncSurrounding() { + //TODO 根据自己的位子,获取周围九宫格内的玩家PID + + //TODO 根据获取的PID集合, 获取所有的玩家信息 + + //TODO 构建自己的上线地点坐标 + + //TODO +} + + +/* + 发送消息给客户端, + 主要是将pb的protobuf数据序列化之后发送 + */ +func (p *Player) SendMsg(msgId uint32, data proto.Message) { + fmt.Printf("before Marshal data = %+v\n", data) + //将proto Message结构体序列化 + msg, err := proto.Marshal(data) + if err != nil { + fmt.Println("marshal msg err: ", err) + return + } + fmt.Printf("after Marshal data = %+v\n", msg) + + if p.Conn == nil { + fmt.Println("connection in player is nil") + return + } + + //调用Zinx框架的SendMsg发包 + if err := p.Conn.SendMsg(msgId, msg); err != nil { + fmt.Println("Player SendMsg error !") + return + } + + return +} \ No newline at end of file diff --git a/zinx_app_demo/mmo_game/game_client/client.exe b/zinx_app_demo/mmo_game/game_client/client.exe new file mode 100644 index 0000000..024c0fa Binary files /dev/null and b/zinx_app_demo/mmo_game/game_client/client.exe differ diff --git a/zinx_app_demo/mmo_game/pb/build.sh b/zinx_app_demo/mmo_game/pb/build.sh new file mode 100755 index 0000000..a3768f4 --- /dev/null +++ b/zinx_app_demo/mmo_game/pb/build.sh @@ -0,0 +1,2 @@ +#!/bin/bash +protoc --go_out=. *.proto diff --git a/zinx_app_demo/mmo_game/pb/msg.pb.go b/zinx_app_demo/mmo_game/pb/msg.pb.go new file mode 100644 index 0000000..b203109 --- /dev/null +++ b/zinx_app_demo/mmo_game/pb/msg.pb.go @@ -0,0 +1,263 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: msg.proto + +package pb + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +//同步客户端玩家ID +type SyncPid struct { + Pid int32 `protobuf:"varint,1,opt,name=Pid,proto3" json:"Pid,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SyncPid) Reset() { *m = SyncPid{} } +func (m *SyncPid) String() string { return proto.CompactTextString(m) } +func (*SyncPid) ProtoMessage() {} +func (*SyncPid) Descriptor() ([]byte, []int) { + return fileDescriptor_c06e4cca6c2cc899, []int{0} +} + +func (m *SyncPid) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SyncPid.Unmarshal(m, b) +} +func (m *SyncPid) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SyncPid.Marshal(b, m, deterministic) +} +func (m *SyncPid) XXX_Merge(src proto.Message) { + xxx_messageInfo_SyncPid.Merge(m, src) +} +func (m *SyncPid) XXX_Size() int { + return xxx_messageInfo_SyncPid.Size(m) +} +func (m *SyncPid) XXX_DiscardUnknown() { + xxx_messageInfo_SyncPid.DiscardUnknown(m) +} + +var xxx_messageInfo_SyncPid proto.InternalMessageInfo + +func (m *SyncPid) GetPid() int32 { + if m != nil { + return m.Pid + } + return 0 +} + +//玩家位置 +type Position struct { + X float32 `protobuf:"fixed32,1,opt,name=X,proto3" json:"X,omitempty"` + Y float32 `protobuf:"fixed32,2,opt,name=Y,proto3" json:"Y,omitempty"` + Z float32 `protobuf:"fixed32,3,opt,name=Z,proto3" json:"Z,omitempty"` + V float32 `protobuf:"fixed32,4,opt,name=V,proto3" json:"V,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Position) Reset() { *m = Position{} } +func (m *Position) String() string { return proto.CompactTextString(m) } +func (*Position) ProtoMessage() {} +func (*Position) Descriptor() ([]byte, []int) { + return fileDescriptor_c06e4cca6c2cc899, []int{1} +} + +func (m *Position) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Position.Unmarshal(m, b) +} +func (m *Position) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Position.Marshal(b, m, deterministic) +} +func (m *Position) XXX_Merge(src proto.Message) { + xxx_messageInfo_Position.Merge(m, src) +} +func (m *Position) XXX_Size() int { + return xxx_messageInfo_Position.Size(m) +} +func (m *Position) XXX_DiscardUnknown() { + xxx_messageInfo_Position.DiscardUnknown(m) +} + +var xxx_messageInfo_Position proto.InternalMessageInfo + +func (m *Position) GetX() float32 { + if m != nil { + return m.X + } + return 0 +} + +func (m *Position) GetY() float32 { + if m != nil { + return m.Y + } + return 0 +} + +func (m *Position) GetZ() float32 { + if m != nil { + return m.Z + } + return 0 +} + +func (m *Position) GetV() float32 { + if m != nil { + return m.V + } + return 0 +} + +//玩家广播数据 +type BroadCast struct { + Pid int32 `protobuf:"varint,1,opt,name=Pid,proto3" json:"Pid,omitempty"` + Tp int32 `protobuf:"varint,2,opt,name=Tp,proto3" json:"Tp,omitempty"` + // Types that are valid to be assigned to Data: + // *BroadCast_Content + // *BroadCast_P + // *BroadCast_ActionData + Data isBroadCast_Data `protobuf_oneof:"Data"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BroadCast) Reset() { *m = BroadCast{} } +func (m *BroadCast) String() string { return proto.CompactTextString(m) } +func (*BroadCast) ProtoMessage() {} +func (*BroadCast) Descriptor() ([]byte, []int) { + return fileDescriptor_c06e4cca6c2cc899, []int{2} +} + +func (m *BroadCast) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BroadCast.Unmarshal(m, b) +} +func (m *BroadCast) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BroadCast.Marshal(b, m, deterministic) +} +func (m *BroadCast) XXX_Merge(src proto.Message) { + xxx_messageInfo_BroadCast.Merge(m, src) +} +func (m *BroadCast) XXX_Size() int { + return xxx_messageInfo_BroadCast.Size(m) +} +func (m *BroadCast) XXX_DiscardUnknown() { + xxx_messageInfo_BroadCast.DiscardUnknown(m) +} + +var xxx_messageInfo_BroadCast proto.InternalMessageInfo + +func (m *BroadCast) GetPid() int32 { + if m != nil { + return m.Pid + } + return 0 +} + +func (m *BroadCast) GetTp() int32 { + if m != nil { + return m.Tp + } + return 0 +} + +type isBroadCast_Data interface { + isBroadCast_Data() +} + +type BroadCast_Content struct { + Content string `protobuf:"bytes,3,opt,name=Content,proto3,oneof"` +} + +type BroadCast_P struct { + P *Position `protobuf:"bytes,4,opt,name=P,proto3,oneof"` +} + +type BroadCast_ActionData struct { + ActionData int32 `protobuf:"varint,5,opt,name=ActionData,proto3,oneof"` +} + +func (*BroadCast_Content) isBroadCast_Data() {} + +func (*BroadCast_P) isBroadCast_Data() {} + +func (*BroadCast_ActionData) isBroadCast_Data() {} + +func (m *BroadCast) GetData() isBroadCast_Data { + if m != nil { + return m.Data + } + return nil +} + +func (m *BroadCast) GetContent() string { + if x, ok := m.GetData().(*BroadCast_Content); ok { + return x.Content + } + return "" +} + +func (m *BroadCast) GetP() *Position { + if x, ok := m.GetData().(*BroadCast_P); ok { + return x.P + } + return nil +} + +func (m *BroadCast) GetActionData() int32 { + if x, ok := m.GetData().(*BroadCast_ActionData); ok { + return x.ActionData + } + return 0 +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*BroadCast) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*BroadCast_Content)(nil), + (*BroadCast_P)(nil), + (*BroadCast_ActionData)(nil), + } +} + +func init() { + proto.RegisterType((*SyncPid)(nil), "pb.SyncPid") + proto.RegisterType((*Position)(nil), "pb.Position") + proto.RegisterType((*BroadCast)(nil), "pb.BroadCast") +} + +func init() { proto.RegisterFile("msg.proto", fileDescriptor_c06e4cca6c2cc899) } + +var fileDescriptor_c06e4cca6c2cc899 = []byte{ + // 218 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x90, 0xb1, 0x4e, 0x86, 0x30, + 0x10, 0xc7, 0x69, 0xbf, 0xaf, 0x1f, 0x72, 0x12, 0x63, 0x3a, 0x35, 0xea, 0x40, 0x98, 0x9c, 0x18, + 0xf4, 0x09, 0x04, 0x07, 0xc6, 0xa6, 0x12, 0x02, 0x6c, 0x2d, 0x18, 0xd3, 0xc1, 0xb6, 0x81, 0x2e, + 0x3e, 0x86, 0xaf, 0xe1, 0x53, 0x9a, 0x96, 0x90, 0x98, 0x38, 0xdd, 0xfd, 0xfe, 0x97, 0xfc, 0xee, + 0x72, 0x90, 0x7d, 0x6e, 0x1f, 0x95, 0x5b, 0xad, 0xb7, 0x14, 0x3b, 0x55, 0xde, 0x43, 0xfa, 0xf6, + 0x65, 0x66, 0xae, 0x17, 0x7a, 0x0b, 0x27, 0xae, 0x17, 0x86, 0x0a, 0xf4, 0x48, 0x44, 0x68, 0xcb, + 0x1a, 0xae, 0xb8, 0xdd, 0xb4, 0xd7, 0xd6, 0xd0, 0x1c, 0xd0, 0x10, 0x67, 0x58, 0xa0, 0x21, 0xd0, + 0xc8, 0xf0, 0x4e, 0x63, 0xa0, 0x89, 0x9d, 0x76, 0x9a, 0x02, 0xf5, 0xec, 0xbc, 0x53, 0x5f, 0x7e, + 0x23, 0xc8, 0xea, 0xd5, 0xca, 0xa5, 0x91, 0x9b, 0xff, 0xbf, 0x83, 0xde, 0x00, 0xee, 0x5c, 0x54, + 0x11, 0x81, 0x3b, 0x47, 0xef, 0x20, 0x6d, 0xac, 0xf1, 0xef, 0xc6, 0x47, 0x63, 0xd6, 0x26, 0xe2, + 0x08, 0xe8, 0x03, 0x20, 0x1e, 0xcd, 0xd7, 0x4f, 0x79, 0xe5, 0x54, 0x75, 0x1c, 0xd7, 0x26, 0x02, + 0x71, 0x5a, 0x00, 0xbc, 0xcc, 0x01, 0x5f, 0xa5, 0x97, 0x8c, 0x04, 0x63, 0x9b, 0x88, 0x3f, 0x59, + 0x7d, 0x81, 0x73, 0xac, 0xe4, 0x07, 0x63, 0xae, 0xd4, 0x25, 0xbe, 0xe1, 0xf9, 0x37, 0x00, 0x00, + 0xff, 0xff, 0x3b, 0x27, 0xe7, 0x05, 0x13, 0x01, 0x00, 0x00, +} diff --git a/zinx_app_demo/mmo_game/pb/msg.proto b/zinx_app_demo/mmo_game/pb/msg.proto new file mode 100644 index 0000000..e8f3ee0 --- /dev/null +++ b/zinx_app_demo/mmo_game/pb/msg.proto @@ -0,0 +1,27 @@ +syntax="proto3"; //Proto协议 +package pb; //当前包名 +option csharp_namespace="Pb"; //给C#提供的选项 + +//同步客户端玩家ID +message SyncPid{ + int32 Pid=1; +} + +//玩家位置 +message Position{ + float X=1; + float Y=2; + float Z=3; + float V=4; +} + +//玩家广播数据 +message BroadCast{ + int32 Pid=1; + int32 Tp=2; + oneof Data { + string Content=3; + Position P=4; + int32 ActionData=5; + } +} \ No newline at end of file diff --git a/zinx_app_demo/mmo_game/server.go b/zinx_app_demo/mmo_game/server.go new file mode 100644 index 0000000..d92d7af --- /dev/null +++ b/zinx_app_demo/mmo_game/server.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "zinx/ziface" + "zinx/zinx_app_demo/mmo_game/core" + "zinx/znet" +) + +//当客户端建立连接的时候的hook函数 +func OnConnecionAdd(conn ziface.IConnection) { + temp_pid := 1 + //创建一个玩家 + player := core.NewPlayer(conn, int32(temp_pid)) + //同步当前的PlayerID给客户端, 走MsgID:1 消息 + player.SyncPid() + //同步当前玩家的初始化坐标信息给客户端,走MsgID:200消息 + player.BroadCastStartPosition() + + fmt.Println("=====> Player pidId = ", temp_pid, " arrived ====") +} + +func main() { + //创建服务器句柄 + s := znet.NewServer() + + //注册客户端连接建立和丢失函数 + s.SetOnConnStart(OnConnecionAdd) + + //启动服务 + s.Serve() +}