mirror of
https://github.com/ivanvorobei/SwiftUI.git
synced 2026-01-16 14:06:40 +01:00
128 lines
4.3 KiB
Swift
Executable File
128 lines
4.3 KiB
Swift
Executable File
//
|
|
// GameView.swift
|
|
// SwiftUI2048
|
|
//
|
|
// Created by Hongyu on 6/5/19.
|
|
// Copyright © 2019 Cyandev. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
extension Edge {
|
|
|
|
static func from(_ from: GameLogic.Direction) -> Self {
|
|
switch from {
|
|
case .down:
|
|
return .top
|
|
case .up:
|
|
return .bottom
|
|
case .left:
|
|
return .trailing
|
|
case .right:
|
|
return .leading
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
struct GameView : View {
|
|
|
|
@State var gestureStartLocation: CGPoint = .zero
|
|
@State var lastGestureDirection: GameLogic.Direction = .up
|
|
@EnvironmentObject var gameLogic: GameLogic
|
|
|
|
fileprivate struct LayoutTraits {
|
|
let bannerOffset: CGSize
|
|
let containerAlignment: Alignment
|
|
}
|
|
|
|
fileprivate func layoutTraits(`for` proxy: GeometryProxy) -> LayoutTraits {
|
|
let landscape = proxy.size.width > proxy.size.height
|
|
|
|
return LayoutTraits(
|
|
bannerOffset: landscape
|
|
? .init(width: proxy.safeAreaInsets.leading + 32, height: 0)
|
|
: .init(width: 0, height: proxy.safeAreaInsets.top + 32),
|
|
containerAlignment: landscape ? .leading : .top
|
|
)
|
|
}
|
|
|
|
var gesture: some Gesture {
|
|
let threshold: CGFloat = 44
|
|
let drag = DragGesture()
|
|
.onChanged { v in
|
|
guard self.gestureStartLocation != v.startLocation else { return }
|
|
|
|
withTransaction(Transaction()) {
|
|
self.gestureStartLocation = v.startLocation
|
|
|
|
if v.translation.width > threshold {
|
|
// Move right
|
|
self.gameLogic.move(.right)
|
|
self.lastGestureDirection = .right
|
|
} else if v.translation.width < -threshold {
|
|
// Move left
|
|
self.gameLogic.move(.left)
|
|
self.lastGestureDirection = .left
|
|
} else if v.translation.height > threshold {
|
|
// Move down
|
|
self.gameLogic.move(.down)
|
|
self.lastGestureDirection = .down
|
|
} else if v.translation.height < -threshold {
|
|
// Move up
|
|
self.gameLogic.move(.up)
|
|
self.lastGestureDirection = .up
|
|
} else {
|
|
// Direction cannot be deduced, reset gesture state.
|
|
self.gestureStartLocation = .zero
|
|
}
|
|
}
|
|
|
|
// After the scene is updated, reset the last gesture direction
|
|
// to make sure the animation is right when user starts a new
|
|
// game.
|
|
OperationQueue.main.addOperation {
|
|
self.lastGestureDirection = .up
|
|
}
|
|
}
|
|
return drag
|
|
}
|
|
|
|
var body: some View {
|
|
GeometryReader { proxy in
|
|
bind(self.layoutTraits(for: proxy)) { layoutTraits in
|
|
ZStack(alignment: layoutTraits.containerAlignment) {
|
|
Text("2048")
|
|
.font(Font.system(size: 48).weight(.black))
|
|
.color(Color(red:0.47, green:0.43, blue:0.40, opacity:1.00))
|
|
.offset(layoutTraits.bannerOffset)
|
|
|
|
ZStack(alignment: .top) {
|
|
BlockGridView(matrix: self.gameLogic.blockMatrix,
|
|
blockEnterEdge: .from(self.lastGestureDirection))
|
|
.gesture(self.gesture)
|
|
}
|
|
.frame(width: proxy.size.width, height: proxy.size.height, alignment: .center)
|
|
}
|
|
.frame(width: proxy.size.width, height: proxy.size.height, alignment: .center)
|
|
.background(
|
|
Rectangle().fill(Color(red:0.96, green:0.94, blue:0.90, opacity:1.00))
|
|
)
|
|
}
|
|
}
|
|
.edgesIgnoringSafeArea(.all)
|
|
}
|
|
|
|
}
|
|
|
|
#if DEBUG
|
|
struct GameView_Previews : PreviewProvider {
|
|
|
|
static var previews: some View {
|
|
GameView()
|
|
.environmentObject(GameLogic())
|
|
}
|
|
|
|
}
|
|
#endif
|