2017年6月30日 星期五

俄羅斯方塊 (1) - 旋轉方塊

這回合來談談方塊的旋轉是怎麼做的?

其實也一樣是那 4 個點的座標變化而已。我的旋轉方式以 p2 為支點來轉動, 也就是轉動時, p2 是不改變座標的。

一樣是 z Tetromino。

  • Tetromino Z.svg Z: two stacked horizontal dominoes with the top one offset to the left.

以下畫出 z Tetromino 的四個旋轉圖, 應該就很清楚了。

旋轉一

0

1

2

3

4

5

6

1


*
p0

*
p1




2



*
p2

*
p3



3







4







5



































旋轉一 p0, p1, p2, p3 的座標是:
p0: (2,1)
p1: (3,1)
p2: (3,2)
p3: (4,2)

旋轉二

0

1

2

3

4

5

6

1





*
p0



2


*
p2
*
p1



3


*
p3




4







5



































旋轉二 p0, p1, p2, p3 的座標是:
p0: (4,1)
p1: (4,2)
p2: (3,2)
p3: (3,3)


旋轉三

0

1

2

3

4

5

6

1









2

*
p3

*
p2





3


*
p1
*
p0



4







5



































旋轉三 p0, p1, p2, p3 的座標是:
p0: (4,3)
p1: (3,3)
p2: (3,2)
p3: (2,2)

旋轉四

0

1

2

3

4

5

6

1




*
p3




2

*
p1

*
p2




3

*
p0





4







5



































旋轉四 p0, p1, p2, p3 的座標是:
p0: (2,3)
p1: (2,2)
p2: (3,2)
p3: (3,1)

把規則找出來, 轉成程式碼便是:

list 1.
int ZTetromino::rotate()
{
  state_ = ((state_+1) % 4);
  printf("state_: %d\n", state_);
  switch (state_)
  {
    case 0:
    {
      printf("mode 0 \n");
      p0_.y_-=2;
      ++p1_.x_;
      --p1_.y_;
      ++p3_.x_;
      ++p3_.y_;
      break;
    }
    case 1:
    {
      printf("mode 1 \n");
      p0_.x_+=2;
      ++p1_.x_;
      ++p1_.y_;
      --p3_.x_;
      ++p3_.y_;
      break;
    }
    case 2:
    {
      p0_.y_+=2;
      --p1_.x_;
      ++p1_.y_;
      --p3_.x_;
      --p3_.y_;
      break;
    }
    case 3:
    {
      p0_.x_-=2;
      --p1_.x_;
      --p1_.y_;
      ++p3_.x_;
      --p3_.y_;

      break;
    }
  }
}

list 1. case 1 便是 '旋轉一' 切換到 '旋轉二' 的座標變化:
p0 的 x 座標 +2 
p1 的 x 座標 +1
p1 的 y 座標 +1
p3 的 x 座標 -1
p3 的 y 座標 +1

旋轉規則就是這樣把圖一個個畫出來, 然後找到的, 所以我才會說我在筆記本畫了一堆圖形。

  • Tetromino S.svg S: two stacked horizontal dominoes with the top one offset to the right.

s Tetromino 也是用同樣的方法實作出來的。

相信其他 Tetromino 也難不倒你了。

這次我用了 c++ 的多型來處理不同的 Tetromino, 只要繼承 base class, 就可以很快的寫出一個新的 Tetromino, 當然也可以不要用多型, 不過這次選用多型帶來比較多的好處, 我就這麼用了, 雖然 virtual function 帶來了較差的執行效率, 但瑕不掩瑜, 程式的確比較容易撰寫。

fig 1. 旋轉與消掉方塊

fig 1 展示了方塊的旋轉, 以及最重要的消掉方塊, 下回合來談談怎麼消掉方塊。fig 1 的畫面也比《俄羅斯方塊 (0) - 移動方塊》那時候的好看多了, 有了顏色和邊界, 這沒用到什麼特別函式, 全都是用 printf 印出來的, 這是一步步進化的結果。

我目前只打算靠 printf 來印出畫面, 不靠 ncurses 有定位能力的函式, 還蠻有挑戰性的。不過因為我用 c++, 其實是用 cout 印出來的。

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。