gamebuino制作的小游戏之2048代码分析 loop部分
gb.update
返回true并以固定頻率(默認(rèn)每秒20次)更新所有內(nèi)容(顯示、聲音、電池監(jiān)視器等)。boolean:如果從上一幀開始的時(shí)間足夠長(zhǎng)(每秒20幀=每幀50毫秒),則為真。
while(1){if(gb.update()){//your game here} }下面來看一看DrawBoard函數(shù)
void DrawBoard() {ResetDisplay(); //復(fù)位顯示參見上一篇博客for( int y = 0; y < 4; y++ ) {for( int x = 0; x < 4; x++ ) {gb.display.drawBitmap(x * 13, y * 12, TileSprites[Board2048[y * 4 + x]]);}} }?
int Board2048[16]; const byte *TileSprites[] = { Tile_0,Tile_2,Tile_4,Tile_8,Tile_16,Tile_32,Tile_64,Tile_128,Tile_256,Tile_512,Tile_1024,Tile_2048,Tile_4096,Tile_8192,Tile_16384,Tile_32768,Tile_65536,Tile_131072 };TileSprites[]里是0-131072的24*24的二進(jìn)制字模庫(2048居然可以玩到131072,我的亂點(diǎn)巔峰也就在1024),Board2048長(zhǎng)為16的數(shù)組,用一個(gè)雙重循環(huán)依次打印1-131072? 16個(gè)位圖
bool ButtonPressed = false;if(gb.buttons.pressed(BTN_LEFT)) {ButtonPressed = true;RotateClockwise();RotateClockwise();MoveRight(true);RotateClockwise();RotateClockwise();}
gb.buttons.pressed
用于知道給定按鈕何時(shí)按下的函數(shù)
gb.buttons.pressed(button);- button (byte):按鍵標(biāo)識(shí)符可選參數(shù)BTN_A, BTN_B, BTN_C, BTN_UP, BTN_RIGHT, BTN_DOWN, BTN_LEFT
- boolean: 返回布爾值如果按鍵按下為true
下面看一看RotateClockwise()函數(shù),額暫時(shí)看不懂(RotArray里的好像是4*4矩陣?yán)锏牡谝涣小⒌诙羞@樣子)
void RotateClockwise() {for( int x = 0; x < 16; x++ ) {TempBoard[x] = Board2048[x];}for( int x = 0; x < 16; x++ ) {Board2048[x] = TempBoard[RotArray[x]];} } int TempBoard[16]; int RotArray[] = { 12,8,4,0, 13,9,5,1, 14,10,6,2, 15,11,7,3 };第二個(gè)for語句大概就是執(zhí)行這個(gè)變化....暫時(shí)不太懂啥意思沒事繼續(xù)往下,總能參透
再看一下MoveRight()函數(shù)
void MoveRight(bool Animate) {CompressRight();for( int x = 0; x < 16; x += 4 ) {for( int y = 3; y >= 1; y-- ) {if(Board2048[x + y] == Board2048[x + y - 1] && Board2048[x + y] != 0) {Board2048[x + y] += 1;long MergeScore = 1L;for( int z = 0; z < Board2048[x + y]; z++ ) {MergeScore *= 2;}if (Animate) gameState.score += MergeScore;Board2048[x + y - 1] = 0;}}}if (Animate) {if (gameState.score > gameState.highscore) gameState.highscore = gameState.score;}CompressRight(); }void CompressRight() {for( int x = 0; x < 16; x += 4 ) {int FarthestTile = 4;for( int y = 0; y < 4; y++ ) {if(Board2048[x + y] == 0) FarthestTile = y;}for( int y = 3; y >= 0; y-- ) {if(Board2048[x + y] && y < FarthestTile && FarthestTile < 4) {Board2048[x + FarthestTile] = Board2048[x + y];Board2048[x + y] = 0;FarthestTile -= 1;}}} }FarthestTile字面最深的瓷磚...最里面的那個(gè)小方格?步長(zhǎng)為4的for循環(huán)實(shí)現(xiàn)一行一行掃描,如果Board2048[n]==0,將FartheTile的值設(shè)為對(duì)應(yīng)的列值,這個(gè)FarthestTile的值應(yīng)該是這一行最靠右邊的Board2048[n]==0的列值。再觀察下一個(gè)for循環(huán)if里的內(nèi)容描述的應(yīng)該是這一行找到的FarthestTile左邊的非零值,然后將我們這行的FarthestTile對(duì)應(yīng)的小方塊和這個(gè)非零值小方塊值做一個(gè)互換。腦子不夠畫圖來湊,下圖是四種情況下變化,觀察圖相信大家現(xiàn)在都明白了原來CompressRight函數(shù)就是描述向右壓縮的過程啊
ok,下面繼續(xù)回到MoveRight函數(shù),從每行最右側(cè)開始檢測(cè)左側(cè)相鄰元素是否等值,如果兩個(gè)元素相等,則將右側(cè)的值加1,設(shè)置一個(gè)變量MergeScore為2^Board2048,然后將這次合并的分?jǐn)?shù)加到總分里,并將左側(cè)的值改為0,并判斷更新最高分。
可以將MoveRight函數(shù)理解為向右壓縮合并相同行相同元素,并根據(jù)合并類型更新分?jǐn)?shù)。
if(gb.buttons.pressed(BTN_RIGHT)) {ButtonPressed = true;MoveRight(true);}if(gb.buttons.pressed(BTN_LEFT)) {ButtonPressed = true;RotateClockwise();RotateClockwise();MoveRight(true);RotateClockwise();RotateClockwise();}
等等剛剛那個(gè)函數(shù)是左鍵,這個(gè)函數(shù)是右鍵,但是MoveRight(true)實(shí)現(xiàn)的是向右壓縮的動(dòng)作,看來RotateClockwise();是對(duì)矩陣進(jìn)行了旋轉(zhuǎn)的功能,減少了再寫出MoveLeft,MoveUp,MoveDown的量現(xiàn)在返回去看那個(gè)框圖就明白啦!
加入有一行數(shù)2,2,4,0我要實(shí)現(xiàn)MoveLeft向左壓縮0,4,0,0其實(shí)也就等價(jià)于0,4,2,2MoveRight操作以后0,0,4,0再次翻轉(zhuǎn)。所以我們可以知道為什么有4次RotateClockwise();MoveDown好MoveUp同理構(gòu)造,這里就不展開啦
PopupMessage();int y = 0;bool WinBox = false;int TilesOnBoard = 0;for( int x = 0; x < 16; x++ ) {if (Board2048[x]) TilesOnBoard++;if (Board2048Old[x] == Board2048[x]) y++;if (Board2048[x] == 11 && gameState.winstate == false) {gameState.winstate = true;WinBox = true;}}if (y != 16) {SpawnTile(true);} else if (ButtonPressed) {gb.sound.playCancel();}if (TilesOnBoard == 15 && y != 16) {for( int x = 0; x < 16; x++ ) {TempBoard2[x] = Board2048[x];}? void PopupMessage() {int MaxTile = Board2048[0];for( int x; x < 16; x++ ) {if (MaxTile < Board2048[x]) {MaxTile = Board2048[x];}}for( int x; x < 16; x++ ) {if (MaxTile == Board2048Old[x]) MaxTile = 0;}if (MaxTile >= 3) {gb.popup((const __FlashStringHelper*)pgm_read_word(&newTileStrings[MaxTile-3]),40);} }?const char msg8[] PROGMEM = "8! Good!"; const char msg16[] PROGMEM = "16! Great!"; const char msg32[] PROGMEM = "32! Awesome!"; const char msg64[] PROGMEM = "64! Sweet!"; const char msg128[] PROGMEM = "128! Cool!"; const char msg256[] PROGMEM = "256! Keep it up!"; const char msg512[] PROGMEM = "512! Almost there!"; const char msg1024[] PROGMEM = "1024! One more!"; const char msg2048[] PROGMEM = "2048! You win!"; const char msg4096[] PROGMEM = "4096! Step it up!"; const char msg8192[] PROGMEM = "8192! You're good!"; const char msg16384[] PROGMEM = "16384! Keep playing!"; const char msg32768[] PROGMEM = "32768! Unbelievable!"; const char msg65536[] PROGMEM = "65536! Woohoo!"; const char msg131072[] PROGMEM = "131072! INSANE!!!";const char* const newTileStrings[] PROGMEM = {msg8, msg16, msg32, msg64, msg128, msg256, msg512, msg1024, msg2048, msg4096, msg8192, msg16384, msg32768, msg65536, msg131072};void SpawnTile(bool makeSound) {int RandTile;do {RandTile = random(16);} while(Board2048[RandTile] != 0);for( int x = 0; x < 3; x++ ) {DrawBoard();if (x == 0) gb.display.drawBitmap(RandTile % 4 * 13, RandTile / 4 * 12, NewTile_1);if (x == 1) gb.display.drawBitmap(RandTile % 4 * 13, RandTile / 4 * 12, NewTile_2);if (x == 2) gb.display.drawBitmap(RandTile % 4 * 13, RandTile / 4 * 12, NewTile_3);while(gb.update() == false) {}}if (makeSound) gb.sound.playOK();if(random(10)) {Board2048[RandTile] = 1;} else {Board2048[RandTile] = 2;} }
看PopupMessage()第一個(gè)for循環(huán)找出16個(gè)小方塊里的最大值,啊我想我現(xiàn)在知道了Board2048Old[x]這個(gè)數(shù)組存的是我up、down、left、right操作之前的狀態(tài)信息,Board2048[x]是在這些操作后更新的狀態(tài)信息,每次新的矩陣信息和舊的進(jìn)行對(duì)比如果最大值變更,而且合成的數(shù)字>=8那么就會(huì)gb.popup預(yù)先設(shè)定好的msg
TilesOnBoard顧名思義,用循環(huán)檢測(cè)16個(gè)方格里的值非0的tiles,看到這里....我才明白原來Board2048[x]里放的是2^n的n才對(duì)!而不是2,4,8這樣的值.........Orz哭泣我就說為什么之前合并成功以后是?Board2048[x + y] += 1;原來如此。所以?Board2048[x ] = 11以后就更新gameState.winstate = true;因?yàn)?^11=2048你已經(jīng)贏啦
接下來我們看看?SpawnTile()好了,每次按按鍵的時(shí)候響一下。Newtile_1那幾個(gè)字模,我不想再操作一次逆字模過程還原了,大概就這樣了。其余代碼大同小異也是上述分析的類似。好了明天開始畫瓢,想到啥繼續(xù)來補(bǔ)充
?
總結(jié)
以上是生活随笔為你收集整理的gamebuino制作的小游戏之2048代码分析 loop部分的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 51之按键控制开关
- 下一篇: linux如何在文件中写命令,Linux