diff --git a/OurSketch.ino b/OurSketch.ino index d063582..8826595 100644 --- a/OurSketch.ino +++ b/OurSketch.ino @@ -1,93 +1,212 @@ -#include -#include +Dashboard +M5 Src (.ino) +旧システム -//Bar_Color BLUE -#define BAR_Y 120 -#define BAR_SIZE 50 -#define BAR_SPEED 4 -#define O_SIZE 4 -#define BALL_SPEED 2 +堀 巧摩 +ソースコードの参照 : gpt (作成者: 堀 巧摩) 自分用にCopy Hash: 0bb2f241f053... +注:このページのURLをシェアすると、他のユーザも参照したり、自分用にコピーしたりできるようになります。 +#include +#include + +// --- 色定義 --- +#define BLACK 0x0000 +#define WHITE 0xFFFF +#define GREEN 0x07E0 +#define RED 0xF800 + +#define SCREEN_W 240 +#define SCREEN_H 135 + +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; +bool blocks[BLOCK_ROWS][BLOCK_COLS]; + +bool gameWon = false; +bool gameOver = false; +int life = 3; + +void resetBlocks() { + for (int i = 0; i < BLOCK_ROWS; ++i) + for (int j = 0; j < BLOCK_COLS; ++j) + blocks[i][j] = true; + gameWon = false; + gameOver = false; + life = 3; +} + +bool allBlocksCleared() { + for (int i = 0; i < BLOCK_ROWS; ++i) + for (int j = 0; j < BLOCK_COLS; ++j) + if (blocks[i][j]) return 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(); - cfg.serial_baudrate = 115200; M5.begin(cfg); M5.Display.setRotation(3); - M5.Display.setFont(&fonts::lgfxJapanGothic_16); - - M5.Display.setTextScroll(true); - M5.Display.setBrightness(255); + M5.Display.setTextFont(1); M5.Display.fillScreen(BLACK); + resetBlocks(); } -int bar_x = 0; -int bar_right = 1; -double o_x=30; //ボールの初期座標 -double o_y = 30; -int ball_degree = 45;//ボールの初期方向 -int game = 1; void loop() { - if(game != 1){//ゲームオーバになっていたら初期化 - o_x = 30;//ボールの初期座標 - o_y = 30; - ball_degree = 45;//ボールの初期方向 - game = 1; - } - - - M5.update(); - M5.Display.startWrite(); + if (gameWon) { + showMessage("You Win!"); + resetBlocks(); + resetBall(); + return; + } + + if (gameOver) { + showMessage("You Lose..."); + resetBlocks(); + resetBall(); + return; + } + + // 操作(傾き) + 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; + } + if (ballX >= SCREEN_W - ballR) { + ballX = SCREEN_W - ballR - 1; + ballVX *= -1; + } + if (ballY <= ballR) { + ballY = ballR + 1; + ballVY *= -1; + } + + // バー反射 + 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; + + // 壁に接近してる場合は少し内側に押し戻す + 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]) { + int bx = j * blockW; + int by = i * blockH; + if (ballX + ballR > bx && ballX - ballR < bx + blockW && + ballY + ballR > by && ballY - ballR < by + blockH) { + blocks[i][j] = false; + + 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; + } else { + ballVY *= -1; + } + + 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.fillScreen(BLACK); - M5.Display.drawFastHLine(bar_x,BAR_Y,BAR_SIZE,BLUE); - M5.Display.fillCircle(round(o_x),round(o_y),O_SIZE,RED); - M5.Display.endWrite(); - - o_x += BALL_SPEED * cos(ball_degree/180.0 * 3.14); - o_y += BALL_SPEED * sin(ball_degree/180.0 * 3.14); - bar_x+=BAR_SPEED * bar_right; - - //ボールが画面の横に出ないようにする - if (o_x < 0 + O_SIZE || o_x > 240 - O_SIZE){ - ball_degree = 180 - ball_degree; - if(ball_degree > 180) - ball_degree -= 360; - o_x = (240 - O_SIZE - (o_x - (240 - O_SIZE)))*(o_x > 240 - O_SIZE) +((0 + O_SIZE) - (o_x-O_SIZE))*(o_x < 0 + O_SIZE); - } - /*if (o_y < 0 + O_SIZE || o_y > 135 - O_SIZE){ - ball_degree = -ball_degree; - o_y = ((0 + O_SIZE) - (o_y-O_SIZE))*(o_y < 0 + O_SIZE) + (135 - O_SIZE - (o_y - (135 - O_SIZE)))*(o_y > 135 - O_SIZE); - }*/ - //ボールが画面の上に出ないようにする - if (o_y < 0 + O_SIZE){ - ball_degree = -ball_degree; - o_y = ((0 + O_SIZE) - (o_y-O_SIZE)); - } - //ボールがバーに当たった時の処理 - if (o_y > BAR_Y - O_SIZE && o_y < BAR_Y + 2 && (o_x >= bar_x && o_x <= bar_x + BAR_SIZE)){ - ball_degree = -1*(90 - (o_x - (bar_x + BAR_SIZE/2)) * 85 / (BAR_SIZE/2)); - - o_y = BAR_Y - O_SIZE -1; //ボールの位置をバーの上にする + // ブロック + for (int i = 0; i < BLOCK_ROWS; ++i) { + for (int j = 0; j < BLOCK_COLS; ++j) { + if (blocks[i][j]) { + int bx = j * blockW; + int by = i * blockH; + M5.Display.fillRect(bx + 1, by + 1, blockW - 2, blockH - 2, GREEN); + } + } } - //バーが画面外に出ないようにする - if (bar_x > 240 - BAR_SIZE || bar_x < 0){ - bar_x = (240 - BAR_SIZE - (bar_x - (240 - BAR_SIZE)))*(bar_x > 240 - BAR_SIZE) +(0 - (bar_x))*(bar_x < 0); - bar_right = bar_right*(-1); - } + // バー + M5.Display.fillRect(barX, barY, barW, barH, WHITE); - //ボールが並行に飛んでいる時の処理 - if(ball_degree <= 3 && ball_degree >= -3){ - ball_degree = 6 * (2 *(ball_degree > 0) -1 ); - } - // ボールが画面下に出た時の処理 - if(o_y > 135 - O_SIZE){ - game = 0; //ゲームオーバ - M5.Display.fillScreen(RED); - M5.delay(1000);} - M5.delay(10); + // ボール + M5.Display.fillCircle((int)ballX, (int)ballY, ballR, RED); + // ライフ表示 + M5.Display.setTextColor(WHITE); + M5.Display.setCursor(5, 5); + M5.Display.printf("Life: %d", life); + delay(16); } + \ No newline at end of file