一直以來想做一款遊戲應用,但是又沒有遊戲的專業開發知識和技術,只能開發界面比較簡單的遊戲了,象棋遊戲就是不錯的選擇。
首先看看界面如下。我們打開兩個客戶端
在服務端通過登陸,會新建兩個用戶保存到服務端,然後客戶端獲取下在線的用戶列表。
邀請對局:
進入遊戲房間
1.如果搞定通信?
對於Socket不太熟練的我,選擇了websocket,然後再.net core中有不錯的選擇那就是signalr core了,使用簡單,而且對於客戶端接入也方便,也可以全異步。
我們可以實現一個Server,使用.net core接入signalr,然後實現一個集線器。
Startup.cs中添加中間件和服務配置。
在對應的ChatHub中進行相應的消息事件的註冊聲明。
private static List<Item> Items = new List<Item>(); private static List<string> ChessGroups = new List<string>(); public async Task<IEnumerable<User>> Login(User user) { //從在線集合中去除此人 Items.RemoveAll(o => o.user.UserId == user.UserId); Items.Add(new Item() { Id = Context.ConnectionId, user = user }); return Items.Select(o => o.user); } public async Task<IEnumerable<User>> RequestList() { return Items.Select(o => o.user); } public async Task<string> GameRequest(string source, string target) { //從在線集合中去除此人 var temp = Items.FirstOrDefault(o => o.user.UserId == source); if (temp == null || temp.user.Status == Status.WORKING) return "狀態異常"; var user = Items.FirstOrDefault(o => o.user.UserId == target); if (user == null) { return "對方不在線!"; } if (user.user.Status == Status.WORKING) { return "對方正在對局中!"; } await Clients.Client(user.Id).SendAsync("GameRequest", source); return "SUCCESS"; } public async Task<string> ReceiveRequest(string receiver, string beginner) { //如果接受則不能接受其他的 //從在線集合中去除此人 var temp = Items.FirstOrDefault(o => o.user.UserId == receiver); if (temp == null || temp.user.Status == Status.WORKING) return "狀態異常"; var user = Items.FirstOrDefault(o => o.user.UserId == beginner); if (user == null) { return "對方不在線!"; } if (user.user.Status == Status.WORKING) { return "對方正在對局中!"; } temp.user.Status = Status.WORKING; user.user.Status = Status.WORKING; var groupName = $"{receiver}-{beginner}-{DateTime.Now.ToLongTimeString()}"; //雙方狀態正常則開始對局 await Groups.AddToGroupAsync(temp.Id, groupName); await Groups.AddToGroupAsync(user.Id, groupName); await Clients.Group(groupName).SendAsync("BeginGame", beginner, receiver); ChessGroups.Add(groupName); return "SUCCESS"; } public override Task OnDisconnectedAsync(Exception exception) { Items.RemoveAll(o => o.Id == Context.ConnectionId); return base.OnDisconnectedAsync(exception); } public async Task<string> Action(Point oldPoint, Point newPoint, string receiver) { var temp = Items.FirstOrDefault(o => o.user.UserId == receiver); if (temp == null || temp.user.Status != Status.WORKING) return "狀態異常"; await Clients.Client(temp.Id).SendAsync("ReceiveLocation", oldPoint, newPoint); return "SUCCESS"; } public async Task GameOver() { var temp = Items.FirstOrDefault(o => o.Id == Context.ConnectionId); if (temp == null || temp.user.Status == Status.FREE) return; temp.user.Status = Status.FREE; foreach (var group in ChessGroups) { if (group.Contains(Context.ConnectionId)) { await Groups.RemoveFromGroupAsync(Context.ConnectionId, group); } } ChessGroups.RemoveAll(o => o.Contains(temp.Id)); } public async Task Exit(string receiver) { var temp = Items.FirstOrDefault(o => o.Id == Context.ConnectionId); if (temp == null || temp.user.Status == Status.FREE) return; var target = Items.FirstOrDefault(o => o.user.UserId == receiver); if (target == null || target.user.Status == Status.FREE) return; temp.user.Status = Status.FREE; target.user.Status = Status.FREE; foreach (var group in ChessGroups) { if (group.Contains(Context.ConnectionId)|| group.Contains(target.Id)) { await Groups.RemoveFromGroupAsync(Context.ConnectionId, group); await Groups.RemoveFromGroupAsync(target.Id, group); } } await Clients.Client(target.Id).SendAsync("OtherExit"); }
2.如何搞定客戶端?
對於WPF我還是比較熟悉的,但是WPF的繪畫和動畫我就不太瞭解了,於是我使用了一個網上大神寫的比較不錯的棋盤用戶控件,做了部分修改(主要是重開遊戲會導致卡死的問題)
後來發現是界面某個依賴屬性導致的
大神鏈接如下。我只是使用了其中的棋盤用戶控件:
https://www.cnblogs.com/Curry/archive/2009/05/06/1450383.html
3.業務邏輯
使用MVVMLight自帶的MVVM和消息機制,實現邏輯和界面分離,各模塊調用通過消息實現。
接受對局等方法。
//開啓接收遊戲請求接口 Const.Connection.On<string>(GameRequest, async (str) => { var result = MessageBox.Show("有人邀請你來一局,是否接受?", str, MessageBoxButton.YesNo, MessageBoxImage.Question); if (result == MessageBoxResult.Yes) { var tempResult = await Const.Connection.InvokeAsync<string>(ReceiveRequest, Const.User.UserId, str); if (tempResult != "SUCCESS") { MessageBox.Show(tempResult, "WARNING", MessageBoxButton.OK, MessageBoxImage.Warning); } } }); Const.Connection.On<string, string>(BeginGame, (beginner, receiver) => { ChessWindow window = new ChessWindow(); window.WindowStartupLocation = WindowStartupLocation.CenterScreen; var vm = new ChessWindowViewModel(beginner == Const.User.UserId, beginner == Const.User.UserId ? receiver : beginner,window.chesscontrol.Chessboard); window.DataContext = vm; window.Show(); });
詳細代碼直接運行即可跑起來:https://github.com/BruceQiu1996/Chess
如果覺得可以希望給個Star!!!.