/// <summary> /// Create a new tetromino /// </summary> public Tetromino(TetrominoType type) { this.Type = type; this.MinoTiles = (Vector2Int[])TetrominoTiles(type).Clone(); CurrentRotationState = Rotation.Up; CurrentSpinReward = SpinReward.None; }
/// <summary> /// Rotate the tetromino in the given direction and return whether the rotation was successful. /// Tries to apply SRS kicks. Fails if no kick was possible or the tetromino is locked. /// </summary> public bool Rotate(Rotation dir) { bool rotatedSuccessfully = false; if (!Locked) { Locked = true; Vector2Int[] newMinoTiles = new Vector2Int[MinoTiles.Length]; Rotation newRotationState = CurrentRotationState + dir; for (int i = 0; i < MinoTiles.Length; i++) { newMinoTiles[i] = MinoTiles[i].Rotated(dir); } Dictionary <Rotation, Vector2Int[]> offsets; switch (Type) { case TetrominoType.I: offsets = RotationOffsets_I; break; case TetrominoType.O: offsets = RotationOffsets_O; break; default: offsets = RotationOffsets; break; } int kickTranslationCount = offsets[CurrentRotationState].Length; Vector2Int kickTranslation = Vector2Int.Zero; for (int i = 0; i < kickTranslationCount; i++) { kickTranslation = offsets[CurrentRotationState][i] - offsets[newRotationState][i]; if (rotatedSuccessfully = IsValidMovement(kickTranslation, newMinoTiles)) { this.Position += kickTranslation; break; } } if (rotatedSuccessfully) { CurrentRotationState = newRotationState; for (int i = 0; i < MinoTiles.Length; i++) { MinoTiles[i] = newMinoTiles[i]; } this.CurrentSpinReward = CheckForSpinReward(kickTranslation); } Locked = false; } return(rotatedSuccessfully); }
/// <summary> /// Translate the tetromino by the given vector and return whether the translation was successful. /// Fails if tetromino is currently locked. /// </summary> public bool Translate(Vector2Int vec) { if (!Locked) { Locked = true; if (IsValidMovement(vec, MinoTiles)) { this.Position += vec; this.CurrentSpinReward = SpinReward.None; Locked = false; return(true); } Locked = false; } return(false); }
/// <summary> /// Award points for clearing line, spins, combos, etc. /// </summary> private void AwaredScore(int lineClears, SpinReward spinBonus) { int score; if (spinBonus == SpinReward.Regular) { score = 400 + lineClears * 400; } else { switch (lineClears) { case 1: score = 100; break; case 2: score = 300; break; case 3: score = 500; break; case 4: score = 800; break; default: score = 0; break; } if (spinBonus == SpinReward.Mini) { score += 100; } } // Back to back gives + 50% if (spinBonus == SpinReward.Regular || lineClears == 4) { if (BackToBack) { score += score / 2; } BackToBack = true; } else { BackToBack = false; } // Combo points if (lineClears > 0) { score += Combo * 50; Combo++; } else { Combo = 0; } // Check for a perfect clear if (Board.IsEmpty()) { switch (lineClears) { case 1: score += 800; break; case 2: score += 1000; break; case 3: score += 1800; break; case 4: score += 2000; break; } } this.Score += score; EmitSignal(nameof(ScoreUpdateSignal)); }