麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > HTML > 正文

Html5原創俄羅斯方塊(基于canvas)

2024-08-26 00:21:16
字體:
來源:轉載
供稿:網友

第一次寫俄羅斯方塊的時候已經是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">        /**         * [一個完整的俄羅斯方塊類 design by magic_xiang]         * @param  {number} side     [每個方塊邊長(px),默認35]         * @param  {number} width     [一行包含的方塊數(個),默認20]         * @param  {number} height     [一列包含的方塊數(個),默認15]         * @param  {number} speed     [方塊下落移動速度(ms),默認400]         */        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>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到HTML教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 久草在线高清视频 | 国产精品亚洲综合一区二区三区 | 成人一级黄色片 | 亚洲二区免费 | 欧美日韩在线影院 | 强伦女教师视频 | 黄色毛片视频在线观看 | 欧美日韩在线免费观看 | 国产一区二区国产 | 欧美偷拍一区二区 | 久久久午夜电影 | av大全在线播放 | 日韩视频在线观看免费视频 | 欧洲精品久久久久69精品 | 斗罗破苍穹在线观看免费完整观看 | 97超级碰碰人国产在线观看 | 一边吃奶一边摸下娇喘 | 色悠悠久久久久 | 欧美激情精品久久久久久久久久 | 国产成人高潮免费观看精品 | teensexhd | 精品国产乱码久久久久久丨区2区 | 亚洲第九十九页 | 久久久一区二区精品 | 毛片福利 | 国产精品999在线 | 在线观看精品视频 | 欧美国产综合视频 | 午夜视频中文字幕 | 一本免费视频 | 5xsq在线视频| 日本特级a一片免费观看 | 99精品在线视频观看 | 91久久免费| 国产一级一区 | 一级一级一级一级毛片 | 久久综合综合 | 久久久久久久91 | 色综合视频网 | 最新一区二区三区 | 免费看欧美一级特黄a毛片 九色com |