Tusker/Packages/TTTKit/Sources/TTTKit/UI/GameView.swift

82 lines
2.7 KiB
Swift

//
// GameView.swift
// TTTKit
//
// Created by Shadowfacts on 12/21/22.
//
import SwiftUI
@available(iOS 16.0, *)
public struct GameView: View {
@ObservedObject private var controller: GameController
@State private var cellSize: CGFloat = 0
@State private var scaleAnchor: UnitPoint = .center
@State private var focusedSubBoard: (column: Int, row: Int)? = nil
public init(controller: GameController) {
self.controller = controller
}
public var body: some View {
let scale: CGFloat = focusedSubBoard == nil ? 1 : 2.5
return boardView
.scaleEffect(x: scale, y: scale, anchor: scaleAnchor)
.clipped()
}
private var boardView: some View {
BoardView(board: controller.board, cellSize: $cellSize, spacing: 10) { column, row in
ZStack {
if case .playSpecific(_, column: column, row: row) = controller.state {
Color.teal
.padding(.all, -5)
.opacity(0.4)
}
let board = controller.board.getSubBoard(column: column, row: row)
SubBoardView(board: board, cellTapped: cellTapHandler(column, row))
.environment(\.separatorColor, Color.gray.opacity(0.6))
.contentShape(Rectangle())
.onTapGesture {
switch controller.state {
case .playAnywhere(_), .playSpecific(_, column: column, row: row):
scaleAnchor = UnitPoint(x: CGFloat(column) * 0.5, y: CGFloat(row) * 0.5)
withAnimation(.easeInOut(duration: 0.3)) {
focusedSubBoard = (column, row)
}
default:
break
}
}
.opacity(board.won ? 0.8 : 1)
if let mark = board.win?.mark {
MarkView(mark: mark)
}
}
}
}
private func cellTapHandler(_ column: Int, _ row: Int) -> ((Int, Int) -> Void)? {
guard focusedSubBoard?.column == column && focusedSubBoard?.row == row else {
return nil
}
let subBoard = (column, row)
return { column, row in
controller.play(on: subBoard, column: column, row: row)
withAnimation(.easeInOut(duration: 0.3)) {
focusedSubBoard = nil
}
}
}
}
@available(iOS 16.0, *)
struct GameView_Previews: PreviewProvider {
static var previews: some View {
GameView(controller: GameController())
.padding()
}
}