日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

手写坦克大战联网版(持续更新)

發布時間:2024/1/1 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 手写坦克大战联网版(持续更新) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

用到腳本語言

??????????? javascript es5 es6 es7

??????????? node

??????????????? | ? models

???????????????????????? | ????? socket.io

??????????? mysql

先了解下目錄結構

前端

?????? css:游戲的一些樣式

?????? js:動態腳本 觸碰系統等】

?????? index.html 網頁腳本

?????? images 圖片 ???????

后臺

?????? node_modules? 模塊

?????? main.js? 主啟動

搭建服務

?服務器部署

我使用的是nginx?? node部署到服務器 需要 反向代理接口

server服務

listen?? 監聽端口號80

location/api? 監聽到/api的參數就將值代理給3000端口號

準備工作

brick磚塊

explose爆炸圖

my坦克圖

bullet子彈圖

分享圖片

下載素材當前無效過后我會搭建素材頁面的

地圖計算

所有素材 模型 大小 32 * 32

橫向14 * 32??

豎向18 * 32

<canvas id = 'ctx' width = '448' height = '576'></canvas>

首先我們先獲取canvas

let c = document.getElementById("ctx"); var ctx=c.getContext("2d");

接下來創建繪制圖片系統

drawCreate = async (url,x,y,w,h,id) =>{ //繪制圖片let image = new Image();let app = await new Promise((resolve)=>{image.src = url;image.onload = function(){resolve(image);}}).then((image)=>{if(id == 0){_1ps = {w:w,h:h,x:x,y:y}}ctx.drawImage(image,x,y,w,h);});return image; }

改繪制圖片方法有6個參數? url為圖片路徑? x y 為坐標 w h 為圖片 大小 id 0,1,2?? 0為1p玩家?? 1為2p玩家? 2為地圖繪制也就是素材

移動系統

//添加移動事件 let move = async (url,obj,type,value) =>{ //玩家移動方法ctx.clearRect(obj.x,obj.y,obj.w,obj.h);if(type == 1){if(obj.up == undefined && value < 0){ //判斷是否是首次加載圖片let item = await drawCreate(url,obj.x,obj.y + value,obj.w,obj.h,0);return item;}if(obj.down == undefined && value > 0){if(type == 1){let item = await drawCreate(url,obj.x,obj.y + value,obj.w,obj.h,0);return item;}}}else{if(obj.right == undefined && value > 0){let item = await drawCreate(url,obj.x + value,obj.y,obj.w,obj.h,0);return item;}if(obj.left == undefined && value < 0){let item = await drawCreate(url,obj.x + value,obj.y,obj.w,obj.h,0);return item;}}if(type == 1){ctx.drawImage(url,obj.x,obj.y += value ,obj.w,obj.h);return url;}else{ctx.drawImage(url,obj.x += value,obj.y ,obj.w,obj.h);return url;} } document.body.onkeydown = async (event) =>{let item = "";switch(event.keyCode){case 65: //a后if(mapScope(_1ps.x - 4,0,32,28))return;item = await move(_1ps.left || _1p.left,_1ps,0,-4);_1ps.left = item;break;case 68: //d前if(mapScope(_1ps.x + 4,0,32,28)))return;item = await move(_1ps.right || _1p.right,_1ps,0,4);_1ps.right = item;break;case 83: //s下if(mapScope(_1ps.y + 4,1,32,28)))return;item = await move(_1ps.down || _1p.down,_1ps,1,4);_1ps.down = item;break;case 87: //w上if(mapScope(_1ps.y - 4,1,32,28)))return;item = await move(_1ps.up || _1p.up,_1ps,1,-4);_1ps.up = item;break;} }

范圍限制

let mapScope = (value,type,w,h) => { //檢測是否超出地圖限制 type = 0 左右地圖限制 type = 1 上下地圖限制if(type == 0){if(value < 0 || value > 448 - w)return true;}else{if(value > 576 - h || value < 0)return true;} }

編輯一張地圖

因為先前設置的地圖高度是32*18 寬度是32*14? 我們要創建一個 14*18的二維數組

?

像上面構造玩家一樣構造沒個建筑物 有些不合適 隱藏 需要一個地圖構造器

let level = [ //關卡[[3,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,2,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,2,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,3,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,4,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,5,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,6,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0]] ]

地圖構造器

現在地圖控制器設置一個規則 方便創建出來的對象樣式 然后對該規則做一套適配

1p?? 0

2p?? 1

普通磚 ? 2

剛磚? 3

草坪? 4

水池? 5

冰路? 6

修改上面我們改好的loadGame

let loadGame = async () =>{ //加載游戲let item = await drawCreate(_1p.up,32,545,32,32,0);mapCreate(); } let mapCreate = async () => {//地圖構造器 // 1p:1 普通磚:2 剛轉:3 草坪:4 水池:5 冰路:6let s = 0;for(let i = 0;level[levels][i]!=undefined;i++){for(let j = 0;level[levels][i][j]!=undefined;j++){if(level[levels][i][j] > 0){if(level[levels][i][j] >= 1){let item = await drawCreate(matter[level[levels][i][j] - 2],j*32,i*32,32,32);obj.push({ //將所有建筑物的坐標保存到objw:32,h:32,x:j*32,y:i*32,ev:level[levels][i][j],index:s++,el:item,id:createId()})}}}} } let createId = (length = 32)=>{ //創建idlet str = "";let arr = "qwertyuiopasdfghjklmnbcvxzQWERTYUIOPLKJHGFDSAZXCBNM1234567890"for(let i = 0;i<=length;i++){str += arr[Math.round(Math.random() * 61)];}return str; }

地圖構造器原理其實很簡單 就是遍歷關卡的數組中以及對應的位置

當前現在雖然地圖制作好了 但是由于沒有觸碰檢測 觸碰磚塊時怪物就會消失? 因此我們還要寫個觸碰檢測

每次移動和子彈發射以及一系列的操作都需要通過觸碰檢測

觸碰檢測

let detection = (x,y,w,h,type) => { //檢測觸碰for(let i = 0;obj[i]!=undefined;i++){if(type == 0){if((y < obj[i].y + 40 && y > obj[i].y) && (x >= obj[i].x - 28 && x <= obj[i].x + 28))return true;}else if(type == 1){if((y < obj[i].y + 28 && y > obj[i].y - 40) && (x >= obj[i].x - 28 && x <= obj[i].x + 28))return true;}else if(type == 2){if((y < obj[i].y + 32 && y > obj[i].y - 28) && (x >= obj[i].x - 28 && x <= obj[i].x + 28))return true;}else if(type == 3){if((y < obj[i].y + 32 && y > obj[i].y - 28) && (x >= obj[i].x - 28 && x <= obj[i].x + 28))return true;}} }

將該檢測放到移動時

document.body.onkeydown = async (event) => {let item = "";switch(event.keyCode){case 65: //a后if(mapScope(_1ps.x - 4,0,32,28)))return;if(detection(_1ps.x - 4,_1ps.y,32,32,2))return;item = await move(_1ps.left || _1p.left,_1ps,0,-4);_1ps.left = item;break;case 68: //d前if(mapScope(_1ps.x + 4,0,32,28)))return;if(detection(_1ps.x + 4,_1ps.y,32,32,3))return;item = await move(_1ps.right || _1p.right,_1ps,0,4);_1ps.right = item;break;case 83: //s下if(mapScope(_1ps.y + 4,1,32,28)))return;if(detection(_1ps.x,_1ps.y - 4,32,32,1))return;item = await move(_1ps.down || _1p.down,_1ps,1,4);_1ps.down = item;break;case 87: //w上if(mapScope(_1ps.y - 4,1,32,28)))return;if(detection(_1ps.x,_1ps.y + 4,32,32,0))return;item = await move(_1ps.up || _1p.up,_1ps,1,-4);_1ps.up = item;break;case 74: //j子彈createBullet();break;} }

接下來我們構造子彈

構造子彈

let createBullet = async (x,y,direction) => { //創建子彈if(disabled == true)return;if(direction == 0){ //上_bullet = await drawCreate(bullet,x + 11,y - 8,8,8);bulletMove(0,x+11,y - 8,8,8);}if(direction == 1){ //下_bullet = await drawCreate(bullet,x + 11,y + 24,8,8);bulletMove(1,x+11,y+24,8,8)}if(direction == 2){ //右_bullet = await drawCreate(bullet,x + 32,y + 4,8,8);bulletMove(2,x+32,y+4,8,8);} if(direction == 3){ //左_bullet = await drawCreate(bullet,x - 8,y+4,8,8);bulletMove(3,x - 8,y+4,8,8);}disabled = true;setTimeout(()=>{ //子彈設置0.5秒一發disabled = false;},500) }

當然 現在這些子彈還是不會動的

稍后我們修改讓其動起來

會動的子彈

function bulletMove(d,x,y,w,h){ //子彈移動 方向 坐標 大小let value = d == 0 || d == 3?-4:4;if(disabled == true)return;let move = setInterval(()=>{if(d == 0 || d == 1){ctx.clearRect(x,y,w,h);if(mapScope(y + value,1)){clearInterval(move);return false;}ctx.drawImage(_bullet,x,y += value,w,h);}else{ctx.clearRect(x,y,w,h);if(mapScope(x + value,0)){clearInterval(move);return false;}ctx.drawImage(_bullet,x += value,y,w,h);}},20); }

子彈觸碰

let bulletDetection = (d,x,y,w,h) =>{ //子彈觸碰檢測for(let i = 0;obj[i]!=undefined;i++){if(d == 0){if((y - 36 <= obj[i].y && y + 8 >= obj[i].y) && (x >= obj[i].x - 8 && x <= obj[i].x + 28))return true;}else if(d == 1){if((y >= obj[i].y - 8 && y <= obj[i].y + 8) && (x >= obj[i].x - 8 && x <= obj[i].x + 28))return true;}else if(d == 2){if((x >= obj[i].x - 8 && x <= obj[i].x + 32) && (y >= obj[i].y - 8 && y <= obj[i].y + 32))return true;}else if(d == 3){if((x >= obj[i].x - 8 && x <= obj[i].x + 32) && (y >= obj[i].y - 8 && y <= obj[i].y + 32))return true;}} }

?

let bulletDetection = (d,x,y,w,h) =>{ //子彈觸碰檢測for(let i = 0;obj[i]!=undefined;i++){if(d == 0){if((y - 36 <= obj[i].y && y + 8 >= obj[i].y) && (x >= obj[i].x - 8 && x <= obj[i].x + 28)){if(touchBulletElement(obj[i]))return true;}}else if(d == 1){if((y >= obj[i].y - 8 && y <= obj[i].y + 8) && (x >= obj[i].x - 8 && x <= obj[i].x + 28)){let bullet = {x:x,y:y,}if(touchBulletElement(obj[i],bullet))return true;}}else if(d == 2){if((x >= obj[i].x - 8 && x <= obj[i].x + 32) && (y >= obj[i].y - 8 && y <= obj[i].y + 32)){if(touchBulletElement(obj[i],bullet))return true;}}else if(d == 3){if((x >= obj[i].x - 8 && x <= obj[i].x + 32) && (y >= obj[i].y - 8 && y <= obj[i].y + 32)){if(touchBulletElement(obj[i],bullet))return true;}}} }

判斷當前打到的道具是什么

let touchBulletElement = (obj,bullets,d) =>{ //判斷子彈觸碰到的是什么元素switch(obj.ev){case 2:attackDirection(obj,bullets,d)break;case 3: //剛轉attackDirection(obj,bullets,d)break;case 6: //草地ctx.clearRect(obj.x,obj.y,obj.w,obj.h);ctx.drawImage(obj.el,obj.x,obj.y,obj.w,obj.h);return false;case 5: //水池ctx.clearRect(obj.x,obj.y,obj.w,obj.h);ctx.drawImage(obj.el,obj.x,obj.y,obj.w,obj.h);return false;}return true; }

修改這些后需要將創建子彈套上觸碰

接下來該判斷子彈打中了什么元素了

在此我們來分析一下

? 每塊磚都要一分為四? 也就是說當前x ~ 16? y ~ 16為第一塊磚? x + 16 ~ x + 32 ~ y ~ y + 16 第二塊磚

?????????????????????????????????????????????????????????????????? x ~ 16 y + 16 ~ y + 32第三塊磚? x + 16 y + 16 ~ y + 32 最后一塊磚

在bulletDetection嵌套檢測攻擊子彈函數

打中后清空磚塊

let attackDirection = (obj,bullets,d) =>{ //攻擊磚塊ctx.clearRect(obj.x,obj.y,32,32);removeObj(obj.id) } let removeObj = (id) =>{ //刪除對象for(let i = 0;obj[i]!=undefined;i++){if(obj[i].id == id)obj.splice(i,1);} }

?

?

?

?

?

總結

以上是生活随笔為你收集整理的手写坦克大战联网版(持续更新)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。