文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Html5中基于canvas实现原创俄罗斯方块的示例

2023-06-09 13:33

关注

这篇文章将为大家详细讲解有关Html5中基于canvas实现原创俄罗斯方块的示例,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

第一次写俄罗斯方块的时候已经是1年多前了,也是我刚刚学js不久。

为了加强对js的理解又加上对游戏的爱好,于是在没有参考他人的思路和代码下,自己用最基本的js代码写出了基于canvas的俄罗斯方块。

Html5中基于canvas实现原创俄罗斯方块的示例

在大三的暑假,我又用了es6的语法进行了改进,包含了class的语法糖、箭头函数等,进一步增加自己对es6的理解,代码有400+行

想要做这个小游戏,必须先熟悉H5的canvas,js对数组的处理,键盘事件监听和处理,定时器的使用等,其他的就是基本的逻辑处理了。

游戏的规则就是核心,也是我们代码的重中之重

这里的逻辑核心是需要判断方块是否碰撞(当前运动的方块和已经定位好的方块有碰撞以致于当前的运动的方块不能在向下走,因为我们的方块默认是向下走的,如果不能向下走,是视为已经定位好的方块,然后在生成一个新的方块从初始位置继续往下走)。

而且这个碰撞还需要应用在方块变形的时候,同样地,如果方块在变形的过程中和其他定位好的方块进行碰撞,则我们应该阻止这个方块进行变形成功,

附上代码,欢迎讨论和指正

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <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">                class tetris{            constructor(side=35, width=20, height=15, speed=400){                this.side = side            // 每个方块边长                this.width = width            // 一行包含的方块数                this.height = height        // 一列包含的方块数                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-1                if (type == 'rBlock'){         //如果是方块类型                    this.num_blcok = Math.round(Math.random()*4+1)                    switch(this.num_blcok){                        case 1:                            this.arr_bX.push(temp,temp-1,temp,temp+1)                            this.arr_bY.push(0,1,1,1)                            break                        case 2:                            this.arr_bX.push(temp,temp-1,temp-1,temp+1)                            this.arr_bY.push(1,0,1,1)                            break                        case 3:                            this.arr_bX.push(temp,temp-1,temp+1,temp+2)                            this.arr_bY.push(0,0,0,0)                            break                        case 4:                            this.arr_bX.push(temp,temp-1,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 == -1) {                //变形时是否越过左边界                        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(-1)                    if (flag_all_left) {                        for(let i=0; i < this.arr_bY.length; i++){                            this.arr_bX[i] = this.arr_bX[i]-1                        }                    }                }                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-1,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-1,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-1,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-1,ay_temp+1,ay_temp)                            break                    }                }                if (num_blcok == 2) {                                        switch(this.direction%4){                        case 1:                            this.arr_bX.push(ax_temp,ax_temp-1,ax_temp-1,ax_temp+1)                            this.arr_bY.push(ay_temp,ay_temp,ay_temp-1,ay_temp)                            break                        case 2:                            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 3:                            this.arr_bX.push(ax_temp,ax_temp-1,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-1,ay_temp+1,ay_temp-1)                            break                    }                }                if (num_blcok == 3) {                                        switch(this.direction%4){                        case 1:                            this.arr_bX.push(ax_temp,ax_temp-1,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-1,ay_temp+1,ay_temp+2)                            break                        case 3:                            this.arr_bX.push(ax_temp,ax_temp-1,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-1,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-1,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-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-1,ay_temp,ay_temp-1)                            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-1,ay_temp,ay_temp+1)                            break                    }                }                                if (! (this.judgeCollision_other(-1) && 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()            }            //一行满了清空方块,上面方块Y坐标+1            clearUnderBlock(){                //删除低层方块                let arr_row=[]                let line_num                if (this.arr_store_X.length != 0) {                    for(let j = this.height-1; 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)                    }                                    //让上面的方块往下掉一格                    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(-1)                    tetrisObj.drawBlock(tetrisObj.type_color)                    break                case 39:  // 方向为右                    tetrisObj.initBackground()                    tetrisObj.move(1)                    tetrisObj.drawBlock(tetrisObj.type_color)                    break            }            }    </script></body></html>

关于“Html5中基于canvas实现原创俄罗斯方块的示例”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯