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

20260421

我靠不行了,这烂代码太折磨人了,越写越恶心,越写问题越多,明天立刻马上重构骨架,果然联机逻辑啥的还是得放在后端。

虽然已经完成了移动发射子弹减少血量判断死亡等逻辑,但还是有很多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     if (me == null) {
 56       return
 57     }
 58     //计算方向
 59     const dx = keys.mouseX - me.x
 60     const dy = keys.mouseY - me.y
 61     const dist = Math.sqrt(dx * dx + dy * dy)
 62     const speed = 5
 63 
 64     //保证所有方向速度一致
 65     const vx = (dx / dist) * speed
 66     const vy = (dy / dist) * speed
 67 
 68     const bullet = new Bullet(me.x, me.y, 10, 10, "green", vx, vy, null, myName, Date.now())
 69 
 70     bullets.push(bullet)
 71 
 72     ws.send(JSON.stringify({ type: "bjoin", data: bullet }))
 73 
 74     keys.mouseDown = false
 75     keys.mouseLatestDown = Date.now()
 76   }
 77 
 78 }
 79 //画鼠标准心
 80 function drawMouse() {
 81   const cx = keys.mouseX
 82   const cy = keys.mouseY
 83   const len = 8
 84   const gap = 3
 85 
 86   ctx.strokeStyle = '#fff'
 87   ctx.lineWidth = 2
 88 
 89   ctx.beginPath()
 90   ctx.moveTo(cx, cy - gap - len)
 91   ctx.lineTo(cx, cy - gap)
 92   ctx.moveTo(cx, cy + gap)
 93   ctx.lineTo(cx, cy + gap + len)
 94 
 95   ctx.moveTo(cx - gap - len, cy)
 96   ctx.lineTo(cx - gap, cy)
 97   ctx.moveTo(cx + gap, cy)
 98   ctx.lineTo(cx + gap + len, cy)
 99   ctx.stroke()
100 }
101 
102 //更新位置
103 function updatedPosition() {
104   //自己移动
105   players.forEach(player => {
106     if (player.name == myName) {
107       if (keys.w || keys.a || keys.s || keys.d) {
108         if (keys.w) player.y -= player.ySpeed
109         if (keys.s) player.y += player.ySpeed
110         if (keys.a) player.x -= player.xSpeed
111         if (keys.d) player.x += player.xSpeed
112         //发送自己新位置
113         ws.send(JSON.stringify({ type: "pupdate", data: player }))
114       }
115     }
116   })
117   //子弹移动
118   bullets.forEach((bullet, index) => {
119     bullet.x += bullet.xSpeed
120     bullet.y += bullet.ySpeed
121 
122     ws.send(JSON.stringify({ type: "bupdate", data: bullet }))
123 
124     if (bullet.x < 0 || bullet.x > backgroundCanvas.value.width || bullet.y < 0 || bullet.y > backgroundCanvas.value.height) {
125       bullets.splice(index, 1)
126       ws.send(JSON.stringify({ type: "bleave", data: bullet }))
127       console.log(bullet.from + "已移除子弹")
128     }
129 
130   })
131 
132 }
133 //更新事件
134 function updateEvent() {
135   //碰撞检测
136   bullets.forEach((bullet, bIndex) => {
137     players.forEach((player, pIndex) => {
138       if (bullet.from == myName && player.name != myName) {
139         if (bullet.x + bullet.width / 2 > player.x - player.width / 2 &&
140           bullet.x - bullet.width / 2 < player.x + player.width / 2 &&
141           bullet.y + bullet.height / 2 > player.y - player.height / 2 &&
142           bullet.y - bullet.height / 2 < player.y + player.height / 2) {
143 
144           //移除子弹
145           bullets.splice(bIndex, 1)
146           ws.send(JSON.stringify({ type: "bleave", data: bullet }))
147           console.log(bullet.name + "已移除子弹")
148           //玩家受伤
149           player.hp -= 20
150           if (player.hp <= 0) {
151             //玩家死亡
152             players.splice(pIndex, 1)
153             ws.send(JSON.stringify({ type: "pleave", data: player }))
154             console.log(player)
155           } else {
156             //更新玩家血量
157             ws.send(JSON.stringify({ type: "pupdate", data: player }))
158           }
159 
160         }
161       }
162     })
163   })
164 }
165 //
166 function draw() {
167   //清空画布
168   ctx.clearRect(0, 0, backgroundCanvas.value.width, backgroundCanvas.value.height)
169 
170   players.forEach(player => {
171     player.draw()
172   })
173 
174   bullets.forEach(bullet => {
175     bullet.draw()
176   })
177   drawMouse()
178 }
179 //动画
180 function animate() {
181   updatedPosition()
182   updateEvent()
183   draw()
184   requestAnimationFrame(animate)
185 }
186 //初始化
187 onMounted(() => {
188 
189   myName = prompt("请输入你的昵称")
190 
191   const canvas = backgroundCanvas.value
192   ctx = canvas.getContext("2d")
193 
194   ws = new WebSocket("ws://192.168.174.97:5000")
195 
196   ws.onopen = () => {
197     let x = Math.random() * canvas.width
198     let y = Math.random() * canvas.height
199     const player1 = new Player(x, y, 60, 60, "red", 100, 100, 2, 2, myName)
200     players.push(player1)
201     ws.send(JSON.stringify({ type: "pjoin", data: player1 }))
202     //绑定按键事件
203     window.addEventListener('keydown', keyDown)
204     window.addEventListener('keyup', keyUp)
205     window.addEventListener('mousemove', mouseMove)
206     window.addEventListener('mousedown', mouseDown)
207     //启动
208     animate()
209   }
210 
211   ws.onmessage = (res) => {
212     const response = JSON.parse(res.data)
213     const data = response.data
214     const type = response.type
215     if (type == "pjoin" || type == "pupdate" || type == "pleave") {
216       const player = new Player(data.x, data.y, data.width, data.height, data.color, data.hp, data.maxHp, data.xSpeed, data.ySpeed, data.name)
217       if (type == "pjoin") {
218         const index = players.findIndex(p => p.name == player.name)
219         if (index != -1) {
220           players[index] = player
221         } else {
222           players.push(player)
223         }
224       } else if (type == "pupdate") {
225         const index = players.findIndex(p => p.name == player.name)
226         if (index != -1) {
227           players[index] = player
228         }
229       } else if (type == "pleave") {
230         const index = players.findIndex(p => p.name == player.name)
231         if (player.name == myName) {
232           players.splice(index, 1)
233           alert("你趋势了!!!")
234         } else if (index != -1) {
235           players.splice(index, 1)
236         }
237       }
238     } else if (type == "bjoin" || type == "bupdate" || type == "bleave") {
239       const bullet = new Bullet(data.x, data.y, data.width, data.height, data.color, data.xSpeed, data.ySpeed, data.angle, data.from, data.name)
240       if (type == "bjoin") {
241         if (!bullets.find(b => b.name == bullet.name)) {
242           bullets.push(bullet)
243         }
244       } else if (type == "bupdate") {
245         const index = bullets.findIndex(b => b.name == bullet.name)
246         if (index != -1) {
247           bullets[index] = bullet
248         }
249       } else if (type == "bleave") {
250         const index = bullets.findIndex(b => b.name == bullet.name)
251         if (index != -1) {
252           bullets.splice(index, 1)
253         }
254       }
255     }
256   }
257 
258 })
259 //玩家类
260 class Player {
261   constructor(x, y, width, height, color, hp, maxHp, xSpeed, ySpeed, name) {
262     this.x = x
263     this.y = y
264     this.width = width
265     this.height = height
266     this.color = color
267     this.hp = hp
268     this.maxHp = maxHp
269     this.xSpeed = xSpeed
270     this.ySpeed = ySpeed
271     this.name = name
272   }
273 
274   //绘制玩家本体
275   drawPlayer() {
276     ctx.fillStyle = this.color
277     ctx.fillRect(this.x - this.width / 2, this.y - this.height / 2, this.width, this.height)
278   }
279 
280   //绘制头顶血条
281   drawHpBar() {
282     const barWidth = this.width
283     const barHeight = 4
284     const barY = this.y - this.height / 2 - 10
285 
286     //血条背景
287     ctx.fillStyle = "#ff3333"
288     ctx.fillRect(this.x - barWidth / 2, barY, barWidth, barHeight)
289 
290     //当前血量
291     const currentWidth = (this.hp / this.maxHp) * barWidth
292     ctx.fillStyle = "#33ff33"
293     ctx.fillRect(this.x - barWidth / 2, barY, currentWidth, barHeight)
294   }
295 
296   //画名字
297   drawName() {
298     ctx.fillStyle = "#fff"
299     ctx.font = "14px Arial"
300     ctx.textAlign = "center"
301     ctx.textBaseline = "top"
302     ctx.fillText(this.name, this.x, this.y + this.height / 2 + 5)
303   }
304 
305   draw() {
306     this.drawPlayer()
307     this.drawHpBar()
308     this.drawName()
309   }
310 
311 }
312 //子弹类
313 class Bullet {
314   constructor(x, y, width, height, color, xSpeed, ySpeed, angle, from, name) {
315     this.x = x
316     this.y = y
317     this.width = width
318     this.height = height
319     this.color = color
320     this.xSpeed = xSpeed
321     this.ySpeed = ySpeed
322     this.angle = angle
323     this.from = from
324     this.name = name
325   }
326 
327   draw() {
328     ctx.fillStyle = this.color
329     ctx.fillRect(this.x - this.width / 2, this.y - this.height / 2, this.width, this.height)
330 
331   }
332 }
333 </script>
334 
335 <style scoped>
336 .CanvasContainer {
337   display: flex;
338   width: 100vw;
339   height: 100vh;
340   background-color: #000;
341   align-items: center;
342   justify-content: center;
343 }
344 
345 canvas {
346   background-color: #000333;
347   border: red solid 2px;
348   cursor: none;
349 }
350 </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             const index = players.findIndex(p => p.name == data.name)
53             if(index != -1) {
54                 players.splice(index, 1)
55 
56             }
57             wss.clients.forEach(client => {
58                 client.send(JSON.stringify({type: "pleave", data: data}))
59             })
60         }else if(type == "bjoin"){
61             bullets.push(data)
62             wss.clients.forEach(client => {
63                 client.send(JSON.stringify({type: "bjoin", data: data}))
64             })
65         }else if(type == "bupdate"){
66             const index = bullets.findIndex(b => b.name == data.name)
67             if(index != -1) {
68                 bullets[index] = data
69             }
70             wss.clients.forEach(client => {
71                 client.send(JSON.stringify({type: "bupdate", data: data}))
72             })
73         }else if(type == "bleave"){
74             const index = bullets.findIndex(b => b.name == data.name)
75             if(index != -1) {
76                 bullets.splice(index, 1)
77                 wss.clients.forEach(client => {
78                     client.send(JSON.stringify({type: "bleave", data: data}))
79                 })
80             }
81         }
82     })
83 })

 

http://www.jsqmd.com/news/678610/

相关文章:

  • Kubernetes里AlertManager总启动失败?排查这个Storage Path坑和3个常见配置错误
  • 从‘晶振不启振’到‘信号不稳’:盘点晶体电路设计的5个常见坑与避坑指南
  • 【研报325】香港电动车普及化路线图:2026-2035电动化实施路径
  • 打印尺寸
  • 统信UOS蓝牙管理实战:从systemctl服务控制到rfkill硬件开关
  • XUnity.AutoTranslator:如何用一款插件彻底改变你的Unity游戏本地化体验?
  • 从CASE 2023看自动化新趋势:农业、医疗、建筑,哪些领域正在被AI重塑?
  • Autosar Arxml实战:5分钟搞懂CANFD的Container-PDU与I-Signal-PDU布局
  • 从滑滑梯到电磁场:曲线积分在物理引擎与游戏开发中的实际应用
  • Autosar Dcm模块性能调优实战:从DcmTaskTime到SplitTasks的Vector工具配置全解析
  • 零基础想要系统学习 Agent,千万别错过这两个开源项目!
  • 别再混淆了!用Keil MDK调试Cortex-M3/M4时,MSP和PSP到底怎么切换的?
  • 豆包AI有官方广告渠道吗?第三方GEO服务商提供内容优化路径 - 品牌2026
  • ECharts 响应式设计指南
  • 内存管理-31-每进程内存统计-5-/proc/pid/maps - Hello
  • 【ROS2机器人进阶指南】动作(Action)通信:从原理剖析到自定义接口实战
  • Inspirit Capital将收购Kaplan Languages Group
  • ux-grid进阶:处理表格排序中的特殊数据与边界场景
  • STM32新手避坑:Keil报‘Not a genuine ST Device’?别慌,两步搞定ST-LINK驱动和配置
  • 终极指南:3步彻底卸载Windows系统顽固的Microsoft Edge浏览器
  • 流量图5 - 小镇
  • 【UE5 Cesium实战】从零到一:在Unreal Engine中高效加载与校准本地倾斜摄影模型
  • 2026年可静电吸附皮革基材靠谱厂商TOP5技术解析 - 优质品牌商家
  • 别再死记硬背YOLO的9个anchors了!用Python可视化带你搞懂它在特征图上的调整过程
  • 华为云服务器迁移
  • 从‘炼丹’到‘工程’:复盘InceptionV3论文中那些被验证与‘打脸’的设计(附代码对比)
  • 2026年精密平面磨床top5推荐:精密外圆磨床/精密平面磨床/精密无心磨床/高精度无心磨床/数控内圆磨床/选择指南 - 优质品牌商家
  • Eigen库ldlt().solve()一行代码求解线性方程组,性能实测与避坑指南
  • 鸣潮自动化工具ok-ww:5分钟搞定每日重复任务的终极解决方案
  • 保姆级教程:在Ubuntu 18.04上为Firefly RK3399 ProC交叉编译Python 3.7.10(含zlib、numpy、pyserial)