用unity做了锄大地(单机,联机)
游戏界面
单人游戏
多人游戏-房间
各玩家画面
多人游戏-开始
难点
出牌判断
记录最后出的牌
用[将要出的牌]与[最后出的牌] 先进行数量
确保数量一致进行牌型判断
牌型一致再细分判断,比如3+2由3张同样牌的点数判断 [55544] < [66633] 因为 [555]<[666]
联机
协议选择
unity上没挑选到合适的联机方案,纯局域网或者限制多
摇摇脑袋决定自己写
一般联机主要有几种方案 Socket WebSocket之类
因为WebSocket支持双向发消息 所以服务端选择用JAVA 编写 WebSocket
选择JAVA的原因是相对其他语言比较熟悉JAVA
实现选择
unity WebSocket客户端可用js可用c#
因为原先编写单人模式就用了纯c#,不想客户端 js+c#,所以选择c#
不过找c# unity的WebSocket支持方案浪费了很多时间和精力
有比较出名的Mirror-NetWorking [https://mirror-networking.com/]
还有unity asset store上面一些其他的server 插件
不过觉得定制化有点重
然后选择了BestHTTP
传输数据
然后就是熟悉的套路:
传输用json
server用springboot jackson objectmapper
client用 JsonUtility(JsonUtility只支持简单的json) 和 LitJson.JsonMapper
client与server通过WebSocket协议进行握手
握手成功相当于进入大厅
client在大厅中能获得server传来房间列表刷新的信息
client进入房间后能获得server传来房间内部玩家的信息
client在房间的操作传给server ,server再传给房间所有玩家,再进行渲染
玩法
维基百科有介绍
这里以香港玩法
点数 2>A>K>Q>J>10>9>8>7>6>5>4>3
花色 黑桃>红桃>梅花>方块
https://zh.wikipedia.org/zh-hans/%E9%8B%A4%E5%A4%A7%E5%BC%9F
代码
这次的代码比较多又杂
稍微挑一些出来
server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| @ServerEndpoint("/webSocket/room/{playerName}") @Component @Slf4j public class RoomEndpoint { private static final Map<String, Room> roomMap = new ConcurrentHashMap<>(); public static final String LIST = "LIST"; public static final String CREATE = "CREATE"; public static final String JOIN = "JOIN"; public static final String EXIT = "EXIT"; public static final String READY = "READY"; public static final String CANCEL_READY = "CANCEL_READY"; public static final String SET_HANDCARD = "SET_HANDCARD"; public static final String START_GAME = "START_GAME"; public static final String GET_TURN = "GET_TURN"; public static final String PLAY_CARD = "PLAY_CARD"; public static final String PASS = "PASS"; public static final String CLEAN_DROP_ZONE = "CLEAN_DROP_ZONE"; public static final String WIN = "WIN";
private static Map<Session, String> playerInHall = new ConcurrentHashMap<>();
private ObjectMapper objectMapper = new ObjectMapper();
@OnOpen public void onOpen(@PathParam("playerName") String playerName, Session session) throws IOException {
log.info("{}连入大厅", playerName); if (playerInHall.values().contains(playerName) || roomMap.values().stream().map(room -> room.getPlayerList()).map(players -> playerName) .collect(Collectors.toList()).equals(playerName)) { sendMessage(session, CommonResponse.buildFail(ResponseCodeEnum.已存在此用户名.code, ResponseCodeEnum.已存在此用户名.message)); return; } playerInHall.put(session, playerName); } ......
|
client
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| [Serializable] public class CommonResponse<T> { public int code;
public string message;
public T data; }
[Serializable] public class Room { public string name; public int roomNumber; public int playerCount; public List<string> playerNameList; }
[Serializable] public class Player { public int index; public String name; public List<PokerController.Poker> poker; }
private void OnMessage(WebSocket websocket, string message) { Debug.Log("OnMessage" + message); var commonResponse = JsonUtility.FromJson<CommonResponse<string>>(message); switch (commonResponse.code) { case 200: case 201: var roomList = JsonUtility.FromJson<CommonResponse<List<Room>>>(message).data; if (roomList != null && roomList.Count > 0) RoomManager.RefreshRoomList(roomList); break; case 202: var room = JsonUtility.FromJson<CommonResponse<Room>>(message).data; GameManager.RefreshRoom(room, room.playerNameList.FindLastIndex(name => name.Equals(_username))); break; case 203: var handcardList = JsonMapper.ToObject<CommonResponse<List<PokerController.Poker>>>(message).data; GameManager.SetHandCard(handcardList); break; case 204: var player = JsonMapper.ToObject<CommonResponse<Player>>(message).data; GameManager.SetLastPlay(player.index, player.poker); break; case 205: var turn = JsonMapper.ToObject<CommonResponse<int>>(message).data; GameManager.SetTurn(turn); break; case 206: GameManager.CleanDropZone(); break; case 207: var passIndex = JsonMapper.ToObject<CommonResponse<int>>(message).data; GameManager.SetPass(passIndex); break; case 208: var playerList = JsonMapper.ToObject<CommonResponse<List<Player>>>(message).data; GameManager.RefreshPlayer(playerList); break; case 209: var winMessage = JsonMapper.ToObject<CommonResponse<string>>(message).data; GameManager.AnnounceWin(winMessage); break; } }
|