Use GamePieceView to encapsulate displaying the current piece
This commit is contained in:
parent
18c2938470
commit
907d92b3b8
|
@ -27,7 +27,7 @@ struct ContentView: View {
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
if self.controller.heldTetromino != nil {
|
if self.controller.heldTetromino != nil {
|
||||||
Group {
|
Group {
|
||||||
TetrominoView(tetromino: self.controller.heldTetromino!)
|
TetrominoView(size: 100 / 4, tetromino: self.controller.heldTetromino!)
|
||||||
}.frame(width: 100, height: 100, alignment: .center)
|
}.frame(width: 100, height: 100, alignment: .center)
|
||||||
} else {
|
} else {
|
||||||
Rectangle().foregroundColor(.clear).frame(width: 100, height: 100)
|
Rectangle().foregroundColor(.clear).frame(width: 100, height: 100)
|
||||||
|
@ -49,7 +49,7 @@ struct ContentView: View {
|
||||||
Text("Next")
|
Text("Next")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
NextTetromioesView(tetrominoes: self.controller.nextTetrominoes)
|
NextTetromioesView(size: 100, tetrominoes: self.controller.nextTetrominoes)
|
||||||
.frame(width: 100)
|
.frame(width: 100)
|
||||||
}
|
}
|
||||||
.padding(.trailing, 8)
|
.padding(.trailing, 8)
|
||||||
|
|
|
@ -60,8 +60,9 @@
|
||||||
D608564723551602005BE4BC /* BoardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608564523551602005BE4BC /* BoardView.swift */; };
|
D608564723551602005BE4BC /* BoardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608564523551602005BE4BC /* BoardView.swift */; };
|
||||||
D608564923551BAC005BE4BC /* GridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608564823551BAC005BE4BC /* GridView.swift */; };
|
D608564923551BAC005BE4BC /* GridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608564823551BAC005BE4BC /* GridView.swift */; };
|
||||||
D608564A23551BAC005BE4BC /* GridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608564823551BAC005BE4BC /* GridView.swift */; };
|
D608564A23551BAC005BE4BC /* GridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608564823551BAC005BE4BC /* GridView.swift */; };
|
||||||
D6D84DED23551E5E002968FB /* CurrentPieceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D84DEB23551E37002968FB /* CurrentPieceView.swift */; };
|
D6AA0AE6235D273E00D2FFE8 /* GamePieceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AA0AE4235D272200D2FFE8 /* GamePieceView.swift */; };
|
||||||
D6D84DEE23551E5E002968FB /* CurrentPieceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D84DEB23551E37002968FB /* CurrentPieceView.swift */; };
|
D6AA0AE7235D273F00D2FFE8 /* GamePieceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AA0AE4235D272200D2FFE8 /* GamePieceView.swift */; };
|
||||||
|
D6AA0AE8235D273F00D2FFE8 /* GamePieceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AA0AE4235D272200D2FFE8 /* GamePieceView.swift */; };
|
||||||
D6D84DF523567415002968FB /* Tetromino+Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D84DF323567231002968FB /* Tetromino+Color.swift */; };
|
D6D84DF523567415002968FB /* Tetromino+Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D84DF323567231002968FB /* Tetromino+Color.swift */; };
|
||||||
D6D84DF623567415002968FB /* Tetromino+Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D84DF323567231002968FB /* Tetromino+Color.swift */; };
|
D6D84DF623567415002968FB /* Tetromino+Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D84DF323567231002968FB /* Tetromino+Color.swift */; };
|
||||||
D6D84DF92356B903002968FB /* TetrominoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D84DF72356B8F0002968FB /* TetrominoView.swift */; };
|
D6D84DF92356B903002968FB /* TetrominoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D84DF72356B8F0002968FB /* TetrominoView.swift */; };
|
||||||
|
@ -87,7 +88,6 @@
|
||||||
D6E5606C2357D65700BF9ACF /* TetrisUI.h in Headers */ = {isa = PBXBuildFile; fileRef = D608560723550D3A005BE4BC /* TetrisUI.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
D6E5606C2357D65700BF9ACF /* TetrisUI.h in Headers */ = {isa = PBXBuildFile; fileRef = D608560723550D3A005BE4BC /* TetrisUI.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
D6E5606D2357D65700BF9ACF /* GridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608564823551BAC005BE4BC /* GridView.swift */; };
|
D6E5606D2357D65700BF9ACF /* GridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608564823551BAC005BE4BC /* GridView.swift */; };
|
||||||
D6E5606E2357D65700BF9ACF /* TilesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608562F23551269005BE4BC /* TilesView.swift */; };
|
D6E5606E2357D65700BF9ACF /* TilesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608562F23551269005BE4BC /* TilesView.swift */; };
|
||||||
D6E5606F2357D65700BF9ACF /* CurrentPieceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D84DEB23551E37002968FB /* CurrentPieceView.swift */; };
|
|
||||||
D6E560702357D65700BF9ACF /* BoardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608564523551602005BE4BC /* BoardView.swift */; };
|
D6E560702357D65700BF9ACF /* BoardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608564523551602005BE4BC /* BoardView.swift */; };
|
||||||
D6E560712357D65700BF9ACF /* TetrominoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D84DF72356B8F0002968FB /* TetrominoView.swift */; };
|
D6E560712357D65700BF9ACF /* TetrominoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D84DF72356B8F0002968FB /* TetrominoView.swift */; };
|
||||||
D6E560722357D65700BF9ACF /* NextTetrominoesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DC0E9823579A4D008A0A98 /* NextTetrominoesView.swift */; };
|
D6E560722357D65700BF9ACF /* NextTetrominoesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DC0E9823579A4D008A0A98 /* NextTetrominoesView.swift */; };
|
||||||
|
@ -305,7 +305,7 @@
|
||||||
D608562F23551269005BE4BC /* TilesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TilesView.swift; sourceTree = "<group>"; };
|
D608562F23551269005BE4BC /* TilesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TilesView.swift; sourceTree = "<group>"; };
|
||||||
D608564523551602005BE4BC /* BoardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoardView.swift; sourceTree = "<group>"; };
|
D608564523551602005BE4BC /* BoardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoardView.swift; sourceTree = "<group>"; };
|
||||||
D608564823551BAC005BE4BC /* GridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GridView.swift; sourceTree = "<group>"; };
|
D608564823551BAC005BE4BC /* GridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GridView.swift; sourceTree = "<group>"; };
|
||||||
D6D84DEB23551E37002968FB /* CurrentPieceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentPieceView.swift; sourceTree = "<group>"; };
|
D6AA0AE4235D272200D2FFE8 /* GamePieceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GamePieceView.swift; sourceTree = "<group>"; };
|
||||||
D6D84DF323567231002968FB /* Tetromino+Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Tetromino+Color.swift"; sourceTree = "<group>"; };
|
D6D84DF323567231002968FB /* Tetromino+Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Tetromino+Color.swift"; sourceTree = "<group>"; };
|
||||||
D6D84DF72356B8F0002968FB /* TetrominoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TetrominoView.swift; sourceTree = "<group>"; };
|
D6D84DF72356B8F0002968FB /* TetrominoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TetrominoView.swift; sourceTree = "<group>"; };
|
||||||
D6DC0E9323575D7C008A0A98 /* DPadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DPadView.swift; sourceTree = "<group>"; };
|
D6DC0E9323575D7C008A0A98 /* DPadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DPadView.swift; sourceTree = "<group>"; };
|
||||||
|
@ -524,9 +524,9 @@
|
||||||
D6E5609F2358C68C00BF9ACF /* BundleHelper.swift */,
|
D6E5609F2358C68C00BF9ACF /* BundleHelper.swift */,
|
||||||
D608564823551BAC005BE4BC /* GridView.swift */,
|
D608564823551BAC005BE4BC /* GridView.swift */,
|
||||||
D608562F23551269005BE4BC /* TilesView.swift */,
|
D608562F23551269005BE4BC /* TilesView.swift */,
|
||||||
D6D84DEB23551E37002968FB /* CurrentPieceView.swift */,
|
|
||||||
D608564523551602005BE4BC /* BoardView.swift */,
|
D608564523551602005BE4BC /* BoardView.swift */,
|
||||||
D6D84DF72356B8F0002968FB /* TetrominoView.swift */,
|
D6D84DF72356B8F0002968FB /* TetrominoView.swift */,
|
||||||
|
D6AA0AE4235D272200D2FFE8 /* GamePieceView.swift */,
|
||||||
D6DC0E9823579A4D008A0A98 /* NextTetrominoesView.swift */,
|
D6DC0E9823579A4D008A0A98 /* NextTetrominoesView.swift */,
|
||||||
D6D84DF323567231002968FB /* Tetromino+Color.swift */,
|
D6D84DF323567231002968FB /* Tetromino+Color.swift */,
|
||||||
D6E5609B2358C50A00BF9ACF /* Media.xcassets */,
|
D6E5609B2358C50A00BF9ACF /* Media.xcassets */,
|
||||||
|
@ -1056,9 +1056,9 @@
|
||||||
D608564623551602005BE4BC /* BoardView.swift in Sources */,
|
D608564623551602005BE4BC /* BoardView.swift in Sources */,
|
||||||
D608564923551BAC005BE4BC /* GridView.swift in Sources */,
|
D608564923551BAC005BE4BC /* GridView.swift in Sources */,
|
||||||
D6DC0E9923579A4D008A0A98 /* NextTetrominoesView.swift in Sources */,
|
D6DC0E9923579A4D008A0A98 /* NextTetrominoesView.swift in Sources */,
|
||||||
D6D84DED23551E5E002968FB /* CurrentPieceView.swift in Sources */,
|
|
||||||
D60856332355128F005BE4BC /* TilesView.swift in Sources */,
|
D60856332355128F005BE4BC /* TilesView.swift in Sources */,
|
||||||
D6D84DF523567415002968FB /* Tetromino+Color.swift in Sources */,
|
D6D84DF523567415002968FB /* Tetromino+Color.swift in Sources */,
|
||||||
|
D6AA0AE8235D273F00D2FFE8 /* GamePieceView.swift in Sources */,
|
||||||
D6E560A02358C68C00BF9ACF /* BundleHelper.swift in Sources */,
|
D6E560A02358C68C00BF9ACF /* BundleHelper.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -1071,9 +1071,9 @@
|
||||||
D608564723551602005BE4BC /* BoardView.swift in Sources */,
|
D608564723551602005BE4BC /* BoardView.swift in Sources */,
|
||||||
D608564A23551BAC005BE4BC /* GridView.swift in Sources */,
|
D608564A23551BAC005BE4BC /* GridView.swift in Sources */,
|
||||||
D6DC0E9A23579A4D008A0A98 /* NextTetrominoesView.swift in Sources */,
|
D6DC0E9A23579A4D008A0A98 /* NextTetrominoesView.swift in Sources */,
|
||||||
D6D84DEE23551E5E002968FB /* CurrentPieceView.swift in Sources */,
|
|
||||||
D60856342355128F005BE4BC /* TilesView.swift in Sources */,
|
D60856342355128F005BE4BC /* TilesView.swift in Sources */,
|
||||||
D6D84DF623567415002968FB /* Tetromino+Color.swift in Sources */,
|
D6D84DF623567415002968FB /* Tetromino+Color.swift in Sources */,
|
||||||
|
D6AA0AE7235D273F00D2FFE8 /* GamePieceView.swift in Sources */,
|
||||||
D6E560A12358C68C00BF9ACF /* BundleHelper.swift in Sources */,
|
D6E560A12358C68C00BF9ACF /* BundleHelper.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -1110,8 +1110,8 @@
|
||||||
D6E560732357D65700BF9ACF /* Tetromino+Color.swift in Sources */,
|
D6E560732357D65700BF9ACF /* Tetromino+Color.swift in Sources */,
|
||||||
D6E560702357D65700BF9ACF /* BoardView.swift in Sources */,
|
D6E560702357D65700BF9ACF /* BoardView.swift in Sources */,
|
||||||
D6E560712357D65700BF9ACF /* TetrominoView.swift in Sources */,
|
D6E560712357D65700BF9ACF /* TetrominoView.swift in Sources */,
|
||||||
D6E5606F2357D65700BF9ACF /* CurrentPieceView.swift in Sources */,
|
|
||||||
D6E5606D2357D65700BF9ACF /* GridView.swift in Sources */,
|
D6E5606D2357D65700BF9ACF /* GridView.swift in Sources */,
|
||||||
|
D6AA0AE6235D273E00D2FFE8 /* GamePieceView.swift in Sources */,
|
||||||
D6E560A22358C68C00BF9ACF /* BundleHelper.swift in Sources */,
|
D6E560A22358C68C00BF9ACF /* BundleHelper.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
|
@ -29,7 +29,7 @@ struct ContentView: View {
|
||||||
Text("Held")
|
Text("Held")
|
||||||
if self.controller.heldTetromino != nil {
|
if self.controller.heldTetromino != nil {
|
||||||
Group {
|
Group {
|
||||||
TetrominoView(tetromino: self.controller.heldTetromino!)
|
TetrominoView(size: 50 / 4, tetromino: self.controller.heldTetromino!)
|
||||||
}.frame(width: 50, height: 50, alignment: .center)
|
}.frame(width: 50, height: 50, alignment: .center)
|
||||||
} else {
|
} else {
|
||||||
Rectangle().foregroundColor(.clear).frame(width: 50, height: 50)
|
Rectangle().foregroundColor(.clear).frame(width: 50, height: 50)
|
||||||
|
@ -48,7 +48,7 @@ struct ContentView: View {
|
||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
Text("Next")
|
Text("Next")
|
||||||
NextTetromioesView(tetrominoes: self.controller.nextTetrominoes)
|
NextTetromioesView(size: 50, tetrominoes: self.controller.nextTetrominoes)
|
||||||
.frame(width: 50)
|
.frame(width: 50)
|
||||||
}
|
}
|
||||||
.padding(.trailing, 8)
|
.padding(.trailing, 8)
|
||||||
|
|
|
@ -11,8 +11,9 @@ import Foundation
|
||||||
public struct GamePiece {
|
public struct GamePiece {
|
||||||
public let tetromino: Tetromino
|
public let tetromino: Tetromino
|
||||||
public var topLeft: (Int, Int)
|
public var topLeft: (Int, Int)
|
||||||
|
public internal(set) var rotation: Double = 0
|
||||||
public internal(set) var tiles: [[Bool]]
|
public internal(set) var tiles: [[Bool]]
|
||||||
|
|
||||||
public init(tetromino: Tetromino, topLeft: (Int, Int) = (0, 0)) {
|
public init(tetromino: Tetromino, topLeft: (Int, Int) = (0, 0)) {
|
||||||
self.tetromino = tetromino
|
self.tetromino = tetromino
|
||||||
self.tiles = tetromino.shape
|
self.tiles = tetromino.shape
|
||||||
|
@ -23,8 +24,10 @@ public struct GamePiece {
|
||||||
switch direction {
|
switch direction {
|
||||||
case .clockwise:
|
case .clockwise:
|
||||||
self.tiles.rotateClockwise()
|
self.tiles.rotateClockwise()
|
||||||
|
rotation += 90
|
||||||
case .counterClockwise:
|
case .counterClockwise:
|
||||||
self.tiles.rotateCounterclockwise()
|
self.tiles.rotateCounterclockwise()
|
||||||
|
rotation -= 90
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,17 @@ public struct BoardView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
ZStack {
|
GeometryReader { (geometry) in
|
||||||
TilesView(board: $board)
|
ZStack(alignment: .topLeading) {
|
||||||
|
TilesView(board: self.$board)
|
||||||
CurrentPieceView(boardWidth: board.width, boardHeight: board.height, currentPiece: $currentPiece, droppedPiece: $droppedPiece)
|
|
||||||
|
if self.currentPiece != nil {
|
||||||
|
GamePieceView(size: min(geometry.size.width / CGFloat(self.board.width), geometry.size.height / CGFloat(self.board.height)), piece: self.currentPiece!)
|
||||||
|
}
|
||||||
|
if self.droppedPiece != nil {
|
||||||
|
GamePieceView(size: min(geometry.size.width / CGFloat(self.board.width), geometry.size.height / CGFloat(self.board.height)), piece: self.droppedPiece!, color: .gray, border: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
//
|
|
||||||
// CurrentPieceView.swift
|
|
||||||
// Tetris
|
|
||||||
//
|
|
||||||
// Created by Shadowfacts on 10/14/19.
|
|
||||||
// Copyright © 2019 Shadowfacts. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
import TetrisKit
|
|
||||||
|
|
||||||
struct CurrentPieceView: View {
|
|
||||||
let boardWidth: Int
|
|
||||||
let boardHeight: Int
|
|
||||||
@Binding var currentPiece: GamePiece?
|
|
||||||
@Binding var droppedPiece: GamePiece?
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
GridView(rows: self.boardHeight, columns: self.boardWidth) { (col, row, size) in
|
|
||||||
if self.currentPieceAt(col, row) {
|
|
||||||
Rectangle()
|
|
||||||
.foregroundColor(self.currentPiece!.tetromino.color)
|
|
||||||
.frame(width: size, height: size)
|
|
||||||
.border(self.currentPiece!.tetromino.borderColor, width: 6)
|
|
||||||
} else if self.droppedPieceAt(col, row) {
|
|
||||||
Rectangle()
|
|
||||||
.foregroundColor(.gray)
|
|
||||||
.frame(width: size, height: size)
|
|
||||||
} else {
|
|
||||||
Rectangle()
|
|
||||||
.foregroundColor(.clear)
|
|
||||||
.frame(width: size, height: size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func currentPieceAt(_ col: Int, _ row: Int) -> Bool {
|
|
||||||
guard let currentPiece = self.currentPiece else { return false }
|
|
||||||
let (left, top) = currentPiece.topLeft
|
|
||||||
let pieceHeight = currentPiece.tiles.count
|
|
||||||
let pieceWidth = currentPiece.tiles.first!.count
|
|
||||||
return col - left >= 0 && col - left < pieceWidth && row - top >= 0 && row - top < pieceHeight && currentPiece.tiles[row - top][col - left]
|
|
||||||
}
|
|
||||||
|
|
||||||
func droppedPieceAt(_ col: Int, _ row: Int) -> Bool {
|
|
||||||
guard let droppedPiece = self.droppedPiece else { return false }
|
|
||||||
let (left, top) = droppedPiece.topLeft
|
|
||||||
let pieceHeight = droppedPiece.tiles.count
|
|
||||||
let pieceWidth = droppedPiece.tiles.first!.count
|
|
||||||
return col - left >= 0 && col - left < pieceWidth && row - top >= 0 && row - top < pieceHeight && droppedPiece.tiles[row - top][col - left]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CurrentPieceView_Previews: PreviewProvider {
|
|
||||||
@State static var currentPiece: GamePiece? = GamePiece(tetromino: .t)
|
|
||||||
@State static var droppedPiece: GamePiece? = {
|
|
||||||
var piece = GamePiece(tetromino: .t)
|
|
||||||
return piece.moved(by: (0, 16 - piece.tiles.count))
|
|
||||||
}()
|
|
||||||
|
|
||||||
static var previews: some View {
|
|
||||||
CurrentPieceView(boardWidth: 10, boardHeight: 16, currentPiece: $currentPiece, droppedPiece: $droppedPiece)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// GamePieceView.swift
|
||||||
|
// Tetris
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 10/20/19.
|
||||||
|
// Copyright © 2019 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import TetrisKit
|
||||||
|
|
||||||
|
struct GamePieceView: View {
|
||||||
|
let size: CGFloat
|
||||||
|
let piece: GamePiece
|
||||||
|
let color: Color
|
||||||
|
let border: Bool
|
||||||
|
|
||||||
|
init(size: CGFloat, piece: GamePiece, color: Color? = nil, border: Bool = true) {
|
||||||
|
self.size = size
|
||||||
|
self.piece = piece
|
||||||
|
self.color = color ?? piece.tetromino.color
|
||||||
|
self.border = border
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
return TetrominoView(size: size, tetromino: piece.tetromino, color: color, border: border)
|
||||||
|
.rotationEffect(.degrees(piece.rotation))
|
||||||
|
.offset(x: CGFloat(piece.topLeft.0) * size, y: CGFloat(piece.topLeft.1) * size)
|
||||||
|
.frame(width: size * CGFloat(piece.tiles.count), height: size * CGFloat(piece.tiles.count))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GamePieceView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
GamePieceView(size: 100, piece: GamePiece(tetromino: .t))
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,16 +10,18 @@ import SwiftUI
|
||||||
import TetrisKit
|
import TetrisKit
|
||||||
|
|
||||||
public struct NextTetromioesView: View {
|
public struct NextTetromioesView: View {
|
||||||
|
let size: CGFloat
|
||||||
let tetrominoes: [Tetromino]
|
let tetrominoes: [Tetromino]
|
||||||
|
|
||||||
public init(tetrominoes: [Tetromino]) {
|
public init(size: CGFloat, tetrominoes: [Tetromino]) {
|
||||||
|
self.size = size
|
||||||
self.tetrominoes = tetrominoes
|
self.tetrominoes = tetrominoes
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
ForEach(0..<self.tetrominoes.count, id: \.self) { (index) in
|
ForEach(0..<self.tetrominoes.count, id: \.self) { (index) in
|
||||||
TetrominoView(tetromino: self.tetrominoes[index]).aspectRatio(1, contentMode: .fit)
|
TetrominoView(size: self.size / 4, tetromino: self.tetrominoes[index]).aspectRatio(1, contentMode: .fit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +29,6 @@ public struct NextTetromioesView: View {
|
||||||
|
|
||||||
struct NextTetrominoesView_Previews: PreviewProvider {
|
struct NextTetrominoesView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
NextTetromioesView(tetrominoes: [.t, .l, .z])
|
NextTetromioesView(size: 50, tetrominoes: [.t, .l, .z])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,51 +10,47 @@ import SwiftUI
|
||||||
import TetrisKit
|
import TetrisKit
|
||||||
|
|
||||||
public struct TetrominoView: View {
|
public struct TetrominoView: View {
|
||||||
|
let size: CGFloat
|
||||||
let tetromino: Tetromino
|
let tetromino: Tetromino
|
||||||
|
let color: Color
|
||||||
|
let border: Bool
|
||||||
|
|
||||||
public init(tetromino: Tetromino) {
|
public init(size: CGFloat, tetromino: Tetromino, color: Color? = nil, border: Bool = true) {
|
||||||
|
self.size = size
|
||||||
self.tetromino = tetromino
|
self.tetromino = tetromino
|
||||||
|
self.color = color ?? tetromino.color
|
||||||
|
self.border = border
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
GridView(rows: self.rows, columns: self.columns) { (col, row, size) in
|
GridView(rows: tetromino.shape.count, columns: tetromino.shape.first!.count) { (col, row, _) in
|
||||||
if row < self.tetromino.shape.count && col < self.tetromino.shape[row].count && self.tetromino.shape[row][col] {
|
if row < self.tetromino.shape.count && col < self.tetromino.shape[row].count && self.tetromino.shape[row][col] {
|
||||||
Rectangle()
|
if self.border {
|
||||||
.foregroundColor(self.tetromino.color)
|
Rectangle()
|
||||||
.frame(width: size, height: size)
|
.foregroundColor(self.color)
|
||||||
.border(self.tetromino.borderColor, width: 6)
|
.frame(width: self.size, height: self.size)
|
||||||
|
.border(self.tetromino.borderColor, width: 6)
|
||||||
|
} else {
|
||||||
|
Rectangle()
|
||||||
|
.foregroundColor(self.color)
|
||||||
|
.frame(width: self.size, height: self.size)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.foregroundColor(.clear)
|
.foregroundColor(.clear)
|
||||||
.frame(width: size, height: size)
|
.frame(width: self.size, height: self.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var rows: Int {
|
|
||||||
self.tetromino.shape.firstIndex(where: { row in
|
|
||||||
row.allSatisfy({ el in
|
|
||||||
!el
|
|
||||||
})
|
|
||||||
}) ?? self.tetromino.shape.count
|
|
||||||
}
|
|
||||||
|
|
||||||
var columns: Int {
|
|
||||||
self.tetromino.shape.map { row in
|
|
||||||
(row.firstIndex(where: { el in
|
|
||||||
!el
|
|
||||||
}) ?? row.count - 1) + 1
|
|
||||||
}.max() ?? self.tetromino.shape.first!.count
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TetrominoView_Previews: PreviewProvider {
|
struct TetrominoView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
Group {
|
Group {
|
||||||
TetrominoView(tetromino: .t)
|
TetrominoView(size: 50, tetromino: .t)
|
||||||
TetrominoView(tetromino: .i)
|
TetrominoView(size: 50, tetromino: .i)
|
||||||
TetrominoView(tetromino: .z)
|
TetrominoView(size: 50, tetromino: .z)
|
||||||
TetrominoView(tetromino: .j)
|
TetrominoView(size: 50, tetromino: .j)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue