前言
好友沒有寫部落格啦。沒啥可說的,就是因為懶。今後幾篇為大家帶來一個俄羅斯方塊遊戲的實現,網上有很多類似部落格,大致原理一致,我自己想的思路也沒有多大的偏差。不過我稍微加了一些聯機元素在裡面。先放一張效果圖吧,我不會做介面,就醬紫了,不改了。
主要功能
- 單機版的俄羅斯方塊遊戲體驗:即俄羅斯方塊遊戲的基礎實現,方塊定義,方塊旋轉等
- 聯機兩人(或多人)一起玩遊戲,增加競技樂趣
- 類似遊戲大廳的功能,玩家可選擇房間進入
- 訊息推送功能,聯機必備
- 方塊介面由canvas實現
開發準備
首先我們要開發一個聯機遊戲,那麼訊息推送是必不可少的,由於我只會一丟丟的WebSocket,那我只好用它了。另外這次還是使用了 tio 框架。tio-http-server tio-ws-server 都有用到。第二,就是俄羅斯方塊的遊戲分析。其實遊戲名稱裡的”方塊“就能給我們帶來思路。整個遊戲介面就是一個佈滿200(10 * 20)個座標點的一個陣列。下面畫一個圖,方便大家瞭解。
開發參考圖:
上圖中分別用不同的座標組合表示出相應的形狀。那麼我們的方塊還有旋轉功能,這就要考慮到旋轉方向的問題,根據旋轉方向和當前狀態是否可以旋轉來進行旋轉操作。
請看下圖:
我以這種型別的方塊為例子講解一下旋轉過程。首先,我定義了一個規則,就是一個方塊由四個座標點組成,然後他們的排序規則為從上到下,從左到右。如上圖中標註出的序號。那麼當我們對該方塊做”右轉“操作時候。最關鍵的,我們要找到第一個點在哪裡,那麼後續就好說了。看一下右轉的程式碼:
case UP:
//第一個點不變
// points[0] = points[0];
//第二個點在第一個點下面
points[1] = points[0].down();
//第三個點在第一個點右邊
points[2] = points[1].right();
//第四個點在二個點下面
points[3] = points[1].down();
blockStatus = BlockStatus.RIGHT;
break;
所以,旋轉程式碼就變得很簡單了,先確定第一個點,然後根據圖形規則,分別找到其他的點。上述程式碼中的down,right等方法,其實就是一個 x+-1 或者 y+-1的操作。其他旋轉同理,不過要注意好中心點的位置,否則會出現轉了幾圈之後,方塊不走直線的情況。
方塊構造好並且可以旋轉之後,下面要做的就是細活了。第一:方塊什麼時候停止,第二:方塊什麼時候消除,消除之後怎麼處理其他方塊。第三:方塊什麼時候不能旋轉。
方塊和地圖的關係
下面我一一解答上節遺留的問題。
方塊停止的條件:1.碰到地圖最下邊緣 2.方塊碰到其他的方塊。 第一個很好理解,方塊到底下了,就要停下。(一個方塊中四個點任意一個點碰到地圖底部都會停下)
//一個點的Y值 = 地圖界限值
private static boolean onBottom(Point point){
return point.getY() == GameMap.MAX_RANGE_HEIGHT - 1;
}
第二個,方塊碰到其他的方塊,就是說,比如遊戲中已經積累了很多方塊,那麼新的方塊要落到其他方塊之上,所以判斷一下方塊下一步的移動軌跡是否與已經停止的方塊的點有重合,如果有重合,那麼方塊不能繼續移動。不管是向下、向左、向右、旋轉,都用此方法判斷。
方塊消除的條件:這個就很簡單了,當達到滿行之後進行消除。如下圖所示:
黃色區域需要消除掉,然後處理加分邏輯。消除掉之後呢,需要將其他的點(Y值 < 當前消除行的Y值)的Y值 + 相對應的行數。為什麼說是相對應的行數呢?因為有的點下方只消除了一行,有的點下方消除了兩行或者多行,那麼根據行數來改變點的Y值。上圖中,黃色行以上的點的Y值都需要加1.
方塊的操作
方塊有上(變形)下(加速)左(左移)右(右移)四種操作。變形和左右移就是一些點的座標替換。變形已經在上文中講過了,左右移和加速其實道理一樣。就是一個塊中的所有點的X+-1或者Y+1.
操作響應
操作之後,使用者要有回饋,否則,伺服器資料變化了,使用者得不到回饋,就會出現類似網遊中的卡頓現象,或者其他bug,體驗非常不好。響應流程後續在講。
遊戲的執行
通過ScheduledExecutorService 的 scheduleWithFixedDelay 方法達到週期重新整理遊戲介面的效果,同樣,服務端每重新整理一次,如果使用者不做任何操作的話,方塊會自動向下移動一格。然後推送到使用者端。
總結
其實俄羅斯方塊的實現原理並不難,只是需要考慮的細節比較多,而且根據我的程式碼執行情況,還時不時出現bug。。。我猜測和多執行緒有關。唉,多執行緒,併發,非同步等是我的弱項,我還得在研究研究。不知道這麼講解大家能否看得懂呢?不懂的或者有其他疑問的可以留言。拜拜~~