声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢!

  过年的十八天假期迷迷糊糊一下子就过去了(LZ还是实习生,鉴于大学最后一个寒假了,所以就多请了好多天假),又要返工上班了。这是年后的第一篇博客了。其实就是水一下,毕竟不能冷落博客太久啊。

  这两天刚好抱着玩的心情写了个接水管游戏,本来用css3更容易写。。。就旋转那些东西,不过因为LZ比较喜欢canvas的写法,所以还是用了canvas来写。

  先上个DEMO吧:接水管   玩法很简单:点击水管块就可以旋转水管,连通水管后点击上面的水阀,然后就可以了。可能还有bug,LZ暂时没去测试了。

  因为代码也很简单,重点也不多,就先说下游戏思路:

  【游戏逻辑】

  游戏逻辑很简单,就是水管总共有4个面,给四个面一个代号:0,1,2,3;然后水管有两个口,一个进水口,一个出水口,就可以用0,1,2,3来表示水管的两个口(如果想写更复杂的,多个口的,也一个样,一个进水口,多个出水口,用数组保存就行了。我写的这个比较简单,只有两个口,所以后面判断连通性也比较容易。),保存好水管块的进出口数据后,当水管旋转时,相应改变水管进出口参数就行了。

  然后就是连通性判断:水管只有两个口的话就很简单了。一般有一个最初的进水口,然后就从那个水管块开始,先获取出水口,然后再遍历当前水管块周围的水管块的进水口是否跟当前水管块的出水口相连通(被遍历的水管块的进水口和出水口都要进行判断,因为水管可以旋转,也就是说进水口和出水口在一开始是无法确定的,当确定了连通关系后,就可以确定水管的进水口和出水口了,之后的循环也一样),如果对的上。就说明连通了。然后就跳到那个水管块,再进行那个水管块周围的水管块的遍历,就这样重复遍历,直到最后一个也就是出水的那个水管块也连通了,就说明整条水管连通了。

  上面的是只有两个口的水管连通性判断,如果游戏中有三个口的水管甚至四个口的水管,判断方式就没那么简单了。我写的是两个口的,不过也想了一下多口的判断,大概就是找到水管的进水口,因为是多个出水口,所以就得一个一个来,对每一条线路进行判断,每当跳转到一个新的水管块,就把之前的那个水管块保存为新水管块的父类水管。然后对新水管的出水口进行循环判断,如果没有发现有连通的水管,则跳转至父类水管,并将新水管块加入“此路不通”列表,再次遍历父类水管块的其他出水口进行判断,如此循环,当循环到父类为最初进水口的那个水管块的时候,就说明水管没有连通路线,当然,如果循环到新水管块为出口水管时,就说明连通了。

  楼主比较懒,所以就只写了两个口的,没写多个口的了。

  【代码部分】

  首先定义水管块对象:

var Box = function(center , style , Gateway , angle , coordinate){this.center = center;this.style = style;this.angle = angle;this.endangle = angle;this.Gateway = Gateway;this.coordinate = coordinate;}Box.prototype = {constructor:Box,draw:function(){this.setHole();if(this.angle!==this.endangle){canclick = false;this.rotate();}var ext = [{x:0,y:-boxWidth/2},{x:boxWidth/2,y:0},{x:0,y:boxWidth/2},{x:-boxWidth/2,y:0},
                        ]ctx.save();ctx.translate(this.center.x , this.center.y);ctx.rotate(this.angle);//画管道switch(this.style){case 0:break;case 1:ctx.drawImage(document.getElementById("pipe1") , -boxWidth/2 , -boxWidth/2 , boxWidth , boxWidth);break;case 2:ctx.drawImage(document.getElementById("pipe2") , -boxWidth/2 , -boxWidth/2 , boxWidth , boxWidth);break;case 3:ctx.drawImage(document.getElementById("start") , -boxWidth/2 , -boxWidth/2 , boxWidth , boxWidth);break;}ctx.restore();},rotate:function(){if(Math.abs(this.endangle-this.angle)<=0.01){canclick = true;this.endangle = this.endangle>=2*Math.PI?0:this.endangle;this.angle = this.endangle;if(this.style===3){var result = connectPipes();if(result){// alert('成功连通')connectSuccess = true;}else {alert("游戏失败")window.location.reload();}}}else {this.angle += (this.endangle-this.angle)*0.2;}},setHole:function(){if(this.style===1){var zl = this.endangle/(0.5*Math.PI);var initHole1 = 0 , initHole2 = 2;this.inHole = (initHole1+zl)>=4?((initHole1+zl)-4):(initHole1+zl);this.outHole = (initHole2+zl)>=4?((initHole2+zl)-4):(initHole2+zl);}else if(this.style===2){var zl = this.endangle/(0.5*Math.PI);var initHole1 = 1 , initHole2 = 2;this.inHole = (initHole1+zl)>=4?((initHole1+zl)-4):(initHole1+zl);this.outHole = (initHole2+zl)>=4?((initHole2+zl)-4):(initHole2+zl);}}}

对象主要属性包括:水管位置,水管种类(主要就两个,1为直线的,2为九十度折角的),水管是否可以旋转的判定,水管旋转的初始角度,以及水管所处位置的行和列。

如何让水管点击后旋转,其实也很简单,就是先把画布平移到水管块中心,然后旋转,然后再把水管画出来,就旋转好了。

然后就是判断水管连通性的代码:

//判断水管连通性function connectPipes(){var index = 0;while(1){var result = getHole(boxes[index]);if(boxes[index+result.nextBox]){if(result.hole===boxes[index+result.nextBox].inHole){index = index+result.nextBox;}else if(result.hole===boxes[index+result.nextBox].outHole){var num = boxes[index+result.nextBox].inHole;boxes[index+result.nextBox].inHole = result.hole;boxes[index+result.nextBox].outHole = num;index = index+result.nextBox;}else {break;}}else {break;}}if(index===boxes.length-1) return true;else return false;}function getHole(box){var hole="0";var nextBox=0;switch(box.outHole){case 0 : hole = 2;nextBox = -cols;break;case 1 : hole = 3;if(box.coordinate.cols===cols-1){nextBox = 1000000;}else nextBox = 1;break;case 2 : hole = 0;nextBox = cols;break;case 3 : hole = 1;if(box.coordinate.cols===0){nextBox = 1000000;}else nextBox = -1;break;}return {hole:hole , nextBox:nextBox};}

逻辑之前已经说过了,而且代码也比较简单,就不解释了,getHole是返回当前水管块的出水口如果要连通,需要的进水口的参数以及水管在水管数组里的位置。

  然后就是路径,如何保证一定有条成功的路呢?因为如果管道全部随机的话,可能会陷入死路。所以,我就干脆定好几条正确的路径,每次刷新页面就取其中一条,其他水管块也添加一些随机出来的水管作干扰。所以,我就专门用一个data.js文件来存放所有的路径,路径文件代码如下:

//水管路径
var allPath = [
[{rows:0,cols:0,style:1},{rows:1,cols:0,style:1},{rows:2,cols:0,style:1},{rows:3,cols:0,style:2},{rows:3,cols:1,style:2},{rows:2,cols:1,style:2},{rows:2,cols:2,style:1},{rows:2,cols:3,style:1},{rows:2,cols:4,style:1},{rows:2,cols:5,style:1},{rows:2,cols:6,style:1},{rows:2,cols:7,style:2},{rows:3,cols:7,style:1},
],[{rows:0,cols:0,style:1},{rows:1,cols:0,style:1},{rows:2,cols:0,style:2},{rows:2,cols:1,style:2},{rows:1,cols:1,style:2},{rows:1,cols:2,style:2},{rows:2,cols:2,style:2},{rows:2,cols:3,style:1},{rows:2,cols:4,style:1},{rows:2,cols:5,style:1},{rows:2,cols:6,style:2},{rows:1,cols:6,style:2},{rows:1,cols:7,style:2},{rows:2,cols:7,style:1},{rows:3,cols:7,style:1},
],[{rows:0,cols:0,style:1},{rows:1,cols:0,style:1},{rows:2,cols:0,style:1},{rows:3,cols:0,style:2},{rows:3,cols:1,style:2},{rows:2,cols:1,style:1},{rows:1,cols:1,style:2},{rows:1,cols:2,style:1},{rows:1,cols:3,style:1},{rows:1,cols:4,style:1},{rows:1,cols:5,style:2},{rows:1,cols:5,style:2},{rows:2,cols:5,style:2},{rows:2,cols:6,style:1},{rows:2,cols:7,style:2},{rows:3,cols:7,style:1},
],]

View Code

路径的每一个点包含的参数就是行列位置以及水管的类型,如果想游戏更多变化,可以再多加几条路径,我就只弄了三条啦:下面是取路径然后生成相对应的水管,同时把水管的旋转角度也随机。

var n = getRandom(0 , allPath.length-1);var path = allPath[n];path.foreach(function(){var index = this.rows*cols + this.cols;if((this.rows==0&&this.cols==0)||(this.rows==(rows-1)&&this.cols==(cols-1))){boxes[index] = new Box({x:(this.cols*boxWidth)+boxWidth/2+jiange , y:(this.rows*boxWidth)+boxWidth/2+marginTop} , this.style , true , 0 , {rows:this.rows , cols:this.cols});}else if(this.rows>0&&this.rows<3&&this.cols>2&&this.cols<5){boxes[index] = new Box({x:(this.cols*boxWidth)+boxWidth/2+jiange , y:(this.rows*boxWidth)+boxWidth/2+marginTop} , this.style , true , 0.5*Math.PI ,  {rows:this.rows , cols:this.cols});}else{boxes[index] = new Box({x:(this.cols*boxWidth)+boxWidth/2+jiange , y:(this.rows*boxWidth)+boxWidth/2+marginTop} , this.style , false , parseInt(getRandom(0,3))*0.5*Math.PI ,  {rows:this.rows , cols:this.cols});}});

然后就木有啦。。。。

源码地址:https://github.com/whxaxes/canvas-test/tree/gh-pages/src/Game-demo/connectPipe

转载于:https://www.cnblogs.com/axes/p/3552683.html

用canvas写个接水管小游戏相关推荐

  1. 使用canvas写一个flappy bird小游戏

    简介 canvas 是HTML5 提供的一种新标签,它可以支持 JavaScript 在上面绘画,控制每一个像素,它经常被用来制作小游戏,接下来我将用它来模仿制作一款叫flappy bird的小游戏. ...

  2. 《uni-app》一个非canvas的飞机对战小游戏实现-碰撞检测的实现

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言-博主看到后会去代替大家踩坑的-接下来的几篇都是uni-app的小实战,有助于我们更好的去学 ...

  3. 《uni-app》一个非canvas的飞机对战小游戏实现-敌机模型实现

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言-博主看到后会去代替大家踩坑的-接下来的几篇都是uni-app的小实战,有助于我们更好的去学 ...

  4. 《uni-app》一个非canvas的飞机对战小游戏实现(一)准备

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言-博主看到后会去代替大家踩坑的-接下来的几篇都是uni-app的小实战,有助于我们更好的去学 ...

  5. 《uni-app》一个非canvas的飞机对战小游戏-启动页

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言-博主看到后会去代替大家踩坑的-接下来的几篇都是uni-app的小实战,有助于我们更好的去学 ...

  6. 《uni-app》一个非canvas的飞机对战小游戏实现-我方飞机实现

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言-博主看到后会去代替大家踩坑的-接下来的几篇都是uni-app的小实战,有助于我们更好的去学 ...

  7. python的pygame库使用方法_python基础教程使用Python第三方库pygame写个贪吃蛇小游戏...

    今天看到几个关于pygame模块的博客和视频,感觉非常有趣,这里照猫画虎写了一个贪吃蛇小游戏,目前还有待完善,但是基本游戏功能已经实现,下面是代码: # 导入模块 import pygame impo ...

  8. 【牛客刷题】上手用C语言写一个三子棋小游戏超详解哦(电脑优化)

    作者:[南航科院小张 南航科院小张的博客 专栏:从c语言的入门到进阶 学习知识不只是要懂,还要会用:想要找到好的工作,这里给大家介绍一件可以斩获诸多大厂offer的利器–牛客网 点击免费注册和我一起开 ...

  9. 你写一个web网页小游戏

    写一个 web 网页小游戏需要以下几个步骤: 选择一种编程语言,常用的有 HTML.CSS.JavaScript 和 Python. 使用编辑器创建一个 HTML 文件,这个文件将是你的网页的基础. ...

  10. c语言写一个简单的小游戏-推箱子

    在学习C语言之后,写了一个简单的小游戏来锻炼自己的代码以及C语言知识的掌握能力. 推箱子作为手机上最常见的简单游戏,其代码也相对简单,想法也比较简单,下面为其代码和运行图. /************ ...

最新文章

  1. VB100年底测试:McAfee金山遗憾出局 瑞星表现令人意外
  2. Docker存储驱动devicemapper介绍和配置
  3. 编程语言中,差、交、并、自然连接、选择、投影、笛卡尔积分别都是什么运算...
  4. 90后过年,吃零下18度的年夜饭
  5. 年底促销海报还没准备好?电商美工看这里
  6. 31.前端之html
  7. java是什么_Java是什么?Java的特点有哪些?
  8. Notepad++下载
  9. 从零到无学单片机——画原理图、PCB
  10. ChinaITLab-Linux工程师培训课程笔记7
  11. python棋盘放米的故事_棋盘摆米的故事你得到了什么启发
  12. 《不要等到毕业以后》读书笔记
  13. 服务器光纤信号灯lan,光纤猫光信号灯不亮怎么办 光纤猫光信号灯不亮解决方法...
  14. 计算机替换字体怎么操作,电脑怎么更换字体-电脑更换字体的方法 - 河东软件园...
  15. 搭建静态的响应式个人官网
  16. 斯帅变阵只为讨好皇帝 36岁高龄大Z成热火首发
  17. [4G5G专题-46]:物理层-自适应编码调制AMC与调制编码方案(MCS, CQI, SINR, HARQ,Code Rate, efficiency)
  18. ubuntu yah3c 自动认证可执行脚本
  19. 2022图灵奖出炉!以太网之父鲍勃·梅特卡夫获奖,76岁进入新领域再出发
  20. 在html中 常见的块级元素有哪些,常见的css块级元素有哪些

热门文章

  1. C++ RQNOJ 星门龙跃
  2. coffeescript html5,CoffeeScript入门
  3. 动态平衡网格交易_网格交易 套利:期货经典书籍
  4. kangle安装php7.0_搭建Kangle+EasyPanel对接SWAP IDC虚拟主机自助开通完整教程
  5. 用代理服务器加速爬虫速率
  6. Arduino ESP32通过心知天气获取城市三天的信息
  7. 邮箱有效性验证(是否真实存在可发送)
  8. sql中interval用法总结
  9. 戴尔DELL OEM Win7SP1简体中文旗舰版原版光盘镜像64位
  10. 浏览器被hao123拦截