diff --git a/Another.ino b/Another.ino deleted file mode 100644 index 8b256ab..0000000 --- a/Another.ino +++ /dev/null @@ -1,338 +0,0 @@ -#include -#include -#include -#include - -// --- 色定義 --- -#define BLACK 0x0000 -#define WHITE 0xFFFF -#define GREEN 0x07E0 -#define RED 0xF800 -#define GRAY 0x8410 // おじゃまブロック用の色 - -#define SCREEN_W 240 -#define SCREEN_H 135 - -#define STACK_MAX 10 // おじゃまブロックの送信スタックの最大数 - -// --- バー設定 --- -int barW = 40; -int barH = 5; -int barX = (SCREEN_W - barW) / 2; -int barY = SCREEN_H - 10; - -// --- ボール設定 --- -float ballX = SCREEN_W / 2; -float ballY = SCREEN_H / 2; -float ballVX = 2.5; -float ballVY = -2.0; -int ballR = 3; - -// --- ブロック設定 --- -const int BLOCK_ROWS = 4; -const int BLOCK_COLS = 8; -int blockW = SCREEN_W / BLOCK_COLS; -int blockH = 12; -// ブロックの状態: 0 = なし, 1 = 通常, 2 = おじゃま -int blocks[BLOCK_ROWS][BLOCK_COLS]; - -// --- ゲーム状態 --- -bool gameWon = false; -bool gameOver = false; -int life = 3; - -// --- 通信とおじゃまブロック用のスタック --- -int sent_stack = 0; // 送信用のスタック -volatile int recv_stack = 0; // 受信したおじゃまブロックのスタック (ISRから変更されるためvolatile) - -// --- ESP-NOW関連 --- -// ブロードキャストアドレス(すべてのESP-NOWデバイスに送信) -uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; -esp_now_peer_info_t peerInfo; - -// 送受信するデータの構造体 -typedef struct struct_message { - char type; // 'A' = Attack (おじゃまブロック送信) -} struct_message; - -struct_message myData; - - -// --- 関数プロトタイプ --- -void Init_ESPNOW(); -void onESPNOWSent(const uint8_t *mac_addr, esp_now_send_status_t status); -// ★★★ エラー修正箇所 ★★★ -void onESPNOWReceive(const esp_now_recv_info_t *info, const uint8_t *incomingData, int len); -void sendAttack(); -void addOjamaBlock(); -void resetBlocks(); -void resetBall(); - -// ESP-NOW データ送信後のコールバック -void ICACHE_RAM_ATTR onESPNOWSent(const uint8_t *mac_addr, esp_now_send_status_t status) { - // 送信結果はここでは特に処理しない -} - -// ESP-NOW データ受信時のコールバック -// ★★★ ESP32コアのバージョンアップに対応した引数に変更 ★★★ -void ICACHE_RAM_ATTR onESPNOWReceive(const esp_now_recv_info_t *info, const uint8_t *incomingData, int len) { - struct_message msg; - memcpy(&msg, incomingData, sizeof(msg)); - if (msg.type == 'A') { - recv_stack++; // おじゃまスタックを増やす - } -} - -// ESP-NOW初期化 -void Init_ESPNOW() { - WiFi.mode(WIFI_STA); - WiFi.disconnect(); - if (esp_now_init() == ESP_OK) { - M5.Display.println("ESP-Now Init Success"); - esp_now_register_send_cb(onESPNOWSent); - // ★★★ ここで呼び出す関数のシグネチャがコンパイルエラーの原因だった ★★★ - esp_now_register_recv_cb(onESPNOWReceive); - } else { - M5.Display.println("ESP-Now Init Failed"); - return; - } - - memcpy(peerInfo.peer_addr, broadcastAddress, 6); - peerInfo.channel = 0; - peerInfo.encrypt = false; - - if (esp_now_add_peer(&peerInfo) != ESP_OK){ - M5.Display.println("Failed to add peer"); - return; - } - M5.Display.println("Peer added"); -} - -// 攻撃(おじゃまブロック)を送信 -void sendAttack() { - myData.type = 'A'; - esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); -} - -// おじゃまブロックを追加 -void addOjamaBlock() { - // 下の行から空いている場所を探す - for (int i = BLOCK_ROWS - 1; i >= 0; --i) { - for (int j = 0; j < BLOCK_COLS; ++j) { - if (blocks[i][j] == 0) { // 空のマスを見つけたら - blocks[i][j] = 2; // おじゃまブロック(2)を設置 - return; // 1つ追加したら終了 - } - } - } -} - - -void resetBlocks() { - for (int i = 0; i < BLOCK_ROWS; ++i) - for (int j = 0; j < BLOCK_COLS; ++j) - blocks[i][j] = 1; // 通常ブロック(1)で初期化 - gameWon = false; - gameOver = false; - life = 3; - sent_stack = 0; - recv_stack = 0; -} - -bool allBlocksCleared() { - for (int i = 0; i < BLOCK_ROWS; ++i) - for (int j = 0; j < BLOCK_COLS; ++j) - if (blocks[i][j] != 0) return false; // ブロックが1つでも残っていたらfalse - return true; -} - -void showMessage(const char* msg) { - M5.Display.fillScreen(BLACK); - M5.Display.setTextColor(WHITE); - M5.Display.setCursor(60, SCREEN_H / 2 - 8); - M5.Display.println(msg); - delay(1500); -} - -void resetBall() { - ballX = SCREEN_W / 2; - ballY = SCREEN_H / 2; - ballVX = 2.5; - ballVY = -2.0; -} - - -void setup() { - auto cfg = M5.config(); - M5.begin(cfg); - M5.Display.setRotation(3); - M5.Display.setTextFont(1); - M5.Display.fillScreen(BLACK); - - - delay(500); // 通信初期化のための待機 - M5.Display.clear(); - - resetBlocks(); -} - -void loop() { - M5.update(); - - if (gameWon) { - showMessage("You Win!"); - resetBlocks(); - resetBall(); - return; - } - - if (gameOver) { - showMessage("You Lose..."); - resetBlocks(); - resetBall(); - return; - } - - // 受信したおじゃまブロックを処理 - if (recv_stack > 0) { - addOjamaBlock(); - recv_stack--; - } - - // 操作(傾き) - if (M5.Imu.update()) { - auto data = M5.Imu.getImuData(); - float tilt = -data.accel.y; - float speed = tilt * 10.0; - barX += (int)speed; - if (barX < 0) barX = 0; - if (barX > SCREEN_W - barW) barX = SCREEN_W - barW; - } - - // ボール移動 - ballX += ballVX; - ballY += ballVY; - - // 壁反射 - if (ballX <= ballR) { - ballX = ballR + 1; - ballVX *= -1; - M5.Speaker.tone(2000, 100); - } - if (ballX >= SCREEN_W - ballR) { - ballX = SCREEN_W - ballR - 1; - ballVX *= -1; - M5.Speaker.tone(2000, 100); - } - if (ballY <= ballR) { - ballY = ballR + 1; - ballVY *= -1; - M5.Speaker.tone(2000, 100); - } - - // バー反射 - if (ballY + ballR >= barY && ballY + ballR <= barY + barH && - ballX >= barX && ballX <= barX + barW) { - float offset = (ballX - (barX + barW / 2)) / (barW / 2); - float angle_deg = 15 + 60 * fabs(offset); - float angle_rad = angle_deg * M_PI / 180.0; - float speed = sqrt(ballVX * ballVX + ballVY * ballVY); - ballVX = speed * sin(offset >= 0 ? angle_rad : -angle_rad); - ballVY = -speed * cos(angle_rad); - ballY = barY - ballR - 1; - M5.Speaker.tone(2000, 100); // バーに当たった音 - - if (ballX <= ballR) { - ballX = ballR + 1; - } - if (ballX >= SCREEN_W - ballR) ballX = SCREEN_W - ballR - 1; - } - - // ブロックとの衝突 - for (int i = 0; i < BLOCK_ROWS; ++i) { - for (int j = 0; j < BLOCK_COLS; ++j) { - if (blocks[i][j] > 0) { // ブロックが存在すれば - int bx = j * blockW; - int by = i * blockH; - if (ballX + ballR > bx && ballX - ballR < bx + blockW && - ballY + ballR > by && ballY - ballR < by + blockH) { - - if(blocks[i][j] == 1) { // 通常ブロックの場合 - blocks[i][j] = 0; // ブロックを消す - sent_stack++; // 送信用スタックを+1 - if (sent_stack >= STACK_MAX) { - sendAttack(); // STACK_MAXつ溜まったら攻撃 - sent_stack = 0; // スタックリセット - } - } else if (blocks[i][j] == 2) { // おじゃまブロックの場合 - blocks[i][j] = 1; // 通常ブロックに変化させる - } - - // 反射方向の計算 - float cx = bx + blockW / 2; - float cy = by + blockH / 2; - float dx = ballX - cx; - float dy = ballY - cy; - if (fabs(dx / blockW) > fabs(dy / blockH)) { - ballVX *= -1; - M5.Speaker.tone(2000, 100); - } else { - ballVY *= -1; - M5.Speaker.tone(2000, 100); - } - - goto block_hit_done; - } - } - } - } -block_hit_done: - - // ボールが下に落ちたらライフ減 - if (ballY > SCREEN_H) { - life--; - if (life <= 0) { - gameOver = true; - return; - } else { - resetBall(); - } - } - - if (allBlocksCleared()) { - gameWon = true; - return; - } - - - // === 描画 === - M5.Display.startWrite(); - M5.Display.fillScreen(BLACK); - - // ブロック - for (int i = 0; i < BLOCK_ROWS; ++i) { - for (int j = 0; j < BLOCK_COLS; ++j) { - int bx = j * blockW; - int by = i * blockH; - if (blocks[i][j] == 1) { // 通常ブロック - M5.Display.fillRect(bx + 1, by + 1, blockW - 2, blockH - 2, GREEN); - } else if (blocks[i][j] == 2) { // おじゃまブロック - M5.Display.fillRect(bx + 1, by + 1, blockW - 2, blockH - 2, GRAY); - } - } - } - - // バー - M5.Display.fillRect(barX, barY, barW, barH, WHITE); - - // ボール - M5.Display.fillCircle((int)ballX, (int)ballY, ballR, RED); - - // ライフ表示 - M5.Display.setTextColor(WHITE); - M5.Display.setCursor(5, 5); - M5.Display.printf("Life: %d", life); - M5.Display.endWrite(); - - delay(16); -} \ No newline at end of file