Skip to content

Commit

Permalink
Merge pull request #2 from jVirus/maintenance/warning-fixes
Browse files Browse the repository at this point in the history
Maintenance/warning fixes
  • Loading branch information
eleev authored Aug 15, 2022
2 parents f9a33e4 + a701d3b commit 5f951a7
Show file tree
Hide file tree
Showing 18 changed files with 263 additions and 173 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# swiftui-2048[![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome)

[![Language](https://img.shields.io/badge/Language-Swift_5.5-orange.svg)]()
[![Language](https://img.shields.io/badge/Language-Swift_5.7-orange.svg)]()
[![Framework](https://img.shields.io/badge/Framework-SwiftUI_3.0-red.svg)]()
[![Shaders](https://img.shields.io/badge/Platforms-iOS|iPadOS|macOS-green.svg)]()
[![Last Commit](https://img.shields.io/github/last-commit/jvirus/swiftui-2048)]()
Expand Down Expand Up @@ -32,7 +32,7 @@ Please wait while the `.gif` files are loading...
- Supports `iPhone`, `iPad` & `macOS`-enabled devices
- No graphical assets
- Minimum deployment target is `iOS 14.0` & `macOS 11.0`
- `Swift 5.3`
- `Swift 5.7`
- Pure `SwiftUI 2.0` app
- Score & merge streak system: when multiple merges occur in a row - you got a score multiplier 😎
- Settings
Expand Down
4 changes: 4 additions & 0 deletions T2iles.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,9 @@
);
PRODUCT_BUNDLE_IDENTIFIER = eleev.astemir.T2iles;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
Expand All @@ -868,7 +870,9 @@
);
PRODUCT_BUNDLE_IDENTIFIER = eleev.astemir.T2iles;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
Expand Down
10 changes: 6 additions & 4 deletions T2iles/Sources/Models/Board/GameBoardSizeState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct GameBoardSizeState {
private(set) var boardSize: BoardSize = .fourByFour {
didSet {
defaults.set(boardSize.rawValue, forKey: Notification.Name.gameBoardSize.rawValue)
self.publishState()
publishState()
}
}

Expand Down Expand Up @@ -88,8 +88,10 @@ struct GameBoardSizeState {
// MARK: - Private Methods

private func publishState() {
NotificationCenter.default.post(name: .gameBoardSize,
object: nil,
userInfo: [Notification.Name.gameBoardSizeUserInfoKey : boardSize])
NotificationCenter.default.post(
name: .gameBoardSize,
object: nil,
userInfo: [Notification.Name.gameBoardSizeUserInfoKey : boardSize]
)
}
}
45 changes: 27 additions & 18 deletions T2iles/Sources/Models/Board/GameLogic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ final class GameLogic: ObservableObject {
// MARK: - Initializers

init(size: Int) {
self.boardSize = size
boardSize = size
reset(boardSize: size)

NotificationCenter
Expand All @@ -54,10 +54,10 @@ final class GameLogic: ObservableObject {
.map {
$0.userInfo?[Notification.Name.gameBoardSizeUserInfoKey] as? BoardSize
}
.sink {
.sink { [unowned self] in
guard let gameBoardSize = $0 else { return }
let rawValue = gameBoardSize.rawValue
self.reset(boardSize: rawValue)
reset(boardSize: rawValue)
}.store(in: &cancellables)
}

Expand Down Expand Up @@ -93,11 +93,13 @@ final class GameLogic: ObservableObject {
var rowSnapshot = [IdentifiedTile?]()
var compactRow = [IdentifiedTile]()

computeIntermediateSnapshot(&rowSnapshot,
&compactRow,
axis: axis,
currentRow: row)

computeIntermediateSnapshot(
&rowSnapshot,
&compactRow,
axis: axis,
currentRow: row
)

if merge(blocks: &compactRow, reverse: direction == .down || direction == .right) {
hasMergedBlocks = true
}
Expand All @@ -116,17 +118,21 @@ final class GameLogic: ObservableObject {
tileMatrix.add($1, to: axis ? ($0, row) : (row, $0))
}
}
return finalizeMove(previousMatrixSnapshot,
hasMoved: moved,
hasMergedBlocks: hasMergedBlocks)
return finalizeMove(
previousMatrixSnapshot,
hasMoved: moved,
hasMergedBlocks: hasMergedBlocks
)
}

// MARK: - Private Methods

private func computeIntermediateSnapshot(_ rowSnapshot: inout [IdentifiedTile?],
_ compactRow: inout [IdentifiedTile],
axis: Bool,
currentRow row: Int) {
private func computeIntermediateSnapshot(
_ rowSnapshot: inout [IdentifiedTile?],
_ compactRow: inout [IdentifiedTile],
axis: Bool,
currentRow row: Int
) {
for col in 0..<boardSize {
if let block = tileMatrix[axis ? (col, row) : (row, col)] {
rowSnapshot.append(block)
Expand Down Expand Up @@ -270,9 +276,12 @@ final class GameLogic: ObservableObject {
var blankLocations = blankLocations
blankLocations[placeLocIndex] = lastLoc
placeLocIndex = Int.random(in: 0..<(blankLocations.count - 1))
tileMatrix.add(IdentifiedTile(id: mutableInstanceId,
value: 2),
to: blankLocations[placeLocIndex])
tileMatrix.add(
IdentifiedTile(
id: mutableInstanceId,
value: 2),
to: blankLocations[placeLocIndex]
)
return true
}
}
2 changes: 1 addition & 1 deletion T2iles/Sources/Styles/FilledBackgroundStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ struct FilledBackgroundStyle: ButtonStyle {
.scaleEffect(configuration.isPressed ? 0.9 : 1.0)
.background(Color.primary)
.cornerRadius(25)
.animation(.modalSpring)
.animation(.modalSpring, value: configuration.isPressed)
}
}
20 changes: 10 additions & 10 deletions T2iles/Sources/View Modifiers/BottomSlidableModalModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,28 @@ struct BottomSlidableModalModifier: ViewModifier {
@Binding var sideMenuViewState: CGSize
@Binding var hasGameEnded: Bool
var onGameEndCompletion: () -> Void = { }
let sideMenuDragHeight: CGFloat = 100

func body(content: Content) -> some View {
content
.offset(y: self.presentEndGameModal ? (proxy.size.height / 2.0) : (proxy.size.height + proxy.size.height / 2))
.offset(y: self.sideMenuViewState.height)
.animation(.modalSpring)
.offset(y: presentEndGameModal ? (proxy.size.height / 2.0) : (proxy.size.height + proxy.size.height / 2))
.offset(y: sideMenuViewState.height)
.animation(.modalSpring, value: presentEndGameModal)
.gesture(
DragGesture().onChanged { value in
if value.translation.height > 0 {
self.sideMenuViewState.height = value.translation.height
sideMenuViewState.height = value.translation.height
}
}
.onEnded { value in
if self.sideMenuViewState.height > 100 {

if sideMenuViewState.height > sideMenuDragHeight {
withAnimation(.modalSpring) {
self.presentEndGameModal = false
self.hasGameEnded = false
self.onGameEndCompletion()
presentEndGameModal = false
hasGameEnded = false
onGameEndCompletion()
}
}
self.sideMenuViewState = .zero
sideMenuViewState = .zero
}
)
}
Expand Down
14 changes: 7 additions & 7 deletions T2iles/Sources/View Modifiers/MainViewModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ struct MainViewModifier: ViewModifier {

func body(content: Content) -> some View {
content
.offset(y: self.presentEndGameModal ? self.horizontalSizeClass == .regular ? (proxy.size.width < proxy.size.height ? -proxy.size.height / 4 : -proxy.size.height / 3) : -proxy.size.height / 3 : 0)
.rotation3DEffect(Angle(degrees: self.presentEndGameModal ? proxy.size.width < proxy.size.height ? Double(self.viewState.height / 10) - 10 : Double(self.viewState.height / 10) - 20 : 0), axis: (x: 10.0, y: 0, z: 0))
.scaleEffect(self.presentEndGameModal ? 0.9 : 1)
.rotation3DEffect(Angle(degrees: self.presentSideMenu ? Double(self.viewState.width / 10) - (self.horizontalSizeClass == .regular ? 10 : 20) : 0), axis: (x: 0, y: 10, z: 0))
.offset(x: self.presentSideMenu ? (self.horizontalSizeClass == .regular ? proxy.size.width / 3 : proxy.size.width / 1.5) : 0)
.offset(x: -self.viewState.width)
.scaleEffect(self.presentSideMenu ? 0.9 : 1)
.offset(y: presentEndGameModal ? horizontalSizeClass == .regular ? (proxy.size.width < proxy.size.height ? -proxy.size.height / 4 : -proxy.size.height / 3) : -proxy.size.height / 3 : 0)
.rotation3DEffect(Angle(degrees: presentEndGameModal ? proxy.size.width < proxy.size.height ? Double(viewState.height / 10) - 10 : Double(viewState.height / 10) - 20 : 0), axis: (x: 10.0, y: 0, z: 0))
.scaleEffect(presentEndGameModal ? 0.9 : 1)
.rotation3DEffect(Angle(degrees: presentSideMenu ? Double(viewState.width / 10) - (horizontalSizeClass == .regular ? 10 : 20) : 0), axis: (x: 0, y: 10, z: 0))
.offset(x: presentSideMenu ? (horizontalSizeClass == .regular ? proxy.size.width / 3 : proxy.size.width / 1.5) : 0)
.offset(x: -viewState.width)
.scaleEffect(presentSideMenu ? 0.9 : 1)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct RoundedClippedBackground: ViewModifier {

func body(content: Content) -> some View {
content
.background(Rectangle().fill(self.backgroundColor))
.background(Rectangle().fill(backgroundColor))
.clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous))
.shadow(color: Color.primary.opacity(0.3), radius: 20)
}
Expand Down
7 changes: 3 additions & 4 deletions T2iles/Sources/View Modifiers/SlideViewModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@
import SwiftUI

struct SlideViewModifier<T: Gesture>: ViewModifier {

var gesture: T
@Binding var presentEndGameModal: Bool
@Binding var presentSideMenu: Bool

func body(content: Content) -> some View {
content
.gesture(self.gesture, including: .all)
.scaleEffect((self.presentEndGameModal || self.presentSideMenu) ? 0.9 : 1.0)
.allowsHitTesting(!(self.presentEndGameModal || self.presentSideMenu))
.gesture(gesture, including: .all)
.scaleEffect((presentEndGameModal || presentSideMenu) ? 0.9 : 1.0)
.allowsHitTesting(!(presentEndGameModal || presentSideMenu))
}
}
120 changes: 80 additions & 40 deletions T2iles/Sources/Views/Game/GameStateBottomView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import SwiftUI

struct GameStateBottomView: View {

// MARK: - Properties

@Binding var hasGameEnded: Bool
@Binding var presentEndGameModal: Bool
@Binding var sideMenuViewState: CGSize
Expand All @@ -19,54 +21,92 @@ struct GameStateBottomView: View {
private let plist = PlistConfiguration(name: "Strings")
private let gameBoardState: [String : [String : String]]

init(hasGameEnded: Binding<Bool>,
presentEndGameModal: Binding<Bool>,
sideMenuViewState: Binding<CGSize>,
score: Binding<Int>,
resetGame: @escaping () -> Void) {
self._hasGameEnded = hasGameEnded
self._presentEndGameModal = presentEndGameModal
self._sideMenuViewState = sideMenuViewState
self._score = score
// MARK: - Initializers

init(
hasGameEnded: Binding<Bool>,
presentEndGameModal: Binding<Bool>,
sideMenuViewState: Binding<CGSize>,
score: Binding<Int>,
resetGame: @escaping () -> Void
) {
_hasGameEnded = hasGameEnded
_presentEndGameModal = presentEndGameModal
_sideMenuViewState = sideMenuViewState
_score = score
self.resetGame = resetGame

gameBoardState = plist?.getItem(named: PlistConfigurationKeyPath.gameState.rawValue) ?? ["" : [:]]
}

// MARK: - Views

private var modalGameEnd: some View {
ModalView(
title: gameBoardState[PlistConfigurationKeyPath.gameState.rawValue]?[PlistConfigurationKeyPath.gameOverTitle.rawValue] ?? "",
subtitle: (gameBoardState[PlistConfigurationKeyPath.gameState.rawValue]?[PlistConfigurationKeyPath.gameOverSubtitle.rawValue] ?? "") + "\(score)",
completionHandler: {
withAnimation(.modalSpring) {
resetGame()
presentEndGameModal = false
}
hasGameEnded = false
}
)
}

private var modalExistingGame: some View {
ModalView(
title: gameBoardState[PlistConfigurationKeyPath.gameState.rawValue]?[PlistConfigurationKeyPath.resetGameTitle.rawValue] ?? "",
subtitle: gameBoardState[PlistConfigurationKeyPath.gameState.rawValue]?[PlistConfigurationKeyPath.resetGameSubtitle.rawValue] ?? "",
completionHandler: {
withAnimation(.modalSpring) {
resetGame()
presentEndGameModal = false
}
}
) {
withAnimation(.modalSpring) {
presentEndGameModal = false
}
}
}

// MARK: - Conformance to View protocol

var body: some View {
GeometryReader { proxy in
if self.hasGameEnded {
ModalView(title: gameBoardState[PlistConfigurationKeyPath.gameState.rawValue]?[PlistConfigurationKeyPath.gameOverTitle.rawValue] ?? "",
subtitle: (gameBoardState[PlistConfigurationKeyPath.gameState.rawValue]?[PlistConfigurationKeyPath.gameOverSubtitle.rawValue] ?? "") + "\(score)", completionHandler: {
withAnimation(.modalSpring) {
resetGame()
presentEndGameModal = false
}
hasGameEnded = false
})
.modifier(BottomSlidableModalModifier(proxy: proxy,
presentEndGameModal: $presentEndGameModal,
sideMenuViewState: $sideMenuViewState,
hasGameEnded: $hasGameEnded,
onGameEndCompletion: {
resetGame() // Reset the game on interactive dismiss gesture
}))
} else {
ModalView(title: gameBoardState[PlistConfigurationKeyPath.gameState.rawValue]?[PlistConfigurationKeyPath.resetGameTitle.rawValue] ?? "", subtitle: gameBoardState[PlistConfigurationKeyPath.gameState.rawValue]?[PlistConfigurationKeyPath.resetGameSubtitle.rawValue] ?? "", completionHandler: {
withAnimation(.modalSpring) {
resetGame()
presentEndGameModal = false
}
}) {
withAnimation(.modalSpring) {
presentEndGameModal = false
}
}
.modifier(BottomSlidableModalModifier(proxy: proxy,
presentEndGameModal: $presentEndGameModal,
sideMenuViewState: $sideMenuViewState,
hasGameEnded: .constant(false)))
switch hasGameEnded {
case true:
modalGameEnd
.modifier(bottomGameOverSheet(proxy))
case false:
modalExistingGame
.modifier(bottomExistingGameSheet(proxy))
}
}
}

// MARK: - Private View Modifiers

private func bottomGameOverSheet(_ proxy: GeometryProxy) -> some ViewModifier {
BottomSlidableModalModifier(
proxy: proxy,
presentEndGameModal: $presentEndGameModal,
sideMenuViewState: $sideMenuViewState,
hasGameEnded: $hasGameEnded,
onGameEndCompletion: {
resetGame() // Reset the game on interactive dismiss gesture
}
)
}

private func bottomExistingGameSheet(_ proxy: GeometryProxy) -> some ViewModifier {
BottomSlidableModalModifier(
proxy: proxy,
presentEndGameModal: $presentEndGameModal,
sideMenuViewState: $sideMenuViewState,
hasGameEnded: .constant(false)
)
}
}
Loading

0 comments on commit 5f951a7

Please sign in to comment.