You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

297 lines
5.5 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package main
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "fmt"
  6. "io"
  7. "math/rand"
  8. "net"
  9. "runtime"
  10. "sync"
  11. "time"
  12. "github.com/aceld/zinx/zinx_app_demo/mmo_game/pb"
  13. "github.com/golang/protobuf/proto"
  14. )
  15. type Message struct {
  16. Len uint32
  17. MsgID uint32
  18. Data []byte
  19. }
  20. type TcpClient struct {
  21. conn net.Conn
  22. X float32
  23. Y float32
  24. Z float32
  25. V float32
  26. PID int32
  27. isOnline chan bool
  28. }
  29. func (this *TcpClient) Unpack(headdata []byte) (head *Message, err error) {
  30. headBuf := bytes.NewReader(headdata)
  31. head = &Message{}
  32. // 读取Len
  33. if err = binary.Read(headBuf, binary.LittleEndian, &head.Len); err != nil {
  34. return nil, err
  35. }
  36. // 读取MsgID
  37. if err = binary.Read(headBuf, binary.LittleEndian, &head.MsgID); err != nil {
  38. return nil, err
  39. }
  40. // 封包太大
  41. //if head.Len > MaxPacketSize {
  42. // return nil, packageTooBig
  43. //}
  44. return head, nil
  45. }
  46. func (this *TcpClient) Pack(msgID uint32, dataBytes []byte) (out []byte, err error) {
  47. outbuff := bytes.NewBuffer([]byte{})
  48. // 写Len
  49. if err = binary.Write(outbuff, binary.LittleEndian, uint32(len(dataBytes))); err != nil {
  50. return
  51. }
  52. // 写MsgID
  53. if err = binary.Write(outbuff, binary.LittleEndian, msgID); err != nil {
  54. return
  55. }
  56. //all pkg data
  57. if err = binary.Write(outbuff, binary.LittleEndian, dataBytes); err != nil {
  58. return
  59. }
  60. out = outbuff.Bytes()
  61. return
  62. }
  63. func (this *TcpClient) SendMsg(msgID uint32, data proto.Message) {
  64. // 进行编码
  65. binaryData, err := proto.Marshal(data)
  66. if err != nil {
  67. fmt.Println(fmt.Sprintf("marshaling error: %s", err))
  68. return
  69. }
  70. sendData, err := this.Pack(msgID, binaryData)
  71. if err == nil {
  72. _, _ = this.conn.Write(sendData)
  73. } else {
  74. fmt.Println(err)
  75. }
  76. return
  77. }
  78. func (this *TcpClient) AIRobotAction() {
  79. //聊天或者移动
  80. //随机获得动作
  81. tp := rand.Intn(2)
  82. if tp == 0 {
  83. content := fmt.Sprintf("hello 我是player %d, 你是谁?", this.PID)
  84. msg := &pb.Talk{
  85. Content: content,
  86. }
  87. this.SendMsg(2, msg)
  88. } else {
  89. //移动
  90. x := this.X
  91. z := this.Z
  92. randPos := rand.Intn(2)
  93. if randPos == 0 {
  94. x -= float32(rand.Intn(10))
  95. z -= float32(rand.Intn(10))
  96. } else {
  97. x += float32(rand.Intn(10))
  98. z += float32(rand.Intn(10))
  99. }
  100. //纠正坐标位置
  101. if x > 410 {
  102. x = 410
  103. } else if x < 85 {
  104. x = 85
  105. }
  106. if z > 400 {
  107. z = 400
  108. } else if z < 75 {
  109. z = 75
  110. }
  111. //移动方向角度
  112. randV := rand.Intn(2)
  113. v := this.V
  114. if randV == 0 {
  115. v = 25
  116. } else {
  117. v = 335
  118. }
  119. //封装Position消息
  120. msg := &pb.Position{
  121. X: x,
  122. Y: this.Y,
  123. Z: z,
  124. V: v,
  125. }
  126. fmt.Println(fmt.Sprintf("player ID: %d. Walking...", this.PID))
  127. //发送移动MsgID:3的指令
  128. this.SendMsg(3, msg)
  129. }
  130. }
  131. /*
  132. 处理一个回执业务
  133. */
  134. func (this *TcpClient) DoMsg(msg *Message) {
  135. //处理消息
  136. //fmt.Println(fmt.Sprintf("msg ID :%d, data len: %d", msg.MsgID, msg.Len))
  137. if msg.MsgID == 1 {
  138. //服务器回执给客户端 分配ID
  139. //解析proto
  140. syncpID := &pb.SyncPID{}
  141. _ = proto.Unmarshal(msg.Data, syncpID)
  142. //给当前客户端ID进行赋值
  143. this.PID = syncpID.PID
  144. } else if msg.MsgID == 200 {
  145. //服务器回执客户端广播数据
  146. //解析proto
  147. bdata := &pb.BroadCast{}
  148. _ = proto.Unmarshal(msg.Data, bdata)
  149. //初次玩家上线 广播位置消息
  150. if bdata.Tp == 2 && bdata.PID == this.PID {
  151. //本人
  152. //更新客户端坐标
  153. this.X = bdata.GetP().X
  154. this.Y = bdata.GetP().Y
  155. this.Z = bdata.GetP().Z
  156. this.V = bdata.GetP().V
  157. fmt.Println(fmt.Sprintf("player ID: %d online.. at(%f,%f,%f,%f)", bdata.PID, this.X, this.Y, this.Z, this.V))
  158. //玩家已经成功上线
  159. this.isOnline <- true
  160. } else if bdata.Tp == 1 {
  161. fmt.Println(fmt.Sprintf("世界聊天,玩家%d说的话是: %s", bdata.PID, bdata.GetContent()))
  162. }
  163. }
  164. }
  165. func (this *TcpClient) Start() {
  166. go func() {
  167. for {
  168. //读取服务端发来的数据 ==》 SyncPID
  169. //1.读取8字节
  170. //第一次读取,读取数据头
  171. headData := make([]byte, 8)
  172. if _, err := io.ReadFull(this.conn, headData); err != nil {
  173. fmt.Println(err)
  174. return
  175. }
  176. pkgHead, err := this.Unpack(headData)
  177. if err != nil {
  178. return
  179. }
  180. //data
  181. if pkgHead.Len > 0 {
  182. pkgHead.Data = make([]byte, pkgHead.Len)
  183. if _, err := io.ReadFull(this.conn, pkgHead.Data); err != nil {
  184. return
  185. }
  186. }
  187. //处理服务器回执业务
  188. this.DoMsg(pkgHead)
  189. }
  190. }()
  191. // 10s后,断开连接
  192. for {
  193. select {
  194. case <-this.isOnline:
  195. go func() {
  196. for {
  197. this.AIRobotAction()
  198. time.Sleep(time.Second)
  199. }
  200. }()
  201. case <-time.After(time.Second * 10):
  202. _ = this.conn.Close()
  203. return
  204. }
  205. }
  206. }
  207. func NewTcpClient(ip string, port int) *TcpClient {
  208. addrStr := fmt.Sprintf("%s:%d", ip, port)
  209. conn, err := net.Dial("tcp", addrStr)
  210. if err != nil {
  211. panic(err)
  212. }
  213. client := &TcpClient{
  214. conn: conn,
  215. PID: 0,
  216. X: 0,
  217. Y: 0,
  218. Z: 0,
  219. V: 0,
  220. isOnline: make(chan bool),
  221. }
  222. return client
  223. }
  224. func main() {
  225. // 开启一个waitgroup,同时运行3个goroutine
  226. runtime.GOMAXPROCS(runtime.NumCPU())
  227. var wg sync.WaitGroup
  228. wg.Add(3)
  229. go func() {
  230. defer wg.Done()
  231. for i := 0; i < 10; i++ {
  232. client := NewTcpClient("127.0.0.1", 8999)
  233. client.Start()
  234. }
  235. }()
  236. go func() {
  237. defer wg.Done()
  238. for i := 0; i < 10; i++ {
  239. client := NewTcpClient("127.0.0.1", 8999)
  240. client.Start()
  241. }
  242. }()
  243. go func() {
  244. defer wg.Done()
  245. for i := 0; i < 10; i++ {
  246. client := NewTcpClient("127.0.0.1", 8999)
  247. client.Start()
  248. }
  249. }()
  250. fmt.Println("AI robot start")
  251. wg.Wait()
  252. fmt.Println("AI robot exit")
  253. }