// // GameController.swift // TetrisKit // // Created by Shadowfacts on 10/13/19. // Copyright © 2019 Shadowfacts. All rights reserved. // import Foundation import Combine public class GameController: ObservableObject { public let width = 10 public let height = 20 var paused = false public var state: GameState = .waitingForStart @Published public var board: GameBoard @Published public var currentPiece: GamePiece? { didSet { updateCurrentPieceAtDropPoint() } } @Published public var currentPieceAtDropPoint: GamePiece? @Published public var nextTetrominoes: [Tetromino] = [] @Published public var heldTetromino: Tetromino? var currentBag: [Tetromino] = [] @Published public var score = 0 var previousPieceWasTetris = false public init() { self.board = GameBoard(width: width, height: height) self.currentPiece = nil } public func start() { state = .playing(.normal) generateBag() nextPiece() } func nextPiece() { let tetromino = nextTetrominoes.first! let nextPiece = GamePiece(tetromino: tetromino, topLeft: ((width - tetromino.shape.count) / 2, 0)) if overlapsAny(nextPiece) { state = .ended } else { nextTetrominoes.removeFirst() if currentBag.isEmpty { generateBag() } nextTetrominoes.append(currentBag.removeFirst()) currentPiece = nextPiece } } func generateBag() { currentBag = Array(0..= 0 { if board.rowFull(row) { board.tiles.remove(at: row) cleared += 1 } row -= 1 } for _ in 0.. Bool { let (left, top) = piece.topLeft for y in 0..= height || left + x < 0 || left + x >= width || board[left + x, top + y] { return true } } } return false } } public enum GameState { case waitingForStart case playing(PlayState) case ended } public enum PlayState { case normal case dropped case switched }