|
@@ -0,0 +1,246 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html lang="en">
|
|
|
+<head>
|
|
|
+ <meta charset="UTF-8">
|
|
|
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
|
+ <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 id="chess_area">
|
|
|
+
|
|
|
+ <canvas id="chess" width="450px" height="450px"></canvas>
|
|
|
+
|
|
|
+ <div id="screen"> 等待玩家连接中... </div>
|
|
|
+ </div>
|
|
|
+ <div id="chat_area" width="400px" height="300px">
|
|
|
+ <div id="chat_show">
|
|
|
+ <p id="self_msg">你好!</p></br>
|
|
|
+ <p id="peer_msg">你好!</p></br>
|
|
|
+ </div>
|
|
|
+ <div id="msg_show">
|
|
|
+ <input type="text" id="chat_input">
|
|
|
+ <button id="chat_button">发送</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <script>
|
|
|
+ let chessBoard = [];
|
|
|
+ let BOARD_ROW_AND_COL = 15;
|
|
|
+ let chess = document.getElementById('chess');
|
|
|
+ //获取chess控件区域2d画布
|
|
|
+ let context = chess.getContext('2d');
|
|
|
+
|
|
|
+ // 将http协议切换为游戏房间的websocket长连接协议
|
|
|
+ var ws_url = "ws://" + location.host + "/room";
|
|
|
+ var ws_hdl = new WebSocket(ws_url);
|
|
|
+
|
|
|
+ // 设置离开当前页面立即断开websocket连接
|
|
|
+ window.onbeforeunload = function () {
|
|
|
+ ws_hdl.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存房间信息与是否轮到己方走棋
|
|
|
+ var room_info;
|
|
|
+ var is_me;
|
|
|
+
|
|
|
+ function initGame() {
|
|
|
+ initBoard();
|
|
|
+ // 背景图片
|
|
|
+ let logo = new Image();
|
|
|
+ logo.src = "image/sky.jpeg";
|
|
|
+ logo.onload = function () {
|
|
|
+ // 绘制图片
|
|
|
+ context.drawImage(logo, 0, 0, 450, 450);
|
|
|
+ // 绘制棋盘
|
|
|
+ drawChessBoard();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ function initBoard() {
|
|
|
+ for (let i = 0; i < BOARD_ROW_AND_COL; i++) {
|
|
|
+ chessBoard[i] = [];
|
|
|
+ for (let j = 0; j < BOARD_ROW_AND_COL; j++) {
|
|
|
+ chessBoard[i][j] = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 绘制棋盘网格线
|
|
|
+ function drawChessBoard() {
|
|
|
+ context.strokeStyle = "#BFBFBF";
|
|
|
+ for (let i = 0; i < BOARD_ROW_AND_COL; i++) {
|
|
|
+ //横向的线条
|
|
|
+ context.moveTo(15 + i * 30, 15);
|
|
|
+ context.lineTo(15 + i * 30, 430);
|
|
|
+ context.stroke();
|
|
|
+ //纵向的线条
|
|
|
+ context.moveTo(15, 15 + i * 30);
|
|
|
+ context.lineTo(435, 15 + i * 30);
|
|
|
+ context.stroke();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //绘制棋子
|
|
|
+ function oneStep(i, j, isWhite) {
|
|
|
+ if (i < 0 || j < 0) return;
|
|
|
+ context.beginPath();
|
|
|
+ context.arc(15 + i * 30, 15 + j * 30, 13, 0, 2 * Math.PI);
|
|
|
+ context.closePath();
|
|
|
+ //createLinearGradient() 方法创建放射状/圆形渐变对象
|
|
|
+ var gradient = context.createRadialGradient(15 + i * 30 + 2, 15 + j * 30 - 2, 13, 15 + i * 30 + 2, 15 + j * 30 - 2, 0);
|
|
|
+ // 区分黑白子
|
|
|
+ if (!isWhite) {
|
|
|
+ gradient.addColorStop(0, "#0A0A0A");
|
|
|
+ gradient.addColorStop(1, "#636766");
|
|
|
+ } else {
|
|
|
+ gradient.addColorStop(0, "#D1D1D1");
|
|
|
+ gradient.addColorStop(1, "#F9F9F9");
|
|
|
+ }
|
|
|
+ context.fillStyle = gradient;
|
|
|
+ context.fill();
|
|
|
+ }
|
|
|
+ //棋盘区域的点击事件
|
|
|
+ chess.onclick = function (e) {
|
|
|
+ // 如果当前轮到对方走棋,则直接返回
|
|
|
+ if(is_me == false) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ let x = e.offsetX;
|
|
|
+ let y = e.offsetY;
|
|
|
+ // 注意, 横坐标是列, 纵坐标是行
|
|
|
+ // 这里是为了让点击操作能够对应到网格线上
|
|
|
+ let col = Math.floor(x / 30);
|
|
|
+ let row = Math.floor(y / 30);
|
|
|
+ if (chessBoard[row][col] != 0) {
|
|
|
+ alert("当前位置已有棋子");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 发送走棋请求
|
|
|
+ send_chess(row, col);
|
|
|
+ }
|
|
|
+ // 发送走棋请求(websocket长连接通信,直接使用ws_hdl.send,而不是通过ajax)
|
|
|
+ function send_chess(r, c) {
|
|
|
+ var chess_info = {
|
|
|
+ optype: "put_chess",
|
|
|
+ room_id: room_info.room_id,
|
|
|
+ uid: room_info.uid,
|
|
|
+ row: r,
|
|
|
+ col: c
|
|
|
+ };
|
|
|
+ ws_hdl.send(JSON.stringify(chess_info));
|
|
|
+ console.log("click:" + JSON.stringify(chess_info));
|
|
|
+ }
|
|
|
+ // 聊天动作
|
|
|
+ // 给消息发送按钮添加点击事件
|
|
|
+ var chat_button_div = document.getElementById("chat_button");
|
|
|
+ chat_button_div.onclick = function() {
|
|
|
+ // 获取聊天输入框中的消息
|
|
|
+ var chat_msg = {
|
|
|
+ optype: "chat",
|
|
|
+ room_id: room_info.room_id,
|
|
|
+ uid: room_info.uid,
|
|
|
+ message: document.getElementById("chat_input").value
|
|
|
+ };
|
|
|
+ // 将消息发送给服务器
|
|
|
+ ws_hdl.send(JSON.stringify(chat_msg));
|
|
|
+ }
|
|
|
+ // websocket各种事件的执行函数
|
|
|
+ ws_hdl.onopen = function() {
|
|
|
+ console.log("游戏房间长连接建立成功");
|
|
|
+ }
|
|
|
+ ws_hdl.onclose = function() {
|
|
|
+ console.log("游戏房间长连接断开");
|
|
|
+ }
|
|
|
+ ws_hdl.onerror = function() {
|
|
|
+ console.log("游戏房间长连接建立出错");
|
|
|
+ }
|
|
|
+ // 更新screen显示的内容
|
|
|
+ function set_screen(me) {
|
|
|
+ var screen_div = document.getElementById("screen");
|
|
|
+ if(me) screen_div.innerHTML = "轮到己方走棋...";
|
|
|
+ else screen_div.innerHTML = "轮到对方走棋...";
|
|
|
+ }
|
|
|
+ ws_hdl.onmessage = function(evt) {
|
|
|
+ console.log("message:" + evt.data);
|
|
|
+ var resp = JSON.parse(evt.data);
|
|
|
+ // 收到room_ready响应消息
|
|
|
+ if(resp.optype == "room_ready") {
|
|
|
+ // 保存房间信息与执棋用户
|
|
|
+ room_info = resp;
|
|
|
+ // 规定白棋先走
|
|
|
+ is_me = (room_info.uid == room_info.white_id ? true : false);
|
|
|
+ if(resp.result == false) {
|
|
|
+ alert(resp.reason);
|
|
|
+ location.replace("/login.html");
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ // 更新screen显示的内容
|
|
|
+ set_screen(is_me);
|
|
|
+ // 初始化游戏
|
|
|
+ initGame();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 收到put_chess响应消息
|
|
|
+ else if(resp.optype == "put_chess") {
|
|
|
+ // 判断走棋是否成功
|
|
|
+ if(resp.result == false) {
|
|
|
+ alert(resp.reason);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 下棋坐标为-1表示对方掉线
|
|
|
+ if(resp.row != -1 && resp.col != -1) {
|
|
|
+ // 绘制棋子
|
|
|
+ isWhite = (resp.uid == room_info.white_id ? true : false);
|
|
|
+ oneStep(resp.col, resp.row, isWhite);
|
|
|
+ // 更新棋盘
|
|
|
+ chessBoard[resp.row][resp.col] = 1;
|
|
|
+ }
|
|
|
+ // 更新执棋玩家
|
|
|
+ is_me = !is_me;
|
|
|
+ // 更新screen显示的内容
|
|
|
+ set_screen(is_me);
|
|
|
+ // 判断是否有胜利者
|
|
|
+ winner = resp.winner;
|
|
|
+ if(winner == 0) return;
|
|
|
+ // 更新screen信息
|
|
|
+ var screen_div = document.getElementById("screen");
|
|
|
+ if(winner == room_info.uid) screen_div.innerHTML = resp.reason;
|
|
|
+ else screen_div.innerHTML = "游戏失败,再接再厉";
|
|
|
+ // 在chess_area区域下方添加返回大厅按钮
|
|
|
+ var chess_area_div = document.getElementById("chess_area");
|
|
|
+ var button_div = document.createElement("div");
|
|
|
+ button_div.innerHTML = "返回大厅";
|
|
|
+ button_div.onclick = function() {
|
|
|
+ ws_hdl.close();
|
|
|
+ location.replace("/game_hall.html");
|
|
|
+ }
|
|
|
+ chess_area_div.appendChild(button_div);
|
|
|
+ }
|
|
|
+ // 收到chat响应消息
|
|
|
+ else if(resp.optype == "chat") {
|
|
|
+ if(resp.result == false) {
|
|
|
+ alert(resp.reason);
|
|
|
+ document.getElementById("chat_input").value = "";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 创建一个子控件,将消息内嵌到其中
|
|
|
+ var msg_div = document.createElement("p");
|
|
|
+ msg_div.innerHTML = resp.message;
|
|
|
+ // 添加属性
|
|
|
+ if(resp.uid == room_info.uid) msg_div.setAttribute("id", "self_msg");
|
|
|
+ else msg_div.setAttribute("id", "peer_msg");
|
|
|
+ // 添加换行
|
|
|
+ var br_div = document.createElement("br");
|
|
|
+ // 将消息与换行子控件渲染到聊天显示框中
|
|
|
+ var msg_show_div = document.getElementById("chat_show");
|
|
|
+ msg_show_div.appendChild(msg_div);
|
|
|
+ msg_show_div.appendChild(br_div);
|
|
|
+ // 清空输入框内容
|
|
|
+ document.getElementById("chat_input").value = "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ </script>
|
|
|
+</body>
|
|
|
+</html>
|