20260420
这次能同步子弹了,碰撞检测血量啥的还有一些其他bug后续再完善。
我敢说这是我这辈子写过最烂最烂的代码,没有之一,看起来就像东拼西凑的,一点章法逻辑都没有,完全是想到啥写啥,目标只有一个:能跑就行。。
依旧展示代码进度:
RectangleMove.vue
1 <template> 2 <div class="CanvasContainer"> 3 <canvas width="1000" height="800" ref="backgroundCanvas"></canvas> 4 </div> 5 </template> 6 7 <script setup> 8 import axios from "axios" 9 import { onMounted, ref } from "vue" 10 11 const backgroundCanvas = ref(null) 12 let ctx = null 13 let ws = null 14 //我的名字 15 let myName = Date.now() 16 //玩家集合 17 const players = [] 18 //子弹集合 19 const bullets = [] 20 //按键字典 21 const keys = { 22 w: false, 23 a: false, 24 s: false, 25 d: false, 26 mouseX: 0, 27 mouseY: 0, 28 mouseDown: false, 29 mouseLatestDown: 0 30 } 31 //按下按键 32 function keyDown(e) { 33 if (keys.hasOwnProperty(e.key)) { 34 keys[e.key] = true 35 } 36 } 37 //松开按键 38 function keyUp(e) { 39 if (keys.hasOwnProperty(e.key)) { 40 keys[e.key] = false 41 } 42 } 43 //鼠标移动 44 function mouseMove(e) { 45 keys.mouseX = e.clientX - backgroundCanvas.value.getBoundingClientRect().left; 46 keys.mouseY = e.clientY - backgroundCanvas.value.getBoundingClientRect().top; 47 } 48 //鼠标按下 49 function mouseDown(e) { 50 const ts = Date.now() 51 if (ts - keys.mouseLatestDown >= 1000) { 52 //新增子弹 53 const me = players.find(player => player.name == myName) 54 55 //计算方向 56 const dx = keys.mouseX - me.x 57 const dy = keys.mouseY - me.y 58 const dist = Math.sqrt(dx * dx + dy * dy) 59 const speed = 5 60 61 //保证所有方向速度一致 62 const vx = (dx / dist) * speed 63 const vy = (dy / dist) * speed 64 65 const bullet = new Bullet(me.x, me.y, 10, 10, "green", vx, vy, null, myName, Date.now()) 66 67 bullets.push(bullet) 68 69 ws.send(JSON.stringify({ type: "bjoin", data: bullet })) 70 71 keys.mouseDown = false 72 keys.mouseLatestDown = Date.now() 73 } 74 75 } 76 //画鼠标准心 77 function drawMouse() { 78 const cx = keys.mouseX 79 const cy = keys.mouseY 80 const len = 8 81 const gap = 3 82 83 ctx.strokeStyle = '#fff' 84 ctx.lineWidth = 2 85 86 ctx.beginPath() 87 ctx.moveTo(cx, cy - gap - len) 88 ctx.lineTo(cx, cy - gap) 89 ctx.moveTo(cx, cy + gap) 90 ctx.lineTo(cx, cy + gap + len) 91 92 ctx.moveTo(cx - gap - len, cy) 93 ctx.lineTo(cx - gap, cy) 94 ctx.moveTo(cx + gap, cy) 95 ctx.lineTo(cx + gap + len, cy) 96 ctx.stroke() 97 } 98 99 //更新位置 100 function updatedPosition() { 101 //自己移动 102 players.forEach(player => { 103 if (player.name == myName) { 104 if (keys.w || keys.a || keys.s || keys.d) { 105 if (keys.w) player.y -= player.ySpeed 106 if (keys.s) player.y += player.ySpeed 107 if (keys.a) player.x -= player.xSpeed 108 if (keys.d) player.x += player.xSpeed 109 //发送自己新位置 110 ws.send(JSON.stringify({ type: "pupdate", data: player })) 111 } 112 } 113 }) 114 //子弹移动 115 bullets.forEach((bullet, index) => { 116 bullet.x += bullet.xSpeed 117 bullet.y += bullet.ySpeed 118 119 ws.send(JSON.stringify({ type: "bupdate", data: bullet })) 120 121 if (bullet.x < 0 || bullet.x > backgroundCanvas.value.width || bullet.y < 0 || bullet.y > backgroundCanvas.value.height) { 122 bullets.splice(index, 1) 123 ws.send(JSON.stringify({ type: "bleave", data: bullet })) 124 console.log(bullet.from + "已移除子弹") 125 } 126 127 }) 128 129 } 130 //更新事件 131 function updateEvent() { 132 133 } 134 //画 135 function draw() { 136 //清空画布 137 ctx.clearRect(0, 0, backgroundCanvas.value.width, backgroundCanvas.value.height) 138 139 players.forEach(player => { 140 player.draw() 141 }) 142 143 bullets.forEach(bullet => { 144 bullet.draw() 145 }) 146 drawMouse() 147 } 148 //动画 149 function animate() { 150 updatedPosition() 151 updateEvent() 152 draw() 153 requestAnimationFrame(animate) 154 } 155 //初始化 156 onMounted(() => { 157 const canvas = backgroundCanvas.value 158 ctx = canvas.getContext("2d") 159 160 ws = new WebSocket("ws://192.168.174.97:5000") 161 162 ws.onopen = () => { 163 const player1 = new Player(0, 0, 60, 60, "red", 2, 2, myName) 164 players.push(player1) 165 ws.send(JSON.stringify({ type: "pjoin", data: player1 })) 166 //绑定按键事件 167 window.addEventListener('keydown', keyDown) 168 window.addEventListener('keyup', keyUp) 169 window.addEventListener('mousemove', mouseMove) 170 window.addEventListener('mousedown', mouseDown) 171 //启动 172 animate() 173 } 174 175 ws.onmessage = (res) => { 176 const response = JSON.parse(res.data) 177 const data = response.data 178 const type = response.type 179 if (type == "pjoin" || type == "pupdate" || type == "pleave") { 180 const player = new Player(data.x, data.y, data.width, data.height, data.color, data.xSpeed, data.ySpeed, data.name) 181 if (type == "pjoin") { 182 const index = players.findIndex(p => p.name == player.name) 183 if (index != -1) { 184 players[index] = player 185 } else { 186 players.push(player) 187 } 188 } else if (type == "pupdate") { 189 const index = players.findIndex(p => p.name == player.name) 190 if (index != -1) { 191 players[index] = player 192 } else { 193 players.push(player) 194 } 195 } 196 } else if (type == "bjoin" || type == "bupdate" || type == "bleave") { 197 const bullet = new Bullet(data.x, data.y, data.width, data.height, data.color, data.xSpeed, data.ySpeed, data.angle, data.from, data.name) 198 if (type == "bjoin") { 199 if (!bullets.find(b => b.name == bullet.name)) { 200 bullets.push(bullet) 201 } 202 } else if (type == "bupdate") { 203 const index = bullets.findIndex(b => b.name == bullet.name) 204 if (index != -1) { 205 bullets[index] = bullet 206 } else { 207 bullets.push(bullet) 208 } 209 } else if (type == "bleave") { 210 const index = bullets.findIndex(b => b.name == bullet.name) 211 if (index != -1) { 212 bullets.splice(index, 1) 213 } 214 } 215 } 216 } 217 218 }) 219 //玩家类 220 class Player { 221 constructor(x, y, width, height, color, xSpeed, ySpeed, name) { 222 this.x = x 223 this.y = y 224 this.width = width 225 this.height = height 226 this.color = color 227 this.xSpeed = xSpeed 228 this.ySpeed = ySpeed 229 this.name = name 230 } 231 232 draw() { 233 ctx.fillStyle = this.color 234 ctx.fillRect(this.x - this.width / 2, this.y - this.height / 2, this.width, this.height) 235 } 236 237 } 238 //子弹类 239 class Bullet { 240 constructor(x, y, width, height, color, xSpeed, ySpeed, angle, from, name) { 241 this.x = x 242 this.y = y 243 this.width = width 244 this.height = height 245 this.color = color 246 this.xSpeed = xSpeed 247 this.ySpeed = ySpeed 248 this.angle = angle 249 this.from = from 250 this.name = name 251 } 252 253 draw() { 254 ctx.fillStyle = this.color 255 ctx.fillRect(this.x - this.width / 2, this.y - this.height / 2, this.width, this.height) 256 } 257 } 258 </script> 259 260 <style scoped> 261 .CanvasContainer { 262 display: flex; 263 width: 100vw; 264 height: 100vh; 265 background-color: #000; 266 align-items: center; 267 justify-content: center; 268 } 269 270 canvas { 271 background-color: #000333; 272 border: red solid 2px; 273 cursor: none; 274 } 275 </style>
app.js
1 const express = require('express'); 2 const WebSocket = require('ws') 3 const cors = require('cors'); 4 const app = express(); 5 6 app.use(express.json()); 7 app.use(cors()); 8 9 const server = app.listen(5000, () => { 10 console.log(`服务运行在 http://localhost:5000`); 11 }); 12 13 const wss = new WebSocket.Server({server}) 14 15 let clients = [] 16 let players = [] 17 let bullets = [] 18 19 wss.on('connection', ws => { 20 21 console.log("新玩家加入游戏") 22 23 ws.on('message',res => { 24 const response = JSON.parse(res); 25 const data = response.data 26 const type = response.type 27 //判断类型后操作 28 if(type == "pjoin"){ 29 //新添玩家 30 clients.push({name:data.name, ws}) 31 players.push(data) 32 //给所有老玩家同步新玩家 33 wss.clients.forEach(client => { 34 client.send(JSON.stringify({type: "pjoin", data: data})) 35 }) 36 //给新玩家同步所有老玩家 37 players.forEach(p => { 38 ws.send(JSON.stringify({type: "pjoin", data: p})) 39 }) 40 }else if(type == "pupdate"){ 41 //寻找需要更新位置的玩家 42 const index = players.findIndex(p => p.name == data.name) 43 if(index != -1) { 44 //更新玩家 45 players[index] = data 46 } 47 //广播给所有玩家位置 48 wss.clients.forEach(client => { 49 client.send(JSON.stringify({type: "pupdate", data: data})) 50 }) 51 }else if(type == "pleave"){ 52 53 }else if(type == "bjoin"){ 54 bullets.push(data) 55 wss.clients.forEach(client => { 56 client.send(JSON.stringify({type: "bjoin", data: data})) 57 }) 58 }else if(type == "bupdate"){ 59 const index = bullets.findIndex(b => b.name == data.name) 60 if(index != -1) { 61 bullets[index] = data 62 } 63 wss.clients.forEach(client => { 64 client.send(JSON.stringify({type: "bupdate", data: data})) 65 }) 66 }else if(type == "bleave"){ 67 const index = bullets.findIndex(b => b.name == data.name) 68 if(index != -1) { 69 bullets.splice(index, 1) 70 } 71 wss.clients.forEach(client => { 72 client.send(JSON.stringify({type: "bleave", data: data})) 73 }) 74 } 75 }) 76 })
感觉我总有一天会把这个重写一遍的,到时候我绝对要把大部分逻辑写在后端,前端只负责画画

浙公网安备 33010602011771号