一直以来想做一款游戏应用,但是又没有游戏的专业开发知识和技术,只能开发界面比较简单的游戏了,象棋游戏就是不错的选择。
首先看看界面如下。我们打开两个客户端
在服务端通过登陆,会新建两个用户保存到服务端,然后客户端获取下在线的用户列表。
邀请对局:
进入游戏房间
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!!!.