yuandaishi通过本文主要向大家介绍了JS和canvas实现俄罗斯方块等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
效果图:
代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <p style="font-size: 20px;">键盘箭头A,D控制左右移动,S控制快速下滑。W控制变形,空格控制暂停,enter开始游戏</p> <div id="box" style="width: 1000px;height: 800px;border: 1px solid pink;margin: 0 auto;position: relative;"> </div> </body> <script type="text/javascript"> shape_collection = {//图形顺时针旋转变形,感觉有点麻烦,这里还应该加一个参数--距离左右多少格的时候不能变形,有利于后续图形的拓展,但是这里就先不写了 s1: [ { mo: [ [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 1, 1] ], l:true,//通过这两个参数,判断左右碰撞能否变形 r:true }, {//与左边,右边碰撞,都不能变形(距离右边一格的时候,也不能变形) mo: [ [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0] ] , l:false, r:false } ], s2: [ { mo: [//始终不变形 [1, 1, 0, 0], [1, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0] ], l:false, r:false } ], s3: [ { mo: [//右边不能变形 [1, 0, 0, 0], [1, 1, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0] ], l:true, r:false }, { mo: [ [0, 0, 0, 0], [0, 1, 1, 0], [1, 1, 0, 0], [0, 0, 0, 0] ], l:true, r:true } ], s4: [ { mo: [//右边不能变形 [0, 1, 0, 0], [1, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 0] ], l:true, r:false }, { mo: [ [0, 0, 0, 0], [1, 1, 0, 0], [0, 1, 1, 0], [0, 0, 0, 0] ], l:true, r:true } ], s5: [ { mo: [//右边不能变形,左边可以变形 [1, 0, 0, 0], [1, 0, 0, 0], [1, 1, 0, 0], [0, 0, 0, 0] ], l:true, r:false }, { mo: [// [0, 0, 0, 0], [1, 1, 1, 0], [1, 0, 0, 0], [0, 0, 0, 0] ], l:true, r:true }, { mo: [//右边不能变形 [1, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0] ], l:true, r:false }, { mo: [ [0, 0, 0, 0], [0, 0, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0] ], l:true, r:true } ], s6: [ { mo: [//右边不能变形,左边可以变形 [0, 1, 0, 0], [0, 1, 0, 0], [1, 1, 0, 0], [0, 0, 0, 0] ], l:true, r:false }, { mo: [// [0, 0, 0, 0], [1, 0, 0, 0], [1, 1, 1, 0], [0, 0, 0, 0] ], l:true, r:true }, { mo: [//右边不能变形 [1, 1, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [0, 0, 0, 0] ], l:true, r:false }, { mo: [ [0, 0, 0, 0], [1, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, 0] ], l:true, r:true } ], s7: [ { mo: [// [0, 0, 0, 0], [0, 1, 0, 0], [1, 1, 1, 0], [0, 0, 0, 0] ], l:true, r:true }, { mo: [//右边不能变形 [1, 0, 0, 0], [1, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 0] ], l:true, r:false }, { mo: [// [0, 0, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0] ], l:true, r:true }, { mo: [//右边不能变形 [0, 1, 0, 0], [1, 1, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0] ], l:true, r:false } ], } </script> <script type="text/javascript"> ;(function(){ var tetris=function(a){ var _this=this; this.settings={ dom:"", side_length:25,//方块边长 row:20,//行数 col:15,//列数 v_dowm:10, side_width:1//分隔线条宽度默认为1 }; var k=this.extend(a,this.settings); var dom=document.getElementById(this.settings.dom); var fall_2=undefined;//用于判断快速下落 var score=0;//分数 this.p_dom(dom,"初始级别:"); this.p_dom(dom,"分数:","score"); var score_dom=dom.getElementsByClassName("score")[0]; score_dom.style.cssText="position:absolute;left: 0;right: 0;top: 30px;margin: auto auto;text-align: center;"; var score_num=document.createElement("span"); score_num.className="score_num"; score_num.style.cssText="color:gold;font-size: 30px;"; score_num.innerText=score; score_dom.appendChild(score_num); this.input_dom(dom,4); var start_con=false;//是否开始游戏 var shape =shape_collection;//各种形状,这是一种思路,也很利于以后形状的添加 var shape_key=_this.obj_list(shape);//[s1,s2,s3,s4,s5,s6,s7] var color=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"];//颜色 var cube_arr=[];//用来装建造区域小方块 var cube_arr_s=[];//用来装提示图形区域小方块 var shape_arr={//用来表示下落的滑块 shape_solo:undefined,//s1——s7中某一个的某一个图形 solo_key:undefined,//shape_solo的key值 mo_list:undefined,//绘制的图形在数组shape_solo的下标,变换图形的时候用到 serial:[],//小方块坐标集合,默认为空,不绘制小块。绘制小方块的参考,重要参数 re_point_x:(_this.settings.col/2)|0,//以第几个为初始参考X坐标(用于左右移动) re_point_y:0,//y坐标参考。(不要在serial里面修改值,serial总在4X4里面,容易做参考) width:_this.settings.side_length,//小方块的宽度 v:_this.settings.side_length+_this.settings.side_width,//每次移动的距离等于方块边长+grid线宽 collision_l:false,//与左边是否碰撞 collision_r:false,//与右边是否碰撞 collision_d:false,//与下边是否碰撞 draw:function(a){//绘制小方块函数,写在这里,才是这个对象的私有方法,而_proto_的写法是所有对象都拥有 var se=this.serial; //console.log(se) for(var i=0;i<se.length;i++){ a.beginPath(); a.fillStyle=se[0][2];//this指向这个对象.第三个参数是颜色 a.fillRect(this.v*(this.re_point_x+se[i][0]),this.v*(this.re_point_y+se[i][1]),this.width,this.width); } } }; //创建提示图形 var ts="ts";//提示图形ID; this.canvas_dom(dom,this.settings.side_length,4,4,this.settings.side_width); var canvas_s=dom.getElementsByTagName("canvas")[0]; canvas_s.setAttribute("style","position: absolute;right: 130px;border:3px solid goldenrod;top: 82px;") var ctx_s=canvas_s.getContext("2d"); var cube_obj_s=_this.cube_obj_arr(ctx_s,this.settings.side_length,4,4,this.settings.side_width,cube_arr_s); var shape_arr_s=this.clone_obj(this.draw_shape(ts,shape,shape_arr,shape_key,_this.make_color(color)));//因为返回的是shape_arr,所以这里导致了shape_arr_s和shape_arr有关联,也就是说以后的代码中,其中一个改变的话,另一个也会跟着改变,用clone方法去掉关联 cube_obj_s.forEach(function(e){ e.draw(ctx_s); }); shape_arr_s.draw(ctx_s); //创建堆砌图形 var dq="dq";//堆砌图形ID; this.canvas_dom(dom,this.settings.side_length,this.settings.row,this.settings.col,this.settings.side_width); var canvas=dom.getElementsByTagName("canvas")[1]; var ctx=canvas.getContext("2d"); var cube_obj=_this.cube_obj_arr(ctx,this.settings.side_length,this.settings.row,this.settings.col,this.settings.side_width,cube_arr); //this.grid(ctx,this.settings.side_length,this.settings.row,this.settings.col,this.settings.side_width);//网格 //console.log(cube_obj); cube_obj.forEach(function(e){ e.draw(ctx); }); var shape_arr_t=this.clone_obj(this.draw_shape(ctx,shape,shape_arr,shape_key,_this.make_color(color))); //console.log(shape_arr); shape_arr_t.draw(ctx); //鼠标事件 window.onkeydown=function(e){ switch (e.keyCode){ case 87://up up(); break; case 83://down //down(); break; case 65://left left(); break; case 68://right right() break; case 32://workspace //up(); break; case 13://enter enter(); break; default: break; } }; window.onkeypress=function(e){//onkeypress和onkeydown,即使按下的是同一个按键,e.keyCode也不一样 if(start_con){ switch (e.keyCode){ case 115: if(fall_2==undefined){//做这个判断是为了防止快速的点击S键时,出现的多次fall_2事件,因为50ms之后,fall_2的值才变成undefined fall_2=setInterval(fall,10);//clearInterval返回的值是undefined,而setInterval返回的值是一个整数 setTimeout(function(){