1. 程式人生 > >30分鐘,學會經典小遊戲編程!

30分鐘,學會經典小遊戲編程!

保存 ota 參考點 最大 編程 經典 通過 屬性 可能

在80後、90後的兒時記憶裏,俄羅斯方塊是必備的消遣小遊戲,它的玩法非常簡單基本大家都懂,但如何用編程語言開發一款兒時同款「俄羅斯方塊」,恐怕知道的同學就很少啦。

位置掩碼和旋轉掩碼

俄羅斯方塊遊戲中的格子一般是10列20行(10*20),我們稱之為世界地圖。

技術分享圖片

一般都是這種豎屏的界面

10*20的空間是用來盛放方塊的,當方塊落定之後位置便不能再改變。這個時候它會被保存到地圖的狀態中,我們給地圖狀態設計一個二維的數組。

方塊有7種樣式組成,最大的長寬是4個方格,為了在邏輯上比較好的處理所有類型的方塊,我們構建了一個4x4的邏輯區域,用來統一描述所有類型的方塊,包括顯示、旋轉等。這一區域就成為了它自身的空間整體,而方塊被放到世界地圖中時,也是以這樣的整體加入進去的。

我們給方塊定義了四種屬性,分別是方向、顏色、種類以及在世界地圖中的坐標。

方塊可以做旋轉,每經過四次旋轉便會回到原始的狀態,分別用0123來表示方塊的四個方向,新產生的方塊設定的是默認方向。

下圖中的數值代表它在自己的空間內,哪些格子是有方塊的,哪些是沒有的。這是一個二進制的16位的顯示掩碼,0x4444代表的就是第一行第三列,第二行的第三列,第三行的第三列和第四行的第三列。

技術分享圖片

旋轉掩碼是用一個16bit的數據表示的,每個旋轉掩碼後面跟著的是一個16bit的顯示掩碼。

我們以S型方塊作為參考來介紹,方向為零的時候它占據第一行的第二列第三列,第二行的第四列第三列,當它做一次旋轉,方向由0到1這個過程中,它的旋轉是會掃過這些位置,變成方向1的狀態。在旋轉過程中,如果它掃過的位置有其他方塊占住,那麽它便不能旋轉。

技術分享圖片

還有,如果方塊到達邊緣的時候,旋轉時超出了世界地圖的範圍,也是失敗的,會繼續維持現在這種狀態。

旋轉掩碼和顯示掩碼組合在一起,旋轉掩碼的意義是,當前方向值下的方塊,旋轉到下一個方向值的時候,需要參考的障礙區域有哪些,以上就是位置掩碼以及旋轉掩碼的介紹。

遊戲中的主要邏輯

接下來我們來看下遊戲中的主要邏輯判斷。

移動邏輯

遊戲中產生的方塊,在產生之後,做周期性的下落運動。

同一時刻地圖中只會有一個方塊處於活動狀態,可以在地圖中做移動、旋轉等操作,方塊每次自由下落都會做一個下落判斷,判斷是否已經觸底。

觸底指的是,方塊不能再往下移動,導致方塊不能再往下移動的原因有2種,第一種是方塊的下邊緣已經在世界地圖的邊緣;第二種是方塊再往下更新的位置,被其他已經落定的方塊占據了。

技術分享圖片

如圖上代碼所示,方塊移動的位置被其他方塊所占據

方塊觸底之後,狀態就由活動狀態切換到了落定狀態。此時方塊的顯示掩碼中標註的所有可顯示的塊,都將會寫入地圖的狀態中,以用來表明,這些塊已經被占據了,寫入地圖狀態中的值有兩項屬性:哪些塊被占據了,已經被占據的塊的顏色值。

假定方塊當前的坐標是(x1,y2),從方塊的當前移動方向中,我們可以得到方塊等待判斷是否可以移動過去的更新坐標(x2, y2)。

例如,方塊向左移動,則:x2 = x1 - 1, y2 = y1;方塊向右移動,則:x2 = x1 + 1, y2 =y1;方塊向下移動,則:x2 = x1, y2 = y1 + 1;

技術分享圖片

那怎麽判斷方塊是否可以移動成功呢?

根據方塊的類型以及當前的方向值,從掩碼表中可以拿到方塊當前的顯示掩碼,方塊是否能放置到新位置,只需要判斷顯示掩碼中標明需要顯示出來的位置,是否已經有其他方塊占據,掩碼中所有需要顯示出來的位置,只要有一個位置被其他方塊占據,本次移動判斷失敗,方塊維持原有坐標

旋轉邏輯

能夠旋轉涉及到一個方塊是否改變它的方向,x、y是方塊在世界地圖中的坐標,block是它的狀態值。

我們取它的種類、方向這兩個屬性,在4×4的空間裏,計算出每一格對應到世界中的坐標。

“isBoxRotateMaskEmpty”這個代表什麽意思呢?這是旋轉掩碼在旋轉過程中要參照的點,方塊旋轉掃過的點,以及它落定之後的這幾個點,這些點就是它的旋轉掩碼。

技術分享圖片

轉寫掩碼值用一個七行四列的數組來保存,分別對應七種方塊樣式以及四個方向對應的值。它的高16位是旋轉掩碼,低16位是顯示掩碼。

技術分享圖片

方塊的掩碼表

方塊是否能夠旋轉,先要看它的旋轉掩碼裏面是為空,掩碼為空則可以旋轉,旋轉完之後,需要判斷方塊新的坐標是否還在世界地圖裏,如果它超出邊緣超出底線,那肯定是旋轉不了的。

還有就是判斷當前格子在世界地圖中是否被其他的方塊給占了,如果被占了的話,也是旋轉不了的,這就是基本的旋轉判定邏輯。

得分邏輯

方塊落定之後,根據方塊落定是的邏輯坐標,從上往下依次遍歷地圖中的4行狀態值,當某一行的所有地圖塊的狀態都是被占據狀態,該行被判定為得分行,得分行會被消掉,當消完所有的得分行之後,得分行上方的所有未得分行,依次向下平移。

我們控制遊戲難度的時候也是以這個為參考,玩家獲得的分數越多,遊戲難度越大。

我們可以通過修改方塊出現的時間間隔,以及下落速度,來控制整個遊戲的難度。

當玩家拿的分數越多,每消除一行的等級就會加一,分數是遞增100,方塊下降的速度是通過5的取模方式從1秒裏面去扣,最小值是0.6秒。

技術分享圖片

如果某一行格子只要有一個空著的話,消除便失敗。某一行的方塊全部被消掉之後,上面的方塊會向下平移,對應的行數需要刷新。

這便是關於得分的判斷邏輯 。

遊戲流程圖

最後再來看下整個遊戲玩的流程圖。

技術分享圖片

遊戲的核心邏輯是時間間隔,玩家點開始之後,每隔一段時間會調度一次,如果遊戲沒有結束,判斷當前是屬於暫停狀態,沒有說暫停的話,就做一個moveBlock。

當然,moveBlock有可能是玩家點了操縱的方向鍵,如果沒點的話直接就返回了。緊接著處理方塊的下落過程,判斷它落定的時候是否結束了。

沒有結束暫停的話,就處理移動,移動處理完之後,再去處理下落,如果剛好時間間隔已經到了,那它就會往下落一次,往下落的話有可能成功,也有可能失敗。

判斷結束後會出現遊戲結束界面,可以選擇是否重來一次,如果再來一次便會做一次重置。

這裏需要做一個關於世界地圖的補充說明,這裏補充了一個地圖的坐標系,遊戲地圖的坐標系X軸沿著水平方向向右,Y軸是沿著垂直方向向下增長,坐標系的原點是在左上角。

方塊在邏輯空間中的坐標,是以左上角為參考點的,方塊的坐標隨著而改變。

30分鐘,學會經典小遊戲編程!