こんにちは、あんみんどうふです。
今回はフィールドを見やすくするためにマス目と、ミノの置く場所をわかりやすくするためにゴーストを実装します。
前回の記事はこちら。
こんにちは、あんみんどうふです。 今回はミノを即時落下させる「ハードドロップ」、ミノを1つだけ保持できる「ホールド」の実装を行います。 前回の記事はこちら。 https://www.terasol.co.jp/%e3%83...
こんにちは、あんみんどうふです。間に挟んでちょっとしたことをします。 前回の記事はこちら。 全編見たい方はタグからどうぞ。 ...
全編見たい方はタグからどうぞ。
8-1.マス目の描画
等間隔でフィールド上に線を引くだけです。drawメソッドに追記します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | void draw() { Bitmap canvas = new Bitmap(view_field.Width, view_field.Height); Graphics g = Graphics.FromImage(canvas); for (int i = 0; i < field.GetLength(0); i++) { for (int j = 0; j < field.GetLength(1); j++) { if (field[i, j] != 0) { // テトリミノの描画 Color color = MinoColor.getColor(field[i, j]); SolidBrush brush = new SolidBrush(color); g.FillRectangle(brush, j * SQUARE - FIELD_WALL * SQUARE, (i - FIELD_SPACE) * SQUARE, SQUARE, SQUARE); brush.Dispose(); } } } // 線を描画 Color line = Color.FromArgb(80, 200, 200, 200); Pen p = new Pen(line, 1); // 横 for (int i = 1; i < field.GetLength(0); i++) { g.DrawLine(p, 0, SQUARE * i, SQUARE * FIELD_HEIGHT, SQUARE * i); } // 縦 for (int i = 1; i < field.GetLength(1); i++) { g.DrawLine(p, SQUARE * i, 0, SQUARE * i, SQUARE * FIELD_HEIGHT); } p.Dispose(); g.Dispose(); view_field.Image = canvas; } |
流石に真っ黒な線だと違和感しかないので、適当にグレーっぽく(#C8C8C8)してアルファ値(透明度)を80にして薄めてます。後はfor文で縦列横列分増やせば、
あっという間にできあがりです。
8-2.ゴースト
実はこれも結構簡単です。新メソッド「minoGhost」、作ります。
1 2 3 4 5 6 7 8 9 | /** * ゴーストの高さを決定 */ int minoGhost() { int ghostY = 0; while (minoMoveCheck(2, 1, 0, ghostY)) ghostY++; return ghostY + y; } |
下方向に壁やミノがあるか確認し続けて、ぶつかった所のY座標を返しています。
そして更にdrawメソッドに追記します。今回二度目の追記です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | void draw() { Bitmap canvas = new Bitmap(view_field.Width, view_field.Height); Graphics g = Graphics.FromImage(canvas); for (int i = 0; i < field.GetLength(0); i++) { for (int j = 0; j < field.GetLength(1); j++) { if (field[i, j] != 0) { // テトリミノの描画 Color color = MinoColor.getColor(field[i, j]); SolidBrush brush = new SolidBrush(color); g.FillRectangle(brush, j * SQUARE - FIELD_WALL * SQUARE, (i - FIELD_SPACE) * SQUARE, SQUARE, SQUARE); brush.Dispose(); } } } for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (mino[next[0], dir, i, j] != 0) { // ゴーストの描画 Color color = MinoColor.getColor(mino[next[0], dir, i, j], 100); SolidBrush brush = new SolidBrush(color); g.FillRectangle(brush, (x + j) * SQUARE, (minoGhost() + i - 1) * SQUARE, SQUARE, SQUARE); brush.Dispose(); } } } // 線を描画 Color line = Color.FromArgb(80, 200, 200, 200); Pen p = new Pen(line, 1); // 横 for (int i = 1; i < field.GetLength(0); i++) { g.DrawLine(p, 0, SQUARE * i, SQUARE * FIELD_HEIGHT, SQUARE * i); } // 縦 for (int i = 1; i < field.GetLength(1); i++) { g.DrawLine(p, SQUARE * i, 0, SQUARE * i, SQUARE * FIELD_HEIGHT); } p.Dispose(); g.Dispose(); view_field.Image = canvas; } |
レイヤー的にマス目の線を前に出したいので、線描画の前に書きました。
minoGhostで取得した座標と現在のX座標を参照した位置にゴーストを描画しています。つまり、今操作している位置から真下にぶつかるまでの位置です。
ちゃんと動いてますね。床だけでなく、既に置いたミノにも対応してます。これだけでグンと遊びやすくなりました!
置きミスにはツッコまないで!
・・・しかし、まだゲームとして機能していません。何故なら、ゲームオーバーが無いからです。このままでは鬼○の刃無限テトリス編です(?)。
ということで、次回はゲームオーバー実装します。といっても、すぐできそうなのでゲーム始める時のカウントダウンとかも作る予定です。
#9 ゲームオーバー+α実装編に続く。
こんにちは、あんみんどうふです。 今回はゲームオーバーの実装…だけだとすぐ終わっちゃうので、ゲームが始まるときのカウントダウンも実装します。 前回の記事はこちら。 https://www.terasol.co.jp/%e3...