package entertainment import ( "go_dreamfactory/comm" "go_dreamfactory/lego/sys/timewheel" "go_dreamfactory/modules" "go_dreamfactory/pb" "time" "go.mongodb.org/mongo-driver/bson/primitive" "google.golang.org/protobuf/proto" ) const ( MaxPs = 2 // 最大体力 MaxRound = 7 // 最大回合数 MaxTime = 1800 // 游戏操作时间 AITime = 4 // AI延迟操作时间操作时间 随机+-3 ) //游戏房间 type Room struct { modules.ModuleBase Id string // 房间id szSession []comm.IUserSession player1 *pb.PlayerData // 玩家1 player2 *pb.PlayerData // 玩家2 chessboard *MapData module *Entertainment power string // 谁的权限 round int32 // 轮数 operatetimer *timewheel.Task //操作倒计时定时器 aiTimer *timewheel.Task //AI操作随机做个延时 } func (this *Room) operateTimeOut(task *timewheel.Task, args ...interface{}) { if this.operatetimer != nil { timewheel.Remove(this.operatetimer) } if this.player1.Uid == this.power { // 给玩家2 this.power = this.player2.Uid this.player2.Ps = MaxPs // 恢复体力 } else { // 权限给1号玩家 this.power = this.player1.Uid this.player1.Ps = MaxPs // 恢复体力 } this.round++ // 回合+1 if this.round > MaxRound*2 { // 游戏结束 this.GameOver() } this.operatetimer = timewheel.Add(time.Second*MaxTime, this.operateTimeOut) // 开启新的定时器 var szMap []*pb.MapData szMap = append(szMap, &pb.MapData{ Data: this.chessboard.Plat, }) //this.module.Debugf("超时%d", configure.Now().Unix()) if err := this.module.SendMsgToSession(string(this.module.GetType()), "operatorrst", &pb.EntertainOperatorRstPush{ Mpadata: szMap, Power: this.power, Score: 0, Round: this.round, User1: this.player1, User2: this.player2, }, this.szSession...); err != nil { this.Errorln(err) } } func (this *Room) InitRoom(module *Entertainment, s1 comm.IUserSession, s2 comm.IUserSession, p1 *pb.PlayerData, p2 *pb.PlayerData) *Room { this.chessboard = new(MapData) this.chessboard.InitMap(module) // 初始化棋盘 this.szSession = append(this.szSession, s1.Clone()) if p2.Uid != "999" { // 是否是机器人 this.szSession = append(this.szSession, s2.Clone()) } return &Room{ ModuleBase: modules.ModuleBase{}, Id: primitive.NewObjectID().Hex(), player1: p1, player2: p2, chessboard: this.chessboard, module: module, power: s1.GetUserId(), round: 1, szSession: this.szSession, } } // AI 操作了 func (this *Room) AiTimeOut(task *timewheel.Task, args ...interface{}) { var ( curScore int32 szMap []*pb.MapData ) this.player2.Ps-- if this.player2.Ps <= 0 { // 权限给下一个人 this.power = this.player1.Uid this.round++ } this.player1.Ps = MaxPs if this.aiTimer != nil { timewheel.Remove(this.aiTimer) } // 交换元素 bSwap := this.chessboard.AiSwapGirde() // 交换格子 if !bSwap { this.module.Errorf("AiSwapGirde fialed") } szMap = append(szMap, &pb.MapData{ Data: this.chessboard.Plat, }) if score, m := this.chessboard.CheckMap(); score > 0 { curScore += score szMap = append(szMap, m...) } this.player2.Score += curScore // 清理旧的计时器 开启一个新的 if this.operatetimer != nil { timewheel.Remove(this.operatetimer) } this.operatetimer = timewheel.Add(time.Second*MaxTime, this.operateTimeOut) // 开启新的定时器 // 广播消息 if err := this.module.SendMsgToSession(string(this.module.GetType()), "operatorrst", &pb.EntertainOperatorRstPush{ Mpadata: szMap, Power: this.power, Score: curScore, Round: this.round, User1: this.player1, User2: this.player2, }, this.szSession...); err != nil { this.Errorln(err) } } func (this *Room) ReceiveMessage(session comm.IUserSession, stype string, msg proto.Message) (errdata *pb.ErrorData) { switch stype { case "operator": // 操作消息 var ( curScore int32 ) var szMap []*pb.MapData req := msg.(*pb.EntertainOperatorReq) if session.GetUserId() != this.power { // 校验是不是你的权限 return } if this.operatetimer != nil { timewheel.Remove(this.operatetimer) } // 交换元素 this.chessboard.SwapGirde(req.Curid, req.Targetid) // 交换格子 szMap = append(szMap, &pb.MapData{ Data: this.chessboard.Plat, }) if score, m := this.chessboard.CheckMap(); score > 0 { curScore += score szMap = append(szMap, m...) } //this.player2.Score += curScore // 开启新的定时器 if this.operatetimer != nil { timewheel.Remove(this.operatetimer) } this.operatetimer = timewheel.Add(time.Second*MaxTime, this.operateTimeOut) // 开启新的定时器 if this.power == this.player1.Uid { //权限校验 this.player1.Score += curScore this.player1.Ps-- if this.player1.Ps <= 0 { // 权限给下一个人 this.power = this.player2.Uid if len(this.szSession) == 1 { // 校验2号玩家是不是AI // 起一个定时器 if this.aiTimer != nil { timewheel.Remove(this.aiTimer) } this.aiTimer = timewheel.Add(time.Second*AITime, this.AiTimeOut) } this.round++ } this.player2.Ps = MaxPs } else if this.power == this.player2.Uid { this.player2.Score += curScore this.player2.Ps-- if this.player2.Ps <= 0 { // 权限给下一个人 this.power = this.player1.Uid this.round++ } this.player1.Ps = MaxPs } else { // err 未知权限 return } // 广播消息 if err := this.module.SendMsgToSession(string(this.module.GetType()), "operatorrst", &pb.EntertainOperatorRstPush{ Mpadata: szMap, Power: this.power, Score: curScore, Round: this.round, User1: this.player1, User2: this.player2, }, this.szSession...); err != nil { this.Errorln(err) } case "ready": if len(this.szSession) == 1 { // AI对战的话直接开始游戏 if err := this.module.SendMsgToSession(string(this.module.GetType()), "startgame", &pb.EntertainStartGamePush{ User1: this.player1, User2: this.player2, Mpadata: &pb.MapData{ Data: this.chessboard.Plat, }, Power: this.power, Round: this.round, }, session); err != nil { this.Errorln(err) } this.operatetimer = timewheel.Add(time.Second*MaxTime, this.operateTimeOut) } } return } // 玩家操作 func (this *Room) Opertor(uid string, iType int32, old int32, new int32) (errdata *pb.ErrorData) { if iType == 1 { this.chessboard.SwapGirde(old, new) // 交换格子 } return } func (this *Room) StartGame() (errdata *pb.ErrorData) { if err := this.module.SendMsgToSession(string(this.module.GetType()), "startgame", &pb.EntertainStartGamePush{ User1: this.player1, User2: this.player2, Mpadata: &pb.MapData{ Data: this.chessboard.Plat, }, Power: this.power, Round: this.round, }, this.szSession...); err != nil { this.Errorln(err) } return } // 游戏结束 func (this *Room) GameOver() (errdata *pb.ErrorData) { if this.aiTimer != nil { timewheel.Remove(this.aiTimer) } if this.operatetimer != nil { timewheel.Remove(this.operatetimer) } this.module.SendMsgToSession(string(this.module.GetType()), "gameover", &pb.EntertainGameOverPush{ User1: this.player1, User2: this.player2, Mpadata: &pb.MapData{ Data: this.chessboard.Plat, }, Power: "", Round: this.round, }) return }