脚本宝典收集整理的这篇文章主要介绍了

H5原创俄罗斯方块(基于canvas)

脚本宝典小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助你少写一行代码,多一份安全和惬意。
<p><code></p> <p>第一次写俄罗斯方块的时候已经是1年多前了,也是我刚刚学js不久。<br />为了加强对js的理解又加上对游戏的爱好,于是在没有参考他人的思路和代码下,自己用最基本的js代码写出了基于canvas的俄罗斯方块。<br /><span class="img-wrap"><img data-src="/img/bVbmOlD?w=993&amp;h=601" src="/img/bVbmOlD?w=993&amp;h=601" alt="图片描述" title="图片描述" style="cursor: pointer; display: inline;"></span></p> <p>在大三的暑假,我又用了<a href="http://www.js-code.com/tag/es6" title="es6" target="_blank">es6</a>的语法进行了改进,包含了<a href="http://www.js-code.com/tag/class" title="class" target="_blank">class</a>的语法糖、<a href="http://www.js-code.com/tag/%e7%ae%ad%e5%a4%b4%e5%87%bd%e6%95%b0" title="箭头函数" target="_blank">箭头函数</a>等,进一步增加自己对<a href="http://www.js-code.com/tag/es6" title="es6" target="_blank">es6</a>的理解,代码有400+行</p> <p>想要做这个小游戏,必须先熟悉H5的canvas,js对<a href="http://www.js-code.com/tag/%e6%95%b0%e7%bb%84" title="数组" target="_blank">数组</a>的处理,键盘事件监听和处理,定时器的使用等,其他的就是基本的逻辑处理了。</p> <p><strong>游戏的规则就是核心,也是我们代码的重中之重</strong></p> <p>这里的逻辑核心是需要判断方块是否碰撞(当前运动的方块和已经定位好的方块有碰撞以致于当前的运动的方块不能在向下走,因为我们的方块默认是向下走的,如果不能向下走,是视为已经定位好的方块,然后在生成一个新的方块从初始位置继续往下走)。</p> <p>而且这个碰撞还需要应用在方块变形的时候,同样地,如果方块在变形的过程中和其他定位好的方块进行碰撞,则我们应该阻止这个方块进行变形成功,</p> <p>附上代码,欢迎讨论和指正</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="<a href="http://www.js-code.com/tag/button" title="button" target="_blank">button</a>" <a href="http://www.js-code.com/tag/class" title="class" target="_blank">class</a>="copyCode code-tool" data-toggle="tooltip" data-placement="<a href="http://www.js-code.com/tag/top" title="top" target="_blank">top</a>" data-clipboard-<a href="http://www.js-code.com/tag/text" title="text" target="_blank">text</a>="<!DOCTYPE html><br /> <html lang=&quot;en&quot;><br /> <head><br /> <meta charset=&quot;UTF-8&quot;><br /> <title><a href="http://www.js-code.com/tag/es6" title="浏览关于“es6”的文章" target="_blank" class="tag_link">es6</a>-重构俄罗斯方块(基于canvas)</title></p> <style type=&quot;text/css&quot;> #tetris{ marg<a href="http://www.js-code.com/tag/in" title="in" target="_blank">in</a>: 10px 250px;} </style> <p></head><br /> <body><br /> <canvas width=&quot;700&quot; height=&quot;525&quot; id=&quot;tetris&quot;></canvas></p> <div id=&quot;text&quot; style='color: red;font-size: 30px;'>当前分数:0</div> <p> <script type=&quot;text/javascript&quot;> /** * [一个完整的俄罗斯方块类 design by magic_xiang] * @param {number} side [每个方块边长(px),默认35] * @param {number} width [一行包含的方块数(个),默认20] * @param {number} height [一列包含的方块数(个),默认15] * @param {number} speed [方块下落移动速度(ms),默认400] */ class tetris{ <a href="http://www.js-code.com/tag/const" title="const" target="_blank">const</a>ructor(side=35, width=20, height=15, speed=400){ <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.side = side // 每个方块边长 <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.width = width // 一行包含的方块数 <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.height = height // 一列包含的方块数 <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.speed = speed // 方块下落移动速度 <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.num_blcok // 当前方块类型的数字变量 <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.type_color // 当前颜色类型的字符串变量 <a href="http://www.js-code.com/tag/this" title="浏览关于“this”的文章" target="_blank" class="tag_link">this</a>.ident // <a href="http://www.js-code.com/tag/setInterval" title="setInterval" target="_blank">setInterval</a>的标识 this.direction = 1 // 方块方向,初始化为1,默认状态 this.grade = 0 // 用来计算分数 this.over = <a href="http://www.js-code.com/tag/false" title="false" target="_blank">false</a> // 游戏是否结束 this.arr_bX = [] // 存放当前方块的X坐标 this.arr_bY = [] // 存放当前方块的Y坐标 this.arr_store_X = [] // 存放到达底部所有方块的X坐标 this.arr_store_Y = [] // 存放到达底部所有方块的Y坐标 this.arr_store_color = [] // 存放到达底部所有方块的颜色 this.pa<a href="http://www.js-code.com/tag/int" title="int" target="_blank">int</a>s = <a href="http://www.js-code.com/tag/do" title="do" target="_blank">do</a>cument.getElementById('tetris').getCon<a href="http://www.js-code.com/tag/text" title="text" target="_blank">text</a>('2d') //获取画笔 <a href="http://www.js-code.com/tag/self" title="self" target="_blank">self</a> = this }</p> <p> // 封装pa<a href="http://www.js-code.com/tag/in" title="in" target="_blank">in</a>ts方法,让代码更简洁 pa<a href="http://www.js-code.com/tag/int" title="int" target="_blank">int</a>fr(x, y, scale=1){ this.pa<a href="http://www.js-code.com/tag/int" title="浏览关于“int”的文章" target="_blank" class="tag_link">int</a>s.fillRect(x*this.side, y*this.side, scale*this.side, scale*this.side) }</p> <p> // 游戏开始 gameStart(){ this.<a href="http://www.js-code.com/tag/in" title="浏览关于“in”的文章" target="_blank" class="tag_link">in</a>it() this.run() }</p> <p> // 初始化工作 init(){ this.initBackground() this.initBlock() }</p> <p> // 方块自动下落 run(){ this.ident = <a href="http://www.js-code.com/tag/setInterval" title="setInterval" target="_blank">setInterval</a>(&quot;<a href="http://www.js-code.com/tag/self" title="self" target="_blank">self</a>.<a href="http://www.js-code.com/tag/do" title="do" target="_blank">do</a>wn_speed_up()&quot;, this.speed) }</p> <p> // 初始化地图 initBackground(){ this.paints.beginPath() this.paints.fillStyle='#000000' //地图填充颜色为黑色 <a href="http://www.js-code.com/tag/for" title="for" target="_blank">for</a>(<a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> i = 0; i < this.height; i++){ <a href="http://www.js-code.com/tag/for" title="for" target="_blank">for</a>(<a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> j = 0; j < this.width; j++){ this.paintfr(j, i) } } this.paints.closePath() } // 初始化方块的位置和颜色 initBlock(){ this.paints.beginPath() this.createRandom('rColor') //生成颜色字符串, this.paints.fillStyle = this.type_color this.createRandom('rBlock') //生成方块类型数字 this.arr_bX.forEach((item, index) => { this.paintfr(item, this.arr_bY[index], 0.9) }) this.paints.closePath() }</p> <p> // 利用数组画方块 drawBlock(color){ this.paints.beginPath() this.paints.fillStyle = color this.arr_bX.forEach((item, index) => { this.paintfr(item, this.arr_bY[index], 0.9) }) this.paints.closePath() }</p> <p> // 画已经在定位好的方块 drawStaticBlock(){ this.arr_store_X.forEach((item, index) => { this.paints.beginPath() this.paints.fillStyle = this.arr_store_color[index] this.paintfr(item, this.arr_store_Y[index], 0.9) this.paints.<a href="http://www.js-code.com/tag/close" title="close" target="_blank">close</a>Path() }) }</p> <p> // 生成随机数返回方块类型或颜色类型 createRan<a href="http://www.js-code.com/tag/do" title="浏览关于“do”的文章" target="_blank" class="tag_link">do</a>m(type){ <a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> temp = this.width/2-1</p> <p> <a href="http://www.js-code.com/tag/if" title="if" target="_blank">if</a> (type == 'rBlock'){ //如果是方块类型 this.num_blcok = <a href="http://www.js-code.com/tag/Math" title="Math" target="_blank">Math</a>.round(<a href="http://www.js-code.com/tag/Math" title="Math" target="_blank">Math</a>.random()*4+1) <a href="http://www.js-code.com/tag/switch" title="switch" target="_blank">switch</a>(this.num_blcok){ <a href="http://www.js-code.com/tag/case" title="case" target="_blank">case</a> 1: this.arr_bX.push(temp,temp-1,temp,temp+1) this.arr_bY.push(0,1,1,1) <a href="http://www.js-code.com/tag/break" title="break" target="_blank">break</a> <a href="http://www.js-code.com/tag/case" title="case" target="_blank">case</a> 2: this.arr_bX.push(temp,temp-1,temp-1,temp+1) this.arr_bY.push(1,0,1,1) <a href="http://www.js-code.com/tag/break" title="break" target="_blank">break</a> <a href="http://www.js-code.com/tag/case" title="浏览关于“case”的文章" target="_blank" class="tag_link">case</a> 3: this.arr_bX.push(temp,temp-1,temp+1,temp+2) this.arr_bY.push(0,0,0,0) <a href="http://www.js-code.com/tag/break" title="浏览关于“break”的文章" target="_blank" class="tag_link">break</a> case 4: this.arr_bX.push(temp,temp-1,temp,temp+1) this.arr_bY.push(0,0,1,1) break case 5: this.arr_bX.push(temp,temp+1,temp,temp+1) this.arr_bY.push(0,0,1,1) break } } <a href="http://www.js-code.com/tag/if" title="if" target="_blank">if</a> (type == 'rColor'){ //如果是颜色类型 <a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> num_color = <a href="http://www.js-code.com/tag/Math" title="浏览关于“Math”的文章" target="_blank" class="tag_link">Math</a>.round(Math.random()*8+1) </p> <p> <a href="http://www.js-code.com/tag/switch" title="switch" target="_blank">switch</a>(num_color){ case 1: this.type_color='#3EF72A' break case 2: this.type_color='yellow' break case 3: this.type_color='#2FE0BF' break case 4: this.type_color='red' break case 5: this.type_color='gray' break case 6: this.type_color='#C932C6' break case 7: this.type_color= '#FC751B' break case 8: this.type_color= '#6E6EDD' break case 9: this.type_color= '#F4E9E1' break } } }</p> <p> // 判断方块之间是否碰撞(下),以及变形时是否越过下边界 judgeCollision_down(){ <a href="http://www.js-code.com/tag/for" title="浏览关于“for”的文章" target="_blank" class="tag_link">for</a>(<a href="http://www.js-code.com/tag/let" title="浏览关于“let”的文章" target="_blank" class="tag_link">let</a> i = 0; i < this.arr_bX.<a href="http://www.js-code.com/tag/length" title="length" target="_blank">length</a>; i++){ <a href="http://www.js-code.com/tag/if" title="浏览关于“if”的文章" target="_blank" class="tag_link">if</a> (this.arr_bY[i] + 1 == this.height){ //变形时是否越过下边界 <a href="http://www.js-code.com/tag/return" title="return" target="_blank">return</a> <a href="http://www.js-code.com/tag/false" title="false" target="_blank">false</a> } if (this.arr_store_X.<a href="http://www.js-code.com/tag/length" title="length" target="_blank">length</a> != 0) { //判断方块之间是否碰撞(下) for(let j = 0; j < this.arr_store_X.<a href="http://www.js-code.com/tag/length" title="浏览关于“length”的文章" target="_blank" class="tag_link">length</a>; j++){ if (this.arr_bX[i] == this.arr_store_X[j]) { if (this.arr_bY[i] + 1 == this.arr_store_Y[j]) { <a href="http://www.js-code.com/tag/return" title="return" target="_blank">return</a> <a href="http://www.js-code.com/tag/false" title="浏览关于“false”的文章" target="_blank" class="tag_link">false</a> } }</p> <p> } } } <a href="http://www.js-code.com/tag/return" title="return" target="_blank">return</a> <a href="http://www.js-code.com/tag/true" title="true" target="_blank">true</a> }</p> <p> //判断方块之间是否碰撞(左右),以及变形时是否越过左右边界 judgeCollision_other(num){ for(let i = 0; i < this.arr_bX.length; i++){ if (num == 1) { //变形时是否越过右边界 if (this.arr_bX[i] == this.width - 1) <a href="http://www.js-code.com/tag/return" title="return" target="_blank">return</a> false } if (num == -1) { //变形时是否越过左边界 if (this.arr_bX[i] == 0) <a href="http://www.js-code.com/tag/return" title="浏览关于“return”的文章" target="_blank" class="tag_link">return</a> false } if (this.arr_store_X.length != 0) { //判断方块之间是否碰撞(左右) for(let j = 0; j < this.arr_store_X.length; j++){ if (this.arr_bY[i] == this.arr_store_Y[j]) { if (this.arr_bX[i] + num == this.arr_store_X[j]) { return false } } } } } return <a href="http://www.js-code.com/tag/true" title="true" target="_blank">true</a>; }</p> <p> //方向键为下的加速函数 down_speed_up(){ let flag_<a href="http://www.js-code.com/tag/all" title="all" target="_blank">all</a>_down = <a href="http://www.js-code.com/tag/true" title="浏览关于“true”的文章" target="_blank" class="tag_link">true</a> flag_<a href="http://www.js-code.com/tag/all" title="all" target="_blank">all</a>_down = this.judgeCollision_down()</p> <p> if (flag_<a href="http://www.js-code.com/tag/all" title="浏览关于“all”的文章" target="_blank" class="tag_link">all</a>_down) { this.initBackground() for(let i = 0; i < this.arr_bY.length; i++){ this.arr_bY[i] = this.arr_bY[i] + 1 } } <a href="http://www.js-code.com/tag/else" title="else" target="_blank">else</a>{ for(let i=0; i < this.arr_bX.length; i++){ this.arr_store_X.push(this.arr_bX[i]) this.arr_store_Y.push(this.arr_bY[i]) this.arr_store_color.push(this.type_color) } this.arr_bX.splice(0,this.arr_bX.length) this.arr_bY.splice(0,this.arr_bY.length) this.initBlock() } this.clearUnderBlock() this.drawBlock(this.type_color) this.drawStaticBlock() this.gameover() } //方向键为左右的左移动函数 move(dir_temp){ this.initBackground() if (dir_temp == 1) { //右 let flag_all_right = true flag_all_right = this.judgeCollision_other(1) if (flag_all_right) { for(let i = 0; i < this.arr_bY.length; i++){ this.arr_bX[i] = this.arr_bX[i]+1 } } } <a href="http://www.js-code.com/tag/else" title="else" target="_blank">else</a>{ let flag_all_left = true flag_all_left = this.judgeCollision_other(-1)</p> <p> if (flag_all_left) { for(let i=0; i < this.arr_bY.length; i++){ this.arr_bX[i] = this.arr_bX[i]-1 } } } this.drawBlock(this.type_color) this.drawStaticBlock() } //方向键为空格的变换方向函数 up_change_direction(num_blcok){ if (num_blcok == 5) { return } let arr_tempX = [] let arr_tempY = [] //因为不知道是否能够变形成功,所以先存储起来 for(let i = 0;i < this.arr_bX.length; i++){ arr_tempX.push(this.arr_bX[i]) arr_tempY.push(this.arr_bY[i]) } this.direction++ //将中心坐标提取出来,变形都以当前中心为准 let ax_temp = this.arr_bX[0] let ay_temp = this.arr_bY[0] this.arr_bX.splice(0, this.arr_bX.length) //将<a href="http://www.js-code.com/tag/%e6%95%b0%e7%bb%84" title="数组" target="_blank">数组</a>清空 this.arr_bY.splice(0, this.arr_bY.length)</p> <p> if (num_blcok == 1) {</p> <p> <a href="http://www.js-code.com/tag/switch" title="switch" target="_blank">switch</a>(this.direction%4){ case 1: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp+1,ay_temp+1,ay_temp+1) break case 2: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp,ax_temp) this.arr_bY.push(ay_temp,ay_temp,ay_temp-1,ay_temp+1) break case 3: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp,ay_temp+1,ay_temp) break case 0: this.arr_bX.push(ax_temp,ax_temp,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp) break } } if (num_blcok == 2) {</p> <p> <a href="http://www.js-code.com/tag/switch" title="switch" target="_blank">switch</a>(this.direction%4){ case 1: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp-1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp,ay_temp-1,ay_temp) break case 2: this.arr_bX.push(ax_temp,ax_temp,ax_temp,ax_temp-1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp+1) break case 3: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp+1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp,ay_temp,ay_temp+1) break case 0: this.arr_bX.push(ax_temp,ax_temp,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp-1) break } } if (num_blcok == 3) {</p> <p> <a href="http://www.js-code.com/tag/switch" title="浏览关于“switch”的文章" target="_blank" class="tag_link">switch</a>(this.direction%4){ case 1: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp+1,ax_temp+2) this.arr_bY.push(ay_temp,ay_temp,ay_temp,ay_temp) break case 2: this.arr_bX.push(ax_temp,ax_temp,ax_temp,ax_temp) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp+2) break case 3: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp+1,ax_temp+2) this.arr_bY.push(ay_temp,ay_temp,ay_temp,ay_temp) break case 0: this.arr_bX.push(ax_temp,ax_temp,ax_temp,ax_temp) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp+2) break } } if (num_blcok == 4) {</p> <p> switch(this.direction%4){ case 1: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp,ay_temp+1,ay_temp+1) break case 2: this.arr_bX.push(ax_temp,ax_temp,ax_temp+1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp+1,ay_temp,ay_temp-1) break case 3: this.arr_bX.push(ax_temp,ax_temp,ax_temp-1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp,ay_temp-1) break case 0: this.arr_bX.push(ax_temp,ax_temp,ax_temp+1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp,ay_temp+1) break } }</p> <p> if (! (this.judgeCollision_other(-1) &amp;&amp; this.judgeCollision_down() &amp;&amp; this.judgeCollision_other(1) )) { //如果变形不成功则执行下面代码 this.arr_bX.splice(0, this.arr_bX.length) this.arr_bY.splice(0, this.arr_bY.length) for(let i=0; i< arr_tempX.length; i++){ this.arr_bX.push(arr_tempX[i]) this.arr_bY.push(arr_tempY[i]) } } this.drawStaticBlock() } //一行满了清空方块,上面方块Y坐标+1 clearUnderBlock(){ //删除低层方块 let arr_row=[] let line_num if (this.arr_store_X.length != 0) { for(let j = this.height-1; j >= 0; j--){ for(let i = 0; i < this.arr_store_color.length; i++){ if (this.arr_store_Y[i] == j) { arr_row.push(i) } } if (arr_row.length == this.width) { line_num = j break }<a href="http://www.js-code.com/tag/else" title="浏览关于“else”的文章" target="_blank" class="tag_link">else</a>{ arr_row.splice(0, arr_row.length) } } }</p> <p> if (arr_row.length == this.width) { //计算成绩grade this.grade++</p> <p> <a href="http://www.js-code.com/tag/document" title="document" target="_blank">document</a>.getElementById('<a href="http://www.js-code.com/tag/text" title="浏览关于“text”的文章" target="_blank" class="tag_link">text</a>').inner<a href="http://www.js-code.com/tag/html" title="HTML" target="_blank">HTML</a> = '当前成绩:'+this.grade for(let i = 0; i < arr_row.length; i++){ this.arr_store_X.splice(arr_row[i]-i, 1) this.arr_store_Y.splice(arr_row[i]-i, 1) this.arr_store_color.splice(arr_row[i]-i, 1) } //让上面的方块往下掉一格 for(let i = 0; i < this.arr_store_color.length; i++){ if (this.arr_store_Y[i] < line_num) { this.arr_store_Y[i] = this.arr_store_Y[i]+1 } } } } //判断游戏结束 gameover(){ for(let i=0; i < this.arr_store_X.length; i++){ if (this.arr_store_Y[i] == 0) { clearInterval(this.ident) this.over = true } } } } let tetrisObj = new tetris() tetrisObj.gameStart() //方向键功能函数 document.onkeydown = (e) => { if (tetrisObj.over) return</p> <p> switch(e.keyCode){ case 40: // 方向为下 tetrisObj.down_speed_up() break case 32: // 空格换方向 tetrisObj.initBackground() //重画地图 tetrisObj.up_change_direction(tetrisObj.num_blcok) tetrisObj.drawBlock(tetrisObj.type_color) break case 37: // 方向为左 tetrisObj.initBackground() tetrisObj.move(-1) tetrisObj.drawBlock(tetrisObj.type_color) break case 39: // 方向为右 tetrisObj.initBackground() tetrisObj.move(1) tetrisObj.drawBlock(tetrisObj.type_color) break } }</p> <p> </script><br /> </body><br /> </html>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml"><code class="html">&lt;!DOCTYPE html&gt; &lt;html lang="en"&gt; &lt;head&gt; &lt;meta <a href="http://www.js-code.com/tag/char" title="浏览关于“char”的文章" target="_blank" class="tag_link">char</a>set="UTF-8"&gt; &lt;title&gt;es6-重构俄罗斯方块(基于canvas)&lt;/title&gt; &lt;style type="text/css"&gt; #tetris{ margin: 10px 250px;} &lt;/style&gt; &lt;/head&gt; &lt;body&gt; &lt;canvas width="700" height="525" id="tetris"&gt;&lt;/canvas&gt; &lt;<a href="http://www.js-code.com/tag/div" title="浏览关于“div”的文章" target="_blank" class="tag_link">div</a> id="text" style='color: red;font-size: 30px;'&gt;当前分数:0&lt;/div&gt; &lt;script type="text/<a href="http://www.js-code.com/tag/java" title="浏览关于“java”的文章" target="_blank" class="tag_link">java</a>script"&gt; /** * [一个完整的俄罗斯方块类 design by magic_xiang] * @param {number} side [每个方块边长(px),默认35] * @param {number} width [一行包含的方块数(个),默认20] * @param {number} height [一列包含的方块数(个),默认15] * @param {number} speed [方块下落移动速度(ms),默认400] */ class tetris{ <a href="http://www.js-code.com/tag/constructor" title="浏览关于“constructor”的文章" target="_blank" class="tag_link">constructor</a>(side=35, width=20, height=15, speed=400){ this.side = side // 每个方块边长 this.width = width // 一行包含的方块数 this.height = height // 一列包含的方块数 this.speed = speed // 方块下落移动速度 this.num_blcok // 当前方块类型的数字变量 this.type_color // 当前颜色类型的字符串变量 this.ident // <a href="http://www.js-code.com/tag/setInterval" title="浏览关于“setInterval”的文章" target="_blank" class="tag_link">setInterval</a>的标识 this.direction = 1 // 方块方向,初始化为1,默认状态 this.grade = 0 // 用来计算分数 this.over = false // 游戏是否结束 this.arr_bX = [] // 存放当前方块的X坐标 this.arr_bY = [] // 存放当前方块的Y坐标 this.arr_store_X = [] // 存放到达底部所有方块的X坐标 this.arr_store_Y = [] // 存放到达底部所有方块的Y坐标 this.arr_store_color = [] // 存放到达底部所有方块的颜色 this.paints = <a href="http://www.js-code.com/tag/document" title="浏览关于“document”的文章" target="_blank" class="tag_link">document</a>.getElementById('tetris').getContext('2d') //获取画笔 <a href="http://www.js-code.com/tag/self" title="浏览关于“self”的文章" target="_blank" class="tag_link">self</a> = this } // 封装paints方法,让代码更简洁 paintfr(x, y, scale=1){ this.paints.fillRect(x*this.side, y*this.side, scale*this.side, scale*this.side) } // 游戏开始 gameStart(){ this.init() this.run() } // 初始化工作 init(){ this.initBackground() this.initBlock() } // 方块自动下落 run(){ this.ident = setInterval("self.down_speed_up()", this.speed) } // 初始化地图 initBackground(){ this.paints.beginPath() this.paints.fillStyle='#000000' //地图填充颜色为黑色 for(let i = 0; i &lt; this.height; i++){ for(let j = 0; j &lt; this.width; j++){ this.paintfr(j, i) } } this.paints.<a href="http://www.js-code.com/tag/close" title="浏览关于“close”的文章" target="_blank" class="tag_link">close</a>Path() } // 初始化方块的位置和颜色 initBlock(){ this.paints.beginPath() this.createRandom('rColor') //生成颜色字符串, this.paints.fillStyle = this.type_color this.createRandom('rBlock') //生成方块类型数字 this.arr_bX.forEach((item, index) =&gt; { this.paintfr(item, this.arr_bY[index], 0.9) }) this.paints.closePath() } // 利用<a href="http://www.js-code.com/tag/%e6%95%b0%e7%bb%84" title="浏览关于“数组”的文章" target="_blank" class="tag_link">数组</a>画方块 drawBlock(color){ this.paints.beginPath() this.paints.fillStyle = color this.arr_bX.forEach((item, index) =&gt; { this.paintfr(item, this.arr_bY[index], 0.9) }) this.paints.closePath() } // 画已经在定位好的方块 drawStaticBlock(){ this.arr_store_X.forEach((item, index) =&gt; { this.paints.beginPath() this.paints.fillStyle = this.arr_store_color[index] this.paintfr(item, this.arr_store_Y[index], 0.9) this.paints.closePath() }) } // 生成随机数返回方块类型或颜色类型 createRandom(type){ let temp = this.width/2-1 if (type == 'rBlock'){ //如果是方块类型 this.num_blcok = Math.round(Math.random()*4+1) switch(this.num_blcok){ case 1: this.arr_bX.push(temp,temp-1,temp,temp+1) this.arr_bY.push(0,1,1,1) break case 2: this.arr_bX.push(temp,temp-1,temp-1,temp+1) this.arr_bY.push(1,0,1,1) break case 3: this.arr_bX.push(temp,temp-1,temp+1,temp+2) this.arr_bY.push(0,0,0,0) break case 4: this.arr_bX.push(temp,temp-1,temp,temp+1) this.arr_bY.push(0,0,1,1) break case 5: this.arr_bX.push(temp,temp+1,temp,temp+1) this.arr_bY.push(0,0,1,1) break } } if (type == 'rColor'){ //如果是颜色类型 let num_color = Math.round(Math.random()*8+1) switch(num_color){ case 1: this.type_color='#3EF72A' break case 2: this.type_color='yellow' break case 3: this.type_color='#2FE0BF' break case 4: this.type_color='red' break case 5: this.type_color='gray' break case 6: this.type_color='#C932C6' break case 7: this.type_color= '#FC751B' break case 8: this.type_color= '#6E6EDD' break case 9: this.type_color= '#F4E9E1' break } } } // 判断方块之间是否碰撞(下),以及变形时是否越过下边界 judgeCollision_down(){ for(let i = 0; i &lt; this.arr_bX.length; i++){ if (this.arr_bY[i] + 1 == this.height){ //变形时是否越过下边界 return false } if (this.arr_store_X.length != 0) { //判断方块之间是否碰撞(下) for(let j = 0; j &lt; this.arr_store_X.length; j++){ if (this.arr_bX[i] == this.arr_store_X[j]) { if (this.arr_bY[i] + 1 == this.arr_store_Y[j]) { return false } } } } } return true } //判断方块之间是否碰撞(左右),以及变形时是否越过左右边界 judgeCollision_other(num){ for(let i = 0; i &lt; this.arr_bX.length; i++){ if (num == 1) { //变形时是否越过右边界 if (this.arr_bX[i] == this.width - 1) return false } if (num == -1) { //变形时是否越过左边界 if (this.arr_bX[i] == 0) return false } if (this.arr_store_X.length != 0) { //判断方块之间是否碰撞(左右) for(let j = 0; j &lt; this.arr_store_X.length; j++){ if (this.arr_bY[i] == this.arr_store_Y[j]) { if (this.arr_bX[i] + num == this.arr_store_X[j]) { return false } } } } } return true; } //方向键为下的加速函数 down_speed_up(){ let flag_all_down = true flag_all_down = this.judgeCollision_down() if (flag_all_down) { this.initBackground() for(let i = 0; i &lt; this.arr_bY.length; i++){ this.arr_bY[i] = this.arr_bY[i] + 1 } } else{ for(let i=0; i &lt; this.arr_bX.length; i++){ this.arr_store_X.push(this.arr_bX[i]) this.arr_store_Y.push(this.arr_bY[i]) this.arr_store_color.push(this.type_color) } this.arr_bX.splice(0,this.arr_bX.length) this.arr_bY.splice(0,this.arr_bY.length) this.initBlock() } this.clearUnderBlock() this.drawBlock(this.type_color) this.drawStaticBlock() this.gameover() } //方向键为左右的左移动函数 move(dir_temp){ this.initBackground() if (dir_temp == 1) { //右 let flag_all_right = true flag_all_right = this.judgeCollision_other(1) if (flag_all_right) { for(let i = 0; i &lt; this.arr_bY.length; i++){ this.arr_bX[i] = this.arr_bX[i]+1 } } } else{ let flag_all_left = true flag_all_left = this.judgeCollision_other(-1) if (flag_all_left) { for(let i=0; i &lt; this.arr_bY.length; i++){ this.arr_bX[i] = this.arr_bX[i]-1 } } } this.drawBlock(this.type_color) this.drawStaticBlock() } //方向键为空格的变换方向函数 up_change_direction(num_blcok){ if (num_blcok == 5) { return } let arr_tempX = [] let arr_tempY = [] //因为不知道是否能够变形成功,所以先存储起来 for(let i = 0;i &lt; this.arr_bX.length; i++){ arr_tempX.push(this.arr_bX[i]) arr_tempY.push(this.arr_bY[i]) } this.direction++ //将中心坐标提取出来,变形都以当前中心为准 let ax_temp = this.arr_bX[0] let ay_temp = this.arr_bY[0] this.arr_bX.splice(0, this.arr_bX.length) //将数组清空 this.arr_bY.splice(0, this.arr_bY.length) if (num_blcok == 1) { switch(this.direction%4){ case 1: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp+1,ay_temp+1,ay_temp+1) break case 2: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp,ax_temp) this.arr_bY.push(ay_temp,ay_temp,ay_temp-1,ay_temp+1) break case 3: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp,ay_temp+1,ay_temp) break case 0: this.arr_bX.push(ax_temp,ax_temp,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp) break } } if (num_blcok == 2) { switch(this.direction%4){ case 1: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp-1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp,ay_temp-1,ay_temp) break case 2: this.arr_bX.push(ax_temp,ax_temp,ax_temp,ax_temp-1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp+1) break case 3: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp+1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp,ay_temp,ay_temp+1) break case 0: this.arr_bX.push(ax_temp,ax_temp,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp-1) break } } if (num_blcok == 3) { switch(this.direction%4){ case 1: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp+1,ax_temp+2) this.arr_bY.push(ay_temp,ay_temp,ay_temp,ay_temp) break case 2: this.arr_bX.push(ax_temp,ax_temp,ax_temp,ax_temp) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp+2) break case 3: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp+1,ax_temp+2) this.arr_bY.push(ay_temp,ay_temp,ay_temp,ay_temp) break case 0: this.arr_bX.push(ax_temp,ax_temp,ax_temp,ax_temp) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp+2) break } } if (num_blcok == 4) { switch(this.direction%4){ case 1: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp,ay_temp+1,ay_temp+1) break case 2: this.arr_bX.push(ax_temp,ax_temp,ax_temp+1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp+1,ay_temp,ay_temp-1) break case 3: this.arr_bX.push(ax_temp,ax_temp,ax_temp-1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp,ay_temp-1) break case 0: this.arr_bX.push(ax_temp,ax_temp,ax_temp+1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp,ay_temp+1) break } } if (! (this.judgeCollision_other(-1) &amp;&amp; this.judgeCollision_down() &amp;&amp; this.judgeCollision_other(1) )) { //如果变形不成功则执行下面代码 this.arr_bX.splice(0, this.arr_bX.length) this.arr_bY.splice(0, this.arr_bY.length) for(let i=0; i&lt; arr_tempX.length; i++){ this.arr_bX.push(arr_tempX[i]) this.arr_bY.push(arr_tempY[i]) } } this.drawStaticBlock() } //一行满了清空方块,上面方块Y坐标+1 clearUnderBlock(){ //删除低层方块 let arr_row=[] let line_num if (this.arr_store_X.length != 0) { for(let j = this.height-1; j &gt;= 0; j--){ for(let i = 0; i &lt; this.arr_store_color.length; i++){ if (this.arr_store_Y[i] == j) { arr_row.push(i) } } if (arr_row.length == this.width) { line_num = j break }else{ arr_row.splice(0, arr_row.length) } } } if (arr_row.length == this.width) { //计算成绩grade this.grade++ document.getElementById('text').inner<a href="http://www.js-code.com/tag/html" title="浏览关于“HTML”的文章" target="_blank" class="tag_link">HTML</a> = '当前成绩:'+this.grade for(let i = 0; i &lt; arr_row.length; i++){ this.arr_store_X.splice(arr_row[i]-i, 1) this.arr_store_Y.splice(arr_row[i]-i, 1) this.arr_store_color.splice(arr_row[i]-i, 1) } //让上面的方块往下掉一格 for(let i = 0; i &lt; this.arr_store_color.length; i++){ if (this.arr_store_Y[i] &lt; line_num) { this.arr_store_Y[i] = this.arr_store_Y[i]+1 } } } } //判断游戏结束 gameover(){ for(let i=0; i &lt; this.arr_store_X.length; i++){ if (this.arr_store_Y[i] == 0) { <a href="http://www.js-code.com/tag/clearInterval" title="浏览关于“clearInterval”的文章" target="_blank" class="tag_link">clearInterval</a>(this.ident) this.over = true } } } } let tetrisObj = <a href="http://www.js-code.com/tag/new" title="浏览关于“new”的文章" target="_blank" class="tag_link">new</a> tetris() tetrisObj.gameStart() //方向键功能函数 document.<a href="http://www.js-code.com/tag/onkeydown" title="浏览关于“onkeydown”的文章" target="_blank" class="tag_link">onkeydown</a> = (e) =&gt; { if (tetrisObj.over) return switch(e.keyCode){ case 40: // 方向为下 tetrisObj.down_speed_up() break case 32: // 空格换方向 tetrisObj.initBackground() //重画地图 tetrisObj.up_change_direction(tetrisObj.num_blcok) tetrisObj.drawBlock(tetrisObj.type_color) break case 37: // 方向为左 tetrisObj.initBackground() tetrisObj.move(-1) tetrisObj.drawBlock(tetrisObj.type_color) break case 39: // 方向为右 tetrisObj.initBackground() tetrisObj.move(1) tetrisObj.drawBlock(tetrisObj.type_color) break } } &lt;/script&gt; &lt;/body&gt; &lt;/html&gt;</code></pre> <p></code></p>

总结

以上是脚本宝典为你收集整理的

H5原创俄罗斯方块(基于canvas)

全部内容,希望文章能够帮你解决

H5原创俄罗斯方块(基于canvas)

所遇到的程序开发问题,欢迎加入QQ群277859234一起讨论学习。如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典网站推荐给程序员好友。 本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

80%的人都看过