前回の続きです。
MovingTetriminoクラスを示します。
まずミノの位置とこれを構成するブロックに関するプロパティとメソッドを示します。
GetBlocks(TetriminoAngle angle)メソッドは現在のテトリミノの種類とその位置からそれを構成するブロックを返すものです。
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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
static public class MovingTetrimino { // ミノの位置とこれを構成するブロックに関する情報 static int PosX { get; set; } static int PosY { get; set; } static public TetriminoAngle Angle { get; private set; } static public List<Block> GetBlocks(TetriminoAngle angle) { List<Block> blocks = new List<Block>(); Color color = Color.Empty; if (Type == TetriminoTypes.I) { List<Block> blocks0 = new List<Block>(); blocks0.Add(new Block(0, 1)); blocks0.Add(new Block(1, 1)); blocks0.Add(new Block(2, 1)); blocks0.Add(new Block(3, 1)); blocks = GetRotateBlocks44(blocks0, angle); color = TetriminoColor.I; } if (Type == TetriminoTypes.J) { List<Block> blocks0 = new List<Block>(); blocks0.Add(new Block(0, 0)); blocks0.Add(new Block(0, 1)); blocks0.Add(new Block(1, 1)); blocks0.Add(new Block(2, 1)); blocks = GetRotateBlocks33(blocks0, angle); color = TetriminoColor.J; } if (Type == TetriminoTypes.L) { List<Block> blocks0 = new List<Block>(); blocks0.Add(new Block(2, 0)); blocks0.Add(new Block(0, 1)); blocks0.Add(new Block(1, 1)); blocks0.Add(new Block(2, 1)); blocks = GetRotateBlocks33(blocks0, angle); color = TetriminoColor.L; } if (Type == TetriminoTypes.O) { blocks.Add(new Block(1, 0)); blocks.Add(new Block(1, 1)); blocks.Add(new Block(2, 0)); blocks.Add(new Block(2, 1)); color = TetriminoColor.O; } if (Type == TetriminoTypes.S) { List<Block> blocks0 = new List<Block>(); blocks0.Add(new Block(1, 0)); blocks0.Add(new Block(2, 0)); blocks0.Add(new Block(0, 1)); blocks0.Add(new Block(1, 1)); blocks = GetRotateBlocks33(blocks0, angle); color = TetriminoColor.S; } if (Type == TetriminoTypes.Z) { List<Block> blocks0 = new List<Block>(); blocks0.Add(new Block(0, 0)); blocks0.Add(new Block(1, 0)); blocks0.Add(new Block(1, 1)); blocks0.Add(new Block(2, 1)); blocks = GetRotateBlocks33(blocks0, angle); color = TetriminoColor.Z; } if (Type == TetriminoTypes.T) { List<Block> blocks0 = new List<Block>(); blocks0.Add(new Block(1, 0)); blocks0.Add(new Block(0, 1)); blocks0.Add(new Block(1, 1)); blocks0.Add(new Block(2, 1)); blocks = GetRotateBlocks33(blocks0, angle); color = TetriminoColor.T; } List<Block> ret = new List<Block>(); foreach (Block block0 in blocks) { Block block = new Block(block0.PosX + PosX, block0.PosY + PosY); block.Color = color; ret.Add(block); } return ret; } static List<Block> GetRotateBlocks33(List<Block> blocks, TetriminoAngle angle) { if (angle == TetriminoAngle.Angle0) return blocks; else if(angle == TetriminoAngle.Angle90) return blocks.Select(x => new Block(3 - x.PosY - 1, x.PosX)).ToList(); else if(angle == TetriminoAngle.Angle180) return blocks.Select(x => new Block(3 - x.PosX - 1, 3 - x.PosY - 1)).ToList(); else// if (angle == TetriminoAngle.Angle270) return blocks.Select(x => new Block(x.PosY, 3 - x.PosX - 1)).ToList(); } static List<Block> GetRotateBlocks44(List<Block> blocks, TetriminoAngle angle) { if (angle == TetriminoAngle.Angle0) return blocks; else if (angle == TetriminoAngle.Angle90) return blocks.Select(x => new Block(4 - x.PosY - 1, x.PosX)).ToList(); else if (angle == TetriminoAngle.Angle180) return blocks.Select(x => new Block(4 - x.PosX - 1, 4 - x.PosY - 1)).ToList(); else// if (angle == TetriminoAngle.Angle270) return blocks.Select(x => new Block(x.PosY, 4 - x.PosX - 1)).ToList(); } } |
次にテトリミノの移動に関するメソッドを示します。回転処理はあとまわしにして左右、下に移動する処理を考えます。
最初にGetMoveLeft()、GetMoveRight()、GetMoveDown()の各メソッドで移動先のブロックを取得して、これが壁にあたったりすでに設置されているブロックと重ならないか調べています。問題なければ移動させます。
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 |
static public class MovingTetrimino { static public void MoveLeft() { List<Block> blocks = GetMoveLeft(); if (blocks.Min(x => x.PosX) >= 0 && !FixedTetrimino.ExistsBlock(blocks)) PosX--; } static public void MoveRight() { List<Block> blocks = GetMoveRight(); if (blocks.Max(x => x.PosX) < Constant.FieldWidth && !FixedTetrimino.ExistsBlock(blocks)) PosX++; } static public void MoveDown() { List<Block> blocks = GetMoveDown(); if (blocks.Max(x => x.PosY) < Constant.FieldHeight && !FixedTetrimino.ExistsBlock(blocks)) PosY++; else FixTetrimino(); } static List<Block> GetMoveLeft() { List<Block> ret = GetBlocks(Angle); return ret.Select(x => new Block(x.PosX - 1, x.PosY)).ToList(); } static List<Block> GetMoveRight() { List<Block> ret = GetBlocks(Angle); return ret.Select(x => new Block(x.PosX + 1, x.PosY)).ToList(); } static List<Block> GetMoveDown() { List<Block> ret = GetBlocks(Angle); return ret.Select(x => new Block(x.PosX, x.PosY + 1)).ToList(); } } |
次に回転処理を考えます。回転は右回りと左回りがあります。Oミノは回転しないので考える必要はないのですが、それ以外のミノは単純に回転させたときに壁やすでに設置されているブロックにぶつかってしまう場合、回転後に別の方向にそのままずらせないか考えます。
左回転の場合
普通の方法で回転できるか?
できないのであれば・・・
(1)
0度,270度の場合は右へ1マス移動
90度、180度の場合は左へ1マス移動
これで回転できない場合は
(2)
その状態から
90度,270度の場合は上へ1マス移動
0度,180度の場合は下へ1マス移動
それでも回転できない場合は
(3)
元に戻し
90度,270度の場合は下へ2マス移動
0度,180度の場合は上へ2マス移動
それでも回転できない場合は
(4)
その状態から
0度,180度、270度の場合は右へ1マス移動
90度、180度の場合は左へ1マス移動
それでも回転できない場合は回転できないと判断します。
また右回転の場合は・・・
(1)
0度,90度の場合は左へ1マス移動
180度、270度の場合は右へ1マス移動
(2)
その状態から
90度,270度の場合は上へ1マス移動
0度,180度の場合は下へ1マス移動
(3)
元に戻し
90度,270度の場合は下へ2マス移動
0度,180度の場合は上へ2マス移動
(4)
その状態から
0度,90度の場合は左へ1マス移動
180度、270度の場合は右へ1マス移動
・・・となります。
それを判定する処理を書くと長くなるので別のクラス(SuperRotationクラス)にしました。
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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
static public class MovingTetrimino { static public void RotateL() { SuperRotationResult result = null; if (Type != TetriminoTypes.I && Type != TetriminoTypes.O) result = GetSuperRotationResultLeftTSZLJ(); if (Type == TetriminoTypes.I) result = GetSuperRotationResultLeftI(); if (result != null) { Angle = GetAngleRotateL(); PosX += result.MoveX; PosY += result.MoveY; PlaySoundeffect.Rotate(); } } static public void RotateR() { SuperRotationResult result = null; if (Type != TetriminoTypes.I && Type != TetriminoTypes.O) result = GetSuperRotationResultRightTSZLJ(); if (Type == TetriminoTypes.I) result = GetSuperRotationResultRightI(); if (result != null) { Angle = GetAngleRotateR(); PosX += result.MoveX; PosY += result.MoveY; PlaySoundeffect.Rotate(); } } static TetriminoAngle GetAngleRotateL() { if (Angle == TetriminoAngle.Angle0) return TetriminoAngle.Angle270; else if (Angle == TetriminoAngle.Angle90) return TetriminoAngle.Angle0; else if (Angle == TetriminoAngle.Angle180) return TetriminoAngle.Angle90; else// if (Angle == TetriminoAngle.Angle270) return TetriminoAngle.Angle180; } static TetriminoAngle GetAngleRotateR() { if (Angle == TetriminoAngle.Angle0) return TetriminoAngle.Angle90; else if (Angle == TetriminoAngle.Angle90) return TetriminoAngle.Angle180; else if (Angle == TetriminoAngle.Angle180) return TetriminoAngle.Angle270; else// if (Angle == TetriminoAngle.Angle270) return TetriminoAngle.Angle0; } static SuperRotationResult GetSuperRotationResultLeftTSZLJ() { TetriminoAngle angle = GetAngleRotateL(); List<Block> blocks = GetBlocks(angle); if (CanRotate(blocks)) return new SuperRotationResult(0, 0); return SuperRotation.GetRotateL_TSZLJ(blocks, angle); } static SuperRotationResult GetSuperRotationResultRightTSZLJ() { TetriminoAngle angle = GetAngleRotateR(); List<Block> blocks = GetBlocks(angle); if (CanRotate(blocks)) return new SuperRotationResult(0, 0); return SuperRotation.GetRotateR_TSZLJ(blocks, angle); } static SuperRotationResult GetSuperRotationResultRightI() { TetriminoAngle angle = GetAngleRotateR(); List<Block> blocks = GetBlocks(angle); if (CanRotate(blocks)) return new SuperRotationResult(0, 0); return SuperRotation.GetRotateR_I(blocks, angle); } static SuperRotationResult GetSuperRotationResultLeftI() { TetriminoAngle angle = GetAngleRotateL(); List<Block> blocks = GetBlocks(angle); if (CanRotate(blocks)) return new SuperRotationResult(0, 0); return SuperRotation.GetRotateL_I(blocks, angle); } static public bool CanRotate(List<Block> blocks) { if (blocks.Min(x => x.PosX) < 0) return false; if (blocks.Max(x => x.PosX) >= Constant.FieldWidth) return false; if (blocks.Max(x => x.PosY) >= Constant.FieldHeight) return false; if (FixedTetrimino.ExistsBlock(blocks)) return false; return true; } } |
さて問題のSuperRotationクラスですが、そのまえに処理の結果を返すときに必要になるSuperRotationResultクラスを先に示します。
このクラスはどれだけ回転軸をずらすかを示すものです。SuperRotationResult.MoveX == 0 && SuperRotationResult.MoveY == 0であれば通常回転で問題ないということですし、それ以外の値であればその方向にずらすということです。もしnullが返ってきたら回転はできないということになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class SuperRotationResult { public SuperRotationResult(int moveX, int moveY) { MoveX = moveX; MoveY = moveY; } public int MoveX { get; private set; } public int MoveY { get; private set; } } |
SuperRotationクラスを示します。
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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
public static class SuperRotation { static bool SuperRotationJuge(List<Block> blocks, int moveX, int moveY) { List<Block> blocks2 = blocks.Select(x => new Block(x.PosX + moveX, x.PosY + moveY)).ToList(); if (MovingTetrimino.CanRotate(blocks2)) return true; else return false; } public static SuperRotationResult GetRotateL_TSZLJ(List<Block> blocks, TetriminoAngle angle) { // (1) // 0度,270度の場合は右へ1マス移動 // 90度、180度の場合は左へ1マス移動 // (2) // その状態から // 90度,270度の場合は上へ1マス移動 // 0度,180度の場合は下へ1マス移動 // (3) // 元に戻し // 90度,270度の場合は下へ2マス移動 // 0度,180度の場合は上へ2マス移動 // (4) // その状態から // 0度,180度、270度の場合は右へ1マス移動 // 90度、180度の場合は左へ1マス移動 int moveX = 0; int moveY = 0; // (1) if (angle == TetriminoAngle.Angle0 || angle == TetriminoAngle.Angle270) moveX = 1; else moveX = -1; if (SuperRotationJuge(blocks, moveX, moveY)) return new SuperRotationResult(moveX, moveY); // (2) if (angle == TetriminoAngle.Angle90 || angle == TetriminoAngle.Angle270) moveY = -1; else moveY = 1; if (SuperRotationJuge(blocks, moveX, moveY)) return new SuperRotationResult(moveX, moveY); // (3) moveX = 0; moveY = 0; if (angle == TetriminoAngle.Angle90 || angle == TetriminoAngle.Angle270) moveY = 2; else moveY = -2; if (SuperRotationJuge(blocks, moveX, moveY)) return new SuperRotationResult(moveX, moveY); // (4) if (angle == TetriminoAngle.Angle0 || angle == TetriminoAngle.Angle270) moveX = 1; else moveX = -1; if (SuperRotationJuge(blocks, moveX, moveY)) return new SuperRotationResult(moveX, moveY); return null; } public static SuperRotationResult GetRotateR_TSZLJ(List<Block> blocks, TetriminoAngle angle) { // (1) // 0度,90度の場合は左へ1マス移動 // 180度、270度の場合は右へ1マス移動 // (2) // その状態から // 90度,270度の場合は上へ1マス移動 // 0度,180度の場合は下へ1マス移動 // (3) // 元に戻し // 90度,270度の場合は下へ2マス移動 // 0度,180度の場合は上へ2マス移動 // (4) // その状態から // 0度,90度の場合は左へ1マス移動 // 180度、270度の場合は右へ1マス移動 int moveX = 0; int moveY = 0; // (1) if (angle == TetriminoAngle.Angle0 || angle == TetriminoAngle.Angle90) moveX = -1; else moveX = 1; if (SuperRotationJuge(blocks, moveX, moveY)) return new SuperRotationResult(moveX, moveY); // (2) if (angle == TetriminoAngle.Angle90 || angle == TetriminoAngle.Angle270) moveY = -1; else moveY = 1; if (SuperRotationJuge(blocks, moveX, moveY)) return new SuperRotationResult(moveX, moveY); // (3) moveX = 0; moveY = 0; if (angle == TetriminoAngle.Angle90 || angle == TetriminoAngle.Angle270) moveY = 2; else moveY = -2; if (SuperRotationJuge(blocks, moveX, moveY)) return new SuperRotationResult(moveX, moveY); // (4) if (angle == TetriminoAngle.Angle0 || angle == TetriminoAngle.Angle90) moveX = -1; else moveX = 1; if (SuperRotationJuge(blocks, moveX, moveY)) return new SuperRotationResult(moveX, moveY); return null; } public static SuperRotationResult GetRotateL_I(List<Block> blocks, TetriminoAngle angle) { if (angle == TetriminoAngle.Angle0) { // (1) if(SuperRotationJuge(blocks, 2, 0)) return new SuperRotationResult(2, 0); // (2) if (SuperRotationJuge(blocks, -1, 0)) return new SuperRotationResult(-1, 0); // (3) if (SuperRotationJuge(blocks, 2, -1)) return new SuperRotationResult(2, -1); // (4) if (SuperRotationJuge(blocks, -1, 2)) return new SuperRotationResult(-1, 2); return null; } else if (angle == TetriminoAngle.Angle90) { // (1) if (SuperRotationJuge(blocks, 1, 0)) return new SuperRotationResult(1, 0); // (2) if (SuperRotationJuge(blocks, -2, 0)) return new SuperRotationResult(-2, 0); // (3) if (SuperRotationJuge(blocks, 1, 2)) return new SuperRotationResult(1, 2); // (4) if (SuperRotationJuge(blocks, -2, -1)) return new SuperRotationResult(-2, -1); return null; } else if (angle == TetriminoAngle.Angle180) { // (1) if (SuperRotationJuge(blocks, 1, 0)) return new SuperRotationResult(1, 0); // (2) if (SuperRotationJuge(blocks, -2, 0)) return new SuperRotationResult(-2, 0); // (3) if (SuperRotationJuge(blocks, -2, 1)) return new SuperRotationResult(-2, 1); // (4) if (SuperRotationJuge(blocks, -2, -1)) return new SuperRotationResult(-2, -1); return null; } else //if (angle == TetriminoAngle.Angle270) { // (1) if (SuperRotationJuge(blocks, -1, 0)) return new SuperRotationResult(-1, 0); // (2) if (SuperRotationJuge(blocks, 2, 0)) return new SuperRotationResult(2, 0); // (3) if (SuperRotationJuge(blocks, -1, -2)) return new SuperRotationResult(-1, -2); // (4) if (SuperRotationJuge(blocks, 2, 1)) return new SuperRotationResult(2, 1); return null; } } public static SuperRotationResult GetRotateR_I(List<Block> blocks, TetriminoAngle angle) { if (angle == TetriminoAngle.Angle0) { // (1) if (SuperRotationJuge(blocks, -2, 0)) return new SuperRotationResult(-2, 0); // (2) if (SuperRotationJuge(blocks, 1, 0)) return new SuperRotationResult(1, 0); // (3) if (SuperRotationJuge(blocks, 1, 2)) return new SuperRotationResult(1, 2); // (4) if (SuperRotationJuge(blocks, -2, -1)) return new SuperRotationResult(-2, -1); return null; } else if (angle == TetriminoAngle.Angle90) { // (1) if (SuperRotationJuge(blocks, -2, 0)) return new SuperRotationResult(-2, 0); // (2) if (SuperRotationJuge(blocks, 1, 0)) return new SuperRotationResult(1, 0); // (3) if (SuperRotationJuge(blocks, -2, 1)) return new SuperRotationResult(-2, 1); // (4) if (SuperRotationJuge(blocks, 1, -2)) return new SuperRotationResult(1, -2); return null; } else if (angle == TetriminoAngle.Angle180) { // (1) if (SuperRotationJuge(blocks, -1, 0)) return new SuperRotationResult(-1, 0); // (2) if (SuperRotationJuge(blocks, 2, 0)) return new SuperRotationResult(2, 0); // (3) if (SuperRotationJuge(blocks, -1, -2)) return new SuperRotationResult(-1, -2); // (4) if (SuperRotationJuge(blocks, 2, 1)) return new SuperRotationResult(2, 1); return null; } else //if (angle == TetriminoAngle.Angle270) { // (1) if (SuperRotationJuge(blocks, 2, 0)) return new SuperRotationResult(2, 0); // (2) if (SuperRotationJuge(blocks, -1, 0)) return new SuperRotationResult(-1, 0); // (3) if (SuperRotationJuge(blocks, 2, -1)) return new SuperRotationResult(2, -1); // (4) if (SuperRotationJuge(blocks, -1, 2)) return new SuperRotationResult(-1, 2); return null; } } } |
急速落下(ハードドロップ)させる場合はHardDrop()メソッドが呼び出されます。これは瞬時に下までミノが落下して固定されてしまいます。またドロップポイントが加算されます。
ハードドロップする場合は落下先のブロックを求めます。それがGetHardDropedBlocks(ref int count)メソッドです。このメソッドは何回下へ移動させることができるかをカウントしてその分だけ下にずらした場合のブロックのリストを返します。
ミノが設置して固定されたらFixTetrimino()メソッドが呼び出され、TetriminoFixedイベントが発生します。
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 |
static public class MovingTetrimino { static public int DropPoint = 0; static public void HardDrop() { int count = 0; GetHardDropedBlocks(ref count); PosY += count; DropPoint = count; FixTetrimino(); } static List<Block> GetHardDropedBlocks(ref int count) { List<Block> blocks = GetMoveDown(); int i = 0; while (blocks.Max(x => x.PosY) < Constant.FieldHeight && !FixedTetrimino.ExistsBlock(blocks)) { i++; blocks = blocks.Select(x => new Block(x.PosX, x.PosY + 1)).ToList(); } count = i; blocks = GetBlocks(Angle).Select(x => new Block(x.PosX, x.PosY + i)).ToList(); return blocks; } static public event EventHandler TetriminoFixed; static void FixTetrimino() { List<Block> blocks = GetBlocks(Angle); FixedTetrimino.Blocks.AddRange(blocks); PlaySoundeffect.Drop(); FixedTetrimino.DeleteLines(); Type = PopNext(); TetriminoFixed?.Invoke(null, new EventArgs()); DropPoint = 0; } } |
次に現在のミノと次以降のミノの管理するためのメソッドを示します。
Typeプロパティは現在落下中のミノの種類を示します。新しい値をセットするとミノの座標が上部の出現場所である(3,-3)に変更されます。
フィールド変数 NextTetoroTypesには次以降に落ちてくるTetriminoTypesが格納されます。7種類1個ずつで1セット(バッグという)が構成され、残りが少なくなると乱数で新しいバッグがつくられます。
Init()メソッドではNextTetoroTypesがクリアされ、新しいバッグが作り直されます。
それから新しいミノを(3,-3)に出現させてみたものの、すでに設置されているブロックと重なってしまった場合は上部までミノが積み上がっていると判断します。そのときはForm1クラスでゲームオーバーの処理をおこなわせるためにCantPutNewTetriminoイベントが発生します。
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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
static public class MovingTetrimino { static public event EventHandler CantPutNewTetrimino; static TetriminoTypes _type = TetriminoTypes.None; public static TetriminoTypes Type { get { return _type; } set { _type = value; PosX = 3; PosY = -3; Angle = TetriminoAngle.Angle0; if (FixedTetrimino.ExistsBlock(GetBlocks(Angle))) { CantPutNewTetrimino?.Invoke(null, new EventArgs()); } } } static List<TetriminoTypes> NextTetoroTypes = new List<TetriminoTypes>(); static public void Init() { NextTetoroTypes.Clear(); GetNext7(); Type = PopNext(); } static Random _random = new Random(); static void CreateBag() { int r; List<TetriminoTypes> types = new List<TetriminoTypes>(); types.Add(TetriminoTypes.I); r = _random.Next(0, types.Count + 1); types.Insert(r, TetriminoTypes.J); r = _random.Next(0, types.Count + 1); types.Insert(r, TetriminoTypes.L); r = _random.Next(0, types.Count + 1); types.Insert(r, TetriminoTypes.O); r = _random.Next(0, types.Count + 1); types.Insert(r, TetriminoTypes.S); r = _random.Next(0, types.Count + 1); types.Insert(r, TetriminoTypes.T); r = _random.Next(0, types.Count + 1); types.Insert(r, TetriminoTypes.Z); NextTetoroTypes.AddRange(types); } static public TetriminoTypes GetNext() { if (NextTetoroTypes.Count == 0) CreateBag(); return NextTetoroTypes[0]; } static public List<TetriminoTypes> GetNext7() { if (NextTetoroTypes.Count < 7) CreateBag(); return NextTetoroTypes.Take(7).ToList(); } static public TetriminoTypes PopNext() { TetriminoTypes ret = GetNext(); NextTetoroTypes.RemoveAt(0); return ret; } } |
描画に関する処理をおこなうメソッドを示します。Draw(Graphics g)メソッドは落下中のミノを描画するメソッドであり、DrawGohst(Graphics g)メソッドはハードドロップするとどこに設置されるかを示すゴーストを描画します。
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 |
static public class MovingTetrimino { static public void Draw(Graphics g) { if (Type == TetriminoTypes.None) return; List<Block> blocks = GetBlocks(Angle); foreach (Block block in blocks) { g.FillRectangle(new SolidBrush(block.Color), new Rectangle(block.X, block.Y, block.Width, block.Height)); g.DrawRectangle(new Pen(Color.Black), new Rectangle(block.X, block.Y, block.Width, block.Height)); } } static public void DrawGohst(Graphics g) { if (Type == TetriminoTypes.None) return; List<Block> blocks = GetGohstBlocks(); foreach (Block block in blocks) { Color color = Color.FromArgb(80, block.Color); g.FillRectangle(new SolidBrush(color), new Rectangle(block.X, block.Y, block.Width, block.Height)); g.DrawRectangle(new Pen(Color.Black), new Rectangle(block.X, block.Y, block.Width, block.Height)); } } static public List<Block> GetGohstBlocks() { int count = 0; return GetHardDropedBlocks(ref count); } } |
TetriminoColorクラスはTetriminoTypesからミノの色を取得するための静的クラスです。
1 2 3 4 5 6 7 8 9 10 |
static public class TetriminoColor { static public Color I = Color.Aqua; // I - テトリミノ(水色) static public Color O = Color.Yellow; // O - テトリミノ(黄色) static public Color S = Color.Green; // S - テトリミノ(緑) static public Color Z = Color.Red; // Z - テトリミノ(赤) static public Color J = Color.Blue; // J - テトリミノ(青) static public Color L = Color.Orange; // L - テトリミノ(オレンジ) static public Color T = Color.Violet; // T - テトリミノ(紫) } |
PlaySoundeffectクラスは効果音を鳴らすための静的クラスです。
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 |
static public class PlaySoundeffect { static WMPLib.WindowsMediaPlayer mediaPlayer1 = new WMPLib.WindowsMediaPlayer(); static WMPLib.WindowsMediaPlayer mediaPlayer2 = new WMPLib.WindowsMediaPlayer(); static public void Rotate() { string path = Application.StartupPath + "\\rotate.mp3"; if (System.IO.File.Exists(path)) { mediaPlayer1.settings.autoStart = true; mediaPlayer1.URL = path; } } static public void Drop() { string path = Application.StartupPath + "\\drop.mp3"; if (System.IO.File.Exists(path)) { mediaPlayer1.settings.autoStart = true; mediaPlayer1.URL = path; } } static public void DeleteLine() { string path = Application.StartupPath + "\\delete.mp3"; if (System.IO.File.Exists(path)) { mediaPlayer2.settings.autoStart = true; mediaPlayer2.URL = path; } } } |