d3.js 制作简单的贪吃蛇

d3.js是一个不错的可视化框架,同时对于操作dom也是十分方便的。今天我们使用d3.js配合es6的类来制作一个童年小游戏–贪吃蛇。话不多说先上图片。

1. js snaker类

class Snaker {constructor() {this._size = 30;this._len = 3;this._width = 900;this._height = 690;this._rows = 23;this._cols = 30;this._colors = d3.scaleLinear().range(['#E75229','#FFBF35']);this._svg = null;this._currentArray = [[0,2],[0,1],[0,0]];this._interval = null;this._duration = 1000;this._direction = 1;//上右下左0123this._randomPosition = [0,6];this.initSvg();this.addKeyListener();}initSvg() {this._svg = d3.select('.svg-container').append('svg').attr('width', this._width).attr('height', this._height)this._svg.selectAll('line.rows').data(d3.range(this._rows)).enter().append('line').attr('class', 'line rows').attr('x1', 0).attr('y1', d => d * this._size).attr('x2', this._width).attr('y2', d => d * this._size)this._svg.selectAll('line.cols').data(d3.range(this._cols)).enter().append('line').attr('class', 'line cols').attr('x1', d => d * this._size).attr('y1', 0).attr('x2', d => d * this._size).attr('y2', this._height)}addKeyListener() {d3.select('body').on('keydown', () => {switch (d3.event.keyCode) {case 37:this.rotate(3);break;case 38:this.rotate(0);break;case 39:this.rotate(1);break;case 40:this.rotate(2);break;case 32:console.log('空格');break;case 80:console.log('暂停');break;default:break;}})}rotate(num) {if(num == this._direction) {this.rotateMove();} else if(num % 2 != this._direction % 2) {this._direction = num;this.rotateMove();}}renderSnaker() {this._svg.selectAll('rect.active').remove();this._svg.selectAll('rect.active').data(this._currentArray).enter().append('rect').attr('class', 'active').attr('x', d => d[1] * this._size).attr('y', d => d[0] * this._size).attr('width', this._size).attr('height', this._size).attr('fill', (d,i) => this._colors(i / this._len)).attr('stroke', (d,i) => this._colors(i / this._len))}canMove() {//下一步没有触碰边缘let noTouchBorder = true;//下一步没有触碰自身let noTouchSelf = true;//新数组let newArray = [];//判断方向switch(this._direction) {case 0:if(this._currentArray[0][0] == 0) {noTouchBorder = false;} else {newArray = this._currentArray.map((c,i,arr) => {if(i == 0) {return [c[0] - 1, c[1]]} else {return arr[i - 1]}})}break;case 1:if(this._currentArray[0][1] == this._cols - 1) {noTouchBorder = false;} else {newArray = this._currentArray.map((c,i,arr) => {if(i == 0) {return [c[0], c[1] + 1]} else {return arr[i - 1]}})}break;case 2:if(this._currentArray[0][0] == this._rows - 1) {noTouchBorder = false;} else {newArray = this._currentArray.map((c,i,arr) => {if(i == 0) {return [c[0] + 1, c[1]]} else {return arr[i - 1]}})}break;case 3:if(this._currentArray[0][1] == 0) {noTouchBorder = false;} else {newArray = this._currentArray.map((c,i,arr) => {if(i == 0) {return [c[0], c[1] - 1]} else {return arr[i - 1]}})}break;}//判断新数组第一个元素是否出现在后面其他元素中for(var i=1; i<newArray.length; i++) {if(newArray[0][0] == newArray[i][0] && newArray[0][1] == newArray[i][1]) {noTouchSelf = false;}}return noTouchBorder && noTouchSelf;}setScoreAndSpeed() {d3.select('#score').html(this._len);d3.select('#speed').html((this._duration * (1 - this._len / 1000) / 1000).toString().substr(0,8) + 's')}moveArray() {if(this.canMove()) {if(this._direction == 0) {if(this._currentArray[0][0] - 1 == this._randomPosition[0] && this._currentArray[0][1] == this._randomPosition[1]) {this._currentArray.unshift(this._randomPosition);this._len ++;this.setScoreAndSpeed();this.removeRandomPosition();this.randomPosition();} else {this._currentArray.unshift([this._currentArray[0][0] - 1,this._currentArray[0][1]])this._currentArray.pop();}} else if(this._direction == 1) {if(this._currentArray[0][0] == this._randomPosition[0] && this._currentArray[0][1] + 1 == this._randomPosition[1]) {this._currentArray.unshift(this._randomPosition);this._len ++;this.setScoreAndSpeed();this.removeRandomPosition();this.randomPosition();} else {this._currentArray.unshift([this._currentArray[0][0],this._currentArray[0][1] + 1])this._currentArray.pop();}} else if(this._direction == 2) {if(this._currentArray[0][0] + 1 == this._randomPosition[0] && this._currentArray[0][1] == this._randomPosition[1]) {this._currentArray.unshift(this._randomPosition);this._len ++;this.setScoreAndSpeed();this.removeRandomPosition();this.randomPosition();} else {this._currentArray.unshift([this._currentArray[0][0] + 1,this._currentArray[0][1]])this._currentArray.pop();}} else if(this._direction == 3) {if(this._currentArray[0][0] == this._randomPosition[0] && this._currentArray[0][1] - 1 == this._randomPosition[1]) {this._currentArray.unshift(this._randomPosition);this._len ++;this.setScoreAndSpeed();this.removeRandomPosition();this.randomPosition();} else {this._currentArray.unshift([this._currentArray[0][0],this._currentArray[0][1] - 1])this._currentArray.pop();}}} else {console.log('game over');alert('game over')}}removeRandomPosition() {d3.selectAll('rect.random').remove();}randomPosition() {let random = Math.floor(Math.random() * (this._cols * this._rows - this._len));let temp = [];for(var i=0; i<this._rows; i++) {for(var j=0; j<this._cols; j++) {temp.push([i,j])}}let emptyArray = temp.filter(a => !this._currentArray.some(b => b[0] == a[0] && b[1] == a[1]));this._randomPosition = emptyArray[random];this._svg.append('rect').attr('class', 'random').attr('x', this._randomPosition[1] * this._size).attr('y', this._randomPosition[0] * this._size).attr('width', this._size).attr('height', this._size)}interval() {this._interval = setInterval(() => {this.moveArray();this.renderSnaker();}, this._duration * (1 - this._len / 1000))}//转弯附带移动一次
    rotateMove() {this.moveArray();this.renderSnaker();}initData() {this._currentArray = [[0,2],[0,1],[0,0]];}start() {this.initData();this.renderSnaker();this.interval();this.randomPosition();this.setScoreAndSpeed();}
}

2. css 代码

* {padding: 0;margin: 0;
}
.container {width: 100vw;height: 100vh;
}
.svg-container {margin: 50px;width: 900px;height: 690px;border: 3px double #666;display: inline-block;overflow: hidden;
}
aside {width: 200px;height: 300px;display: inline-block;vertical-align: top;margin-top: 50px;
}
.line {shape-rendering: crispEdges;stroke: #bbbbbb;
}
.active {stroke-width: 2;fill-opacity: 0.5;
}
.random {fill: #ff00ff;fill-opacity: 0.5;stroke: #ff00ff;stroke-width: 2;
}

3. html代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>$Title$</title><link rel="stylesheet" type="text/css" href="css/base.css"/><script type="text/javascript" src="js/d3.v4.js"></script><script type="text/javascript" src="js/base.js"></script>
</head>
<body><div class="container"><div class="svg-container"></div><aside><table><tr><td>当前分数:</td><td id="score"></td></tr><tr><td>当前速度:</td><td id="speed"></td></tr></table><button onclick="start()">开始游戏</button></aside></div>
<script>
var snaker = new Snaker();
function start() {snaker.start();
}</script>
</body>
</html>

 

有想预览或者下载demo的朋友请移步至个人博客

原文地址 http://www.bettersmile.cn

转载于:https://www.cnblogs.com/vadim-web/p/11496275.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/248138.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js高级第六天

Q课程回顾&#xff1a; ​ 闭包&#xff1a;有权访问另外一个函数的局部变量的函数&#xff0c;作用&#xff1a;延伸变量使用范围 ​ mdn&#xff0c;w3c function fn1 () {var n 3;return function () {console.log(n);} }​ 递归&#xff1a;函数调用其本身 function f…

Chrome 75 lazy-loading

Chrome 75 & lazy-loading https://addyosmani.com/blog/lazy-loading/ https://chromestatus.com/feature/5645767347798016 Chrome 75 将默认启用延迟加载功能 自 Chrome 75 起&#xff0c;将原生支持图片的延迟加载&#xff0c;在代码中编写 <img loading"lazy&…

d3.js 实现烟花鲜果

今天在d3.js官网上看到了一个烟花的DEMO&#xff0c;是canvas制作的&#xff0c;于是我想用d3.js来实现它&#xff0c;js代码只有几行。好了废话不多说&#xff0c;先上图。 1 js 类 因为烟花要有下落的效果&#xff0c;所以里面用到了一些简单的数学和物理知识来模拟重力&…

阿里Sentinel控制台源码修改-对接Apollo规则持久化

改造背景 前面我们讲解了如何对接Apollo来持久化限流的规则&#xff0c;对接后可以直接通过Apollo的后台进行规则的修改&#xff0c;推送到各个客户端实时生效。 但还有一个问题就是Sentinel控制台没有对接Apollo&#xff0c;Sentinel控制台本来就可以修改限流的规则&#xff0…

Python学习(一)

一、版本&#xff1a; Python2.X /Python3.x 官方宣布2020 年 1 月 1 日&#xff0c; 停止 Python 2 的更新。 Python3.x不兼容Python2.x  二、安装&#xff08;以mac 为例&#xff09; MAC 系统一般都自带有 Python2.x版本 的环境&#xff0c;你也可以在链接 https://www.py…

jQuery—淘宝精品服饰案例

<body><div class"wrapper"><ul id"left"><li><a href"#">女靴</a></li><li><a href"#">雪地靴</a></li><li><a href"#">冬裙</a>&l…

Python机器学习实践:决策树判别汽车金融违约用户

文章发布于公号【数智物语】 &#xff08;ID&#xff1a;decision_engine&#xff09;&#xff0c;关注公号不错过每一篇干货。 转自 | 法纳斯特&#xff08;公众号ID:walker398&#xff09; 作者 | 小F 决策树呈树形结构&#xff0c;是一种基本的回归和分类方法。 决策树模型的…

jQuery—tab栏切换

<div class"tab"><div class"tab_list"><ul><li class"current">商品介绍</li><li>规格与包装</li><li>售后保障</li><li>商品评价&#xff08;50000&#xff09;</li><l…

操作系统原理之I/O设备管理(第六章上半部分)

一、I/O系统的组成 I/O系统不仅包括各种I/O设备&#xff0c;还包括与设备相连的设备控制器&#xff0c;有些系统还配备了专⻔⽤ 于输⼊/输出控制的专⽤计算机&#xff0c;即通道。此外&#xff0c;I/O系统要通过总线与CPU、内存相连。 I/O系统的结构&#xff1a; I/O设备的分类…

操作系统原理之I/O设备管理(第六章下半部分)

五、I/O软件原理 输入输出软件的总体目标是将软件组织成一种层次结构 低层软件用来屏蔽硬件的具体细节高层软件则主要是为用户提供一个简洁、规范的界面设备管理的4个层次&#xff1a; 用户层软件 -》向系统发出I/O请求&#xff0c;显示I/O操作的结果&#xff0c;提供⽤户与设备…

切换Debug/Release编译模式和Archive的作用

&#xfeff;在学这个之前&#xff0c;以为很难&#xff0c;也起不到什么作用&#xff0c;但是等真正运用到工程里面&#xff0c;才发现&#xff0c;这个能帮你省下很多工作量。 1&#xff0c;Debug和Release版本区别&#xff1f; 进行iOS开发&#xff0c;在Xcode调试程序时&am…

AFNetworking 对数据进行https ssl加密

参考来源&#xff1a;http://www.cnblogs.com/jys509/p/5001566.html 现在在工作中的工作需求&#xff1a;https请求验证证书一般来讲如果app用了web service , 我们需要防止数据嗅探来保证数据安全.通常的做法是用ssl来连接以防止数据抓包和嗅探其实这么做的话还是不够的 。…

数据库系统原理(第一章概述)

一、数据库基本概念 什么是数据&#xff1a;数据&#xff08;Data&#xff09;是描述事物的符号记录&#xff0c;是指利用物理符号记录下来的、 可以鉴别的信息。 数据是信息存在的一种形式&#xff0c;只有通过解释或处理的数据才能成为有用的信息。 什么是数据库&#xff1a;…

实验二:Linux下Xen环境的安装

实验名称&#xff1a; Linux下Xen环境的安装&#xff08;centOS7&#xff09; 实验环境&#xff1a; 本次实验基本是在centOS7的环境下完成&#xff0c;系统内核和系统版本如下&#xff1a; 实验要求&#xff1a; 为centOS7的环境下安装Xen的平台&#xff0c;能够正常使用Xen下…

IDEA写vue项目出现红色波浪线警告如何解决??

1.看图 2.希望对大家有帮助&#xff0c;只要修改了这个就可以&#xff0c;如有任何问题都可以留言&#xff0c;谢谢大家 2019-09-1923:54:11 作者&#xff1a;何秀好 转载于:https://www.cnblogs.com/itboxue/p/11553395.html

数据可视化(BI报表的开发)第一天

课程回顾&#xff1a; ​ jQuery事件注册&#xff1a; ​ $(元素).click(function () {}); ​ $(元素).on(‘click’, [后代元素], function () {}); ​ $(元素).one(‘click’, function () {}); ​ 解绑事件&#xff1a;off ​ 自动触发&#xff1a; ​ $(元素).click…

在Block中使用weakSelf与strongSelf的意义

在Block中使用weakSelf与strongSelf的意义 我们都会声明一个弱引用在block中使用, 目的就是防止循环引用, 那么weakSelf与strongSelf一起使用目的是什么呢? 首先先定义2个宏: #define YXWeakSelf(type) __weak typeof(type) weak##type type; #define StrongSelf(type) __…

操作系统原理之操作系统简介(第一章)

一、 什么是操作系统 操作系统&#xff1a;是一种复杂的系统软件&#xff0c;是不同程序代码、数据结构、数据初始化文件的集合&#xff0c;可执行。 操作系统是用户与硬件之间的接口&#xff1a;操作系统与硬件部分相互作用&#xff0c;并且为运行在计算机上的应用程序提供执行…

数据可视化(BI报表的开发)第二天

9、公用面板样式 所有的面板的基础样式是一致的&#xff0c;提前布局好。 面板 .panel &#xff1a;box-sizing&#xff0c;边框图&#xff0c;大小&#xff0c;定位【51 38 20 132】容器 .inner&#xff1a;padding&#xff1a;24&#xff0c;36&#xff0c;定位外部拉宽标…

关于Xcode 7.3 7.3.1 断点 卡死 无限菊花

关于Xcode 7.3 7.3.1 断点 卡死 无限菊花 只要一打断点,就无限卡死,变量区一直菊花在转,只有强制退出Xcode才能重新编译,找了Google和Stack OvewFlowe依然没有解决办法. 删除项目,重新安装Xcode,重新运行程序一切办法都解决不到,百度上说的"build setting中将Enable Clang…