/// <summary> /// おじゃまを相手のフィールドに送る /// </summary> /// <param name="ojamas">送るおじゃまの量と種類</param> private void ThrowOjama(OjamaCalculator ojamas) { var n = ojamas.Calculate(); for (var i = 0; i < n; ++i) { var ojama = new OjamaBall(SpriteBatch, Camera, GameMain, this) { IsHard = ojamas.IsHard(), Size = BallSize }; OtherField.EnqueueOjama(ojama); } }
/// <summary> /// 指定した座標の玉を消す。 /// </summary> /// <param name="point">消す玉の座標</param> /// <returns>送られるおじゃまの数 ただし消せない時はnull</returns> private OjamaCalculator DestroyBalls(Point point) { var targetBall = GetBall(point.X, point.Y); if (targetBall is OjamaBall) { return(null); } var color = targetBall.Color; OjamaCalculator result; int[] dx = { -1, 0, 1, 0 }; int[] dy = { 0, -1, 0, 1 }; var destroyed = new List <Point> { point }; var visit = new bool[Column + 1, Row + 1]; var queue = new Queue <Point>(); queue.Enqueue(point); while (0 < queue.Count) { var p = queue.Dequeue(); visit[p.X, p.Y] = true; for (var i = 0; i < 4; ++i) { var tx = p.X + dx[i]; var ty = p.Y + dy[i]; if (!IsInFieldRange(tx, ty) || visit[tx, ty]) { continue; } var ball = GetBall(tx, ty); if (ball.Color != color) { continue; } var tp = new Point(tx, ty); destroyed.Add(tp); queue.Enqueue(tp); visit[tx, ty] = true; } } if (destroyed.Count < GameConfig.MinChain) { return(null); } var sum = new int[Column + 1, Row + 2]; { var destroyedOjama = new List <Point>(); var countLvDown = 0; foreach (var p in destroyed) { for (var i = 0; i < 4; ++i) { var tx = p.X + dx[i]; var ty = p.Y + dy[i]; if (!IsInFieldRange(tx, ty)) { continue; } var ball = GetBall(tx, ty); if (!(ball is OjamaBall) || ball.IsDeath) { continue; } var ojama = ball as OjamaBall; if (ojama.IsHard) { ojama.IsHard = false; countLvDown++; } else { destroyedOjama.Add(new Point(tx, ty)); ball.IsDeath = true; sum[tx, ty - 1]++; } } GetBall(p.X, p.Y).IsDeath = true; sum[p.X, p.Y - 1]++; } result = new OjamaCalculator(countLvDown, destroyedOjama.Count, destroyed.Count); destroyed.AddRange(destroyedOjama); } if (!GameMain.EnableSkippingRender) { SpawnBallDestroyParticles(targetBall, destroyed); } for (var y = Row; 0 <= y; --y) { for (var x = 1; x <= Column; ++x) { sum[x, y] += sum[x, y + 1]; } } var topY = GetBall(1, 1).Y; for (var x = 1; x <= Column; ++x) { if (sum[x, 0] == 0) { continue; } for (var y = Row; 1 <= y; --y) { var ball = GetBall(x, y); if (ball.IsDeath) { continue; } ball.TargetY = GetBall(x, y + sum[x, y]).Y; SetBall(x, y + sum[x, y], ball); } for (var y = 1; y <= sum[x, 0]; ++y) { var oldBall = GetBall(x, y); var newY = -(sum[x, 0] - y + 1) * BallSize + topY; if (_ojamaQueues[x].Count == 0) { SetBall(x, y, new Ball(SpriteBatch, Camera, GameMain, this) { X = oldBall.X, Y = newY, TargetY = oldBall.Y, Size = BallSize, Color = GetNextColor(x, y) }); } else { var ojama = _ojamaQueues[x].Dequeue(); ojama.X = oldBall.X; ojama.Y = newY; ojama.TargetY = oldBall.Y; SetBall(x, y, ojama); } } } return(result); }