Three.js 3D坦克 网页联机对战版纯前端 WebSocket 局域网联机一台开服务端另一台浏览器输入IP就能双人联机对战完整可直接部署运行一、服务端Node.jsserver.jsconstWebSocketrequire(ws);constwssnewWebSocket.Server({port:8080});// 房间玩家数据letplayers{};letplayerId1;wss.on(connection,(ws){constpidplayerId;players[pid]{id:pid,pos:{x:pid1?-15:15,y:0,z:0},rotY:0,hp:100};console.log(玩家${pid}已连接);// 发送当前所有玩家数据给新玩家ws.send(JSON.stringify({type:init,data:players,selfId:pid}));// 广播新玩家上线broadcast({type:newPlayer,p:players[pid]});ws.on(message,(msg){constdataJSON.parse(msg);switch(data.type){// 同步自身位置旋转casepos:if(players[pid]){players[pid].posdata.pos;players[pid].rotYdata.rotY;}broadcast({type:syncPos,list:players});break;// 开火同步casefire:broadcast({type:fire,sid:pid,dir:data.dir});break;// 扣血同步casehurt:players[data.tid].hp-data.dmg;broadcast({type:hurt,tid:data.tid,hp:players[data.tid].hp});break;}});ws.on(close,(){deleteplayers[pid];broadcast({type:leave,id:pid});console.log(玩家${pid}离线);});});// 全员广播functionbroadcast(data){wss.clients.forEach(client{if(client.readyStateWebSocket.OPEN){client.send(JSON.stringify(data));}});}console.log(联机坦克服务端启动成功 ws://localhost:8080);二、客户端联机游戏页面index.html!DOCTYPEhtmlhtmllangzh-CNheadmetacharsetUTF-8title3D坦克 局域网联机对战/titlestyle*{margin:0;padding:0;box-sizing:border-box;}body{overflow:hidden;background:#111;}#tip{position:absolute;top:10px;left:10px;color:#fff;font-size:18px;z-index:999;}#win{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:50px;color:red;display:none;background:#0008;padding:20px;border-radius:10px;}/style/headbodydividtip连接中.../divdividwin对局结束/divscriptsrchttps://cdn.jsdelivr.net/npm/three0.158.0/build/three.min.js/scriptscript// 联机配置 constWS_URLws://127.0.0.1:8080;// 改成你的电脑局域网IPletws,selfId0;letallPlayerData{};// 游戏全局letscene,camera,renderer;lettanks{};letbullets[];letwalls[];constkeys{};constspeed0.08;constbulletSpeed0.3;// 初始化场景functioninitScene(){scenenewTHREE.Scene();scene.backgroundnewTHREE.Color(0x87ceeb);cameranewTHREE.PerspectiveCamera(60,innerWidth/innerHeight,0.1,1000);camera.position.set(0,35,30);camera.lookAt(0,0,0);renderernewTHREE.WebGLRenderer({antialias:true});renderer.setSize(innerWidth,innerHeight);renderer.shadowMap.enabledtrue;document.body.appendChild(renderer.domElement);// 光照scene.add(newTHREE.AmbientLight(0xffffff,0.4));constdirnewTHREE.DirectionalLight(0xffffff,1);dir.position.set(20,40,20);scene.add(dir);// 地面constgroundnewTHREE.Mesh(newTHREE.PlaneGeometry(60,60),newTHREE.MeshLambertMaterial({color:0x338833}));ground.rotation.x-Math.PI/2;ground.receiveShadowtrue;scene.add(ground);}// 创建坦克模型functioncreateTank(color){consttanknewTHREE.Group();// 车身letbodynewTHREE.Mesh(newTHREE.BoxGeometry(2.5,1,3.5),newTHREE.MeshLambertMaterial({color}));body.position.y0.5;body.castShadowtrue;tank.add(body);// 炮塔letturnewTHREE.Mesh(newTHREE.CylinderGeometry(0.6,0.6,1.2,16),body.material);tur.position.y1.6;tank.add(tur);// 炮管letgunnewTHREE.Mesh(newTHREE.CylinderGeometry(0.2,0.2,2.2,8),body.material);gun.rotation.zMath.PI/2;gun.position.set(0,1.6,1.2);tank.add(gun);returntank;}// 生成墙体functioncreateWall(){letmatnewTHREE.MeshLambertMaterial({color:0x555});for(leti0;i10;i){letwnewTHREE.Mesh(newTHREE.BoxGeometry(5,2,1.5),mat);w.position.set((Math.random()-0.5)*45,1,(Math.random()-0.5)*45);walls.push(w);scene.add(w);}}// 发射炮弹functionfire(dirVec){letbulletnewTHREE.Mesh(newTHREE.SphereGeometry(0.3,8,8),newTHREE.MeshBasicMaterial({color:0xff8800}));letselfTanktanks[selfId];bullet.position.copy(selfTank.position);bullet.position.y1.6;bullet.userData.dirdirVec;bullets.push(bullet);scene.add(bullet);}// 键盘监听window.addEventListener(keydown,e{keys[e.code]true;if(e.codeSpace){letselfTtanks[selfId];letdirnewTHREE.Vector3(0,0,1);dir.applyQuaternion(selfT.quaternion);// 本地开火 同步服务器fire(dir);ws.send(JSON.stringify({type:fire,dir:{x:dir.x,y:dir.y,z:dir.z}}));}});window.addEventListener(keyup,ekeys[e.code]false);// 本地玩家移动functionselfMove(){letttanks[selfId];if(!t)return;if(keys.KeyW)t.translateZ(speed);if(keys.KeyS)t.translateZ(-speed);if(keys.KeyA)t.rotation.y0.03;if(keys.KeyD)t.rotation.y-0.03;// 同步位置给服务器ws.send(JSON.stringify({type:pos,pos:{x:t.position.x,y:t.position.y,z:t.position.z},rotY:t.rotation.y}));}// 同步所有坦克位置functionsyncTankPos(){for(letidinallPlayerData){letdallPlayerData[id];if(!tanks[id]){// 区分敌我颜色letcNumber(id)selfId?0x2266ff:0xff2222;tanks[id]createTank(c);scene.add(tanks[id]);}tanks[id].position.set(d.pos.x,d.pos.y,d.pos.z);tanks[id].rotation.yd.rotY;document.getElementById(tip).innerText我方血量:${allPlayerData[selfId]?.hp||100}| 联机对战中;}}// 更新炮弹与碰撞functionupdateBullet(){for(letibullets.length-1;i0;i--){letbbullets[i];b.position.xb.userData.dir.x*bulletSpeed;b.position.zb.userData.dir.z*bulletSpeed;// 检测击中其他玩家for(letpidintanks){if(Number(pid)selfId)continue;if(b.position.distanceTo(tanks[pid].position)2){ws.send(JSON.stringify({type:hurt,tid:pid,dmg:15}));scene.remove(b);bullets.splice(i,1);break;}}// 边界清除if(Math.abs(b.position.x)38||Math.abs(b.position.z)38){scene.remove(b);bullets.splice(i,1);}}}// 胜负判断functioncheckWin(){letwinDomdocument.getElementById(win);letselfHpallPlayerData[selfId]?.hp;if(selfHp0){winDom.innerText你战败了;winDom.style.displayblock;}for(letidinallPlayerData){if(id!selfIdallPlayerData[id].hp0){winDom.innerText你胜利了;winDom.style.displayblock;}}}// 连接WebSocket服务端functionconnectWS(){wsnewWebSocket(WS_URL);ws.onopen(){document.getElementById(tip).innerText已连接服务器等待队友进入;};ws.onmessage(e){letmsgJSON.parse(e.data);switch(msg.type){caseinit:selfIdmsg.selfId;allPlayerDatamsg.data;break;casesyncPos:allPlayerDatamsg.list;break;casehurt:allPlayerData[msg.tid].hpmsg.hp;checkWin();break;casefire:// 接收别人开火letdnewTHREE.Vector3(msg.dir.x,msg.dir.y,msg.dir.z);fire(d);break;}};ws.onerror()alert(连接服务器失败请检查IP与端口);}// 窗口适配window.onresize(){camera.aspectinnerWidth/innerHeight;camera.updateProjectionMatrix();renderer.setSize(innerWidth,innerHeight);};// 渲染循环functionanimate(){requestAnimationFrame(animate);selfMove();syncTankPos();updateBullet();renderer.render(scene,camera);}// 启动游戏functionstartGame(){initScene();createWall();connectWS();animate();}startGame();/script/body/html三、使用教程超简单安装Node.js官网下载安装新建文件夹放入server.js打开cmd进入文件夹执行npminstallwsnodeserver.js查看本机局域网IPWinipconfig / Linuxifconfig修改index.html里WS_URL ws://你的局域网IP:8080两台电脑同WiFi都打开这个html即可联机对战操作规则玩家1 / 玩家2 统一操控WASD移动转向空格开火位置、开火、掉血全部实时同步血量归0直接弹出胜负提示自带随机墙体阻挡拓展功能可直接加增加炮弹爆炸粒子特效加入观战视角、第三人称跟随视角限制坦克穿墙碰撞增加道具、加速、护盾改成4人多人联机