亚洲最大看欧美片,亚洲图揄拍自拍另类图片,欧美精品v国产精品v呦,日本在线精品视频免费

  • 站長資訊網(wǎng)
    最全最豐富的資訊網(wǎng)站

    動手打造html5俄羅斯方塊的(圖文)

    在正文開始之前還要啰嗦一下,標(biāo)題中所謂自給自足,是在沒有參考任何設(shè)計思路的前提下去開發(fā)這游戲的,你可能會不解,如果參考優(yōu)秀的思路,豈不是事半功倍,當(dāng)然,參考與不參考都有利,我只說不參考的利,當(dāng)我煞費(fèi)苦心、歷經(jīng)數(shù)十個BUG修改,終于完成一件作品的時候,我可以很自豪地對別人說:“看,我開發(fā)的游戲!”當(dāng)然,創(chuàng)意不是我的,但這并不影響自己那份“虛榮心”,為一款經(jīng)典的游戲賦予自我的理解,并將它融入游戲中,豈不是一件有意思的事,而且,回過頭來再看一看別人的思路,有時會拍案而起,“這個我當(dāng)初怎么就沒想到呢?”,“原來這個問題可以這樣解決”,“這個設(shè)計思路比我的思路好多了!”,諸如此類總比開始就直接看別人的思路而阻塞自己的思考要強(qiáng)得多,對吧?

    好叻,正文開始~

    想先看效果的,先跳轉(zhuǎn)試玩一下吧!

    俄羅斯方塊,主游戲界面應(yīng)該由一個一個的方塊組成,如下圖,當(dāng)然成品里面這些網(wǎng)格是看不到的,這里只是助于理解,主界面尺寸為400×500,設(shè)定每塊磚(網(wǎng)格)的尺寸為20×20,則每行有20個磚塊,每列有25個磚塊。相關(guān)代碼:

    brickWidth = 20,    //磚塊大小  width = 400, height = 500;  //畫布寬高,20X25

    動手打造html5俄羅斯方塊的(圖文)

    提到主界面的網(wǎng)格,就要提到一個非常重要的變量了,它就是BOARD,一個二維數(shù)組,形象化地說其尺寸是20×26,存儲的值為0或1,0表示該位置沒有磚塊,1表示該位置有磚塊,在接下來的一些判定中有重要作用,游戲細(xì)心的同學(xué)可能發(fā)現(xiàn),為什么是20×26,而不是對應(yīng)主界面網(wǎng)格的20×25,我在一開始的時候也是設(shè)定為20×25的,后來注意到如果加一行而且這一行的值都為1就可以很容易判斷磚塊是否到觸及主界面底部了。相關(guān)代碼:

    // 初始化BOARD,注意縱向有26個,最后一排用來判斷是否觸底  for(i=0;i<20;i++){      BOARD[i] = [];      for(j=0;j<26;j++) {          if(j==25) {              BOARD[i][j] = 1          } else {              BOARD[i][j] = 0;          }      }  }

    動手打造html5俄羅斯方塊的(圖文)

    接下來看由4個磚塊組成的“形狀”,有五種,為了好描述,我把它們?yōu)閯e命名,Tian(田),Chu(鋤頭),Tu(凸起來),Thunder(閃電),Line(一橫),哈哈有趣的名字,原諒我沒找到它們的英文名字吧。

    首先定義一個磚頭類Brick:

    function Brick() { }

    其下有幾個原型變量和方法:

    Brick.prototype.embattle = null;    //磚塊的布局(需重載)  Brick.prototype.isOverturn = 0; //是否翻轉(zhuǎn)  Brick.prototype.originX = 9;    //磚頭的繪制起點(diǎn)X  Brick.prototype.originY = -3;    //磚頭的繪制起點(diǎn)Y  Brick.prototype.direction = 0;  //磚頭朝向  Brick.prototype.autoMoveTimer = null;   //自動移動計時器  Brick.prototype.draw = function() { …… }    //畫磚塊的方法  Brick.prototype.move = function(moveX, moveY) { …… }    //移動的方法  Brick.prototype.autoMove = function() { …… }    //自動移動的方法  Brick.prototype.change = function() { …… }    //變換磚頭朝向

    Brick的子類有:Tian,Chu,Tu,Thunder,Line五個,每個子類中都重載Brick的embattle變量,embattle是什么,英譯中的意思是布陣,這個陣是個什么陣呢?首先,同學(xué)們要理解我的思路,用Tu的embattle來舉例,其代碼如下:

    this.embattle = [      [ [0,4,5,8], [1,4,5,6], [1,4,5,9], [0,1,2,5] ],  //布局表為4X4表格,數(shù)字為磚頭位置      [ [0,4,5,8], [1,4,5,6], [1,4,5,9], [0,1,2,5] ]   //次行為翻轉(zhuǎn)的情況];

    embattle是一個三維數(shù)組,第一維是是否翻轉(zhuǎn)isOverturn(形象來說就像圖片的水平翻轉(zhuǎn)),第二維是方向direction(上左下右),第三維是形狀的4個磚塊分布情況,我把每個新形狀對象定義在一個4×4的陣中,例如,Tu的this.embattle[0][0]為[0,4,5,8],數(shù)字即該磚塊的所在位置,如下圖:

    動手打造html5俄羅斯方塊的(圖文)

    所以要確定一個形狀的位置和樣子,需要isOverturn確定是否翻轉(zhuǎn),需要direction確定其方向,需要originX和originY確定“陣”的位置。

    接下來,分別解釋Brick的4個原型方法。

    Brick.prototype.draw

    ctx.fillStyle = 'rgb('+Math.floor(Math.random()*256)+','+Math.floor(Math.random()*256)+',  '+Math.floor(Math.random()*256)+')';  for(i=0;i<4;i++) {      tmp = this.embattle[this.isOverturn][this.direction][i];      ctx.fillRect((this.originX+tmp%4)*brickWidth, (this.originY+Math.floor(tmp/4))*brickWidth, brickWidth, brickWidth);      ctx.strokeRect((this.originX+tmp%4)*brickWidth+1, (this.originY+Math.floor(tmp/4))*brickWidth+1, brickWidth-2, brickWidth-2);   //注意+1和減2  }

    有上面說的確定形狀的位置和樣子的方法,之后就是純粹canvas畫圖,4個磚塊一個一個地畫,不要看代碼很長其實(shí)就是那么一點(diǎn)點(diǎn),originX、originY和磚塊在陣中的位置就可以確定畫磚塊的起點(diǎn)了。注意到代碼的注釋了沒有,畫邊框的時候,它是從起點(diǎn)向外面畫的,就像我把一個塑料袋套在另一個塑料袋的外面,為了以后的清除的方便且不影響其他的磚塊,把邊框畫進(jìn)fillRect的領(lǐng)土,就像我現(xiàn)在把這個塑料袋不套在外面而是放進(jìn)這另一個塑料袋里面一樣,就這個意思。

    Brick.prototype.move

    這是最長的一個了,移動的時候,moveX和moveY表示橫縱的增量,沒有同時非0的情況(這是人為的設(shè)定,要么橫向移動要么縱向移動),當(dāng)然要判斷即將移動到的位置是否違規(guī):

    橫向:

    如果陣貼靠主界面左側(cè)則不能向左移即moveX不能為-1

    (this.originX==0 && moveX==-1)

    判斷右邊時比較麻煩,因?yàn)椴荒苤苯佑藐噥砼袛嗍欠褓N靠右側(cè)(看前面的圖就知道陣的右邊和下邊可能沒有磚塊的),這時要一個個地判斷4個磚塊是否有至少有一個在最右,這時不能向右移動

    || (this.originX+tmp[0]%4==19 && moveX==1)  || (this.originX+tmp[1]%4==19 && moveX==1)  || (this.originX+tmp[2]%4==19 && moveX==1)  || (this.originX+tmp[3]%4==19 && moveX==1)

    最后還要判斷即將到達(dá)的位置是否已經(jīng)有磚塊了。

    || (BOARD[this.originX+tmp[0]%4+moveX][this.originY+Math.floor(tmp[0]/4)]==1)  || (BOARD[this.originX+tmp[1]%4+moveX][this.originY+Math.floor(tmp[1]/4)]==1)  || (BOARD[this.originX+tmp[2]%4+moveX][this.originY+Math.floor(tmp[2]/4)]==1)  || (BOARD[this.originX+tmp[3]%4+moveX][this.originY+Math.floor(tmp[3]/4)]==1)

    縱向:

    即將到達(dá)的位置是否已經(jīng)有磚塊了,注意到下面的代碼的&& moveX==0,原來是沒有的,后來發(fā)現(xiàn)每次磚塊怎么剛剛靠上下面堆著的磚塊就不能再移動了,原來橫向移動的時候也進(jìn)行了這個判斷,即剛剛靠上下面的磚塊,如果這時想左右移動,但下方有磚塊,但是問題來了,下面有沒有磚塊跟我左右移動有什么關(guān)系呢?是吧。

    if((as==1 || bs==1 || cs==1 || ds==1) && moveX==0) { …… }

    縱向終止判斷里面主要做了幾件事:清除autoMoveTimer,設(shè)置BOARD在該形狀當(dāng)前位置的值為1,有可以消除的整行就消除,加分改分,判斷勝利/失敗,刪除當(dāng)前對象,召喚下一個形狀。

    橫縱都沒違規(guī)時:

    這時,把該形狀前一個位置的磚塊清除,更新originX和originY,再畫出來。

    for(i=0;i<4;i++) {      tmp = this.embattle[this.isOverturn][this.direction][i];      ctx.clearRect((this.originX+tmp%4)*brickWidth, (this.originY+Math.floor(tmp/4))*brickWidth, brickWidth, brickWidth);  }  this.originX += moveX;  this.originY += moveY;  this.draw();

    Brick.prototype.autoMove

    只做一件事,設(shè)置計時器,定時向下移動。

    var status, self = this;this.autoMoveTimer = setInterval(function() {      status = self.move(0,1);  },speed);

    Brick.prototype.change

    改變形狀的朝向,很好辦啊,不是有embattle數(shù)組了嗎?當(dāng)然沒有那么簡單,不只是換個數(shù)組這么簡單。要考慮改變方向之后占用的位置是否已經(jīng)有磚塊了,如果形狀是貼著主界面右邊界就更糟糕了,比如原來是豎著的Line,改變其方向變?yōu)闄M,占用陣的0、1、2、3,如果Line貼著右邊界,originX為19,變?yōu)闄M向,占用陣的0、1、2、3,后面三個磚塊已經(jīng)溢出了主界面。

    動手打造html5俄羅斯方塊的(圖文)

    解決方案是:如果有越界的磚塊就把陣往左挪一挪,直到不再越界。

    while(ox+tmp[0]%4 > 19 || ox+tmp[1]%4 > 19 || ox+tmp[2]%4 > 19 || ox+tmp[3]%4 > 19) {      ox -= 1;  }

    最后,如果都沒事,就可以清除原位置,畫出改變方向之后的形狀了。

    并不是太完美,因?yàn)橛行┛ㄎ坏那闆r沒考慮進(jìn)來,什么是卡位,看下圖,你知道Line實(shí)例調(diào)用change方法的結(jié)果是什么了嗎?事實(shí)上,它不應(yīng)該成功改變方向的,對吧?還有其他一些卡位的情況。

    動手打造html5俄羅斯方塊的(圖文)

    Brick的4個原型方法就介紹到這里了?,F(xiàn)在如果我要在右邊的信息界面顯示下一個的形狀,最直接的方法就是,通過該形狀的構(gòu)造函數(shù)實(shí)例化一個對象,為防止其自動調(diào)用autoMove,為構(gòu)造函數(shù)添加了isModel來判斷是不是供提示用的。

    還有按鍵事件監(jiān)聽、NextBrick函數(shù)和deleteObj自己看看吧,很容易看懂,游戲的入口就是NextBrick函數(shù)。

    還有就是,我無法確定deleteObj是否真的成功讓GC把對象回收了。

    還有就是,我本想增加關(guān)卡功能,因?yàn)榭梢宰杂稍O(shè)置速度(speed變量),就把這功能放一放了。

    贊(0)
    分享到: 更多 (0)
    網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號