JS and Canvas implement Russian square

JS和canvas实现俄罗斯方块 The code is as follows:

      Keyboard arrows A, D control left and right moving, S control fast down. W Control Deformation, Space Control Pause, Enter starts the game   shape_collection = {// graphic clockwise rotate, feel a bit trouble, here should also add a parameter - distance How many of the stiffs can not be deformed when the left and right, which is conducive to the expansion of follow-up graphics, but here will not write S1: [{MO: [0, 0, 0, 0], [0, 0, 0, 0], [0, 0], [0, 0, 0, 0] 0, 0, 0, 0], [1, 1, 1, 1], l: true, // through these two parameters, determining whether the left and right collisions are deformed R: true}, {// with the left, right Collision, you can't deformed (when you are one, you can't deformed) MO: [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0]], L: FALSE, R: FALSE}], S2: [{MO: [// Always do not deform [1, 1, 0, 0], [1, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], L: FALSE, R: FALSE}], S3: [{MO: [// No deformation in the right [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: [// On the right side can not be deformable [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: [// On the right side, the left can be deformable [1, 0 , 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: [// No deformation in the right [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: [// On the right side, the left can be deformable [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: [// On the right side can not be deformable [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: [// Right Cannot deformation [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: [// On the right side can not be deformed[0, 1, 0, 0], [1, 1, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0]], L: True, R: False}]  ; (function () {var tetris = function (a) {var _this = this; this.Settings = {DOM: "", Side_length: 25, // Square edge length Row: 20, /// Route Column COL: 15, // Column number v_dowm: 10, Side_Width: 1 // Separation line width default is 1}; var k = this.extend (a, this.settings); var Dom = Document.getlementByid ( THIS.SETTINGS.DOM); var Fall_2 = undefined; // Used to determine fast drop VAR score = 0; // score this.p_dom (dom, "initial level:"); this.p_dom (dom, "score:" , "score"); var score_dom = dom.GtelementSbyClassName ("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; // Whether to start the game var shape = shape_collection; // Various shapes, this is a kind of thinking, it is also very good Add var Shape_Key = _THIS.Obj_list (shape); // [S1, S2, S3, S4, S5, S6, S7] VAR Color = ["0", "1", "2", "3" , "4", "5", "6", "A", "B", "C", "D", "E", "F"]; // Color var cube_arr = []; // Used to assemble the area small square var cube_arr_s = []; // Used to display the graphic area small square var shape_arr = {// used to indicate the drop slider Shape_Solo: undefined A certain graphic SOLO_KEY: undefined, // shape_solo's key value MO_LIST: undefined, // drawn graphics in array shape_solo, transform graphics when converted graphics , // Small square coordinate set, default is empty, do not draw small pieces. Draw a reference for small squares, important parameters RE_POINT_X: (_ this.settings.col / 2) | 0, // Taking the initial reference X coordinate (for left and right moving) RE_POINT_Y: 0, // Y coordinate reference. (Do not modify the value in Serial, Serial is always in 4x4, easy to do this) Width: _this.Settings.SIDE_LENGTH, // small square width v: _this.Settings.SIDE_LENGTH + _THIS.SETTINGS.SIDE_WIDTH, //Each movement is equal to the square side length + Grid line width COLLISION_L: FALSE, / / ​​Collision_r: false, // with the left side COLLISION_D: false, // Whether to collide with the lower side DRAW: function (a) { // Draw a small square function, write here, is the private method of this object, and _Proto_ is written by all objects with var se = this.serial; //console.log (SE) for (var i = 0; i 

(0- min_coor) &&! Con_suxian) {Shape_arr_t ["Shape_Solo"] = Shape [Shape_arr_t ["Solo_Key"]] [0]; SHAPE_ARR_T ["MO_LIST"] = 0; // Serial number 0 }}} else {shape_arr_t ["Shape_Solo"] = Shape [Shape_arr_t ["Solo_Key"]] [i_List + 1]; SHAPE_ARR_T ["MO_LIST"] + = 1; // Sequence number 1}} else {ix (RE_POINT_X + MAX_COOR > = (_ this.settings.col-1) || con_r_r) {// Close to the right or on the right, there is CON 1 Fast (entity block) IF (CON_R) {IF (i_list

= (_ this.settings. COL-1)) {// CON = false;} for (var i = 0; i
0) {// calculation score switch (Lose_row.Length) {Case 1: score + = 10; Break; Case; 2: score + = 30; BREAK; Case 3: Score + = 60 Break; Case 4: Score + = 100; Break; Default: Break;}} for (var i_sc = 0; i_sc
= 0; i_l -) {// i (con_one [ I_L] ["row"] = 10 && score = 30 && score = 40) {level_t = parseint (k_t) +4;} Fall_1 = setInterval (fall, _this.settings.v_dowm / level_t) // Restart Fall function}, 250)} Return Clear_con; // Used to determine the subsequent mapping}; function fall () {// Drop function var arr_se = []; var con = true; var k = Shape_arr_t ["serial"]. length; // for (var i = 0; i level '+ i; label_d.innerhtml = str; a.Appendchild (label_d);}}, canvas_dom: function (a, b , C, D, E) Create a Canvas Tag Var canvas = Document.createElement ("canvas"); canvas.style.csstext = "Border: 3px Solid # 333333; display: block; margin: 0 auto;"; Canvas.SetaTRibute ("width", D * (B + E); canvas.setttribute ("HEI)GHT ", C * (B + E) -e); A.Appendchild (canvas);}, cube_obj_arr: function (A, B, C, D, E, F) {// Create a small square collection, from left to left Right, from top to bottom, virtual, here you can not draw 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(){ fall_2=clearInterval(fall_2);//重置fall_2的值为undefined },50); } break; default: break; } } } function up(){//shape和shape_arr的关系要弄清楚,这里判断有点复杂 if(start_con){ ctx.clearRect(0,0,canvas.width,canvas.height);//清屏 cube_obj.forEach(function(e){//重新绘制虚拟小方块 e.draw(ctx); }) var l=shape[shape_arr_t["solo_key"]].length-1;//数组长度减1 var i_list=shape_arr_t["mo_list"];//对应数组的key var re_point_x=shape_arr_t["re_point_x"]; var con_l=shape_arr_t["shape_solo"].l; var con_r=shape_arr_t["shape_solo"].r; var con_l_l=false;//用于判断左右是否有con为1的虚拟滑块,不仅仅要判断是否碰到边上,还要判断这个 var con_r_r=false; var con_suxian=false;//竖线 var arr_se=[]; var k_uni=shape_arr_t["serial"].length; for(var i_uni=0;i_uni<k_uni;i_uni++){//取出图形所有小块的横坐标,这里有两个for循环,相同的变量会互相影响,所有设置成i_uni arr_se.push(shape_arr_t["serial"][i_uni][0]); } var min_coor=Math.min.apply(null,arr_se); var max_coor=Math.max.apply(null,arr_se); for(var i_y_a=0;i_y_a<k_uni;i_y_a++){ var c_x_1=shape_arr_t["re_point_x"]+shape_arr_t["serial"][i_y_a][0]; var c_y_1=shape_arr_t["re_point_y"]+shape_arr_t["serial"][i_y_a][1]; if(cube_obj[c_y_1*_this.settings.col+c_x_1+1]!==undefined&&cube_obj[c_y_1*_this.settings.col+c_x_1+1].con==1){//任意滑块con==1的时候 con_r_r=true; break; } } for(var i_y_b=0;i_y_b<k_uni;i_y_b++){//其实左右可以合并成一个判断,省掉一些代码 var c_x_2=shape_arr_t["re_point_x"]+shape_arr_t["serial"][i_y_b][0]; var c_y_2=shape_arr_t["re_point_y"]+shape_arr_t["serial"][i_y_b][1]; if(cube_obj[c_y_2*_this.settings.col+c_x_2-1].con==1){//任意滑块con==1的时候 con_l_l=true; break; } } if(shape_arr_t["solo_key"]==="s1"){//竖线情况特殊,单独处理,其实应该写一个函数来统一判断,不应该出现特殊图形,不然特殊图形增加的话,要增加很多判读 if(i_list==1){//如果是竖线的话 for(var i_y_c=0;i_y_c<k_uni;i_y_c++){//如果是竖线的话,则右边2格处虚拟方块的con是1,也不能变形,这里到下一行的情况也能适应 var c_x_3=shape_arr_t["re_point_x"]+shape_arr_t["serial"][i_y_c][0]; var c_y_3=shape_arr_t["re_point_y"]+shape_arr_t["serial"][i_y_c][1]; if(cube_obj[c_y_3*_this.settings.col+c_x_3+2]!==undefined&&cube_obj[c_y_3*_this.settings.col+c_x_3+2].con==1||cube_obj[c_y_3*_this.settings.col+c_x_3-1].con==1){//任意滑块con==1的时候 con_suxian=true; break; } } if(re_point_x+max_coor <l){ shape_arr_t["shape_solo"]=shape[shape_arr_t["solo_key"]][i_list+1]; shape_arr_t["mo_list"]+=1;//序号加1 }else{ shape_arr_t["shape_solo"]=shape[shape_arr_t["solo_key"]][0]; shape_arr_t["mo_list"]=0;//序号为0 } } }else if(re_point_x<=(0-min_coor)||con_l_l){//靠近左边或者左边有con=1的方块 if(con_l){ if(i_list<l){ shape_arr_t["shape_solo"]=shape[shape_arr_t["solo_key"]][i_list+1]; shape_arr_t["mo_list"]+=1;//序号加1 }else{ shape_arr_t["shape_solo"]=shape[shape_arr_t["solo_key"]][0]; shape_arr_t["mo_list"]=0;//序号为0 } } }else{ if(i_list<l){ shape_arr_t["shape_solo"]=shape[shape_arr_t["solo_key"]][i_list+1]; shape_arr_t["mo_list"]+=1;//序号加1 }else{ shape_arr_t["shape_solo"]=shape[shape_arr_t["solo_key"]][0]; shape_arr_t["mo_list"]=0;//序号为0 } } } var s_cube=shape_arr_t["shape_solo"];//图形变换,根据shape var s_mo=s_cube["mo"];//图形元素 var k=s_mo.length; var color=shape_arr_t["serial"][0][2];//取出颜色 //console.log(color) shape_arr_t["serial"].length=0;//数组置空 //console.log(shape_arr["serial"]) for(var i=0;i<k;i++){//这里的长度是4 for(var j=0;j<k;j++){//这里的长度是4 if(s_mo[i][j]){//如果等于1的话 shape_arr_t["serial"].push([j,i,color])//需要绘制小块的坐标,所有小方块颜色一样,如果想变成不一样,则在for循环内部执行生成颜色函数,j,i才能对应图形 } } } //console.log(shape_arr) shape_arr_t.draw(ctx);//重新绘制 }; } function left(){ if(start_con){ ctx.clearRect(0,0,canvas.width,canvas.height);//清屏 cube_obj.forEach(function(e){//重新绘制虚拟小方块 e.draw(ctx); }) var arr_se=[]; var con=true; var k=shape_arr_t["serial"].length; for(var i_uni=0;i_uni<k;i_uni++){//取出图形所有小块的横坐标 arr_se.push(shape_arr_t["serial"][i_uni][0]); } var min_coor=Math.min.apply(null,arr_se);//取出最小的,其实这里除了竖线那个图形之外,最小的值都是0,但是这里这样写,有利于拓展以后可能出现的其他情况 if(shape_arr_t["re_point_x"]<=(0- min_coor)){//碰到边界的时候 con=false; } for(var i=0;i<k;i++){//判断所有小块左边的虚拟方块的con是否都是0 var c_x=shape_arr_t["re_point_x"]+shape_arr_t["serial"][i][0]; var c_y=shape_arr_t["re_point_y"]+shape_arr_t["serial"][i][1]; if(cube_obj[c_y*_this.settings.col+c_x-1].con==1){//任意滑块con==1的时候。住:加1减一的时候,有可能到上一行下一行,但是这种情况就靠边了,所以这样判断还是对的 con=false; break; } } if(con){ shape_arr_t["re_point_x"]-=1; } shape_arr_t.draw(ctx);//重新绘制 } }; function right(){ if(start_con){ ctx.clearRect(0,0,canvas.width,canvas.height);//清屏 cube_obj.forEach(function(e){//重新绘制虚拟小方块 e.draw(ctx); }) var con=true; var arr_se=[]; var k=shape_arr_t["serial"].length; for(var i_uni=0;i_uni New TETRI ({DOM: "Box", Side_length: 25, Row: 20, Col: 12 , v_dowm: 500 // Setting speed at level 1 drop speed}); <k;i++){//判断所有小块右边的虚拟方块的con是否都是0 var c_x=shape_arr_t["re_point_x"]+shape_arr_t["serial"][i][0]; var c_y=shape_arr_t["re_point_y"]+shape_arr_t["serial"][i][1]; if(cube_obj[c_y*_this.settings.col+c_x+1]!==undefined&&cube_obj[c_y*_this.settings.col+c_x+1].con==1){//任意滑块con==1的时候 con=false; break; } } if(con){ shape_arr_t["re_point_x"]+=1; } shape_arr_t.draw(ctx);//重新绘制 } }; function down(){ }; function enter(){ var radio_arr=document.getElementsByClassName("level"); if(!start_con){//如果还没开始的话,则开始(//设置条件判断。不停的点击enter的时候,只执行一次) Array.prototype.forEach.call(radio_arr,function(e){ if(e.checked==true){ k_t=e.value;//用于级别增加 level_t=e.value; } e.setAttribute("disabled",true); }) fall_1=setInterval(fall,_this.settings.v_dowm/level_t)//全局变量,用于domn函数的清除,但是这样就不能避免外部的污染了 start_con=true; } }; function get_score(){//得分机制,写了很多for循环,感觉应该有更好的判断 var lose_row=[];//消失的行数 var clear_con=false;//是否当前需要重绘 for(var i=0;i<_this.settings.row;i++){ var all_con=true;//默认当前行所有滑块的con都是1 for(var j=0;j <lose_row.length;i_sc++){//把需要消除行的con变为0,用于消除,length为0的时候,表示没有需要消除的行 for(var j_sc=0;j_sc<_this.settings.col;j_sc++){ cube_obj[lose_row[i_sc]*_this.settings.col+j_sc]["con"]=0;//重置为虚拟 cube_obj[lose_row[i_sc]*_this.settings.col+j_sc]["fillStyle"]="pink"//颜色重新变成粉红,这是0的标示 } clear_con=true;//只要有需要消除的行,就要重绘 } if(clear_con){ ctx.clearRect(0,0,canvas.width,canvas.height);//清屏 cube_obj.forEach(function(e){//重新绘制虚拟小方块,移除消除的行 e.draw(ctx); }) score_num.innerText=score;//重新计算分数 } for(var i_sc=0;i_sc<lose_row.length;i_sc++){//con为1的滑块往下移动 var con_one=[];//用来存储所有con为1的虚拟滑块 for(var i_v=0;i_v The above is all the contents of this article, and it is desirable to be the content of this article. Learning or work can bring a certain help, and I hope to support Tumi Cloud!
© Copyright Notice
THE END
Just support it if you like
like0
share
comment Grab the couch

Please log in to comment