网络层
This commit is contained in:
103
Client/web/game.js
Normal file
103
Client/web/game.js
Normal file
@@ -0,0 +1,103 @@
|
||||
const { createApp } = Vue;
|
||||
|
||||
const App = {
|
||||
template: `
|
||||
<div class="app-container">
|
||||
<div class="grid-container">
|
||||
<div class="square" v-for="(square, index) in squares" :key="index">
|
||||
<div class="connection-dot" :class="{ connected: square.connected }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
squares: [
|
||||
{ connected: false, ws: null },
|
||||
{ connected: false, ws: null },
|
||||
{ connected: false, ws: null },
|
||||
{ connected: false, ws: null }
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 为每个正方形建立独立的WebSocket连接
|
||||
this.squares.forEach((square, index) => {
|
||||
this.connectWebSocket(square, index);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
connectWebSocket(square, index) {
|
||||
// 替换为实际的WebSocket服务器地址
|
||||
const wsUrl = `ws://localhost:8501/?token=${index + 1}`;
|
||||
|
||||
try {
|
||||
square.ws = new WebSocket(wsUrl);
|
||||
|
||||
square.ws.onopen = () => {
|
||||
square.connected = true;
|
||||
console.log(`WebSocket ${index + 1} connected`);
|
||||
|
||||
// 连接建立后发送初始消息
|
||||
try {
|
||||
square.ws.send(JSON.stringify({
|
||||
type: "init"
|
||||
}));
|
||||
console.log(`Initial message sent to WebSocket ${index + 1}`);
|
||||
} catch (error) {
|
||||
console.error(`Failed to send initial message to WebSocket ${index + 1}:`, error);
|
||||
}
|
||||
};
|
||||
|
||||
square.ws.onclose = (e) => {
|
||||
square.connected = false;
|
||||
console.log(`WebSocket ${index + 1} disconnected`);
|
||||
console.log(e.code, e.reason, e.wasClean)
|
||||
// 尝试重新连接
|
||||
// setTimeout(() => this.connectWebSocket(square, index), 1000);
|
||||
};
|
||||
|
||||
square.ws.onerror = (error) => {
|
||||
console.error(`WebSocket ${index + 1} error:`, error);
|
||||
};
|
||||
|
||||
square.ws.onmessage = (event) => {
|
||||
console.log(`WebSocket ${index + 1} message:`, event.data);
|
||||
// 处理接收到的消息
|
||||
try {
|
||||
const message = JSON.parse(event.data);
|
||||
const arr = JSON.parse(message.data);
|
||||
|
||||
if (Array.isArray(arr) && arr.length === 2) {
|
||||
const [x, y] = arr;
|
||||
console.log(`Creating dot at (${x}, ${y}) for square ${index}`);
|
||||
|
||||
const squareElement = document.querySelectorAll('.square')[index];
|
||||
if (!squareElement) {
|
||||
console.error('Square element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建圆点元素
|
||||
const dot = document.createElement('div');
|
||||
dot.className = 'game-dot';
|
||||
dot.style.left = `${x}px`;
|
||||
dot.style.top = `${y}px`;
|
||||
dot.style.zIndex = '10';
|
||||
|
||||
// 添加到游戏场景
|
||||
squareElement.appendChild(dot);
|
||||
console.log('Dot added successfully');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error processing message:', error);
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`WebSocket ${index + 1} init error:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
createApp(App).mount('#app');
|
||||
17
Client/web/index.html
Normal file
17
Client/web/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>游戏方块容器</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="game.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
80
Client/web/style.css
Normal file
80
Client/web/style.css
Normal file
@@ -0,0 +1,80 @@
|
||||
/* 重置默认边距 */
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 应用容器填满整个视口并居中 */
|
||||
.app-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 重置body样式 */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 网格容器 - 固定2x2布局 */
|
||||
.grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: 400px 400px;
|
||||
grid-template-rows: 400px 400px;
|
||||
gap: 30px;
|
||||
padding: 40px;
|
||||
background-color: #e0e0e0;
|
||||
min-height: 100vh;
|
||||
width: 100vw;
|
||||
box-sizing: border-box;
|
||||
margin: 0 auto;
|
||||
place-content: center;
|
||||
}
|
||||
|
||||
/* 正方形样式 */
|
||||
.square {
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background-color: #ffffff;
|
||||
background-image:
|
||||
linear-gradient(to right, #ddd 1px, transparent 1px),
|
||||
linear-gradient(to bottom, #ddd 1px, transparent 1px);
|
||||
background-size: 20px 20px;
|
||||
border: 5px solid #555;
|
||||
border-radius: 15px;
|
||||
position: relative;
|
||||
box-shadow: 0 6px 12px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
/* 连接状态圆点 */
|
||||
.connection-dot {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background-color: #ff4444; /* 默认断开状态-红色 */
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.connection-dot.connected {
|
||||
background-color: #44ff44; /* 连接状态-绿色 */
|
||||
}
|
||||
|
||||
/* 游戏动态圆点 */
|
||||
.game-dot {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-color: red;
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
pointer-events: none;
|
||||
}
|
||||
Reference in New Issue
Block a user