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

首頁 > 編程 > HTML > 正文

canvas實現俄羅斯方塊的方法示例

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

好久沒使用canvas了,于是通過寫小游戲“俄羅斯方塊”再次熟悉下canvas,如果有一定的canvas基礎,要實現還是不難的。

原理詳解

看游戲最終界面,可知需要實現以下關鍵功能:

  • 游戲面板,也就是12 * 20的方格,以及是否填充了方塊信息;
  • 運動方塊,方塊需要實現移動,變形的功能。 
     

 canvas,俄羅斯方塊

界面的實現

整個面板就是以左上角(0,0)為原點的坐標系,右上角(12,0)左下角(0,20)右下角(12,20),每個點的坐標位置都可以確定。是否已經填充方塊,我們可以將每個方格看成一個數組元素,0表示沒有,1表示已經填充。12 * 20 的面板使用兩層數組,即用20個長度為12的數組實現。

var maps = [[0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,1,0,1,0], ...];

畫出面板的代碼,用最基礎的canvas的api就能實現

//格子    for(var i=0;i<12;i++){        for(var j=0;j<20;j++){            ctx.fillRect(i*40,j*40,40,40);            ctx.strokeRect(i*40,j*40,40,40);            if(this.maps[j][i]==1){//方格已經有填充內容                ctx.save();                ctx.lineWidth=4;                ctx.fillStyle='hsla(200,100%,50%,.5)';                ctx.strokeStyle='hsla(200,100%,50%,.9)';                ctx.fillRect(i*40,j*40,40,40);                ctx.strokeRect(i*40+2,j*40+2,38,38);                ctx.restore();            }        }    }    //邊框    ctx.lineWidth=4;    ctx.strokeStyle='hsla(0,100%,0%,.3)';    ctx.moveTo(0,0);    ctx.lineTo(0,20*40);    ctx.lineTo(12*40,20*40);    ctx.lineTo(12*40,0);    ctx.stroke();    ctx.restore();

方塊的實現

游戲中用到以下 7 種圖形

canvas,俄羅斯方塊

結合上面介紹的坐標系,數組 [x1, y1, x2, y2, x3, y3, x4, y4] 就是上面圖形中4個點坐標的數據表現形式,7 種圖形的坐標分別如下:

var Arr = [[4,0,4,1,5,1,6,1],[4,1,5,1,6,1,6,0],[4,0,5,0,5,1,6,1],[4,1,5,0,5,1,6,0],[5,0,4,1,5,1,6,1],[4,0,5,0,6,0,7,0],[5,0,6,0,5,1,6,1]];

方塊的移動,遍歷整個數組,加上位移向量就行,非常簡單

class Shape {    constructor(m){        this.m = Object.assign([],m);    }    move(x,y){ // 位移        var m = this.m,            l = m.length;        y = y||0;        for (var i=0;i<l;i=i+2){            m[i]+=x;            m[i+1]+=y;        }        return this;    }

方塊的旋轉,俄羅斯方塊里面方塊除了左右和上下運動,還會旋轉,不是嗎?稍微思考下就知道,這不過就是矩陣變換而已,也就是每次圖形繞中心點旋轉90度。我這里用數組第三個點作為圖形變換的中心點,當然這樣處理不夠完善。

class Shape {    transform(){//二維矩陣變換        var m =this.m,            l = m.length,            c = Math.ceil(l/2),            x = m[c],            y = m[c+1],            cos = Math.cos(Math.PI/180 * 90),            sin = Math.sin(Math.PI/180 * 90);        for (var i=0;i<l;i=i+2){            if(i == c) continue;            var mx = m[i]- x,                my = m[i+1] - y,                nx = mx*cos - my*sin,                ny = my*cos + mx*sin;            m[i]=x+nx;            m[i+1]=y+ny;        }        return this;        }

邊界條件

主要包括如下三個方面

  • 方塊位置不能超出界面的判斷;
  • 方塊到達底部或放置完成的判斷;
  • 游戲結束的判斷。

遍歷數組 (1)任意一個點y坐標為19時表示到達了底部;(2)獲取該坐標的y+1位置在maps的信息,如果為1表示已經填充。這兩種情況下,運動方塊的周期結束,將該方塊的坐標填充到maps對應的數組里面即可。

如果坐標的y+1已經有填充,同時當前坐標小于1,即已經在界面的頂部了,那么表示游戲結束。

var isEnd = false,isOver=false,x,y;for(var i=0,sl=that.shape.m.length;i<sl;i=i+2){    x=that.shape.m[i];    y=that.shape.m[i+1];    if(y >= 19){ // 到了底部        isEnd = true;break;    }    if(that.maps[y+1][x]==1){ // y+1位置已經填充        isEnd = true;        if(y <= 1){isOver=true;} // 游戲結束        break;    }}

方塊運動周期結束時檢測每一層是否滿格,以及滿格后的處理。某項數組全部元素都為1則表示已經滿格,那么刪除該項數組,同時列表頭再壓入一項每個元素都為0的數組即可。

checkPoint(){    var that = this,        maps = that.maps;    for(var i=0,l=maps.length;i<l;i++){        if(Math.min.apply(null,maps[i]) == 1){// 表示該層已經滿格            that.maps.splice(i,1);            that.score+=10; // 增加分數            that.maps.unshift([0,0,0,0,0,0,0,0,0,0,0,0]);        }    }    return this;}

綁定事件

主要就是綁定keydown事件,要注意的是左移和右移事件包括了邊界判斷

bindEvent(){    var that = this;    document.addEventListener('keydown',function(e){        switch(e.keyCode){            case 13:        //enter                cancelAnimationFrame(that.timer);                that.init().update();            break;            case 80:        //p                that.pause = !that.pause;                break;              case 40:        //down                that.d = 0.5;                break;            case 37:        //left                var over = false,                    maps = that.maps,                    shape = that.shape,                    m = shape.m;                for(var i=0,l=m.length;i<l;i=i+2){                    if(m[i]<=0 || maps[m[i+1]][m[i]-1] == 1){                        over = true;break;                    }                }                if(!over) shape.move(-1,0);                break;            case 39:        //right                var over = false,                    shape = that.shape,                    maps = that.maps,                    m = shape.m;                for(var i=0,l=m.length;i<l;i=i+2){                    if(m[i]>=11 || maps[m[i+1]][m[i]+1] == 1){                        over = true;break;                    }                }                if(!over) shape.move(1,0);                break;            case 32:        //space                that.shape.transform();                break;        }    },false);}

總結

這里面實現了俄羅斯方塊的最基本功能,還有關卡等功能點并沒有實現,同時該demo仍然有不完善的地方需要修正。

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


注:相關教程知識閱讀請移步到HTML教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品一区二区三区在线播放| 久久精品国产亚洲| 国产ts人妖一区二区三区| 久久精品91久久久久久再现| 欧美人在线观看| 国产精品扒开腿做爽爽爽的视频| 原创国产精品91| 久久久亚洲福利精品午夜| 亚洲毛片在线观看.| 国产精品av网站| 亚洲精品国产综合久久| 国产日韩欧美综合| 久久露脸国产精品| 国产精品久久久久久婷婷天堂| 欧美精品成人91久久久久久久| 亚洲精品一区二区三区婷婷月| 久久久久久久久91| 欧美综合一区第一页| 亚洲老头老太hd| 亚洲美女av在线播放| 日韩在线激情视频| 在线电影欧美日韩一区二区私密| 欧美一级片在线播放| 日韩极品精品视频免费观看| 国产福利精品视频| 久久影视电视剧免费网站清宫辞电视| 国产成人福利视频| 亚洲欧洲一区二区三区在线观看| 欧美午夜精品久久久久久人妖| 在线一区二区日韩| www.日韩.com| 亚洲最大的网站| 日韩精品在线观看网站| 日本久久中文字幕| 国产成+人+综合+亚洲欧美丁香花| 欧美www视频在线观看| 庆余年2免费日韩剧观看大牛| 91精品国产自产在线| 北条麻妃久久精品| 亚洲一区国产精品| 国产精品va在线播放| 欧美激情亚洲另类| 欧美与欧洲交xxxx免费观看| 成人妇女免费播放久久久| 青青久久av北条麻妃海外网| 国内伊人久久久久久网站视频| 自拍偷拍亚洲区| 国产97免费视| 国产91在线视频| 91青草视频久久| 精品毛片网大全| 久久精品视频网站| 欧美精品在线视频观看| 亚洲aa在线观看| 欧美大片va欧美在线播放| 亚洲精品女av网站| 国产精品白丝av嫩草影院| 国内精久久久久久久久久人| 永久免费看mv网站入口亚洲| 国产精品第一区| 在线视频日本亚洲性| 欧美性jizz18性欧美| 在线激情影院一区| 欧美—级a级欧美特级ar全黄| 国产午夜精品全部视频在线播放| 2019av中文字幕| 日韩av免费在线看| 亚洲韩国青草视频| 精品亚洲永久免费精品| 韩国v欧美v日本v亚洲| 美日韩精品视频免费看| 神马国产精品影院av| 狠狠躁天天躁日日躁欧美| 亚洲国产一区二区三区四区| 91高潮在线观看| 日韩av在线天堂网| 欧美大肥婆大肥bbbbb| 日韩中文娱乐网| 综合国产在线视频| www日韩中文字幕在线看| 69精品小视频| 国产精品中文久久久久久久| 国产精品视频不卡| 日韩精品视频免费在线观看| 欧洲成人免费视频| 久久99久久99精品免观看粉嫩| 亚洲欧洲第一视频| 日韩美女免费观看| 国产精品视频免费在线观看| 日韩在线一区二区三区免费视频| 亚洲欧美国产日韩天堂区| 久久这里只有精品视频首页| 欧美黄色三级网站| 欧美激情视频网址| 欧美黄网免费在线观看| 国产精品扒开腿做爽爽爽男男| 在线视频欧美日韩精品| 成人免费看黄网站| 欧洲成人午夜免费大片| 久久久97精品| 欧美自拍大量在线观看| 日韩免费高清在线观看| 日韩在线播放av| 国产日韩欧美中文| 久久精品影视伊人网| 欧美大全免费观看电视剧大泉洋| 992tv成人免费影院| 欧美日本在线视频中文字字幕| 久久免费精品日本久久中文字幕| 成人黄色中文字幕| 国产91网红主播在线观看| 91天堂在线观看| 亚洲xxxxx| 欧美激情视频一区二区三区不卡| 国产日韩欧美在线观看| 伊人精品在线观看| 国产做受高潮69| 伊人亚洲福利一区二区三区| 久久久999精品免费| 精品久久国产精品| 亚洲区中文字幕| 成人国产精品色哟哟| 欧美精品久久久久a| 红桃视频成人在线观看| 中文字幕亚洲欧美一区二区三区| 日韩在线视频线视频免费网站| 亚洲国产91色在线| 成人一区二区电影| 久久国产视频网站| 一区二区成人精品| 久久久久久久久久国产| 久久色在线播放| 亚洲图片在线综合| 2019最新中文字幕| 亚洲影影院av| 亚州成人av在线| 亚洲精品福利在线观看| 欧美xxxx14xxxxx性爽| 国自产精品手机在线观看视频| 午夜精品在线观看| 亚洲精品视频网上网址在线观看| 国产精品人人做人人爽| 欧美大片va欧美在线播放| 97在线看免费观看视频在线观看| 日韩精品一区二区三区第95| 久久精品亚洲国产| 亚洲区在线播放| 欧美高清在线视频观看不卡| 麻豆乱码国产一区二区三区| 中文字幕一区日韩电影| 伦伦影院午夜日韩欧美限制| 亚洲3p在线观看| 精品亚洲一区二区三区在线播放| 国产精品久久久久久久久久久久久| 久久99精品久久久久久青青91| 精品动漫一区二区三区| 欧美激情亚洲一区| 97精品视频在线| 97国产在线观看| 欧美成在线观看| 国产精品精品视频一区二区三区| 亚洲免费视频一区二区| 欧美日韩精品国产| 国产精品福利久久久|