亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > 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网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线日韩精品视频| 国产福利视频一区| 欧美老女人性视频| 国产专区欧美专区| 高清亚洲成在人网站天堂| 精品久久久久久久久久久| 欧美肥臀大乳一区二区免费视频| 一区二区三区高清国产| 高跟丝袜欧美一区| 国产男女猛烈无遮挡91| 欧美日韩国产在线播放| 亚洲国产精品嫩草影院久久| 欧美色另类天堂2015| 欧美午夜片欧美片在线观看| 91高清免费视频| 日韩大片免费观看视频播放| 欧美高清性猛交| 国产成人中文字幕| 国产亚洲欧洲在线| 国产在线精品成人一区二区三区| xvideos成人免费中文版| 国产精品高潮呻吟久久av野狼| 日韩欧美一区视频| 亚洲精品久久久久久久久久久久| 亚洲欧美日韩久久久久久| 日韩精品www| 国产一区二中文字幕在线看| 这里只有精品久久| 中文字幕久久久| 欧美在线欧美在线| 精品国产乱码久久久久久婷婷| 国产91精品网站| 亚洲乱码一区av黑人高潮| 精品国产欧美一区二区五十路| 全球成人中文在线| 久久久久北条麻妃免费看| 亚洲午夜精品久久久久久久久久久久| 国产精品美女久久久久av超清| 久久久久成人网| 社区色欧美激情 | 日韩视频精品在线| 久久成人这里只有精品| 97视频在线免费观看| 亚洲女同性videos| 精品久久久久久久久久国产| 国产一区二区在线播放| 久久99精品久久久久久噜噜| 亚洲va欧美va在线观看| 国产精品精品久久久久久| 久久久久中文字幕2018| 精品国产乱码久久久久久婷婷| 欧美重口另类videos人妖| 91久久久在线| 国产一区二区三区精品久久久| 国产不卡精品视男人的天堂| 国产精品色婷婷视频| 欧美多人爱爱视频网站| 亚洲国产日韩欧美在线99| 亚洲精品小视频| 亚洲人成电影网站色www| 国产精品久久久久久久久免费看| 国产黑人绿帽在线第一区| 国产欧美一区二区三区四区| 欧美专区在线视频| 亚洲人成电影在线观看天堂色| 国产有码在线一区二区视频| 久久久久久久影视| 国产亚洲欧洲高清| 国产精品日韩欧美综合| 91国自产精品中文字幕亚洲| 久久久久国产精品免费| 欧美激情网友自拍| 午夜剧场成人观在线视频免费观看| 国产精品成av人在线视午夜片| 日韩在线观看免费全集电视剧网站| 国产一区二区三区精品久久久| 成人国产精品久久久久久亚洲| 国产精品久久久久久久电影| 亚洲91av视频| 懂色av中文一区二区三区天美| 国产视频丨精品|在线观看| 国产精品久久久久久久久久久久| 97精品国产97久久久久久免费| 中文字幕v亚洲ⅴv天堂| 国产精品午夜一区二区欲梦| 亚洲精品一区二区久| 国产精品久久久久久久久久三级| 久久国产精品影视| 九色精品免费永久在线| 国产成+人+综合+亚洲欧洲| 欧美综合第一页| 中文字幕日韩av综合精品| 亚洲精品福利资源站| 精品一区精品二区| 精品一区二区三区电影| 日韩欧美国产网站| 久久在精品线影院精品国产| 亚洲国产精品成人av| 69久久夜色精品国产69| 丰满岳妇乱一区二区三区| www.亚洲男人天堂| 91最新在线免费观看| 精品中文视频在线| 亚洲精品久久久久久久久久久| 97视频在线观看免费高清完整版在线观看| 国产主播精品在线| 精品欧美aⅴ在线网站| 成人欧美一区二区三区在线| 久久久久久久久爱| 亚洲欧美在线一区| 亚洲欧美国产va在线影院| 岛国av一区二区三区| 欧美一级电影久久| 97av在线播放| 国产suv精品一区二区| 日韩在线小视频| 91黑丝高跟在线| 亚洲第一页自拍| 亚洲人成电影网站色www| 欧美国产高跟鞋裸体秀xxxhd| 中文字幕视频在线免费欧美日韩综合在线看| 日本成人激情视频| 久久免费视频在线| 91av在线国产| 色系列之999| 欧美激情国产日韩精品一区18| 色综合久久悠悠| 亚洲国产中文字幕在线观看| 一区二区三区视频在线| 亚洲视频网站在线观看| 91久久在线观看| 91在线免费看网站| 国产mv久久久| 日韩日本欧美亚洲| 日本午夜在线亚洲.国产| 亚洲国产又黄又爽女人高潮的| 国产精品久久久久久久久男| 久久精品久久久久久国产 免费| 国产精品久久久久久影视| 亚洲影视中文字幕| 欧美一区二区三区精品电影| 午夜精品蜜臀一区二区三区免费| 欧美性猛交xxxx偷拍洗澡| 亚洲影院色在线观看免费| 精品国产一区av| 热久久美女精品天天吊色| 亚洲精品国精品久久99热| 亚洲精品一区中文| 伊人久久男人天堂| 91手机视频在线观看| 国a精品视频大全| 国产欧美日韩亚洲精品| 亚洲人成在线观| 国产精品视频在线观看| 国产在线高清精品| 欧美亚洲成人xxx| www.美女亚洲精品| 成人网在线视频| 日韩a**站在线观看| 国产一区二区三区久久精品| 中文在线不卡视频| 一区二区av在线| 懂色aⅴ精品一区二区三区蜜月| 欧美高跟鞋交xxxxxhd|