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

 

 

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

 

続き

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

 

ボタンを押す度に左右に移動するプログラム(長押しに対応)

 

int x_pos = 6;
int y_pos = 0;
int select = 6;
int muki = 0;
int fall_speed_count = 0;
boolean rotate_flag = false;
int move_count_l = 0;
int move_count_r = 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];
              
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;
  }
}

void fall(){
  fall_speed_count++;
  if (fall_speed_count > 100){
    fall_speed_count = 0;
    y_pos++;
    if (y_pos > 15)
      y_pos = 0;
  }
}

void data_make(){
  for (int i = 0;i < 16;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;
}

void disp(){
  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);
      digitalWrite(4,HIGH);
      digitalWrite(4,LOW);
    }
    digitalWrite(5,HIGH);
    digitalWrite(5,LOW);
  }
  digitalWrite(6,HIGH);
  digitalWrite(6,LOW);
}

太字が追加部分

 

ブロック移動の様子


www.youtube.com

ボタンを押してx_posを+1または-1して左右に移動するプログラム

move_count_l、move_count_r は移動速度調整用

 

次回はブロックの固定を作って行きます。

 

では、また。

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

 

 

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

 

続き

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

 

ボタンを押す度に90度ずつ右回転するプログラム

 

int x_pos = 6;
int y_pos = 0;
int select = 6;
int muki = 0;
int fall_speed_count = 0;
boolean rotate_flag = false;
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];
              
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);
}

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

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

void fall(){
  fall_speed_count++;
  if (fall_speed_count > 100){
    fall_speed_count = 0;
    y_pos++;
    if (y_pos > 15)
      y_pos = 0;
  }
}

void data_make(){
  for (int i = 0;i < 16;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;
}

void disp(){
  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);
      digitalWrite(4,HIGH);
      digitalWrite(4,LOW);
    }
    digitalWrite(5,HIGH);
    digitalWrite(5,LOW);
  }
  digitalWrite(6,HIGH);
  digitalWrite(6,LOW);
}

太字が追加部分

 

ブロックが回転してる様子


www.youtube.com

 

ボタンを押すごとにmukiを+1して4になったら0に戻すプログラム

rotate_flagは長押し防止用

 

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

 

では、また。

 

mckeechan.hatenadiary.com

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

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

 

続き

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

 

ブロックが一段ずつ落ちていくプログラム

 

int x_pos = 6;
int y_pos = 0;
int select = 0;
int muki = 0;
int fall_speed_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];
              
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);
}

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

void fall(){
  fall_speed_count++;
  if (fall_speed_count > 100){
    fall_speed_count = 0;
    y_pos++;
    if (y_pos > 15)
      y_pos = 0;
  }
}

void data_make(){
  for (int i = 0;i < 16;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 ;
}

void disp(){
  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);
      digitalWrite(4,HIGH);
      digitalWrite(4,LOW);
    }
    digitalWrite(5,HIGH);
    digitalWrite(5,LOW);
  }
  digitalWrite(6,HIGH);
  digitalWrite(6,LOW);
}

太字が追加部分

 

ブロックが落ちていく様子


www.youtube.com

 

難しいことはしていません。

fall_speed_count を使って100回loop()を回る毎に一段落ちるプログラム

 

次回はブロックの回転を作って行きます。

 

では、また。

 

mckeechan.hatenadiary.com

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

 

 

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

 

続き

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

 

作り方は色々ありますがLEDマトリックス用にビット操作がしやすい形で持つようにしました。

また、データもdisp();用を追加しました。

ブロックは二次配列で向き毎のデータも持っています。

 

int x_pos = 6;
int y_pos = 0;
int select = 0;
int muki = 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];
              
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);
}

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

void data_make(){
  for (int i = 0;i < 16;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 ;
}

void disp(){
  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);
      digitalWrite(4,HIGH);
      digitalWrite(4,LOW);
    }
    digitalWrite(5,HIGH);
    digitalWrite(5,LOW);
  }
  digitalWrite(6,HIGH);
  digitalWrite(6,LOW);
}

data_make()で表示データを作っています。

 

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 データは上右下左の順

ブロックはselect、向きはmukiで選べる様にしています。

テスト用なので動きは有りません。

 

次回はブロックの落下を作って行きます。

 

では、また。

 

mckeechan.hatenadiary.com

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

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

 

続き

テトリスに挑戦に向けて先ずは情報を収集しました。

 

情報は山ほどありますが結構難しそうと言うのが第一印象です。

中には7行テトリスなんてのが有りました。(見ても全くわからん)

基本7種類のブロック、スペースは10列が一般的な様です。

ブロックの左右移動、回転、横一線が揃うと段落ち等など

 

ゆっくり進めますのでのんびりとお付き合いください。

 

最初に枠を作りました。

short data_hex[] = {0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004,
                    0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x2004, 0x3ffc};
              
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);
}

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

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

今回はloop()の中は出来るだけ見やすく進めていこうと思います。

 

初回はこんな感じです。

 

では、また。

 

mckeechan.hatenadiary.com

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

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

 

続き

今回は地面に着弾した時や砲台に被弾した時のアクションを作って行きます。

 

砲台に被弾するとゲーム終了

再スタートボタンの追加

砲台の移動をゆっくりスタートに変更

 

太字が変更したところ

int count = 0;
int x_pos = 0;
int old_x_pos = 0;
int y_pos = 0;
int fort_pos = 7;           // 砲台の位置
boolean shot = false;       // ビーム発射
int velocity = 0;           // 落下速度
boolean hit = false;        // 命中
boolean destruction = false;// 破壊
int repeat_count_left = 0;  // 砲台の移動 ゆっくりスタート
int repeat_count_right = 0; // 砲台の移動 ゆっくりスタート
boolean my_hit = false;     // 砲台に命中
boolean start = true;       // 再スタート

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(8,INPUT_PULLUP);
  pinMode(9,INPUT_PULLUP);
  pinMode(10,INPUT_PULLUP);
  pinMode(11,OUTPUT);
  
  old_x_pos = x_pos = random(1, 15);
 }

void loop() {
  // put your main code here, to run repeatedly:
  for (int i = 0;i < 16;i++) {
    for (int j = 0;j < 16;j++) {
      digitalWrite(2,LOW);
      // 破壊シーン
      if (destruction) {
        if (y_pos <= i + 1 && i < y_pos + 2)
          if (fort_pos <= j && j < fort_pos + 3) {
            digitalWrite(2,HIGH);
            hit = false;
          }
      }
      // ビームを描く
      else {
        if (shot) {
          if (x_pos == j) {
            if (j == fort_pos + 1 && i > y_pos) {
              digitalWrite(2,HIGH);
              hit = true;
            }
          }
          else {
            if (j == fort_pos + 1) {
              digitalWrite(2,HIGH);
              hit = false;
            }
          }
        }
      }
      // 地面に落ちたシーン
      if (!my_hit)
      if (i == 14 || i == 15) {
        if (x_pos <= j + 1 && j < x_pos + 2 && y_pos == 15) {
          digitalWrite(2,HIGH);
        }
      }
      // 砲台に被弾したシーン
      if (i == 12 || i == 13 || i == 14 || i == 15) {
        if (fort_pos == x_pos || fort_pos + 1 == x_pos || fort_pos + 2 == x_pos)
          if (fort_pos + 1 <= j + 2 && j < fort_pos + 1 + 3 && y_pos == 14) {
            digitalWrite(2,HIGH);
            my_hit = true;
            start = false;
        }
      }
      // 爆弾を描く
      if (!my_hit && start) { // 再スタート
      if (j == x_pos && i == y_pos)
        digitalWrite(2,HIGH);
      // 砲身
      if (i == 14) {          // 15段目
        if (fort_pos + 1 == j)
        digitalWrite(2,HIGH);
      }
      // 砲台
      if (i == 15) {          // 1番下の16段目
        if (fort_pos <= j && j < fort_pos + 3)
        digitalWrite(2,HIGH);
      }
      }
      digitalWrite(4,HIGH);
      digitalWrite(4,LOW);
    }
    digitalWrite(5,HIGH);
    digitalWrite(5,LOW);
  }
  digitalWrite(6,HIGH);
  digitalWrite(6,LOW);

  digitalWrite(11,LOW);
  shot = false;

  count++;
  if (count > 10) {
    count = 0;

  if (destruction) {
    destruction = false;
    y_pos = 0;
    do {
      x_pos = random(1, 15);
    } while (x_pos == old_x_pos);
    old_x_pos = x_pos;
  }
  else
    if (hit)
      destruction = true;

    // 爆弾の位置 y軸
    velocity++;
    if (velocity > 1) {   // 落下速度
      velocity = 0;
      y_pos++;
      if (y_pos > 15 && !my_hit) { // 再スタート
        y_pos = 0;
        do {
          x_pos = random(1, 15);
        } while (x_pos == old_x_pos);
        old_x_pos = x_pos;
      }
    }
    
    if (digitalRead(7) == 0 && start) {  // 発射
      shot = true;
      digitalWrite(11,HIGH);
    }

    if (digitalRead(8) == 0 && !start) {  // 再スタート
      my_hit = false;
        y_pos = 0;
        do {
          x_pos = random(1, 15);
        } while (x_pos == old_x_pos);
        old_x_pos = x_pos;
        start = true;
    }

    // 砲台の位置
    if (digitalRead(9) == 0) {
      if (fort_pos > 0) {
        if (repeat_count_left > 2 || repeat_count_left == 0)// 砲台の移動 ゆっくりスタート
          fort_pos--;         // 左へ移動
        repeat_count_left++;
      }
    }
    else {
      repeat_count_left = 0;
    }

    if (digitalRead(10) == 0) {
      if (fort_pos < 13) {
        if (repeat_count_right > 2 || repeat_count_right == 0)// 砲台の移動 ゆっくりスタート
          fort_pos++;         // 右へ移動
        repeat_count_right++;
      }
    }
    else {
      repeat_count_right = 0;
    }
  }
}

これで完成しました。

 

遊んでいる様子。


www.youtube.com

今回はこれで終了です。

 

見事なまでのスパゲッティプログラムですが一応ゲームとして成り立っています。

 

こんな簡単なゲームだからこのようなプログラムでも書けますが複雑な物になってくるととても無理です。

 

一度テトリスに挑戦してみようかな

 

勉強しながらになるのでゆっくりです。

 

では、また。

 

mckeechan.hatenadiary.com

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

 

 

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

 

続き

今回は撃破のアクションやサウンド等を作って行きます。

int count = 0;
int x_pos = 0;
int old_x_pos = 0; // ランダムの投下位置が続かない様に追加
int y_pos = 0;
int fort_pos = 7;        // 砲台の位置
boolean shot = false;    // ビーム発射
int velocity = 0;        // 落下速度
boolean hit = false;    // 命中
boolean destruction = false;    // 破壊

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(8,INPUT_PULLUP);
  pinMode(9,INPUT_PULLUP);
  pinMode(10,INPUT_PULLUP);
  pinMode(11,OUTPUT);
  
  old_x_pos = x_pos = random(1, 15);
 }

void loop() {
  // put your main code here, to run repeatedly:
  for (int i = 0;i < 16;i++) {
    for (int j = 0;j < 16;j++) {
      digitalWrite(2,LOW);
      // 破壊シーン
      if (destruction) {
        if (y_pos <= i + 1 && i < y_pos + 2)
          if (fort_pos <= j && j < fort_pos + 3) {
            digitalWrite(2,HIGH);
            hit = false;
          }
      }
      // ビームを描く
      else {
        if (shot) {
          if (x_pos == j) {
            if (j == fort_pos + 1 && i > y_pos) {
              digitalWrite(2,HIGH);
              hit = true;
            }
          }
          else {
            if (j == fort_pos + 1) {
              digitalWrite(2,HIGH);
              hit = false;
            }
          }
        }
      }
      // 爆弾を描く
      if (j == x_pos && i == y_pos)
        digitalWrite(2,HIGH);
      // 砲身
      if (i == 14) {          // 1番下の16段目
        if (fort_pos + 1 == j)
        digitalWrite(2,HIGH);
      }
      // 砲台
      if (i == 15) {          // 1番下の16段目
        if (fort_pos <= j && j < fort_pos + 3)
        digitalWrite(2,HIGH);
      }
      digitalWrite(4,HIGH);
      digitalWrite(4,LOW);
    }
    digitalWrite(5,HIGH);
    digitalWrite(5,LOW);
  }
  digitalWrite(6,HIGH);
  digitalWrite(6,LOW);

  digitalWrite(11,LOW);
  shot = false;
  count++;
  if (count > 10) {
    count = 0;

  if (destruction) { // 破壊
    destruction = false;
    y_pos = 0;
    do {
      x_pos = random(1, 15);
    } while (x_pos == old_x_pos); // ランダムの投下位置が続かない様に
    old_x_pos = x_pos;
  }
  else
    if (hit)
      destruction = true;

    // 爆弾の位置 y軸
    velocity++;
    if (velocity > 5) {   // 落下速度
      velocity = 0;
      y_pos++;
      if (y_pos > 15) {
        y_pos = 0;
        do {
          x_pos = random(1, 15);
        } while (x_pos == old_x_pos); // ランダムの投下位置が続かない様に
        old_x_pos = x_pos;
      }
    }
    
    if (digitalRead(7) == 0) {  // 発射
      shot = true;
      digitalWrite(11,HIGH); // ビーム音
    }

    if (digitalRead(8) == 0) {  // NOP
    }

    // 砲台の位置
    if (digitalRead(9) == 0)
      if (fort_pos > 0)
        fort_pos--;         // 左へ移動

    if (digitalRead(10) == 0)
      if (fort_pos < 13)
        fort_pos++;         // 右へ移動
  }
}

破壊シーンは■を表示しているだけですが表示パターンを作って爆発風に作ってみることも可能かと思います。

 

今回のプログラムを実行した様子


www.youtube.com

 

次回は自陣に着弾した時のアクションや砲台に被弾した時のアクションを作って行きます。

 

では、また。

 

mckeechan.hatenadiary.com