Html5原創俄罗斯方块(根据canvas)

日期:2021-01-19 类型:科技新闻 

关键词:快速建站,网站建设系统,免费网页建站,网站免费建设,建站系统

第1次写俄罗斯方块的情况下早已是1年多前了,也是我不久学js没多久。

以便提升对js的了解又再加对手机游戏的喜好,因而在沒有参照别人的思路和编码下,自身用最基础的js编码写出了根据canvas的俄罗斯方块。

在大3的暑期,我又用了es6的英语的语法开展了改善,包括了class的英语的语法糖、箭头涵数等,进1步提升自身对es6的了解,编码有400+行

要想做这个小手机游戏,务必先熟习H5的canvas,js对数字能量数组的解决,电脑键盘恶性事件监视和解决,定时执行器的应用等,别的的便是基础的逻辑性解决了。

手机游戏的标准便是关键,也是大家编码的头等大事

这里的逻辑性关键是必须分辨方块是不是碰撞(当今健身运动的方块和早已精准定位好的方块有碰撞以至于当今的健身运动的方块不可以在向下走,由于大家的方块默认设置是向下走的,假如不可以向下走,是视作早已精准定位好的方块,随后在转化成1个新的方块从原始部位再次往下走)。

并且这个碰撞还必须运用在方块形变的情况下,一样地,假如方块在形变的全过程中合别的精准定位好的方块开展碰撞,则大家应当阻拦这个方块开展形变取得成功,

附上编码,欢迎探讨和纠正

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF⑻">
    <title>es6-重构俄罗斯方块(根据canvas)</title>
    <style type="text/css">
        #tetris{ margin: 10px 250px;}
    </style>
</head>
<body>
    <canvas width="700" height="525" id="tetris"></canvas>
    <div id="text" style='color: red;font-size: 30px;'>当今分数:0</div>
    <script type="text/javascript">
        /**
         * [1个详细的俄罗斯方块类 design by magic_xiang]
         * @param  {number} side     [每一个方块边长(px),默认设置35]
         * @param  {number} width     [1行包括的方块数(个),默认设置20]
         * @param  {number} height     [1列包括的方块数(个),默认设置15]
         * @param  {number} speed     [方块着落挪动速率(ms),默认设置400]
         */
        class tetris{
            constructor(side=35, width=20, height=15, speed=400){
                this.side = side            // 每一个方块边长
                this.width = width            // 1行包括的方块数
                this.height = height        // 1列包括的方块数
                this.speed = speed             // 方块着落挪动速率
                this.num_blcok                // 当今方块种类的数据自变量
                this.type_color                // 当今色调种类的标识符串自变量
                this.ident                    // setInterval的标志
                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 = document.getElementById('tetris').getContext('2d')
                //获得画笔
                self = 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 < this.height; i++){
                    for(let 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()
            }

            // 运用数字能量数组画方块
            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()
            }

            // 画早已在精准定位好的方块
            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.closePath()
                })
            }

            // 转化成任意数回到方块种类或色调种类
            createRandom(type){
                let temp = this.width/2⑴

                if (type == 'rBlock'){         //假如是方块种类
                    this.num_blcok = Math.round(Math.random()*4+1)
                    switch(this.num_blcok){
                        case 1:
                            this.arr_bX.push(temp,temp⑴,temp,temp+1)
                            this.arr_bY.push(0,1,1,1)
                            break
                        case 2:
                            this.arr_bX.push(temp,temp⑴,temp⑴,temp+1)
                            this.arr_bY.push(1,0,1,1)
                            break
                        case 3:
                            this.arr_bX.push(temp,temp⑴,temp+1,temp+2)
                            this.arr_bY.push(0,0,0,0)
                            break
                        case 4:
                            this.arr_bX.push(temp,temp⑴,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 < 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 < 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 < this.arr_bX.length; i++){
                    if (num == 1) {            //形变时是不是翻过右侧界
                        if (this.arr_bX[i] == this.width - 1) 
                            return false
                    }
                    if (num == ⑴) {                //形变时是不是翻过左侧界
                        if (this.arr_bX[i] == 0)
                            return 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 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 < this.arr_bY.length; i++){
                        this.arr_bY[i] = this.arr_bY[i] + 1
                    }
                }
                else{
                    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
                        }
                    }
                }
                else{
                    let flag_all_left = true
                    flag_all_left = this.judgeCollision_other(⑴)

                    if (flag_all_left) {
                        for(let i=0; i < this.arr_bY.length; i++){
                            this.arr_bX[i] = this.arr_bX[i]⑴
                        }
                    }
                }
                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)            //将数字能量数组清空 
                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⑴,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⑴,ax_temp,ax_temp)
                            this.arr_bY.push(ay_temp,ay_temp,ay_temp⑴,ay_temp+1)
                            break
                        case 3:
                            this.arr_bX.push(ax_temp,ax_temp⑴,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⑴,ay_temp+1,ay_temp)
                            break
                    }
                }
                if (num_blcok == 2) {
                    
                    switch(this.direction%4){
                        case 1:
                            this.arr_bX.push(ax_temp,ax_temp⑴,ax_temp⑴,ax_temp+1)
                            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⑴,ay_temp+1,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,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⑴,ay_temp+1,ay_temp⑴)
                            break
                    }
                }
                if (num_blcok == 3) {
                    
                    switch(this.direction%4){
                        case 1:
                            this.arr_bX.push(ax_temp,ax_temp⑴,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⑴,ay_temp+1,ay_temp+2)
                            break
                        case 3:
                            this.arr_bX.push(ax_temp,ax_temp⑴,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⑴,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⑴,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⑴)
                            break
                        case 3:
                            this.arr_bX.push(ax_temp,ax_temp,ax_temp⑴,ax_temp+1)
                            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+1,ax_temp+1)
                            this.arr_bY.push(ay_temp,ay_temp⑴,ay_temp,ay_temp+1)
                            break
                    }
                }
                
                if (! (this.judgeCollision_other(⑴) && this.judgeCollision_down() && 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()
            }

            //1行满了清空方块,上面方块Y座标+1
            clearUnderBlock(){
                //删掉低层方块
                let arr_row=[]
                let line_num
                if (this.arr_store_X.length != 0) {
                    for(let j = this.height⑴; 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
                        }else{
                            arr_row.splice(0, arr_row.length)
                        }
                    }
                }
                    
                if (arr_row.length == this.width) {
                    //测算考试成绩grade
                    this.grade++
                    
                    document.getElementById('text').innerHTML = '当今考试成绩:'+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)
                    }
                
                    //让上面的方块往下掉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

            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(⑴)
                    tetrisObj.drawBlock(tetrisObj.type_color)
                    break
                case 39:  // 方位为右
                    tetrisObj.initBackground()
                    tetrisObj.move(1)
                    tetrisObj.drawBlock(tetrisObj.type_color)
                    break
            }    
        }

    </script>
</body>
</html>

以上便是本文的所有內容,期待对大伙儿的学习培训有一定的协助,也期待大伙儿多多适用脚本制作之家。