前回の続きです。
せっかくSTM32F103C8T6(with 128k,Bluepill)から自作テトリス風ゲームが動かせるようなので、タッチ機能で操作できないかと悪戦苦闘しました。しかし、出来そうにありません。諦めてシリアル通信に変更、一応完成させました。ついでにArduinoIDEのToolsで2点ほど試しました(右下の写真参照)。
1.CDC(Communication Device Class)を用いたシリアル通信
2.Optimize: "Fastest(-O3) with LTO"
1により別途USBシリアルモジュールが不要になります。2は微妙ですが、2~3%程速くなってると思われます。スケッチにおけるシリアル通信操作は以下のようにしました。
if (Serial.available())
{
char c=Serial.read();
if(c== 'a'){ bLeft(bNum);
}else if(c == 'd') {bRight(bNum);
}else if(c == 's') {bRot(&bNum); // bNum と&bNum の違いに意味はありません
}else if(c == 'z') {jamp=true;
}else if(c == 'x') {scene=RESET;}
}
こちらの方がブロック操作は楽でした。特に「Tera Term」であればリターンキーを押さなくても逐一、キー送信してくれるので楽です。
ピンの接続です。
TFT SPI | BluePill |
---|---|
LED | 3.3 |
TFT_SCK | PA5 |
TFT_MOSI | PA7 |
TFT_DC(RS) | PA2 |
TFT_RESET | PA3 |
TFT_CS | PA4 |
GND | G |
VCC | 5V |
TFT_eSPIライブラリでの「User_Setup.h」とAeduinoIDEのスケッチを以下に載せます。
User_Setup.h
#define USER_SETUP_INFO "User_Setup"
// Define STM32 to invoke optimised processor support (only for STM32)
#define STM32
#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ######
#define STM_PORTA_DATA_BUS
// The TFT can be connected to SPI port 1 or 2
#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
#define TFT_MOSI PA7
#define TFT_MISO PA6
#define TFT_SCLK PA5
#define TFT_DC PA2 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
#define TFT_RST PA3 // Reset pin to TFT RST (or RESET)
#define TFT_CS PA4 // Chip select control pin to TFT CS
#define TOUCH_CS PA1 // Chip select pin (T_CS) of touch screen
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
// this will save ~20kbytes of FLASH
//#define SMOOTH_FONT
// ##################################################################################
//
// Section 4. Other options
//
// ##################################################################################
#define SPI_FREQUENCY 18000000
#define SPI_READ_FREQUENCY 10000000
#define SPI_TOUCH_FREQUENCY 1000000
タッチ機能の部分は実際には役に立っていません。次にスケッチを示します。
F103_Tenoros.ino
F103_Tenoros.ino
#include <TFT_eSPI.h> // Hardware-specific library
#define Y_H 24 // フィールドの高さ(上3段と最下段の壁を含む)
#define X_W 12 // フィールドの幅(両側の壁を含む)
#define Vars 32 // ブロックの種類(回転で得られるもの全部を別種とする)
#define PI 18 // 縦横pixel数 フィールド縦18x24=432 dots, フィールド横18x12=216 dots
#define Y0 0 // フィールド表示位置
#define X0 52
#define Y TFT_YELLOW
#define W TFT_WHITE
#define R TFT_RED
#define D TFT_DARKGREY
#define K TFT_BLACK
#define B TFT_BLUE
#define G TFT_GREEN
#define M TFT_MAGENTA
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
int field[Y_H][X_W]; // ブロックなどのデータを設定
int aline[Y_H]; // 横一列の固定ブロック数
int bXL = 0, bYU = 0, bW = 0, bH = 0, bXR = 0, bYD = 0; // 現ブロックのデータの代入先
int nextB5[5];
int bNum = 0;
int timer = 0;
enum { TITLE,
PLAY,
OVER,
RST }; // 各シーンを定める定数
int scene; // どのシーンの処理を行うか
int bSizeX[Vars] = { 4, 1, 4, 1, // 各ブロックの横サイズ
3, 2, 3, 2,
3, 2, 3, 2,
3, 2, 3, 2,
3, 2, 3, 2,
2, 2, 2, 2,
3, 2, 3, 2,
3, 2, 3, 2 };
int bSizeY[Vars] = { 1, 4, 1, 4, // 各ブロックの縦サイズ
2, 3, 2, 3,
2, 3, 2, 3,
2, 3, 2, 3,
2, 3, 2, 3,
2, 2, 2, 2,
2, 3, 2, 3,
2, 3, 2, 3 };
int blocks[Vars][4][4] = // variety, y, x
{ { { 1, 1, 1, 1 }, // I
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 0, 0, 0 },
{ 1, 0, 0, 0 },
{ 1, 0, 0, 0 },
{ 1, 0, 0, 0 } },
{ { 1, 1, 1, 1 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 0, 0, 0 },
{ 1, 0, 0, 0 },
{ 1, 0, 0, 0 },
{ 1, 0, 0, 0 } },
{ { 1, 1, 1, 0 }, // 逆L
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 1, 1, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 0, 0, 0 },
{ 1, 1, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 1, 0, 0 },
{ 1, 0, 0, 0 },
{ 1, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 0, 0, 1, 0 }, // L
{ 1, 1, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 0, 0, 0 },
{ 1, 0, 0, 0 },
{ 1, 1, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 1, 1, 0 },
{ 1, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 1, 1, 0 }, // T
{ 0, 1, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 0, 1, 0, 0 },
{ 1, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 0, 1, 0, 0 },
{ 1, 1, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 0, 0, 0 },
{ 1, 1, 0, 0 },
{ 1, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 0, 1, 0, 0 }, // 逆T
{ 1, 1, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 0, 0, 0 },
{ 1, 1, 0, 0 },
{ 1, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 1, 1, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 0, 1, 0, 0 },
{ 1, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 1, 0, 0 }, // 正方形
{ 1, 1, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 1, 0, 0 },
{ 1, 1, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 1, 0, 0 },
{ 1, 1, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 1, 0, 0 },
{ 1, 1, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 0, 1, 1, 0 }, // 稲妻
{ 1, 1, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 0, 0, 0 },
{ 1, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 0, 1, 1, 0 },
{ 1, 1, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 0, 0, 0 },
{ 1, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 1, 0, 0 }, // 逆稲妻
{ 0, 1, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 0, 1, 0, 0 },
{ 1, 1, 0, 0 },
{ 1, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 1, 1, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } },
{ { 0, 1, 0, 0 },
{ 1, 1, 0, 0 },
{ 1, 0, 0, 0 },
{ 0, 0, 0, 0 } } };
void initField() { // フィールド情報配列の初期化
for (int i = 0; i < Y_H - 1; i++) {
for (int j = 0; j < X_W; j++) {
if (j == 0 || j == X_W - 1)
field[i][j] = 9;
else field[i][j] = 0; // 何も無い所は0(黒)
}
aline[i] = 0; // 横一列の情報
}
for (int j = 0; j < X_W; j++) field[Y_H - 1][j] = 9; // 壁は9(濃い灰色)
}
void drawWall(void) { // 壁を描画
for (int i = 3; i <= Y_H - 1; i++) { // 0,1,2は壁なし
if (i == Y_H - 1)
for (int j = 0; j < X_W; j++)
tft.fillRect(X0 + PI * j, Y0 + PI * i, PI - 2, PI - 2, D);
else {
tft.fillRect(X0 + PI * 0, Y0 + PI * i, PI - 2, PI - 2, D);
tft.fillRect(X0 + PI * (X_W - 1), Y0 + PI * i, PI - 2, PI - 2, D);
}
}
}
void drawField(void) { // フィールド情報を描画
for (int i = 0; i < Y_H - 1; i++) {
for (int j = 1; j < X_W - 1; j++) {
if (field[i][j] == 1) { // 移動中のブロックは黄
tft.fillRect(X0 + PI * j, Y0 + PI * i, PI - 2, PI - 2, Y);
} else if (field[i][j] == 2) { // 固定ブロックは白
tft.fillRect(X0 + PI * j, Y0 + PI * i, PI - 2, PI - 2, W);
} else { // == 9
tft.fillRect(X0 + PI * j, Y0 + PI * i, PI - 2, PI - 2, K);
}
}
}
}
void bRight(int n) { // 右移動
if (bXR < X_W - 2) {
for (int y = bH - 1; y >= 0; y--) {
for (int x = bW - 1; x >= 0; x--)
if (field[bYU + y][bXL + x + 1] > 1) return; // 固定物に衝突
}
for (int y = bH - 1; y >= 0; y--) {
for (int x = bW - 1; x >= 0; x--) {
if (field[bYU + y][bXL + x] < 2 && field[bYU + y][bXL + x + 1] < 2) // 自分自身のみ移動
field[bYU + y][bXL + x + 1] = field[bYU + y][bXL + x]; // フィールドデータ移動
if (field[bYU + y][bXL + x] >= 2 && field[bYU + y][bXL + x + 1] < 2)
field[bYU + y][bXL + x + 1] = 0;
}
if (field[bYU + y][bXL] < 2) field[bYU + y][bXL] = 0;
}
bXL++;
bXR++;
}
}
void bLeft(int n) { // 左移動
if (bXL > 1) {
for (int y = bH - 1; y >= 0; y--) {
for (int x = 0; x < bW; x++)
if (field[bYU + y][bXL + x - 1] > 1 && field[bYU + y][bXL + x] == 1) return; // 衝突
}
for (int y = bH - 1; y >= 0; y--) {
for (int x = 0; x < bW; x++) {
if (field[bYU + y][bXL + x - 1] < 2 && field[bYU + y][bXL + x] < 2) // 自分自身のみ移動
field[bYU + y][bXL + x - 1] = field[bYU + y][bXL + x];
if (field[bYU + y][bXL + x - 1] < 2 && field[bYU + y][bXL + x] >= 2)
field[bYU + y][bXL + x - 1] = 0;
}
if (field[bYU + y][bXR] < 2) field[bYU + y][bXR] = 0;
}
bXL--;
bXR--;
}
}
int rotCheck(int n0, int bXL, int bYU) {
int l, m, n = n0;
int bW, bH, bXR, bYD;
l = (int)(n / 4) * 4;
m = ((n % 4) + 1) % 4;
n = l + m; // 回転後のブロック番号でチェック
bW = bSizeX[n]; // 各情報更新
bH = bSizeY[n];
bXR = bXL + bW - 1;
bYD = bYU + bH - 1;
if (bXR >= X_W - 1) { // 右壁にぶつかったとき
bXL -= 1;
bXR -= 1;
}
if (bXL < 1) { // 左壁にぶつかったとき
bXL += 1;
bXR += 1;
}
bool flg = true; // Collision Check
for (int y = 0; y < bH; y++) {
for (int x = 0; x < bW; x++) {
if (blocks[n][y][x] == 1 && field[bYU + y][bXL + x] > 1) {
flg = false; // ブロック描画位置に何かある
}
}
}
if (flg == true) return 1;
else return 0;
}
void bRot(int* num) { // 回転(右のみ)
int l, m, n = *num;
if (rotCheck(n, bXL, bYU) == 0) return; // 回転できない
for (int y = 0; y < bH; y++) { // 前ブロックを消す
for (int x = 0; x < bW; x++) {
field[bYU + y][bXL + x] -= blocks[n][y][x];
tft.fillRect(X0 + PI * (bXL + x), Y0 + PI * (bYU + y), PI - 2, PI - 2, D);
}
}
l = (int)(n / 4) * 4;
m = ((n % 4) + 1) % 4;
n = l + m; // 回転後の新ブロック番号
bW = bSizeX[n]; // 各情報更新
bH = bSizeY[n];
bXR = bXL + bW - 1;
bYD = bYU + bH - 1;
if (bXR >= X_W - 1) { // 右壁にぶつかったとき
bXL -= 1;
bXR -= 1;
}
if (bXL < 1) { // 左壁にぶつかったとき
bXL += 1;
bXR += 1;
}
for (int y = 0; y < bH; y++) { // 回転後のブロック描画
for (int x = 0; x < bW; x++) {
if (field[bYU + y][bXL + x] <= 1) {
if (blocks[n][y][x] == 1) {
field[bYU + y][bXL + x] = 1;
tft.fillRect(X0 + PI * (bXL + x), Y0 + PI * (bYU + y), PI - 2, PI - 2, Y);
} else if (blocks[n][y][x] == 0) {
field[bYU + y][bXL + x] = 0;
tft.fillRect(X0 + PI * (bXL + x), Y0 + PI * (bYU + y), PI - 2, PI - 2, K);
}
}
}
}
*num = n;
}
int rakka(int n) {
bool descentflg = true;
bW = bSizeX[n];
bH = bSizeY[n];
for (int x = 0; x < bW; x++) {
for (int y = bH - 1; y > bH - 4; y--) {
if (blocks[n][y][x] == 1 && field[bYU + y + 1][bXL + x] > 1) descentflg = false; // ブロック落下不可
}
}
int sum;
if (descentflg == false) {
for (int y = 0; y < bH; y++) {
for (int x = 0; x < bW; x++) {
if (blocks[n][y][x] == 1) field[bYU + y][bXL + x] = 2; // ブロック固定
}
}
int TG[Y_H];
for (int i = 0; i < Y_H; i++) { TG[i] = -1; }
sum = 0;
for (int i = Y_H - 2; i >= 0; i--) { // 横一列揃ったか調べる
aline[i] = 0;
for (int j = 1; j < X_W - 1; j++) {
if (field[i][j] == 2) aline[i] = aline[i] + 1;
}
if (aline[i] == X_W - 2) { // == 10 揃った
for (int j = 1; j < X_W - 1; j++)
tft.fillRect(X0 + PI * j, Y0 + PI * i, PI - 2, PI - 2, M); // MAGENTAで強調
TG[sum] = i;
sum++;
delay(50);
}
}
if (aline[3] > 0) return aline[3]; //--- GAME OVER ----------------
if (sum > 0) { // 揃った行を消す
for (int t = 0; t < sum; t++) {
for (int i = TG[t] + t; i > 0; i--) {
for (int j = 1; j < X_W - 1; j++)
tft.fillRect(X0 + PI * j, Y0 + PI * i, PI - 2, PI - 2, R); // 赤で強調
delay(50);
for (int j = 1; j < X_W - 1; j++) {
field[i][j] = field[i - 1][j]; // 消去行に上段のデータを移動、上書き
if (field[i][j] == 0) {
tft.fillRect(X0 + PI * j, Y0 + PI * i, PI - 2, PI - 2, K);
} else { // field[i][j] == 2 固定ブロックは描画
tft.fillRect(X0 + PI * j, Y0 + PI * i, PI - 2, PI - 2, W);
}
}
aline[i] = aline[i - 1]; // 固定ブロック数の行データも移動
}
for (int j = 1; j < X_W - 1; j++) field[0][j] = 0; // 最上段は0で埋める
}
}
sum = 0;
descentflg = true;
return -1; // 次の新ブロックの生成落下
} else { // 落下可能
bYU++;
bYD++;
for (int i = Y_H - 2; i >= 0; i--) { // 最上段の0,1,2行もブロックを描画、落下させる
if (i == 0) {
for (int j = 1; j < X_W - 1; j++) field[i][j] = 0; // 最上段は0で埋める
} else {
for (int j = 1; j < X_W - 1; j++) {
if (field[i][j] >= 2) { ; } // 壁、固定物があるので移動できない
else if (field[i - 1][j] == 2) {
;
} // 固定物は移動しない
else {
field[i][j] = field[i - 1][j]; // 一行下に移動
field[i - 1][j] = 0; // 移動後は空欄
}
}
}
}
int tY = bYU;
bool flg = true;
while (flg) {
tY += 1;
for (int y = 0; y < bH; y++) {
for (int x = 0; x < bW; x++) { // 現状、どこまで落下できるか調べる
if (field[tY + y][bXL + x] > 1 && blocks[n][y][x] == 1) {
flg = false;
}
}
}
}
tY -= 1;
for (int y = 0; y < bH; y++) { // 落下予想図
for (int x = 0; x < bW; x++) {
if (blocks[n][y][x] == 1) {
tft.fillRect(X0 + PI * (bXL + x), Y0 + PI * (tY + y), PI - 2, PI - 2, R);
}
}
}
return 0;
}
}
void nbDisp(int* b) { // 次のブロック5個を表示
int X1 = 0, Y1 = PI; // 文字(番号)、ブロック位置
int pi = PI - 5; // 13
int dw = pi * 4, dh = pi * 5;
tft.fillRect(X1, Y1, dw, dh * 5, K);
for (int n = 0; n < 5; n++) {
int i = b[n]; // numbers of next 5 blocks
for (int y = 0; y < bSizeY[i]; y++) {
for (int x = 0; x < bSizeX[i]; x++) {
if (blocks[i][y][x] == 1)
tft.fillRect(X1 + pi * x, Y1 + pi + dh * n + pi * y, pi - 2, pi - 2, Y);
}
}
tft.setTextColor(W);
tft.drawString("Next " + String(n), X1, Y1 + dh * n, 2);
}
Serial.println("New Block");
}
void nbSet(int* num, int* b) { // 新ブロックをセット
bW = bSizeX[*num];
bH = bSizeY[*num];
bYU = 4 - bH;
int j = random(0, X_W - 1 - bSizeX[*num]) + 1;
bXL = j;
bXR = bXL + bW - 1;
bYD = bYU + bH - 1;
for (int y = 0; y < bH; y++) {
for (int x = 0; x < bW; x++) {
if (blocks[*num][y][x] == 1) field[bYU + y][bXL + x] = 1;
else field[bYU + y][bXL + x] = 0;
}
}
for (int n = 0; n < 4; n++) b[n] = b[n + 1]; // キューの更新
b[4] = random(0, 32);
}
void gStart() {
initField();
randomSeed(analogRead(A0));
for (int i = 0; i < 5; i++) nextB5[i] = random(0, 24); // 5個のブロック生成。初手は稲妻型以外。
scene = PLAY;
timer = -1; // timer = -1 で新ブロック生成、落下が始まる
Serial.println("New Game Start");
}
int dtimer = 5;
int machi = 200;
int countRot = 0;
int dButtonW = (320 - 50) / 3; // =90
int bx0 = 0, bx1 = dButtonW + 25, bx2 = bx1 * 2;
int dBH = 479 - (Y0 + PI * 24);
int bx3 = X0 + PI * 12;
int rButtonW = X0, rBH = PI * 4;
void setup() {
Serial.begin(115200);
tft.init(); // DisplayとTouchは同じSPIを使用
// T_DOのみMISOと接続し、SDO(MISO)はMISOと接続しない。
// T_DIN、SDI(MOSI)はMOSIと接続する。
tft.setRotation(2); // J2Pinsが上部の縦使い。
// 描画座標は、右にx(0-319)、下にy(0-479)。
// タッチ座標は、上にt_x(0-319)、左にt_y(0-479)なので換算が必要。
tft.fillScreen(TFT_BLACK); // Clear the screen
tft.setTextColor(K);
tft.fillRect(bx0, Y0 + PI * 24, dButtonW, dBH, B);
tft.drawString("Left", bx0 + PI, Y0 + PI * 24 + 10, 2);
tft.fillRect(bx1, Y0 + PI * 24, dButtonW, dBH, R);
tft.drawString("Rotation", bx1 + PI, Y0 + PI * 24 + 10, 2);
tft.fillRect(bx2, Y0 + PI * 24, dButtonW, dBH, G);
tft.drawString("RIGHT", bx2 + PI, Y0 + PI * 24 + 10, 2);
tft.fillRect(bx3, Y0 + PI * 19, rButtonW, rBH, W);
tft.drawString("Down", bx3 + 10, Y0 + PI * 20, 2);
tft.fillRect(bx3, Y0 + PI * 14, rButtonW, rBH, M);
tft.drawString("Reset", bx3 + 10, Y0 + PI * 15, 2);
drawWall();
scene = TITLE;
timer = 0;
}
uint16_t t_x; // To store the touch coordinates
uint16_t t_y;
bool pressed;
bool jamp = false;
void loop(void) {
tft.fillRect(0, 0, 30, 14, TFT_BLACK);
tft.drawString(String(timer, DEC), 0, 0, 2);
switch (scene) {
case TITLE:
tft.fillRect(90, 185, 140, 32, W);
tft.setTextColor(K);
tft.drawString("TENOROS", 102, 192, 4);
tft.setTextColor(R);
tft.drawString("TENOROS", 100, 190, 4);
if (timer > 10) {
tft.fillRect(90, 185, 140, 32, K);
gStart();
}
break;
case PLAY:
drawField();
// Pressed will be set true as there is a valid touch on the screen
pressed = false;
t_x = -1;
t_y = -1;
if (Serial.available())
{
char c=Serial.read();
if(c== 'a'){ bLeft(bNum);
}else if(c == 'd') {bRight(bNum);
}else if(c == 's') {bRot(&bNum);
}else if(c == 'z') {jamp=true;
}else if(c == 'x') {scene=RESET;}
}
if (tft.getTouch(&t_x, &t_y))
{
pressed = true;
Serial.print(t_x);
Serial.print(" : ");
Serial.print(t_y);
Serial.println("");
delay(1);
if (t_x < dBH * 0.65) { // 0.66=320/480
if (t_y < dButtonW * 1.5) bRight(bNum); //jamp = true; // 1.5= 480/320
if (t_y > bx1 * 1.5 && t_y < (bx1 + dButtonW) * 1.4) { // 感度に合わせ調整
countRot++;
if (countRot > 1) {
bRot(&bNum);
countRot = 0;
}
}
if (t_y > 2 * bx1 * 1.4) bLeft(bNum);
} else {
if (t_x > (PI + dBH) * 0.6 && t_x < (PI + dBH + rBH) * 0.65) jamp = true; // 感度に合わせ調整
if (t_x > (PI + dBH + rBH + PI) * 0.65 && t_x < (PI + dBH + rBH + PI + rBH) * 0.66) scene = RESET;
}
}
if (timer == 0) {
bNum = nextB5[0];
nbSet(&bNum, nextB5);
nbDisp(nextB5);
} else if (timer % dtimer == 0) {
int t = rakka(bNum); // ブロック落下処理
if (t == -1) timer = -1; // 次のtimer++でtimer==0がtrueになり、新ブロックの生成落下
if (t > 0) {
scene = OVER; //if (aline[3] > 0)
timer = 0;
}
}
break;
case OVER:
tft.setTextColor(G);
tft.drawString("GAME OVER", 88, 192, 4);
tft.setTextColor(R);
tft.drawString("GAME OVER", 86, 190, 4);
Serial.println("GAME OVER");
if (timer > 30) {
tft.fillRect(80, 190, 160, 32, K);
gStart(); //scene = PLAY;
}
break;
case RST:
tft.setTextColor(G);
tft.drawString("GAME RESET", 81, 192, 4);
tft.setTextColor(R);
tft.drawString("GAME RESET", 79, 190, 4);
if (timer > 20) {
tft.fillRect(78, 190, 162, 32, K);
gStart(); //scene = PLAY;
}
break;
default:
break;
}
timer++;
if (jamp == true) {
jamp = false; // 待ち時間なし
dtimer = 1;
} else {
dtimer = 5;
delay(machi); // jamp==false 一定時間待つ
}
}
数百円のマイコンボードなのに結構遊べます。最後までご覧いただき有難うございました。