マイコンArduinoを使って電光掲示板を作る。

 

 

マイコンArduinoを使って電光掲示板を作る。

 

続き

テトリスに挑戦の6回目はブロックの固定を作って行きます。

 

地面に着地した時とブロックに着地した時にその位置に留まるプログラム

 

int x_pos = 6;
int y_pos = 0;
int select = 6;
int muki = 0;
int fall_speed_count = 0;
boolean rotate_flag = false;
boolean fixed_flag = false;
int move_count_l = 0;
int move_count_r = 0;
int fixed_count = 0;
int fall_count = 0;
short data_hex[] = {0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004,
                    0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x3ffc};
short block[7][4] = {{0x0660, 0x0660, 0x0660, 0x0660},
                    {0x4444, 0x00f0, 0x2222, 0x0f00},
                    {0x2640, 0x0c60, 0x0264, 0x0630},
                    {0x4620, 0x0630, 0x0462, 0x0360},
                    {0x0644, 0x0470, 0x2260, 0x0e20},
                    {0x0622, 0x0740, 0x4460, 0x02e0},
                    {0x04e0, 0x0262, 0x0720, 0x4640}};
short disp_hex[16];
short fall_hex[16];
              
void setup() {
  // put your setup code here, to run once:
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,INPUT_PULLUP);
  pinMode(9,INPUT_PULLUP);
  pinMode(10,INPUT_PULLUP);
}

void loop() {
  // put your main code here, to run repeatedly:
  move_block();
  rotate();
  fall();
  data_make();
  disp();
 }

void move_block(){
  if (digitalRead(9) == 0){
    move_count_l++;
    if (move_count_l > 30){
      move_count_l = 0;
      x_pos++;
      if (x_pos > 15)
        x_pos = 15;
    }
  }
  else
    move_count_l = 30;
  if (digitalRead(10) == 0){
    move_count_r++;
    if (move_count_r > 30){
      move_count_r = 0;
      x_pos--;
      if (x_pos < 0)
        x_pos = 0;
    }
  }
  else
    move_count_r = 30;
}

void rotate(){
  if (digitalRead(7) == 0){
    if(!rotate_flag){
      rotate_flag = true;
      muki++;
      if (muki > 3)
        muki = 0;
    }
  }
  else {
    rotate_flag = false;
  }
}

boolean fall_check(){
  if (fall_count == 46 + fixed_count)
    return true;
  return false;
}

void fall(){
  fall_speed_count++;
  if (fall_speed_count > 100){
    fall_speed_count = 0;
    if(fall_check())
      y_pos++;
    else
      fixed_flag = true;
  }
}

void data_make(){
  if (fixed_flag){
    for (int i = 0;i < 16;i++)
      data_hex[i] = disp_hex[i];
    fixed_count = fixed_count + 4;
    x_pos = 6;
    y_pos = 0;
    select++;
    if (select > 6)
      select = 0;
  }
  fixed_flag = false;
  for (int i = 0;i < 16;i++)
    fall_hex[i] = disp_hex[i] = data_hex[i];
  for (int i = 0;i < 4;i++){
    disp_hex[i + y_pos] |= ((block[select][muki] >> 4 * i) & 0xf) << x_pos;
    fall_hex[i + y_pos + 1] |= ((block[select][muki] >> 4 * i) & 0xf) << x_pos;
  }
}

void disp(){
  fall_count = 0;
  for (int i = 0;i < 16;i++) {
    for (int j = 0;j < 16;j++) {
      digitalWrite(2,LOW);
      if ((disp_hex[i] & 0x8000 >> j) != 0)
        digitalWrite(2,HIGH);
      if ((fall_hex[i] & 0x8000 >> j) != 0)
        fall_count++;
      digitalWrite(4,HIGH);
      digitalWrite(4,LOW);
    }
    digitalWrite(5,HIGH);
    digitalWrite(5,LOW);
  }
  digitalWrite(6,HIGH);
  digitalWrite(6,LOW);
}

太字が追加部分

 

ブロックが留まる様子


www.youtube.com

 

今回は少し複雑です。ブロックの重なりを判定します。

判定方法はLEDの点灯(仮想)数を数えて(例1個目のブロックの場合は46個)少なければ重なっている。

fall_hex[i + y_pos + 1]で仮想的に1段進めた位置で判定します。

重なっていればそこで固定して次のブロックを落とします。

fixed_countに4加えてselectには1加えてと繰り返す感じ

固定はfor (int i = 0;i < 16;i++) data_hex[i] = disp_hex[i];で元となるデータを更新します。

 

次回はブロックの移動の制限を作って行きます。

 

では、また。

 

mckeechan.hatenadiary.com