斗地主项目总结

一、运行流程

  开始界面

  1. 点击开始游戏按钮,执行 PlayPanel 类 startClick 函数,

1 /// <summary>
2 /// 开始游戏按钮响应函数
3 /// </summary>
4 private void startClick()
5 {
6     Dispatch(AreaCode.UI, UIEvent.START_PANEL_ACTIVE, true);      
7 }

 

  该函数向 UI 层发送 START_PANEL_ACTIVE 事件,传输消息 true。

  然后是 StartPanel 类 Execute 函数,

 1 public override void Execute(int eventCode, object message)
 2 {
 3     switch (eventCode)
 4     {
 5         case UIEvent.START_PANEL_ACTIVE:
 6             setPanelActive((bool)message);
 7             break;
 8         default:
 9             break;
10     }
11 }

  该函数接收消息,调用 setPanelActive 函数显示开始游戏面板。

  点击注册账号按钮流程类似。

 

  登录界面:

 

  2. 点击登录按钮,执行 StartPanel 类 loginClick 函数,

 1 /// <summary>
 2 /// 登录按钮的点击事件处理
 3 /// </summary>
 4 private void loginClick()
 5 {
 6     // 若用户名输入为空
 7     if (string.IsNullOrEmpty(inputAccount.text))
 8     {
 9         promptMsg.Change("用户名输入为空", Color.red);
10         Dispatch(AreaCode.UI, UIEvent.PROMPT_MSG, promptMsg);
11         return;
12     }  
13     // 若密码输入为空
14     if (string.IsNullOrEmpty(inputPassword.text))      
15     {
16         promptMsg.Change("密码输入为空", Color.red);
17         Dispatch(AreaCode.UI, UIEvent.PROMPT_MSG, promptMsg);
18         return;
19     }
20     // 若密码输入不是4到16位
21     if(inputPassword.text.Length < 4
22         || inputPassword.text.Length > 16)
23     {
24         promptMsg.Change("密码输入不是4到16位", Color.red);
25         Dispatch(AreaCode.UI, UIEvent.PROMPT_MSG, promptMsg);
26         return;
27     }
28 
29     //需要和服务器交互了
30     AccountDto dto = new AccountDto(inputAccount.text, inputPassword.text);
31     socketMsg.Change(OpCode.ACCOUNT, AccountCode.LOGIN, dto);
32     Dispatch(AreaCode.NET, 0, socketMsg);
33 }
loginClick

 

 

 

 

  该函数先验证输入是否符合规定,若不符合,则输出相应消息;若符合,则与服务器交互。

  输出相应消息实现,自定义消息类 PromptMsg,

 1 /// <summary>
 2 /// 提示窗口
 3 /// </summary>
 4 class PromptMsg
 5 {
 6     public string text;
 7     public Color color;
 8 
 9     public PromptMsg()
10     {
11 
12     }
13 
14     public PromptMsg(string text, Color color)
15     {
16         this.text = text;
17         this.color = color;
18     }
19 
20     /// <summary>
21     /// 改变属性,防止多次 new 
22     /// </summary>
23     /// <param name="text"></param>
24     /// <param name="color"></param>
25     public void Change(string text, Color color)
26     {
27         this.text = text;
28         this.color = color;
29     }
30 }
PromptMsg

 

 

   然后向 UI 层发送 PROMPT_MSG 事件,

  然后是 PromptPanel 类 Execute 函数接收消息,

 1 public override void Execute(int eventCode, object message)
 2 {
 3     switch (eventCode)
 4     {
 5         case UIEvent.PROMPT_MSG:                    // 提示信息
 6             PromptMsg msg = message as PromptMsg;
 7             PromptMessage(msg.text, msg.color);
 8             break;
 9         default:
10             break;
11     }
12 }
Execute

  通过 PromptMessage 函数显示提醒效果,

 1 /// <summary>
 2 /// 提示消息
 3 /// </summary>
 4 /// <param name="text">显示文字</param>
 5 /// <param name="color">显示颜色</param>
 6 private void PromptMessage(string text, Color color)
 7 {
 8     txt.text = text;
 9     txt.color = color;
10     cg.alpha = 0;
11     StartCoroutine(PromptAnim());       // 播放动画
12 }
PromptMessage

 

 

 

  从上面两个事件流程可得出 UI 事件的一般流程为:

  首先为每个面板创建一个脚本来控制该面板,之后再 Awake 函数里使用 Bind 函数注册事件码,

1 void Awake()
2 {
3     Bind(UIEvent.START_PANEL_ACTIVE);           // 注册事件码
4 }

 

   然后添加 Execute 函数来接收外界发送的事件,

1 public override void Execute(int eventCode, object message)
2 {
3     switch (eventCode)
4     {
5         default:
6             break;
7     }
8 }

  那么当我们需要实现某一事件的时候,只需要调用 Dispatch 函数来发送想发送的消息即可。

1 /// <summary>
2 /// 开始游戏按钮响应函数
3 /// </summary>
4 private void startClick()
5 {
6     Dispatch(AreaCode.UI, UIEvent.START_PANEL_ACTIVE, true);      
7 }

 

 

   那么,如何与服务器交互呢?

  首先也需要自定义消息类 AccountDto(服务器端生成),

1 [Serializable]
2 public class AccountDto
3 {
4     public string Account;
5     public string Password;
6 
7     public AccountDto();
8     public AccountDto(string acc, string pwd);
9 }

  和实际传输的信息类 SocketMsg,

 1 /// <summary>
 2 /// 网络消息
 3 ///     作用:发送的时候 都要发送这个类
 4 /// </summary>
 5 public class SocketMsg
 6 {
 7     /// <summary>
 8     /// 操作码
 9     /// </summary>
10     public int OpCode { get; set; }
11 
12     /// <summary>
13     /// 子操作
14     /// </summary>
15     public int SubCode { get; set; }
16 
17     /// <summary>
18     /// 参数
19     /// </summary>
20     public object Value { get; set; }
21 
22     public SocketMsg()
23     {
24 
25     }
26 
27     public SocketMsg(int opCode, int subCode, object value)
28     {
29         this.OpCode = opCode;
30         this.SubCode = subCode;
31         this.Value = value;
32     }
33 
34     public void Change(int opCode, int subCode, object value)
35     {
36         this.OpCode = opCode;
37         this.SubCode = subCode;
38         this.Value = value;
39     }
40 }
SocketMsg

 

   接下来是把发送消息这个事件和发送的内容使用 Dispatch 派发出去

   NetManager 类中的 Execute 函数接收事件,并向服务器发送信息,

 1 public override void Execute(int eventCode, object message)
 2 {
 3     switch (eventCode)
 4     {
 5         case 0:             // 发送消息
 6             client.Send(message as SocketMsg);
 7             break;
 8         default:
 9             break;
10     }
11 }

 

  这时候服务器已经收到消息了, 服务器端 NetMsgCenter 类 OnReceive 函数接收到消息,并执行相应的逻辑,

 1 public void OnReceive(ClientPeer client, SocketMsg msg)
 2 {
 3     switch (msg.OpCode)
 4     {
 5         case OpCode.ACCOUNT:
 6             account.OnReceive(client, msg.SubCode, msg.Value);
 7             break;
 8         case OpCode.USER:
 9             user.OnReceive(client, msg.SubCode, msg.Value);
10             break;
11         case OpCode.MATCH:
12             match.OnReceive(client, msg.SubCode, msg.Value);
13             break;
14         case OpCode.CHAT:
15             chat.OnReceive(client, msg.SubCode, msg.Value);
16             break;
17         case OpCode.FIGHT:
18             fight.OnReceive(client, msg.SubCode, msg.Value);
19             break;
20         default:
21             break;
22     }
23 }
OnReceive

 

  我们发送的消息的 OpCode 为 ACCOUNT,所以会调用 account.OnReceive 函数,

 1 public void OnReceive(ClientPeer client, int subCode, object value)
 2 {
 3     switch (subCode)
 4     {
 5         case AccountCode.REGIST_CREQ:
 6             {
 7                 AccountDto dto = value as AccountDto;
 8                 //Console.WriteLine(dto.Account);
 9                 //Console.WriteLine(dto.Password);
10                 regist(client, dto.Account, dto.Password);
11             }
12             break;
13         case AccountCode.LOGIN:
14             {
15                 AccountDto dto = value as AccountDto;
16                 //Console.WriteLine(dto.Account);
17                 //Console.WriteLine(dto.Password);
18                 login(client, dto.Account, dto.Password);
19             }
20             break;
21         default:
22             break;
23     }
24 }
OnReceive

 

 

   我们发送的消息的 subCode 为 LOGIN,所以会调用 login 函数,

 1 /// <summary>
 2 /// 登录
 3 /// </summary>
 4 /// <param name="client"></param>
 5 /// <param name="account"></param>
 6 /// <param name="password"></param>
 7 private void login(ClientPeer client, string account, string password)
 8 {
 9     SingleExecute.Instance.Execute(() =>                    // 单线程
10     {
11         if (!accountCache.IsExist(account))
12         {
13             //表示账号不存在
14             //client.Send(OpCode.ACCOUNT, AccountCode.LOGIN, "账号不存在");
15             client.Send(OpCode.ACCOUNT, AccountCode.LOGIN, -1);
16             return;
17         }
18 
19         if (accountCache.IsOnline(account))
20         {
21             //表示账号在线
22             //client.Send(OpCode.ACCOUNT, AccountCode.LOGIN, "账号在线");
23             client.Send(OpCode.ACCOUNT, AccountCode.LOGIN, -2);
24             return;
25         }
26 
27         if (!accountCache.IsMatch(account, password))
28         {
29             //表示账号密码不匹配
30             //client.Send(OpCode.ACCOUNT, AccountCode.LOGIN, "账号密码不匹配");
31             client.Send(OpCode.ACCOUNT, AccountCode.LOGIN, -3);
32             return;
33         }
34 
35         //登陆成功
36         accountCache.Online(client, account);
37         //client.Send(OpCode.ACCOUNT, AccountCode.LOGIN, "登陆成功");
38         client.Send(OpCode.ACCOUNT, AccountCode.LOGIN, 0);
39     });
40 }
login

  该函数验证账号密码,并向客户端发送相应的消息,

  那么客户端已经收到回复了,客户端 NetManager 类 ProcessSocketMsg 函数会处理该消息,

 1 private void ProcessSocketMsg(SocketMsg msg)
 2 {
 3     switch (msg.OpCode)
 4     {
 5         case OpCode.ACCOUNT :
 6             accountHandler.OnReceive(msg.SubCode, msg.Value);
 7             break;
 8         case OpCode.USER:
 9             userHandler.OnReceive(msg.SubCode, msg.Value);
10             break;
11         case OpCode.MATCH:
12             matchHandler.OnReceive(msg.SubCode, msg.Value);
13             break;
14         default:
15             break;
16     }
17 }
ProcessSocketMsg

 

   然后根据接收到的消息会调用 AccountHandler 类的 OnReceive 函数,

 1 public override void OnReceive(int subCode, object message)
 2 {
 3     switch (subCode)
 4     {
 5         case AccountCode.LOGIN:                 // 登录
 6             LoginResponce((int)message);
 7             break;
 8         case AccountCode.REGIST_SRES:           // 注册
 9             RegistResponce((int)message);
10             break;
11         default:
12             break;
13     }
14 }

  根据 sunCode 会调用 LoginResponce 函数,

 1 // 处理登录信息
 2 private void LoginResponce(int value)
 3 {
 4     switch (value)
 5     {
 6         case 0:
 7             //promptMsg.Change("登录成功", Color.green);
 8             //Dispatch(AreaCode.UI, UIEvent.PROMPT_MSG, promptMsg);
 9             // 跳到下一个场景
10             LoadSceneMsg msg = new LoadSceneMsg(1,
11                 delegate()          // 匿名委托
12                 {
13                     // 加载游戏信息
14                     SocketMsg socketMsg = new SocketMsg(OpCode.USER, UserCode.GET_INFO_CREQ, null);
15                     Dispatch(AreaCode.NET, 0, socketMsg);
16                     Debug.Log("场景加载完成!");
17                 }
18                 );
19             Dispatch(AreaCode.SCENE, SceneEvent.LOAD_SCENE, msg);
20             break;
21         case -1:
22             promptMsg.Change("账号不存在", Color.red);
23             Dispatch(AreaCode.UI, UIEvent.PROMPT_MSG, promptMsg);
24             break;
25         case -2:
26             promptMsg.Change("账号在线", Color.red);
27             Dispatch(AreaCode.UI, UIEvent.PROMPT_MSG, promptMsg);
28             break;
29         case -3:
30             promptMsg.Change("账号密码不匹配", Color.red);
31             Dispatch(AreaCode.UI, UIEvent.PROMPT_MSG, promptMsg);
32             break;
33         default:
34             break;
35     }
LoginResponce

  该函数根据接收到的消息给出相应提示信息。

  这就是一个相对完整的客户端服务器交互。

 

posted @ 2018-04-04 17:45  Just_for_Myself  阅读(805)  评论(0编辑  收藏  举报