Arduinoを使ったテトリスのゲーム機の作り方part3 外装・3Dプリント編
Arduinoを使ったテトリスのゲーム機の作り方part3 外装・3Dプリント編
本記事ではマイコンであるArduinoを使ったテトリスのゲーム機の作り方を紹介していきます。今回はpart3 外装・3Dプリント編です。3Dプリンタ―を使って外装を印刷し組み立てていきます。Arduinoがそもそも何か分からないという人は こちらへ。完成はこんな感じです。
目次
・印刷するための準備、印刷
・組み立て
・印刷するための準備、印刷
3Dプリンタ―で印刷するためには以下の準備があります。
①CADソフトを使った設計
こんな感じのソフトでまずスケッチをかいてそれを3D化して設計をしていきます。おすすめはFusion360というソフトです。
Fusion360のダウンロードURL ⇩⇩
Fusion 360 | 3D CAD/CAM/CAE/PCB クラウドベースのソフトウェアAutodesk 公式
テトリスの外装のデータファイルです。ダウンロードしてお使いください。
Parts1 ➡ Tetris_Parts1.stl - Google ドライブ
Parts2 ➡ Tetris_Parts2.stl - Google ドライブ
②スライサーソフトでGコードに変換
設計した3Dデータを3Dプリンタ―本体が理解することができるようにするためにスライサーソフトでGコードに変換します。その他にも印刷する時の詳細設定などもすることができます。おすすめはCuraというソフトです。
CuraのダウンロードURL ⇩⇩
UltiMaker Cura:強力で使いやすい3Dプリントソフトウェア
③3Dプリンタ―の設定
3Dプリンタ―に先ほどのGコードを読み込ませて印刷します。そしてフィラメントを設置し、レベリングをして土台の位置を調節します。
印刷する手順はこれで以上です!それでは実際に印刷してみましょう。先ほどのファイルのParts1とParts2は違う色で印刷するのがおすすめです。
・組み立てる
印刷が出来たら、早速組み立てていきましょう。
①Parts2に含まれていた白い丸をタクトスイッチに接着剤でくっつけます。
②Parts1に含まれていた表側の部品にParts2の部品を取り付けます。この部品は飾りなのでなくてもOKです。
③電子部品を組み込んでいきます。
まずON,OFFのボタンを取り付けます。Part1の表側の穴に取り付けます。
スイッチのリンク https://amzn.asia/d/9RIWag5
④リチウムイオン電池の充電基板を取り付けます。充電端子を穴にはめ込むようにしてスマホのように充電できるようにします。
充電基板のリンク https://amzn.asia/d/iY7uPo1
⑤Part1の回路製作編で作った回路とドットマトリクス、リチウムイオン電池を取り付けます。ボタンは穴にちょうど入るようになるはずです。回路や電池はグルーガンやボンドなどで固定しておくことをお勧めします。
最後に表側の部品を蓋を取り付けたら終わりです!
完成はこんなかんじになっているはずです⇩⇩⇩
お疲れ様でした!!これで完成です!
分からないことや間違っているところがあれば気軽にコメントしてください!
これで最終回です。今まで見てくれてありがとうございます。
参考にしたサイトはこちら
Arduinoを使ったテトリスのゲーム機の作り方part2 プログラミング編
Arduinoを使ったテトリスのゲーム機の作り方part2 プログラミング編
本記事ではマイコンであるArduinoを使ったテトリスのゲームの作り方を紹介していきます。今回はpart2 プログラミング編です。Arduinoがそもそも何か分からないという人は こちらへ。完成はこんな感じです。
目次
・プログラム
・実際に書き込む
・動作確認
・プログラム
今回使うプログラムはこちらです。
#include <LedControl.h>
LedControl lc = LedControl(12, 11, 10, 2); // (dataPin, clockPin, csPin, totalDevices)
int lc0 = {0, 0, 0, 0, 0, 0, 0, 0};
int lc1 = {0, 0, 0, 0, 0, 0, 0, 0};
long active = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
long screen = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int tmpCol = 0;
int figura = 0;
int figuraNext = 0;
int fromLeft = 0;
int fromRight = 0;
int angle = 0;
int colCheck = 0;
int moveCheck = 0;
int score = 0;
int started = 0;
int lcRows = 16;
int lcCols = 8;
int allLines = 0;
int currLines = 0;
int brickDelay = 0;
int defDelay = 500;
int level = 0;
boolean sound = true;
//Pinos
int rotate_button = 2;
int left_button = 3;
int down_button = 4;
int right_button = 5;
int start_button = 6;
int speaker_pin = 7;
int sound_button = 8;
byte X[8] =
{
0b00000,
0b10001,
0b01010,
0b00100,
0b01010,
0b10001,
0b00000,
0b00000
};
byte O[8] =
{
0b00000,
0b11111,
0b11111,
0b11111,
0b11111,
0b11111,
0b00000,
0b00000
};
byte L[8] =
{
0b11000,
0b11000,
0b11000,
0b11000,
0b11000,
0b11111,
0b11111,
0b00000
};
byte J[8] =
{
0b00011,
0b00011,
0b00011,
0b00011,
0b00011,
0b11111,
0b11111,
0b00000
};
byte T[8] =
{
0b00000,
0b00000,
0b11111,
0b11111,
0b01110,
0b01110,
0b00000,
0b00000
};
byte I[8] =
{
0b01100,
0b01100,
0b01100,
0b01100,
0b01100,
0b01100,
0b01100,
0b00000
};
byte Z[8] =
{
0b00000,
0b00000,
0b11110,
0b11110,
0b01111,
0b01111,
0b00000,
0b00000
};
byte S[8] =
{
0b00000,
0b00000,
0b01111,
0b01111,
0b11110,
0b11110,
0b00000,
0b00000
};
//Nuty
int length = 99;
char notes = "EbCDCbaaCEDCbbCDECaa DFAGFEECEDCbbCDECaa EbCDCbaaCEDCbbCDECaa DFAGFEECEDCbbCDECaa ECDbCab ECDbCEAJ ";
int beats = // Som
{
2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, 2, 4, 2,
2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, 2, 4, 1,
2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, 2, 4, 2,
2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, 2, 4, 1,
5, 5, 5, 5, 5, 5, 7, 2, 5, 5, 5, 5, 2, 2, 5, 5, 3
};
int tempo = 128; // Tempo
void playTone(int tone, int duration) {
for (long i = 0; i < duration * 1000L; i += tone * 2) {
digitalWrite(speaker_pin, HIGH);
delayMicroseconds(tone);
digitalWrite(speaker_pin, LOW);
delayMicroseconds(tone);
}
}
void playNote(char note, int duration) {
char names = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' , 'D', 'E', 'F', 'G', 'J', 'A', 'B'};
int tones = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956, 850, 760, 716, 637, 603, 568, 507 };
for (int i = 0; i < 14; i++) {
if (names[i] == note) {
playTone(tones[i], duration);
}
}
}
void updateColumn(int colnum)
{
lc0[colnum] = active[colnum] >> (lcRows / 2);
lc1[colnum] = active[colnum];
lc.setColumn(0,colnum,(screen[colnum] >> (lcRows / 2)) | lc0[colnum]);
lc.setColumn(1,colnum,screen[colnum] | lc1[colnum]);
}
void buttonDelay(int bdelay)
{
if(brickDelay > bdelay)
{
brickDelay -= bdelay;
}
delay(bdelay);
}
void splashScreen()
{
int up =
{
B11101110, // o o o o o o
B01001000, // o o
B01001100, // o o o
B01001000, // o o
B01001110, // o o o o
B00000000, //
B11101110, // o o o o o o
B01001010 // o o o
};
int down =
{
B01001100, // o o o
B01001010, // o o o
B01001001, // o o o
B00000000, //
B01000111, // o o o o
B01000100, // o o
B01000010, // o o
B01001110 // o o o o
};
for(int rownum = 0; rownum < 8; rownum++)
{
lc.setRow(0,rownum,up[rownum]);
lc.setRow(1,rownum,down[rownum]);
}
}
void setup() {
pinMode(speaker_pin, OUTPUT);
pinMode(rotate_button,INPUT_PULLUP);
pinMode(down_button, INPUT_PULLUP);
pinMode(right_button, INPUT_PULLUP);
pinMode(left_button, INPUT_PULLUP);
pinMode(start_button, INPUT_PULLUP);
pinMode(sound_button, INPUT_PULLUP);
lc.shutdown(0,false);
lc.shutdown(1,false);
lc.setIntensity(0,5);
lc.setIntensity(1,5);
lc.clearDisplay(0);
lc.clearDisplay(1);
Serial.begin(9600);
randomSeed(analogRead(0));
}
//LOOP
void loop()
{
if(started == 0)
{
splashScreen();
for (int i = 0; i < length; i++)
{
if(digitalRead(sound_button) == LOW)
{
sound =! sound;
delay(300);
}
if(digitalRead(start_button) == LOW)
{
started = 1;
break;
}
if (notes[i] == ' ')
{
delay(beats[i] * tempo); //Pausa
}
else
{
if (sound == 1){
playNote(notes[i], beats[i] * tempo);
}
else
{
digitalWrite(speaker_pin,LOW);
}
}
delay(tempo / 2);
}
}
else
{
lc.clearDisplay(0);
lc.clearDisplay(1);
memset(lc0, 0, sizeof(lc0));
memset(lc1, 0, sizeof(lc1));
memset(active, 0, sizeof(active));
memset(screen, 0, sizeof(screen));
tmpCol = 0;
while(started == 1)
{
if(allLines < 100)
{
level = 0; //Level 0
}
else if(allLines < 200)
{
level = 1; //Level 1
}
else if(allLines < 300)
{
level = 2; //Level 2
}
else if(allLines < 400)
{
level = 3; //Level 3
}
else if(allLines < 500)
{
level = 4; //Level 4
}
else
{
level = 5; //Level 5
}
defDelay = (5 - level) * 100;
brickDelay = defDelay;
if(figura == 0)
{
figura = random(1,8);
}
else
{
figura = figuraNext;
}
figuraNext = random(1,8);
angle = 0;
switch(figura)
{
case 1:
//"O"
active[3] = 131072 + 65536;
active[4] = 131072 + 65536;
fromLeft = 3;
fromRight = 3;
break;
case 2:
//"L"
active[3] = 262144 + 131072 + 65536;
active[4] = 65536;
fromLeft = 3;
fromRight = 3;
break;
case 3:
//"J"
active[3] = 65536;
active[4] = 262144 + 131072 + 65536;
fromLeft = 3;
fromRight = 3;
break;
case 4:
//"T"
active[2] = 131072;
active[3] = 131072 + 65536;
active[4] = 131072;
fromLeft = 2;
fromRight = 3;
break;
case 5:
//"I"
active[3] = 524288 + 262144 + 131072 + 65536;
fromLeft = 3;
fromRight = 4;
break;
case 6:
//"Z"
active[2] = 131072;
active[3] = 131072 + 65536;
active[4] = 65536;
fromLeft = 2;
fromRight = 3;
break;
case 7:
//"S"
active[2] = 65536;
active[3] = 131072 + 65536;
active[4] = 131072;
fromLeft = 2;
fromRight = 3;
break;
}
for(int krok = 0; krok < lcRows + 1; krok++)
{
colCheck = 0;
for(int i = 0; i < (lcCols / 2); i++)
{
if*1
{
moveCheck = 0;
for(int colnum = fromLeft; colnum < (lcCols - fromRight); colnum++)
{
if*2
{
for(int colnum = (fromLeft - 1); colnum < (lcCols - fromRight); colnum++)
{
if(colnum < (lcCols - 1))
{
active[colnum] = active[colnum+1];
}
else
{
active[colnum] = 0;
}
updateColumn(colnum);
}
fromLeft--;
fromRight++;
playNote('E', 10);
buttonDelay(200);
}
}
}
for(int i = 0; i < (lcCols / 2); i++)
{
if*3
{
moveCheck = 0;
for(int colnum = fromLeft; colnum < (lcCols - fromRight); colnum++)
{
if*4
{
for(int colnum = (lcCols - fromRight); colnum > (fromLeft - 1); colnum--)
{
if(colnum > 0)
{
active[colnum] = active[colnum-1];
}
else
{
active[colnum] = 0;
}
updateColumn(colnum);
}
fromLeft++;
fromRight--;
playNote('E', 10);
buttonDelay(200);
}
}
}
if(digitalRead(down_button) == LOW)
{
brickDelay = 0;
playNote('b', 10);
}
else
{
brickDelay = defDelay;
}
for(int i = 0; i < (lcCols / 2); i++)
{
if(digitalRead(rotate_button) == LOW)
{
switch(figura)
{
case 1:
//"O"
break;
case 2:
//"L"
switch(angle)
{
case 0:
// . o . . . .
// . o . ---> o o o
// . o o o . .
if*5 & screen[fromLeft - 1]) == 0))
{
active[fromLeft - 1] = (active[fromLeft + 1] | (active[fromLeft + 1] << 1));
updateColumn(fromLeft - 1);
active[fromLeft] = (active[fromLeft + 1] << 1);
updateColumn(fromLeft);
active[fromLeft + 1] = (active[fromLeft + 1] << 1);
updateColumn(fromLeft + 1);
fromLeft--;
angle = 1;
}
break;
case 1:
// . . . o o .
// o o o ---> . o .
// o . . . o .
if((((active[fromLeft + 2] << 1) & screen[fromLeft]) == 0)
&& ((((active[fromLeft + 1] << 1) | (active[fromLeft + 1] >> 1)) & screen[fromLeft + 1]) == 0))
{
active[fromLeft] = (active[fromLeft + 2] << 1);
updateColumn(fromLeft);
active[fromLeft + 1] = active[fromLeft + 1] | (active[fromLeft + 1] << 1) | (active[fromLeft + 1] >> 1);
updateColumn(fromLeft + 1);
active[fromLeft + 2] = 0;
updateColumn(fromLeft + 2);
fromRight++;
angle = 2;
}
break;
case 2:
// o o . . . o
// . o . ---> o o o
// . o . . . .
if*6
{
active[fromLeft] = (active[fromLeft] >> 1);
updateColumn(fromLeft);
active[fromLeft + 1] = active[fromLeft];
updateColumn(fromLeft + 1);
active[fromLeft + 2] = *7 & screen[fromLeft + 1]) == 0)
&& (((active[fromLeft] >> 1) & screen[fromLeft + 2]) == 0)
&& (krok < lcRows))
{
active[fromLeft] = 0;
updateColumn(fromLeft);
active[fromLeft + 1] = (active[fromLeft + 2] | (active[fromLeft + 2] >> 1));
updateColumn(fromLeft + 1);
active[fromLeft + 2] = *8;
updateColumn(fromLeft + 2);
fromLeft++;
krok++;
angle = 0;
}
break;
}
break;
case 3:
//"J"
switch(angle)
{
case 0:
// . o . o . .
// . o . ---> o o o
// o o . . . .
if*9 & screen[fromLeft]) == 0)
&& (((active[fromLeft] << 1) & screen[fromLeft + 2]) == 0))
{
active[fromLeft] = *10;
updateColumn(fromLeft);
active[fromLeft + 1] = *11;
updateColumn(fromLeft + 1);
active[fromLeft + 2] = active[fromLeft + 1];
updateColumn(fromLeft + 2);
fromRight--;
krok--;
angle = 1;
}
break;
case 1:
// o . . . o o
// o o o ---> . o .
// . . . . o .
if*12 & screen[fromLeft + 1]) == 0)
&& (((active[fromLeft + 2] << 1) & screen[fromLeft + 2]) == 0))
{
active[fromLeft] = 0;
updateColumn(fromLeft);
active[fromLeft + 1] = (active[fromLeft + 1] | (active[fromLeft + 1] << 1) | (active[fromLeft + 1] >> 1));
updateColumn(fromLeft + 1);
active[fromLeft + 2] = (active[fromLeft + 2] << 1);
updateColumn(fromLeft + 2);
fromLeft++;
krok++;
angle = 2;
}
break;
case 2:
// . o o . . .
// . o . ---> o o o
// . o . . . o
if*13 & screen[fromLeft + 1]) == 0))
{
active[fromLeft - 1] = (active[fromLeft + 1] >> 1);
updateColumn(fromLeft - 1);
active[fromLeft] = active[fromLeft - 1];
updateColumn(fromLeft);
active[fromLeft + 1] = (active[fromLeft] | (active[fromLeft + 1] >> 2));
updateColumn(fromLeft + 1);
fromLeft--;
angle = 3;
}
break;
case 3:
// . . . . o .
// o o o ---> . o .
// . . o o o .
if((((active[fromLeft] >> 1) & screen[fromLeft]) == 0)
&& ((((active[fromLeft] << 1) | (active[fromLeft >> 1])) & screen[fromLeft + 1]) == 0))
{
active[fromLeft] = (active[fromLeft] >> 1);
updateColumn(fromLeft);
active[fromLeft + 1] = *14
{
//active[fromLeft]
active[fromLeft + 1] = active[fromLeft + 1] & (active[fromLeft + 1] << 1);
updateColumn(fromLeft + 1);
active[fromLeft + 2] = active[fromLeft];
updateColumn(fromLeft + 2);
fromRight--;
krok--;
angle = 2;
}
break;
case 2:
// . o . . o .
// o o o ---> . o o
// . . . . o .
if((((active[fromLeft + 1] >> 1) & screen[fromLeft + 1]) == 0)
&& (krok < lcRows))
{
active[fromLeft] = 0;
updateColumn(fromLeft);
active[fromLeft + 1] = active[fromLeft + 1] | (active[fromLeft + 1] >> 1);
updateColumn(fromLeft + 1);
//active[fromLeft + 2]
fromLeft++;
krok++;
angle = 3;
}
break;
case 3:
if*15
{
active[fromLeft - 1] = active[fromLeft + 1];
updateColumn(fromLeft - 1);
active[fromLeft] = active[fromLeft] & (active[fromLeft] >> 1);
updateColumn(fromLeft);
fromLeft--;
angle = 0;
}
break;
}
break;
case 5:
//"I"
switch(angle)
{
case 0:
// . o . . . . . .
// . o . . ---> o o o o
// . o . . . . . .
// . o . . . . . .
if*16 & screen[fromLeft - 1]) & screen[fromLeft + 1]) & screen[fromLeft + 2]) == 0))
{
active[fromLeft - 1] = *17;
updateColumn(fromLeft - 1);
active[fromLeft] = active[fromLeft - 1];
updateColumn(fromLeft);
active[fromLeft + 1] = active[fromLeft];
updateColumn(fromLeft + 1);
active[fromLeft + 2] = active[fromLeft];
updateColumn(fromLeft + 2);
fromLeft--;
fromRight -= 2;
krok -= 2;
angle = 1;
}
break;
case 1:
// . . . . . . o .
// o o o o ---> . . o .
// . . . . . . o .
// . . . . . . o .
if*18
&& (((active[fromLeft] << 1) | (active[fromLeft] >> 1) | (active[fromLeft] >> 2)) & screen[fromLeft + 2]) == 0)
{
active[fromLeft] = 0;
updateColumn(fromLeft);
active[fromLeft + 1] = 0;
updateColumn(fromLeft + 1);
active[fromLeft + 2] = (active[fromLeft + 2] | (active[fromLeft + 2] << 1) | (active[fromLeft + 2] >> 1) | (active[fromLeft + 2] >> 2));
updateColumn(fromLeft + 2);
active[fromLeft + 3] = 0;
updateColumn(fromLeft + 3);
fromLeft += 2;
fromRight++;
krok += 2;
angle = 2;
}
break;
case 2:
// . . o . . . . .
// . . o . ---> . . . .
// . . o . o o o o
// . . o . . . . .
if*19 & screen[fromLeft - 2]) & screen[fromLeft - 1]) & screen[fromLeft + 1]) == 0))
{
active[fromLeft - 2] = *20;
updateColumn(fromLeft - 2);
active[fromLeft - 1] = active[fromLeft - 2];
updateColumn(fromLeft - 1);
active[fromLeft] = active[fromLeft - 1];
updateColumn(fromLeft);
active[fromLeft + 1] = active[fromLeft];
updateColumn(fromLeft + 1);
fromLeft -= 2;
fromRight--;
krok--;
angle = 3;
}
break;
case 3:
// . . . . . o . .
// . . . . ---> . o . .
// o o o o . o . .
// . . . . . o . .
if*21
&& (((active[fromLeft] >> 1) | (active[fromLeft] << 1) | (active[fromLeft] << 2)) & screen[fromLeft + 1]) == 0)
{
active[fromLeft] = 0;
updateColumn(fromLeft);
active[fromLeft + 1] = (active[fromLeft + 1] | (active[fromLeft + 1] >> 1) | (active[fromLeft + 1] << 1) | (active[fromLeft + 1] << 2));
updateColumn(fromLeft + 1);
active[fromLeft + 2] = 0;
updateColumn(fromLeft + 2);
active[fromLeft + 3] = 0;
updateColumn(fromLeft + 3);
fromLeft++;
fromRight += 2;
krok++;
angle = 0;
}
break;
}
break;
case 6:
//"Z"
switch(angle)
{
case 0:
// . . . . o .
// o o . ---> o o .
// . o o o . .
if(((active[fromLeft + 1] & screen[fromLeft]) == 0)
&& (((active[fromLeft + 1] << 1) & screen[fromLeft + 1]) == 0))
{
active[fromLeft] = active[fromLeft + 1];
updateColumn(fromLeft);
active[fromLeft + 1] = (active[fromLeft + 1] << 1);
updateColumn(fromLeft + 1);
active[fromLeft + 2] = 0;
updateColumn(fromLeft + 2);
fromRight++;
angle = 1;
}
break;
case 1:
// . o . o o .
// o o . ---> . o o
// o . . . . .
if*22 & screen[fromLeft]) == 0)
&& (((active[fromLeft] & active[fromLeft + 1]) & screen[fromLeft + 2]) == 0))
{
active[fromLeft] = *23;
updateColumn(fromLeft);
//active[fromLeft + 1]
active[fromLeft + 2] = (active[fromLeft] >> 1);
updateColumn(fromLeft + 2);
fromRight--;
krok--;
angle = 2;
}
break;
case 2:
// o o . . . o
// . o o ---> . o o
// . . . . o .
if*24
{
active[fromLeft] = 0;
updateColumn(fromLeft);
active[fromLeft + 1] = (active[fromLeft + 1] >> 1);
updateColumn(fromLeft + 1);
active[fromLeft + 2] = (active[fromLeft + 2] | (active[fromLeft + 2] << 1));
updateColumn(fromLeft + 2);
fromLeft++;
krok++;
angle = 3;
}
break;
case 3:
// . . o . . .
// . o o ---> o o .
// . o . . o o
if*25
{
active[fromLeft - 1] = (active[fromLeft] & active[fromLeft + 1]);
updateColumn(fromLeft - 1);
//active[fromLeft]
active[fromLeft + 1] = (active[fromLeft - 1] >> 1);
updateColumn(fromLeft + 1);
fromLeft--;
angle = 0;
}
break;
}
break;
case 7:
//"S"
switch(angle)
{
case 0:
// . . . o . .
// . o o ---> o o .
// o o . . o .
if(((active[fromLeft + 1] << 1) & screen[fromLeft]) == 0)
{
active[fromLeft] = (active[fromLeft + 1] << 1);
updateColumn(fromLeft);
//active[fromLeft + 1]
active[fromLeft + 2] = 0;
updateColumn(fromLeft + 2);
fromRight++;
angle = 1;
}
break;
case 1:
// o . . . o o
// o o . ---> o o .
// . o . . . .
if*26 & screen[fromLeft + 2]) == 0))
{
active[fromLeft] = (active[fromLeft] & active[fromLeft + 1]);
updateColumn(fromLeft);
active[fromLeft + 1] = (active[fromLeft + 1] << 1);
updateColumn(fromLeft + 1);
active[fromLeft + 2] = (active[fromLeft] << 1);
updateColumn(fromLeft + 2);
fromRight--;
krok--;
angle = 2;
}
break;
case 2:
// . o o . o .
// o o . ---> . o o
// . . . . . o
if*27
{
active[fromLeft] = 0;
updateColumn(fromLeft);
//active[fromLeft + 1]
active[fromLeft + 2] = (active[fromLeft + 1] >> 1);
updateColumn(fromLeft + 2);
fromLeft++;
krok++;
angle = 3;
}
break;
case 3:
// . o . . . .
// . o o ---> . o o
// . . o o o .
if*28 & screen[fromLeft - 1]) == 0)
&& *29
{
active[fromLeft - 1] = (active[fromLeft + 1] & (active[fromLeft + 1] >> 1));
updateColumn(fromLeft - 1);
active[fromLeft] = active[fromLeft + 1];
updateColumn(fromLeft);
active[fromLeft + 1] = (active[fromLeft - 1] << 1);
updateColumn(fromLeft + 1);
fromLeft--;
angle = 0;
}
break;
}
break;
}
playNote('E', 10);
buttonDelay(200);
}
}
//Restart
if(digitalRead(start_button) == LOW)
{
memset(lc0, 0, sizeof(lc0));
memset(lc1, 0, sizeof(lc1));
memset(active, 0, sizeof(active));
memset(screen, 0, sizeof(screen));
score = 0;
allLines = 0;
figura = 0;
break;
}
for(int colnum = 0; colnum < lcCols; colnum++)
{
if*30 == 0)
{
colCheck++;
}
else
{
colCheck = 0;
if(krok == 0)
{
started = 0;
}
}
}
if*31
{
for(int colnum = 0; colnum < lcCols; colnum++)
{
active[colnum] = active[colnum] >> 1;
updateColumn(colnum);
}
}
else
{
break;
}
delay(brickDelay);
}
for(int colnum = 0; colnum < lcCols; colnum++)
{
screen[colnum] = screen[colnum] | (lc0[colnum] << (lcRows / 2));
screen[colnum] = screen[colnum] | lc1[colnum];
lc0[colnum] = 0;
lc1[colnum] = 0;
active[colnum] = 0;
}
currLines = 0;
for(int rownum = 0; rownum < lcRows; rownum++)
{
colCheck = 0;
for(int colnum = 0; colnum < lcCols; colnum++)
{
if(((screen[colnum] >> rownum) & 1) == 1)
{
colCheck++;
}
}
if(colCheck == lcCols)
{
//Animacja kasowania
for(int colnum = 0; colnum < lcCols; colnum++)
{
tmpCol = ~*32 - 1);
tmpCol = screen[colnum] & tmpCol;
screen[colnum] = (screen[colnum] >> (rownum + 1));
screen[colnum] = (screen[colnum] << rownum);
screen[colnum] = screen[colnum] | tmpCol;
}
for(int colnum = 0; colnum < lcCols; colnum++)
{
updateColumn(colnum);
}
rownum--;
currLines++;
allLines++;
}
}
if(currLines > 0)
{
score += (int) round(pow(4, currLines-1));
}
}
gameOver();
// == Game Over ==
}
}
void gameOver()
{
playNote('F', 80);
playNote('A', 60);
playNote('F', 80);
playNote('A', 60);
int cima =
{
B11111111, // o o o o
B11111111, // o o o o
B11111111, // o o o o
B11111111, // o o
B11111111, // o o o o
B11111111, //
B11111111, // o o o o o o
B11111111 // o o o
};
int baixo =
{
B11111111, // o o o
B11111111, // o o o
B11111111, // o o o
B11111111, //
B11111111, // o o o o
B11111111, // o o
B11111111, // o o
B11111111 // o o o o
};
for(int rownum = 8; rownum >= 0; rownum--)
{
lc.setRow(1,rownum,baixo[rownum]);
delay(100);
}
for(int rownum = 8; rownum >= 0; rownum--)
{
lc.setRow(0,rownum,cima[rownum]);
delay(100);
}
delay(1800);
}
これがプログラムです。とても長いですよね。
・実際に書き込む
それでは実際に書き込んでみます。
まずArduino IDEというプログラミングをするためのアプリを開いてプログラムをコピペします。
そして前回作った回路のArduinoとパソコンをコードで接続します。
最後にArduino IDEでコンパイルのボタンを押すと書込み完了です!
・動作確認
書き込みが完了すると早速音楽が流れてドットマトリクスにTETRISという文字が表示されているはずです。
操作法は
ArduinoのD7につないだボタン ➡ スタートボタン
ArduinoのD2につないだボタン ➡ ミノの向きの変更
ArduinoのD6につないだボタン ➡ 上
ArduinoのD3につないだボタン ➡ 左
ArduinoのD4につないだボタン ➡ 下
ArduinoのD5につないだボタン ➡ 右
となっています。
思う存分遊んでみましょう!
今回はここまでです。
分からないことや間違っているところがあれ ば気軽にコメントしてください!
次回は、外装・3Dプリント編です。
参考にしたサイトはこちら
*1:digitalRead(left_button) == LOW) && (fromLeft > 0
*2:active[colnum] & screen[colnum - 1]) == 0)
{
moveCheck++;
}
}
if(moveCheck == (lcCols - fromLeft - fromRight
*3:digitalRead(right_button) == LOW) && (fromRight > 0
*4:active[colnum] & screen[colnum + 1]) == 0)
{
moveCheck++;
}
}
if(moveCheck == (lcCols - fromLeft - fromRight
*5:fromLeft > 0)
&& (((active[fromLeft + 1] | (active[fromLeft + 1] << 1
*6:fromRight > 0)
&& (((active[fromLeft] >> 1) & screen[fromLeft]) == 0)
&& ((((active[fromLeft + 1] << 1) & active[fromLeft + 1]) & screen[fromLeft + 1]) == 0
*7:active[fromLeft + 1] << 1) | active[fromLeft + 1]);
updateColumn(fromLeft + 2);
fromRight--;
krok--;
angle = 3;
}
break;
case 3:
// . . o . o .
// o o o ---> . o .
// . . . . o o
if(((((active[fromLeft] << 1) | (active[fromLeft] >> 1
*8:active[fromLeft + 2] >> 1) & (active[fromLeft + 2] >> 2
*9:fromRight > 0)
&& ((((active[fromLeft] << 2) | (active[fromLeft] << 1
*10:active[fromLeft] << 2) | (active[fromLeft] << 1
*11:active[fromLeft + 1] << 1) & (active[fromLeft + 1] >> 1
*12:krok < lcRows)
&& ((((active[fromLeft + 1] << 1) | (active[fromLeft + 1] >> 1
*13:fromLeft > 0)
&& (((active[fromLeft + 1] >> 1) & screen[fromLeft - 1]) == 0)
&& ((((active[fromLeft + 1] >> 1) | (active[fromLeft + 1] >> 2
*14:active[fromLeft + 1] << 1) | active[fromLeft + 2]);
updateColumn(fromLeft + 1);
active[fromLeft + 2] = 0;
updateColumn(fromLeft + 2);
fromRight++;
angle = 0;
}
break;
}
break;
case 4:
//"T"
switch(angle)
{
case 0:
// . . . . o .
// o o o ---> o o .
// . o . . o .
if(((active[fromLeft + 1] << 1) & screen[fromLeft + 1]) == 0)
{
//active[fromLeft]
active[fromLeft + 1] = active[fromLeft + 1] | (active[fromLeft + 1] << 1);
updateColumn(fromLeft + 1);
active[fromLeft + 2] = 0;
updateColumn(fromLeft + 2);
fromRight++;
angle = 1;
}
break;
case 1:
// . o . . o .
// o o . ---> o o o
// . o . . . .
if((fromRight > 0)
&& ((active[fromLeft] & screen[fromLeft + 2])== 0
*15:fromLeft > 0)
&& ((active[fromLeft + 1] & screen[fromLeft - 1]) == 0
*16:fromLeft > 0)
&& (fromRight > 1)
&& ((((((active[fromLeft] >> 1) & (active[fromLeft] << 2
*17:active[fromLeft] >> 1) & (active[fromLeft] << 2
*18:krok < (lcRows - 1
*19:fromLeft > 1)
&& (fromRight > 0)
&& ((((((active[fromLeft] << 1) & (active[fromLeft] >> 2
*20:active[fromLeft] << 1) & (active[fromLeft] >> 2
*21:krok < (lcRows
*22:fromRight > 0)
&& ((((active[fromLeft] << 2) & (active[fromLeft] << 1
*23:active[fromLeft] << 2) & (active[fromLeft] << 1
*24:krok < lcRows)
&& (((active[fromLeft + 1] >> 1) & screen[fromLeft + 1]) == 0)
&& (((active[fromLeft + 2] << 1) & screen[fromLeft + 2]) == 0
*25:fromLeft > 0)
&& (((active[fromLeft] & active[fromLeft + 1]) & screen[fromLeft - 1]) == 0)
&& (((active[fromLeft + 1] >> 1) & screen[fromLeft + 1]) == 0
*26:fromRight > 0)
&& (((active[fromLeft + 1] << 1) & screen[fromLeft + 1]) == 0)
&& (((active[fromLeft] & (active[fromLeft] << 1
*27:krok < lcRows)
&& (((active[fromLeft + 1] >> 1) & screen[fromLeft + 2]) == 0
*28:fromLeft > 0)
&& ((active[fromLeft + 1] & ((active[fromLeft + 1] >> 1
*29:active[fromLeft + 1] & screen[fromLeft]) == 0
*30:screen[colnum] & (active[colnum] >> 1
*31:colCheck == lcCols) && (krok < lcRows
*32:int) round(pow(2, rownum)));
screen[colnum] = screen[colnum] & tmpCol;
updateColumn(colnum);
switch(currLines)
{
case 0:
playNote('b', 20);
break;
case 1:
playNote('D', 20);
break;
case 2:
playNote('F', 20);
break;
case 3:
playNote('A', 20);
break;
}
delay(30);
tmpCol = (int) (round(pow(2, rownum
Arduinoを使ったテトリスのゲーム機の作り方part1 回路制作編
Arduinoを使ったテトリスのゲーム機の作り方part1 回路制作編
本記事ではマイコンであるArduinoを使ったテトリスのゲームの作り方を紹介していきます。今回はpart1 回路制作編です。Arduinoがそもそも何か分からないという人は こちらへ。完成はこんな感じです。
目次
- 使う部品紹介
- ブレッドボードに回路を組む(初心者向け)
- ユニバーサル基板にはんだ付けをし部品を実装(上級者向け)
・使う部品紹介
人間でいう脳の部分の部品です。ここにプログラムを書き込んで命令を送ります。
Arduino nanoやArduino unoなど種類がたくさんあります。特に指定はないですが今回はArduino nanoを使います。
・ドットマトリクスLEDモジュール(2つ)
小さなLED(上の画像の○の部分)が64個ついていて先程のArduinoを使って1つ1つ制御します。そうすることによって文字やイラストが作れたりします。これをディスプレイとしてテトリスのゲーム画面にします。
または
・タクトスイッチ
この部品は名前にもあるようにスイッチです。ボタンを押すと内部でつながり。通電するようになります。これをテトリスの入力ボタンにします。
・圧電ブザー
名前にあるようにブザーです。このブザーに電圧を流すことによって内部にある金属板が振動し音が鳴ります。周りにある音が出る機械には大体使われています。これを使いテトリスの音楽や効果音を流します。
・ブレッドボード(初心者向け)
この部品は配線をするときの使います。穴がたくさん開いていてこの穴に電子部品を接続します。縦に並んでいる穴どうしが通電しています。正常に動くかどうかを確認するときに使ったりもします。
・ユニバーサル基盤と半田付けセット(上級者向け)
基盤を作る時に必要になってきます。基盤を作らずブレッドボードだけで良いという方は必要ありません。テトリスのゲーム機をスマートに小さくすることができます。半田付けが必要となってくるので上級者向けです。
ユニバーサル基盤
半田付けセット
・ジャンパーワイヤー
銅線で、電子部品と先ほど紹介したブレッドボードを接続したりするときに使います。
・電池またはバッテリー
機械を動かすには必ず電気が必要となってくるので電池を使います。アルカリ電池のような一回しか使えない電池とリチウムバッテリーのような充電すると何度も使える電池があります。アルカリ電池のほうが入手しやすく使い方も簡単です。
・電池ボックス
アルカリ電池などの電池を使う人はこの電池ボックスが必要となります。ここに電池を入れます。
使う部品は以上です!
これらの部品のほかにたくさんの電子部品が入っているキットがあります。電子工作やプログラミングの基礎を学習できるのでおすすめです。
※ドットマトリクスは一つしか入っていません
・ブレッドボードに回路を組む
それでは早速ブレッドボードに回路を組んでいきます。
回路は上の図のように組んでください。圧電ブザーはトランジスタにつながっていますがなくても全然動きます。トランジスタをつけない場合は圧電ブザーの白い線を直接ArduinoのD7に接続してください。ブレッドボードの特性を生かしながら工夫して組むといい感じになります。
並びは違うかもしれませんが、こんな感じにできているはずです。これで回路は完成です!おつかれさまでした。
・ユニバーサル基盤に回路を組む(上級者向け)
電子工作上級者の方や、半田付けの経験があるという方は挑戦してみてください!ユニバーサル基盤に半田付けをすることによって、回路が小さくなりまとまります。
ユニバーサル基盤に回路を組むとこんな感じになります。ブレッドボードの時よりもだいぶスッキリしてコンパクトになっていますよね。
今回はここまでです。
分からないことや間違っているところがあれば気軽にコメントしてください。次回は、プログラミング編です。
参考にしたサイトはこちら
Seeed-Fusionの使用レビュー
今回はSeeed-Fusionという基板製造や部品実装その他の電子・機械オーダーメイド の注文をするサイトのレビューをしていきます。
[目次]
- 注文方法
- 品質について
- まとめ
注文方法
Seeed-Fusionの公式サイトでガーバーファイルという基板のファイルをアップロードし詳細設定を入力するだけで簡単に注文することができます。もしデータに不備があってもメールで知らせてくれて改善策も教えてくれます。
品質について
大体1カ月くらいで届きます。丁寧に梱包されていて発送中の破損などはなさそうです。
マイコンのArduino UNOの基盤を5枚注文しました。特に問題なく動作して。破損などもなく綺麗にできています。
まとめ
注文も簡単にすることができ品質も良いです。また注文をすると次回使える5%オフクーポンがついてきてサービスも充実しています。電子工作をしていて基盤が必要だという方はぜひSeeed-Fusionで注文してみてください!
注文はこちらから!