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(){

