欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战

程序员文章站 2022-11-27 14:30:30
一、组件化开发 1.1组件化概述 页面特效的制作,特别需要HTML、CSS有固定的布局,所以说现在越来越流行组件开发的模式,就是用JS写一个类,当你实例化这个类的时候,页面上的效果布局也能自动完成。 实例化后,页面中就有一个轮播图的布局结构,而且可以通过参数传递进去。 这个new里面封装了HTML、 ......

一、组件化开发

1.1组件化概述

页面特效的制作,特别需要htmlcss有固定的布局,所以说现在越来越流行组件开发的模式,就是用js写一个类,当你实例化这个类的时候,页面上的效果布局也能自动完成。

new carousel();

 

实例化后,页面中就有一个轮播图的布局结构,而且可以通过参数传递进去。

这个new里面封装了htmlcssjs的业务逻辑。组件开发的规律就是所有按钮、小圆点、图片等等都是这个类(的实例的)属性,自己管理自己。

 

组件开发的好处就是在用的时候可以高度自定义,在new的时候应该能传入一个json参数进行配置,当你的json里面的属性改变的时候,我们的ui界面逻辑就要有响应的变化。

面向对象+设计模式组合各种类(通常是中介者模式),就是组件化开发。

本质思想,组件只考虑两个事情:

l 别人怎么控制我,要提供很多函数,这个函数可以改变我的状态。

我怎么给别人提供接口,比如轮播图被点击时,要提供一个click事件回调。

组件只需要对自己负责,至于别人怎么调用我的接口,在我提供的接口中做什么,自己不需要考虑。

 

特点:

组件都是可以单独测试的,所有组件都可以单独上树,进行测试。

dom都是动态生成的,组件开发中,现在90%以上的,都是将dom写在js中,在“查看源代码”中看见的是空标签。

组件是嵌套的,往往大组件是小组件的中介者。

 

优点:

方便维护,功能易于插拔,很容易找出bug的地方。

l 易于复用,比如我们做一个分页条组件,此时可以非常*在其他项目使用。

 

组件开发是一个非常实用的技术,组件开发越来越火,催生了一些组件开发的框架:reactvueangular等。


 

1.2轮播图组件开发

js对象、dom对象,js对象的属性是dom对象

用轮播图的面向对象举例,js对象中有自己的参数属性(比如当前显示图片的编号、速度、间隔时间、宽度、高度),还dom属性。

<script type="text/javascript" src="js/jquery-1.12.3.min.js"></script>
<script type="text/javascript" src="js/carousel.js"></script>
<script type="text/javascript">
     new carousel({
       "id" : "carousel",
       "images" : [
           {"picurl" : "images/0.jpg", "link" : "http://www.iqianduan.cn"},
           {"picurl" : "images/1.jpg", "link" : "http://www.iqianduan.cn"},
           {"picurl" : "images/2.jpg", "link" : "http://www.iqianduan.cn"},
           {"picurl" : "images/3.jpg", "link" : "http://www.iqianduan.cn"},
           {"picurl" : "images/4.jpg", "link" : "http://www.iqianduan.cn"}
       ],
       "width" : 560,
       "height": 300,
       "speed" : 500,
       "interval" : 2000
     });
</script>

 

 css样式:carousel样式后面动态创建

#carousel{
    width: 560px;
    height: 300px;
    position: relative;
    overflow: hidden;
}
.leftbtn,.rightbtn{
    position: absolute;
    top:50%;
    width: 30px;
    height: 30px;
    background-color: orange;
}
.leftbtn{left: 10px;}
.rightbtn{right: 10px;}
.circls{
    position: absolute;
    bottom: 10px;left: 100px;
    list-style: none;
}
.circls li{
    float: left;
    width: 20px;
    height: 20px;
    background-color: orange;
    margin-right: 10px;
}
.circls li.cur{background-color: red;}

 

(function(){
    //强行暴露一个变量,一枝红杏出墙来
    window.carousel = carousel;
    //轮播图类
    function carousel(json){
        this.$dom = $("#" + json.id); //dom元素
        this.$imagesul = null;
        this.$imagesullis = null;
        this.width = json.width;
        this.height = json.height;
        this.$leftbtn = null;
        this.$rightbtn = null;
        this.$circleol = null;
        this.$circlelis = null;
        this.interval = json.interval;
        this.speed = json.speed; //滑动速度
        this.idx = 0;//信号量
        this.imagesurlarr = json.images;//图片地址数组
        this.picturelength = json.images.length;//图片长度
        this.init();
        this.bindevent();
        this.autoplay(); //定时器
    }
    //初始化dom
    carousel.prototype.init = function(){
        //创建ul节点
        this.$imagesul = $("<ul></ul>");
        this.$dom.append(this.$imagesul);
        //创建li节点
        for(var i = 0; i < this.picturelength; i++) {
            $("<li><img src='"+this.imagesurlarr[i].picurl+"'/></li>")
.appendto(this.$imagesul);
        };
        //获得li元素引用
        this.$imagesullis = this.$imagesul.find("li");
        //大盒子的布局
        this.$dom.css({
            "width" : this.width,
            "height" : this.height,
            "position" : "relative",
            "overflow" : "hidden"
        });
        //猫腻,让所有li藏起来(left移动到显示区域外)
        this.$imagesullis.css({
            "position" : "absolute",
            "left": this.width,
            "top": 0
        });
    //只显示第一张图
        this.$imagesullis.eq(0).css("left",0);
        //创建按钮
        this.$leftbtn = $("<a href='javascript:;' class='leftbtn'></a>");
        this.$rightbtn = $("<a href='javascript:;' class='rightbtn'></a>");
        this.$leftbtn.appendto(this.$dom);
        this.$rightbtn.appendto(this.$dom);
        //创建小圆点
        this.$circleol = $("<ol class='circls'></ol>");
        this.$circleol.appendto(this.$dom);
        for (var i = 0; i < this.picturelength; i++) {
            $("<li></li>").appendto(this.$circleol);
        };
        //获得ol的li元素
        this.$circlelis = this.$circleol.find("li");
        //加cur
        this.$circlelis.eq(0).addclass("cur");
    }
})();

 

事件监听方法:

carousel.prototype.bindevent = function(){
    var self = this;
    //右边按钮的监听
    this.$rightbtn.click(function(){
        if(self.$imagesullis.is(":animated")) return;
        self.shownext();
    });
    //左边按钮的监听
    this.$leftbtn.click(function(){
        if(self.$imagesullis.is(":animated")) return;
        self.showprev();
    });
}

 

 shownext() 显示下一张方法

//展示下一张
carousel.prototype.shownext = function(){
    this.$imagesullis.eq(this.idx).animate({"left" : -this.width},this.speed);
    this.idx++;
    if(this.idx > this.picturelength - 1){
        this.idx = 0;
    }
    this.$imagesullis.eq(this.idx).css("left",this.width).animate({"left" : 0},this.speed);
    //圆点的cur
    this.changecirclescur();
}

 

 changecirclescur()小圆点方法

carousel.prototype.changecirclescur = function(){
    this.$circlelis.eq(this.idx).addclass("cur").siblings().removeclass("cur");
}

 

 showprev() 显示上一张方法

//展示上一张
carousel.prototype.showprev = function(){
    this.$imagesullis.eq(this.idx).animate({"left" : this.width},this.speed);
    this.idx--;
    if(this.idx < 0){
        this.idx = this.picturelength - 1;
    }
    this.$imagesullis.eq(this.idx).css("left",-this.width).animate({"left" : 0},this.speed);
    //圆点的cur
    this.changecirclescur();
}
//自动轮播
carousel.prototype.autoplay = function(){
    var self = this;
    this.timer = setinterval(function(){
        self.shownext();
    },this.interval);
}

 

bindevent()

carousel.prototype.bindevent = function(){
    var self = this;
    //鼠标停表
    this.$dom.mouseenter(function(){
        clearinterval(self.timer);
    });
//离开开启
    this.$dom.mouseleave(function(){
        self.autoplay();
    });
//圆点的监听
this.$circlelis.click(function(){
    self.show($(this).index());
});
}
//小圆点点击展示任意
carousel.prototype.show = function(number){
    var old = this.idx; //旧idx信号量
    this.idx = number;    //当前点击的信号量,改变全局
    //判断
    if(this.idx > old){ //从右到左
        this.$imagesullis.eq(old).animate({"left" : -this.width},this.speed);
        this.$imagesullis.eq(this.idx).css("left",this.width).animate({"left" : 0},this.speed);
    }else if(this.idx < old){//从左到右
        this.$imagesullis.eq(old).animate({"left" : this.width},this.speed);
        this.$imagesullis.eq(this.idx).css("left",-this.width).animate({"left" : 0},this.speed);
    }
    //圆点的cur
    this.changecirclescur();
}

二、俄罗斯方块游戏开发

2.1先认识方块

俄罗斯方块一共有7种:szjloit

前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战

2.2写二维数组的json表(表示砖块)

首先做两种图形:

// s z j l o i t

var block_json = {
    "i":[ //i有2种方向
        [
            [0,1,0,0],
            [0,1,0,0],
            [0,1,0,0],
            [0,1,0,0]
        ],
        [
            [0,0,0,0],
            [0,0,0,0],
            [1,1,1,1],
            [0,0,0,0]
        ]
    ],
    "l":[ //l有4种方向
        [
            [0,1,0,0],
            [0,1,0,0],
            [0,1,1,0],
            [0,0,0,0]
        ],
        [
            [1,1,1,0],
            [1,0,0,0],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [1,1,0,0],
            [0,1,0,0],
            [0,1,0,0],
            [0,0,0,0]
        ],
        [
            [0,0,1,0],
            [1,1,1,0],
            [0,0,0,0],
            [0,0,0,0]
        ]
    ],
    "j":[//j有4种方向
        [
            [0,1,0,0],
            [0,1,0,0],
            [1,1,0,0],
            [0,0,0,0]
        ],
        [
            [1,0,0,0],
            [1,1,1,0],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [1,1,0,0],
            [1,0,0,0],
            [1,0,0,0],
            [0,0,0,0]
        ],
        [
            [1,1,1,0],
            [0,0,1,0],
            [0,0,0,0],
            [0,0,0,0]
        ]
    ],
    "o":[ //o有1种方向
        [
            [1,1,0,0],
            [1,1,0,0],
            [0,0,0,0],
            [0,0,0,0]
        ]
    ],
    "z":[ //z有2种方向
        [
            [1,1,0,0],
            [0,1,1,0],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [0,0,1,0],
            [0,1,1,0],
            [0,1,0,0],
            [0,0,0,0]
        ]
    ],
    "s":[ //s有2种方向
        [
            [0,1,1,0],
            [1,1,0,0],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,0,0],
            [0,1,1,0],
            [0,0,1,0],
            [0,0,0,0]
        ]
    ],
    "t":[//t有4种方向
        [
            [1,1,1,0],
            [0,1,0,0],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,0,0],
            [1,1,0,0],
            [0,1,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,0,0],
            [1,1,1,0],
            [0,0,0,0],
            [0,0,0,0]
        ],
        [
            [0,1,0,0],
            [0,1,1,0],
            [0,1,0,0],
            [0,0,0,0]
        ]
    ]
}

 

2.3基本布局【table表格(12*20)】

都是套路,和贪吃蛇没区别。

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>document</title>
    <style type="text/css">
        table{
            margin:50px auto;
        }
        table,tr,td{border: 1px solid #000;border-collapse:collapse;}
        td{width: 18px;height: 18px;}
    </style>
</head>
<body>
    <div id="app"></div>
</body>
<script type="text/javascript" src="js/game.js"></script>
<script type="text/javascript" src="js/block.js"></script>
<script type="text/javascript">
    var game = new game()
</script>
</html>

循环创建12*20table表格,原因:为了方块能居中。

(function(){
    window.game = function(){
        this.init()
    }

    //20 * 12创建表格
    game.prototype.init = function(){
        this.dom = document.createelement('table');
        document.getelementbyid("app").appendchild(this.dom);

        var tr,td;
        //循环插入行
        for(var i = 0;i < 20;i++){
            tr = document.createelement('tr');
            this.dom.appendchild(tr);
            for(var j = 0;j < 12;j++){
                //循环插入列
                td = document.createelement('td');
                tr.appendchild(td);

            }
        }
    }
})();
//如果别的类修改game类的表格颜色,尽量提供一个方法给其他类调用,不要让其他类修改自己的属性
//设置table表格的颜色
game.prototype.setclass = function(row, col, classname){
    this.dom.getelementsbytagname('tr')[row].getelementsbytagname('td')[col].classname = 
classname
}

 

index.html中写两个类:

.l{background: skyblue;}
.i{background: pink;}

前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战

(function(){
    window.block = function(){
        //在所有的形状中,选择一个砖块形状
        var arr = ["i","l","j"];
        this.alltype = arr[~~(math.random() * arr.length)]
        console.log(this.alltype)
        //自己所有的方向个数
        this.alldirectionnumber = block_json[this.alltype].length;
        //随意一个方向
        this.direction = ~~(math.random() * this.alldirectionnumber);

        //得到形状,马上渲染图形的而进行code码
        this.code = block_json[this.alltype][this.direction];

        //4 * 4小方块的初始位置
        this.row = 0;
        this.col = 4; //保证方块从中间出现
    }
})();

前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战


2.4砖块渲染

(function(){
    window.block = function(){
         ...
    }

    //渲染砖块
    block.prototype.render = function(){
        for(var i = 0; i < 4;i++){
            for(var j = 0; j < 4;j++){
                //显示4 * 4矩阵颜色,写class类
                game.setclass(this.row + i, this.col + j, "gray");
                if(this.code[i][j] == 1){
                    //如果4 * 4 二维数组编码中有1就渲染颜色,0就没色
                    game.setclass(this.row + i, this.col + j, this.alltype)
                }
            }
        }
    }
})();

 

别忘记在game类中添加定时器并render block(渲染方块)

(function(){
    window.game = function(){
        this.init();
        this.start();
        //实例化砖块类
        this.block = new block();
    }

    game.prototype.start = function(){
        var self = this;
        setinterval(function(){
            //渲染砖块
            self.block.render();
        },30);
    }
})();

前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战


2.5砖块下落

//砖块下落
block.prototype.down = function(){
    this.row++;
}

//清屏方法
game.prototype.clearclass = function(){
    for(var i = 0; i < 20;i++){
        for(var j = 0; j < 12;j++){
            game.setclass(i, j, "");
        }
    }
}
game.prototype.start = function(){
    this.f = 0;
    var self = this;
    setinterval(function(){
        self.f++;
        //清屏
        self.clearclass()
        //渲染砖块
        self.block.render();
        //每间隔20帧下落
        self.f % 20 == 0 && self.block.down();
    },30);
}

前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战

砖块就能下落了


2.6 map地图类

map地图类存储死亡的方块

(function(){
    window.map = function(){
        this.code = [
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0,0,0,0,0,0]
        ]
    }
})()

for循环更优雅的创建二维数组

this.code = (function(){
    var arr = [];
    for(var i = 0;i < 20;i++){
        arr.push([]);
        for(var j = 0;j < 12;j++){
            arr[i].push(0)
        }
    }
    return arr;
})();

 

es6语法,写一个二维数组:

new array(20).fill(new array(12).fill(0)
(function(){
    window.map = function(){
        this.code = (function(){
            var arr = [];
            for(var i = 0;i < 20;i++){
                arr.push([]);
                for(var j = 0;j < 12;j++){
                    arr[i].push(0)
                }
            }

            //写一个“一柱擎天”方便测试
            arr[10][5] = "l";
            arr[11][5] = "l";
            arr[12][5] = "l";
            arr[13][5] = "l";
            arr[14][5] = "l";
            arr[15][5] = "l";
            arr[16][5] = "l";
            arr[17][5] = "l";
            arr[18][5] = "l";
            arr[19][5] = "l";

            return arr;
        })();

        console.log(this.code)
    }
})()

前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战

 

map地图类渲染:

//地图渲染
map.prototype.render = function(){
    for(var i = 0;i < 20; i++){
        for(var j = 0;j < 12; j++){
            //如果地图中二维数组中有非0的,就渲染方块
            if(this.code[i][j] != 0){
                game.setclass(i, j, this.code[i][j])
            }
        }
    }
}

前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战


2.7下落的砖块卡住判断

前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战

看下一行能不能进取决于两个条件:

1、地图类的下一行不能是非0

2、方块的下一行不能是1

//检测碰撞,提供check方法,返回值true或false
block.prototype.check = function(row,col){
    for(var i = 0; i < 4; i++){
        for(var j = 0; j < 4; j++){
            if(this.code[i][j] != 0 && game.map.code[row + i][col + j] != 0){
                return false; //如果不能进,返回false
            }
        }
    }
    return true; //能进返回true
}
//砖块下落
block.prototype.down = function(){
    //调用check方法,如果为真就继续row++往下落
    console.log(this.check(this.row+1,this.col))
    if(this.check(this.row+1,this.col)){
        this.row++;
    }
}

到这来碰撞检测完成。

 

当删除测试的“一柱擎天”后,block下落到底的时候,报错了,因为下标越界了,map类最下面没有非0code码,检测block.check方法中循环不到第ij列没有非0的值了。

 前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战

 

解决办法:手动在最后补一行非0的数组值即可。

arr.push([1,1,1,1,1,1,1,1,1,1,1,1]);

arr.push(array(12).fill(1));

前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战


2.8添加键盘事件监听

//键盘事件监听
game.prototype.bindevent = function(){
    var self = this;
    document.onkeyup = function(event){
        if(event.keycode == 37){
            self.block.left();
        }else if(event.keycode == 38){
            self.block.rotate();
        }else if(event.keycode == 39){
            self.block.right();
        }else if(event.keycode == 40){
            self.block.godown();
        }
    }
}

//向左
block.prototype.left = function(){
    if(this.check(this.row,this.col-1)){
        this.col--;
    }
}
// 向右
block.prototype.right = function(){
    if(this.check(this.row,this.col+1)){
        this.col++;
    }
}
//一键到底
block.prototype.godown = function(){
    while(this.check(this.row+1,this.col)){
        this.row++;
    }
}

可以左右、向下控制砖块了。

只要碰到map中的死尸砖块就添加。

//添加死亡方块
block.prototype.adddie = function(){
    for(var i = 0; i < 4;i++){
        for(var j = 0; j < 4;j++){
            // console.log(this.row+i,this.col+j)
            if(this.code[i][j] != 0){
                //如果不是0表示有颜色(有砖块)
                //将随机出来的字母类名,写在地图类的code中
                game.map.code[this.row + i][this.col + j] = this.alltype;
            }
        }
    }
}
//砖块下落
block.prototype.down = function(){
    //调用check方法,如果为真就继续row++往下落
    if(this.check(this.row+1,this.col)){
        this.row++;
    }else{
        //如果为假,表示碰到非0的砖块了,将自己添加到map地图类中
        this.adddie();
        //同时new一个新的砖块出来
        game.block = new block();
    }
}

2.10旋转

//旋转
block.prototype.rotate = function(){
    //备份旧方向
    var olddirection = this.direction;
    //如果旋转的值已经等于自己方向的个数,就回到0,重新翻转
    if(this.direction == this.alldirectionnumber - 1){
        this.direction = 0;
    }else{
        // 否则继续加,可以旋转
        this.direction++;
    }
    //得到自己的方向下标后,马上渲染图形的二维数组的code码
    this.code = block_json[this.alltype][this.direction];
    if(!this.check(this.row,this.col)){
        //已经碰到了
        //如果不可以旋转,就撤回来
        this.direction = olddirection
        //改为刚刚随机出来的旧方向。
        this.code = block_json[this.alltype][this.direction];
    }
}

2.11消行判断

前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战

//消行判断
block.prototype.remove = function(){
    //判断map地图类中的code中某一行是不是没有0,如果没有0,就消行
    for(var i = 0;i < 20;i++){
        if(!game.map.code[i].includes(0)){
            //如果没有0,就删除行
            game.map.code.splice(i,1);
            //删除行之后,再重新在头部填充一行全0的
            game.map.code.unshift(new array(12).fill(0));
        }
    }
}
//砖块下落
block.prototype.down = function(){
    //调用check方法,如果为真就继续row++往下落
    if(this.check(this.row+1,this.col)){
        this.row++;
    }else{
        //如果为假,表示碰到非0的砖块了,将自己添加到map地图类中
        this.adddie();
        //同时new一个新的砖块出来
        game.block = new block();
        //没碰到一次检测是否需要消行
        this.remove();
    }
}

2.12游戏结束判断

//砖块下落
block.prototype.down = function(){
    //判断数组的第0行,有没有不等于0的项,如果有,游戏结束
    game.map.code[0].foreach(function(item){
        if(item != 0){
            clearinterval(game.timer);
            alert`游戏结束`;
        }
    });
    //调用check方法,如果为真就继续row++往下落
    if(this.check(this.row+1,this.col)){
        this.row++;
    }else{
        //如果为假,表示碰到非0的砖块了,将自己添加到map地图类中
        this.adddie();
        //同时new一个新的砖块出来
        game.block = new block();
        //没碰到一次检测是否需要消行
        this.remove();  
    }
}

2.13添加音效和美化

<html>
<head>
    <style type="text/css">
        *{margin: 0;padding: 0;}
        body{
            height: 100%;
            background: url(img/bg.jpg) no-repeat 0 0;
            background-size:cover;
        }
        table{
            margin:50px auto;
            background: rgba(0, 0, 0,0.5);
        }
        table,tr,td{
            border: 1px solid #000;
            border-collapse:collapse;
        }
        td{
            width: 20px;
            height: 20px;
        }
        .l{ background: linear-gradient(to right bottom, #800080, #ffc0cb);}
        .i{ background: linear-gradient(to right bottom, #00f260, #0575e6);}
        .s{ background: linear-gradient(to right bottom, #fc4a1a, #f7b733);}
        .z{ background: linear-gradient(to right bottom, #22c1c3, #fdbb2d);}
        .j{ background: linear-gradient(to right bottom, #ff9966, #ff5e62);}
        .o{ background: linear-gradient(to right bottom, #7f00ff, #e100ff);}
        .t{ background: linear-gradient(to right bottom, #c0392b, #8e44ad);}
        .b{ background:yellow; }
        .a{ background:yellowgreen; }
        h1,h2{color:#fff;text-align:center;}
    </style>
</head>
<body>
    <audio src="audio/bg.wav" autoplay id="bg"></audio>
    <audio src="audio/一键到底.wav" id="godown"></audio>
    <audio src="audio/旋转.wav" id="rotate"></audio>
    <audio src="audio/移动.wav" id="move"></audio>
    <audio src="audio/消行.wav" id="godie"></audio>
    <h1 id="score"></h1>
    <h2 id="info"></h2>
    <div id="app"></div>
</body>
</html>
<script type="text/javascript" src="js/block_json.js"></script>
<script type="text/javascript" src="js/game.js"></script>
<script type="text/javascript" src="js/block.js"></script>
<script type="text/javascript" src="js/map.js"></script>
<script type="text/javascript">
     document.getelementbyid("bg").volume = 0.2;
     var game = new game();
</script>

 

//主循环,游戏定时器
game.prototype.start = function(){
    var self = this;  
    this.f = 0;
    this.score = 0;
    this.timer = setinterval(function(){
        self.f++;
        document.getelementbyid("info").innerhtml = "帧编号:"+ self.f;
        document.getelementbyid("score").innerhtml = "分数:"+ self.score;
        //先清屏,再渲染
        self.clearclass();
        //渲染小方块
        self.block.render();
        //每隔20帧,方块下落
        self.f % 30 == 0 && self.block.down();
        //地图方块渲染
        self.map.render();
    },20);
}

音效:

//旋转
block.prototype.rotate = function(){
    document.getelementbyid("rotate").play();
}
//一键下落
block.prototype.godown = function(){
    document.getelementbyid("godown").play();
}
//向左
block.prototype.left = function(){
    document.getelementbyid("move").play();
}
//向右
block.prototype.right = function(){
    document.getelementbyid("move").play();
}
//消行判断、加分
block.prototype.remove = function(){
    //判断map类中的code中某一行是不是没有0,如果没有0,就消行
    for (var i = 0; i < 20; i++) {
        if(!game.map.code[i].includes(0)){
            game.score++;
            document.getelementbyid("godie").play();
        }
    };
}