当前位置: 首页 > news >正文

[网页五子棋][对战模块]实现游戏房间页面,服务器开发(创建落子请求/响应对象)

实现游戏房间页面

创建 css/game_room.css

  • #screen 用于显示当前的状态,例如“等待玩家连接中…”,“轮到你落子”,“轮到对方落子”等
#screen {  width: 450px;  height: 50px;  margin-top: 10px;  color: #8f4e19;  font-size: 28px;  font-weight: 700;  line-height: 50px;  text-align: center;  
}

实现 game_room.html,这个页面就是匹配成功之后,要跳转到的新页面image.png|439

<!DOCTYPE html>  
<html lang="en">  
<head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>游戏房间</title>  <link rel="stylesheet" href="css/common.css">  <link rel="stylesheet" href="css/game_room.css">  
</head>  
<body>  <div class="nav">五子棋对战</div>  <div class="container">  <div>            <!-- 棋盘区域,需要基于 canva 进行实现 -->  <canvas id="chess" width="450px" height="450px">  </canvas>             <!-- 显示区域 -->  <div id="screen">等待玩家连接中...</div>  </div>    </div>    <script src="js/app.js"></script>  
</body>  
</html>

页面效果

image.png|439

初始化 websocket

js/app.js 中,加入 websocket 的连接代码,实现前后端交互

  • 先删掉原来 initGame() 函数的调用,一会在获取到服务器反馈的就绪响应之后,再初始化棋盘
  • 创建 websocket 对象,并注册 onopen/onclose/onerror 函数
    • 其中在 onopen 中做一个跳转到大厅的逻辑,当网络断开时,则返回大厅
  • 实现 onmessage 方法,onmessage 先处理游戏就绪响应
// 此处写的路径要写作 /game,不要写作 /game/let websocket = new WebSocket("ws://127.0.0.1:8080/game");  websocket.onopen = function() {  console.log("连接游戏房间成功!");  
}  websocket.onclose = function() {  console.log("和游戏服务器断开连接!");  
}  websocket.onerror = function() {  console.log("和服务器的连接出现异常!");  
}  // 用户点击关闭关闭页面,就断开网络连接  
window.onbeforeunload = function() {  websocket.close();  
}  // 处理服务器返回的响应数据  
websocket.onmessage = function(event) {  console.log("[handlerGameReady] " + event.data);  let resp = JSON.parse(event.data);  if(resp.message != 'gameReady') {  console.log("响应类型错误!");  return;  }  if(!resp.ok) {  alert("连接游戏失败! reason: " + resp.reason);  // 如果出现连接失败的情况,就回到游戏大厅  location.assign("/game_hall.html");  return;  }  gameInfo.roomId = resp.roomId;  gameInfo.thisUserId = resp.thisUserId;  gameInfo.thatUserId = resp.thatUserId;  gameInfo.isWhite = resp.isWhite;  // 初始化棋盘  initGame();  // 设置显示区域的内容  setScreenText(gameInfo.isWhite);  
}

服务器开发

创建并注册 GameAPI 类

创建 api.GameAPI,处理 websocket 请求

  • 这里准备一个 ObjectMapper 类,让后面进行消息发送的时候进行序列化
  • 同时注入一个 RoomManagerOnlineUserManager
package org.example.java_gobang.api;  import org.springframework.stereotype.Component;  
import org.springframework.web.socket.CloseStatus;  
import org.springframework.web.socket.TextMessage;  
import org.springframework.web.socket.WebSocketSession;  
import org.springframework.web.socket.handler.TextWebSocketHandler;  @Component  
public class GameAPI extends TextWebSocketHandler {  @Autowired  private ObjectMapper objectMapper = new ObjectMapper();  @Autowired  private RoomManager roomManager;@Override  public void afterConnectionEstablished(WebSocketSession session) throws Exception {  }  @Override  protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {  }  @Override  public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {  }  @Override  public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {  }  
}

修改 WebSocketConfig,将 GameAPI 进行注册

package org.example.java_gobang.config;  import org.example.java_gobang.api.GameAPI;  
import org.example.java_gobang.api.MatchAPI;  
import org.example.java_gobang.api.TestAPI;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.web.socket.config.annotation.EnableWebSocket;  
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;  
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;  
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;  /**  * 这个类是用来注册 WebSocketHandler 的配置类  * 这个类是来告诉 Spring(websocket),哪一个类是和哪一个路径相匹配的  */  
@Configuration  
@EnableWebSocket // 让 Spring 框架知道这个类是用来配置 websocket 的  
public class WebSocketConfig implements WebSocketConfigurer {  @Autowired  private TestAPI testAPI;  @Autowired  private MatchAPI matchAPI;  @Autowired  private GameAPI gameAPI;  @Override  public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {  // 当我们的客户端连接到 /test 路径的时候,就会触发到当前的 TestAPI,然后调用执行里面的方法  webSocketHandlerRegistry.addHandler(testAPI, "/test");  // 通过 .addInterceptors(new HttpSessionHandshakeInterceptor() 这个操作,  // 来把 HttpSession ⾥的属性放到 WebSocket 的 session 中  // 然后就可以在 WebSocket 代码中 WebSocketSession ⾥拿到 HttpSession 中的 attribute        webSocketHandlerRegistry.addHandler(matchAPI,"/findMatch")  .addInterceptors(new HttpSessionHandshakeInterceptor());  webSocketHandlerRegistry.addHandler(gameAPI, "/game")  .addInterceptors(new HttpSessionHandshakeInterceptor());  }  
}

创建落子请求/响应对象

这部分内容要和约定的前后端交互接口匹配

创建 game.GameReadyResponse

package org.example.java_gobang.game;  // 客户端连接到游戏房间后,服务器返回的响应  public class GameReadyResponse {  private String message;  private boolean ok;  private String reason;  private String roomId;  private int thisUserId;  private int thatUserId;  private int whiteUser;  public boolean isOk() {  return ok;  }  public void setOk(boolean ok) {  this.ok = ok;  }  public String getMessage() {  return message;  }  public void setMessage(String message) {  this.message = message;  }  public String getReason() {  return reason;  }  public void setReason(String reason) {  this.reason = reason;  }  public String getRoomId() {  return roomId;  }  public void setRoomId(String roomId) {  this.roomId = roomId;  }  public int getThatUserId() {  return thatUserId;  }  public void setThatUserId(int thatUserId) {  this.thatUserId = thatUserId;  }  public int getThisUserId() {  return thisUserId;  }  public void setThisUserId(int thisUserId) {  this.thisUserId = thisUserId;  }  public int getWhiteUser() {  return whiteUser;  }  public void setWhiteUser(int whiteUser) {  this.whiteUser = whiteUser;  }  
}

创建 game.GameRequest

  • 表示落子请求
package org.example.java_gobang.game;  // 这个类表示落子请求  
public class GameRequest {  // 如果不给 message 设置 getter / setter, 则不会被 jackson 序列化private String message;  private int userId;  private int row;  private int col;  public String getMessage() {  return message;  }  public void setMessage(String message) {  this.message = message;  }  public int getUserId() {  return userId;  }  public void setUserId(int userId) {  this.userId = userId;  }  public int getRow() {  return row;  }  public void setRow(int row) {  this.row = row;  }  public int getCol() {  return col;  }  public void setCol(int col) {  this.col = col;  }  
}

创建 game.Response

  • 表示落子响应
package org.example.java_gobang.game;  // 这个类表示 落子响应  
public class GameResponse {  // 如果不给 message 设置 getter / setter, 则不会被 jackson 序列化  private String message;  private int userId;  private int row;  private int col;  private int winner;  public String getMessage() {  return message;  }  public void setMessage(String message) {  this.message = message;  }  public int getUserId() {  return userId;  }  public void setUserId(int userId) {  this.userId = userId;  }  public int getRow() {  return row;  }  public void setRow(int row) {  this.row = row;  }  public int getCol() {  return col;  }  public void setCol(int col) {  this.col = col;  }  public int getWinner() {  return winner;  }  public void setWinner(int winner) {  this.winner = winner;  }  
}

相关文章:

  • bert扩充或者缩小词表
  • 【NLP 78、手搓Transformer模型结构及实战】
  • 中文NLP with fastai - Fastai Part4
  • G25-05-31Rust开源项目日报 Top10
  • 基于热力学熵增原理的EM-GAM
  • Baklib企业CMS全流程管控与智能协作
  • 尚硅谷redis7 99 springboot整合redis之连接集群
  • 知识管理五强对比:Baklib高效突围
  • Python简易音乐播放器开发教程
  • LeetCode 算 法 实 战 - - - 移 除 链 表 元 素、反 转 链 表
  • 双目相机深度的误差分析(基线长度和相机焦距的选择)
  • Linux系统编程之共享内存
  • 【设计模式-4.5】行为型——迭代器模式
  • KWIC—Implicit Invocation
  • 【代码坏味道】变更阻碍者Change Preventers
  • Tomcat的整体架构及其设计精髓
  • MAC软件游戏打开提示已损坏
  • 通义灵码深度实战测评:从零构建智能家居控制中枢,体验AI编程新范式
  • azure web app创建分步指南系列之二
  • CSS专题之水平垂直居中
  • 快速做网站公司/国际实时新闻
  • 无锡网站推广$做下拉去118cr/今日新闻摘抄十条
  • 如何做手机网站/百度手机助手下载安装
  • 伙购网官方网站/全国疫情最新报告
  • wordpress退出/百度seo优化哪家好
  • 基于h5的企业网站建设/网络推广员的工作内容