用到脚本语言

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);}
}

手写坦克大战联网版(持续更新)相关推荐

  1. 有手就能学会- C语言零基础手写坦克大战

    1.2 项目介绍 2.1. 项目需求 实现1款和经典的<90坦克大战>一样的游戏,任务是消灭敌对坦克,保护己方领地.防止敌方打破你的老窝围墙而把你的鹰打坏. 2.2. 学习目标 回顾经 ...

  2. android studio写坦克大战代码_GitHub 项目推荐:俄罗斯小游戏、Markdown 幻灯片、头像生成器、Logo 制作、坦克大战...

    今天跟大家分享一下,过去几天在各大社交平台分享的一些开源项目. 本周新增了粉丝推荐环节,如果你有发现优质的开源项目,欢迎在公众号或其它平台私信推荐,我们会不定期筛选推送. 小编推荐 俄罗斯方块小游戏 ...

  3. javascript写坦克大战

    无意间浏览到别人写的js坦克大战,这是我这段时间看过最复杂的代码了(相对而言),作者博文链接:http://blog.whlcsj.com/js-tankwar.html github链接:https ...

  4. Unity 2D手游——坦克大战 C#

    需要下载项目的朋友,请打开CSDN链接:Unity2D坦克大战项目工程 本项目涉及到的功能: 1.UI部分: a .游戏开始界面UI       b.主场景UI      c.游戏胜利界面UI     ...

  5. 世界崩塌前要写下游戏心得(持续更新)

    前言 有一部纪录片中问道,你为什么看电影?有人回答"想要体验不同的人生","可以看到丰富的故事,增加人生阅历","因为电影特效好看,很刺激" ...

  6. 在android view中写坦克大战

    我是把以前写在java里的代码直接移植到android上了(后面贴的代码有比较的部分) 只改了画笔的对象,和控制方式 代码大致思路 1.画 我们要画出坦克,炮弹,爆炸效果 1.1画坦克 1.1.1画竖 ...

  7. 《方圆·齐物》手游项目初期总结(持续更新)

    游戏仍在开发中,还有很多功能未实现(试玩地址:方圆·齐物) 游戏功能模块 通用模块 数据配置 资源加载 用户数据操作 场景异步加载 UI界面数据的显示与更新 道具系统 背包系统 任务系统 邮件系统 消 ...

  8. 从零开始用js手写飞机大战全过程(附源码)

    plane game 前言 此文章帮助初学者学习制作一个简单小游戏 目标 利用css,html,js制作出飞机大战的简略版 前置准备 1. 绝对定位与相对定位 这里除了背景都设置为绝对定位,使飞机和敌 ...

  9. python飞机大战联网版_Python 飞机大战搞怪版本

    python 飞机大战搞怪版本 (飞机为迷你亚索,外星人为迷你小诺手,由于时间关系和图片素材较难寻找,仅仅做了简易版,没有贴上背景图片.由于篇幅原因,对于函数讲解较为简略,可以自行搜索相应函数的用法) ...

最新文章

  1. 2018-3-18 中国计算机之母-- 夏培肃
  2. ios玩全民奇迹不显示服务器,全民奇迹关于IOS充值游戏物品不到账公告
  3. Django 1.10中更新modules同步数据库
  4. boost::advance用法的测试程序
  5. R语言心得-分词包的安装
  6. 文献记录(part9)--A biclustering-based method for market segmentation using customer pain points
  7. jvm与非jvm语言优劣_都灵JVM编程语言:使用ANTLR构建高级词法分析器
  8. 西安4年java多少时间_西安学习java一般要多久
  9. ORA-12519: TNS:no appropriate service handler found 解决方法
  10. 8年前端开发的知识点沉淀(不知道会多少字,一直写下去吧,)
  11. ubuntu18.04下hadoop安装与集群配置
  12. 材料的构成 —— 塑料
  13. 多个Excel文件合并成一个文件
  14. 19个程序员接私活平台汇总升级版!你有技术就有钱!
  15. 软件工程:状态,行为,事件
  16. pop,oop,aop编程思想
  17. 什么是JavaScript异步编程?
  18. R语言 AHP层次分析法——如何验证矩阵一致性
  19. basler恢复出厂设置_bios恢复出厂设置
  20. windows sc使用方法之一

热门文章

  1. java+ee+网页修改数据库_基于jsp的作业批改-JavaEE实现作业批改 - java项目源码
  2. java8双层for循环,Java8处理List的双层循环问题
  3. 蓝牙遥控器 – 将手机模拟为键盘、鼠标、翻页笔、遥控器
  4. Python---自动生成二维码
  5. 【毕业设计】Java ssm校园兼职系统 大学生兼职系统
  6. 编码器测距离使用外部中断计脉冲
  7. office 和 wps 对于超链接的处理浅析
  8. 计算机硬件组成学情分析,初中信息技术_探究计算机的硬件组成教学设计学情分析教材分析课后反思.doc...
  9. Excel工作表中最常用的10个经典技巧
  10. python处理大数据量json数据的方法_python-利用json模块处理json数据几个函数总结...