実現したいこと
テトリスでスペースキーを押したら右回転するようにしたい。
発生している問題・分からないこと
スペースキーを押してもまず反応しない。矢印キーの右や左の移動は出来るが回転が行われない。
該当のソースコード
game.c
1void startTetrisGame(int x, int y) 2{ 3 // ゲームの初期化 4 GameState game; 5 Block currentBlock; 6 initGame(&game); 7 generateNewBlock(¤tBlock); 8 9 // ゲームループ 10 timeout(500); // 0.2秒待機 11 while (!game.gameOver) 12 { 13 int ch = getch(); 14 switch (ch) 15 { 16 case KEY_LEFT: 17 if (currentBlock.x > 0) 18 { // 左端に到達していない場合にのみ左に移動 19 currentBlock.x--; 20 if (checkCollision(&game, ¤tBlock)) 21 { 22 currentBlock.x++; 23 } 24 } 25 break; 26 case KEY_RIGHT: 27 currentBlock.x++; 28 if (checkCollision(&game, ¤tBlock)) 29 { 30 currentBlock.x--; 31 } 32 break; 33 case ' ': 34 rotateBlockWithSRS(&game, ¤tBlock, 1); // スペースキーで右回転 35 break; 36 default: 37 break; 38 } 39 40 // ブロックの落下 41 currentBlock.y++; 42 if (checkCollision(&game, ¤tBlock)) 43 { 44 currentBlock.y--; 45 mergeBlock(&game, ¤tBlock); 46 removeLine(&game); 47 generateNewBlock(¤tBlock); 48 if (checkCollision(&game, ¤tBlock)) 49 { 50 game.gameOver = 1; 51 } 52 } 53 54 drawGame(&game); 55 drawBlock(¤tBlock); 56 refresh(); 57 } 58 59 // ゲームオーバー時の処理 60 clear(); 61 mvprintw(y / 2, x / 2 - 5, "ゲームオーバー"); 62 mvprintw(y / 2 + 1, x / 2 - 10, "sキーを押してタイトルに戻る"); 63 refresh(); 64 65 // スコアを更新 66 updateRankingFile(game.score); 67 68 // 's'キーが押されるまで待機 69 timeout(-1); // キー入力を待機する 70 while (getch() != 's'); 71} 72
srs.c
1void rotateBlockWithSRS(GameState *game, Block *block, int direction) 2{ 3 bool rotated = false; 4 5 // 回転方向に基づいて回転関数を選択 6 if (direction == 1) 7 { // 右回転 8 if (block->shape == SHAPE_I) 9 { 10 rotated = RotateRightI(game, block); 11 } 12 else if(block->shape == SHAPE_O){ 13 rotated = true; 14 } 15 else 16 { 17 rotated = RotateRight3(game, block); 18 } 19 } 20 else if (direction == -1) 21 { // 左回転 22 // 左回転の場合、右回転を3回行うことで左回転と同等にする 23 for (int i = 0; i < 3; i++) 24 { 25 if (block->shape == SHAPE_I) 26 { 27 rotated = RotateRightI(game, block); 28 } 29 else if (block->shape != SHAPE_O) 30 { 31 rotated = RotateRight3(game, block); 32 } 33 if (!rotated) 34 break; 35 } 36 } 37 38 // 回転に成功した場合、新しい角度を設定 39 if (rotated) 40 { 41 if (direction == 1) 42 { 43 block->angle = (block->angle + 1) % 4; 44 } 45 else if (direction == -1) 46 { 47 block->angle = (block->angle + 3) % 4; 48 } 49 } 50} 51
rotate.c
1// Iミノの回転処理 2bool RotateRightI(GameState *game, Block *block) 3{ 4 if (CanRotate(game, block, true, -2, 0)) 5 return RotateRight(game, block, 0, 0); 6 7 if (block->angle == Angle0) 8 { 9 if (CanRotate(game, block, true, -2, 0)) 10 return RotateRight(game, block, -2, 0); 11 if (CanRotate(game, block, true, 1, 0)) 12 return RotateRight(game, block, 1, 0); 13 if (CanRotate(game, block, true, -2, 1)) 14 return RotateRight(game, block, -2, 1); 15 if (CanRotate(game, block, true, 1, -2)) 16 return RotateRight(game, block, 1, -2); 17 } 18 else if (block->angle == Angle90) 19 { 20 if (CanRotate(game, block, true, -1, 0)) 21 return RotateRight(game, block, -1, 0); 22 if (CanRotate(game, block, true, 2, 0)) 23 return RotateRight(game, block, 2, 0); 24 if (CanRotate(game, block, true, -1, -2)) 25 return RotateRight(game, block, -1, -2); 26 if (CanRotate(game, block, true, 2, 1)) 27 return RotateRight(game, block, 2, 1); 28 } 29 else if (block->angle == Angle180) 30 { 31 if (CanRotate(game, block, true, 2, 0)) 32 return RotateRight(game, block, 2, 0); 33 if (CanRotate(game, block, true, -1, 0)) 34 return RotateRight(game, block, -1, 0); 35 if (CanRotate(game, block, true, 2, -1)) 36 return RotateRight(game, block, 2, -1); 37 if (CanRotate(game, block, true, -1, 2)) 38 return RotateRight(game, block, -1, 2); 39 } 40 else if (block->angle == Angle270) 41 { 42 if (CanRotate(game, block, true, -2, 0)) 43 return RotateRight(game, block, -2, 0); 44 if (CanRotate(game, block, true, 1, 0)) 45 return RotateRight(game, block, 1, 0); 46 if (CanRotate(game, block, true, 1, 2)) 47 return RotateRight(game, block, 1, 2); 48 if (CanRotate(game, block, true, -2, -1)) 49 return RotateRight(game, block, -2, -1); 50 } 51 return false; 52} 53 54// I,O以外の回転処理 55bool RotateRight3(GameState *game, Block *block) 56{ 57 if (CanRotate(game, block, true, 0, 0)) 58 return RotateRight(game, block, 0, 0); 59 60 if (block->angle == Angle0) 61 { 62 if (CanRotate(game, block, true, -1, 0)) 63 return RotateRight(game, block, -1, 0); 64 if (CanRotate(game, block, true, -1, -1)) 65 return RotateRight(game, block, -1, -1); 66 if (CanRotate(game, block, true, 0, 2)) 67 return RotateRight(game, block, 0, 2); 68 if (CanRotate(game, block, true, -1, 2)) 69 return RotateRight(game, block, -1, 2); 70 } 71 else if (block->angle == Angle90) 72 { 73 if (CanRotate(game, block, true, 1, 0)) 74 return RotateRight(game, block, 1, 0); 75 if (CanRotate(game, block, true, 1, 1)) 76 return RotateRight(game, block, 1, 1); 77 if (CanRotate(game, block, true, 0, -2)) 78 return RotateRight(game, block, 0, -2); 79 if (CanRotate(game, block, true, 1, -2)) 80 return RotateRight(game, block, 1, -2); 81 } 82 else if (block->angle == Angle180) 83 { 84 if (CanRotate(game, block, true, 1, 0)) 85 return RotateRight(game, block, 1, 0); 86 if (CanRotate(game, block, true, 1, -1)) 87 return RotateRight(game, block, 1, -1); 88 if (CanRotate(game, block, true, 0, 2)) 89 return RotateRight(game, block, 0, 2); 90 if (CanRotate(game, block, true, 1, 2)) 91 return RotateRight(game, block, 1, 2); 92 } 93 else if (block->angle == Angle270) 94 { 95 if (CanRotate(game, block, true, -2, 0)) 96 return RotateRight(game, block, -2, 0); 97 if (CanRotate(game, block, true, -2, 1)) 98 return RotateRight(game, block, -2, 1); 99 if (CanRotate(game, block, true, 0, -2)) 100 return RotateRight(game, block, 0, -2); 101 if (CanRotate(game, block, true, -1, -2)) 102 return RotateRight(game, block, -1, -2); 103 } 104 return false; 105} 106
canrotate.c
1bool CanRotate(GameState *game, Block *block, bool isRight, int x, int y) 2{ 3 TetriminoAngle nextAngle; 4 TetriminoPosition tetri[4]; 5 6 if (isRight) 7 nextAngle = Angle90; 8 else 9 nextAngle = Angle270; 10 11 // m_TetriminoPositionX, m_TetriminoPositionY の初期状態を仮定して考える 12 // GetTetriminosPosition(tetri, 4); の実装は必要に応じて置き換える 13 14 // 一時的な計算 15 for (int i = 0; i < 4; i++) 16 { 17 tetri[i].m_column -= m_TetriminoPositionX; 18 tetri[i].m_row -= m_TetriminoPositionY; 19 } 20 21 // m_CurTetriminoType に応じた初期ブロックの取得 22 if (m_CurTetriminoType != SHAPE_I && m_CurTetriminoType != SHAPE_O) 23 { 24 // GetInitBlocksRotate33(tetri, 4, nextAngle); の実装は必要に応じて置き換える 25 } 26 else if (m_CurTetriminoType == SHAPE_I) 27 { 28 // GetInitBlocksRotate44(tetri, 4, nextAngle); の実装は必要に応じて置き換える 29 } 30 31 // SRSを適用した場合の回転軸のズレを加える 32 for (int i = 0; i < 4; i++) 33 { 34 tetri[i].m_column += x; 35 tetri[i].m_row += y; 36 } 37 38 // 現在の m_TetriminoPositionX と m_TetriminoPositionY の分だけ平行移動させる 39 for (int i = 0; i < 4; i++) 40 { 41 tetri[i].m_column += m_TetriminoPositionX; 42 tetri[i].m_row += m_TetriminoPositionY; 43 } 44 45 // これで回転後のブロックの座標が取得できた 46 // 後は当たり判定を行う 47 // フィールドの外に出たり、すでに固定されているブロックがある場合は移動・回転できない 48 for (int i = 0; i < 4; i++) 49 { 50 if (tetri[i].m_column > COLUMN_MAX - 1 || tetri[i].m_column < 0 || 51 tetri[i].m_row > ROW_MAX - 1 || tetri[i].m_FixedBlocks != NULL) 52 { 53 return false; 54 } 55 } 56 57 UNUSED(nextAngle); 58 return true; 59}
rotaterihgt.c
1//右回転 2bool RotateRight(GameState *game, Block *block, int x, int y) 3{ 4 bool ret = false; 5 6 //ブロックがIでもOでもない 7 if (block->shapeMatrix != SHAPE_I && block->shapeMatrix != SHAPE_O) 8 { 9 ret = RotateRight3(game, block); 10 } 11 else if (block->shapeMatrix == SHAPE_I) 12 { 13 ret = RotateRightI(game, block); 14 } 15 16 return ret; 17}
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
チャットgptや検索サイトではあまり意味のある回答がこなかった。回転だけの実装はできたが、SRSが出来ておらず、回転した後壁際に寄れなかったり判定の動かし方がわからない。
rotate.cの回転方法の引数の部分があっているのかがわからない
補足
c言語
ncursesを使用