diff --git a/Tetris Mac/AppDelegate.swift b/Tetris Mac/AppDelegate.swift new file mode 100644 index 0000000..5914ee0 --- /dev/null +++ b/Tetris Mac/AppDelegate.swift @@ -0,0 +1,34 @@ +// +// AppDelegate.swift +// Tetris Mac +// +// Created by Shadowfacts on 10/16/19. +// Copyright © 2019 Shadowfacts. All rights reserved. +// + +import Cocoa +import SwiftUI + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + + var window: NSWindow! + + func applicationDidFinishLaunching(_ aNotification: Notification) { + // Create the window and set the content view. + window = NSWindow( + contentRect: NSRect(x: 0, y: 0, width: 634, height: 804), + styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], + backing: .buffered, defer: false) + window.center() + window.setFrameAutosaveName("Main Window") + window.contentViewController = TetrisViewController() + window.title = "Tetris" + window.makeKeyAndOrderFront(nil) + } + + func applicationWillTerminate(_ aNotification: Notification) { + // Insert code here to tear down your application + } + +} diff --git a/Tetris Mac/Assets.xcassets/AppIcon.appiconset/Contents.json b/Tetris Mac/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/Tetris Mac/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Tetris Mac/Assets.xcassets/Background.colorset/Contents.json b/Tetris Mac/Assets.xcassets/Background.colorset/Contents.json new file mode 100644 index 0000000..22d3ace --- /dev/null +++ b/Tetris Mac/Assets.xcassets/Background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "0.867", + "alpha" : "1.000", + "blue" : "0.867", + "green" : "0.867" + } + } + }, + { + "idiom" : "universal", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "0.133", + "alpha" : "1.000", + "blue" : "0.133", + "green" : "0.133" + } + } + } + ] +} \ No newline at end of file diff --git a/Tetris Mac/Assets.xcassets/Contents.json b/Tetris Mac/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Tetris Mac/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Tetris Mac/Base.lproj/Main.storyboard b/Tetris Mac/Base.lproj/Main.storyboard new file mode 100644 index 0000000..ad03015 --- /dev/null +++ b/Tetris Mac/Base.lproj/Main.storyboard @@ -0,0 +1,683 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tetris Mac/ContentView.swift b/Tetris Mac/ContentView.swift new file mode 100644 index 0000000..391251f --- /dev/null +++ b/Tetris Mac/ContentView.swift @@ -0,0 +1,79 @@ +// +// ContentView.swift +// Tetris Mac +// +// Created by Shadowfacts on 10/16/19. +// Copyright © 2019 Shadowfacts. All rights reserved. +// + +import SwiftUI +import TetrisKit +import TetrisUI + +struct ContentView: View { + @ObservedObject var controller: GameController/* = { + let c = GameController() + c.start() + return c + }()*/ + @State var timer: Timer? + + var body: some View { + GeometryReader { (geometry) in + HStack(alignment: .top, spacing: 8) { + VStack { + Text("Held") + .font(.title) + .fontWeight(.bold) + if self.controller.heldTetromino != nil { + Group { + TetrominoView(tetromino: self.controller.heldTetromino!) + }.frame(width: 100, height: 100, alignment: .center) + } else { + Rectangle().foregroundColor(.clear).frame(width: 100, height: 100) + } + Text("Score") + .font(.title) + .fontWeight(.bold) + Text(verbatim: self.controller.score.description) + .font(.title) + } + .padding(.leading, 8) + + BoardView(board: self.$controller.board, currentPiece: self.$controller.currentPiece, droppedPiece: self.$controller.currentPieceAtDropPoint) + .aspectRatio(CGSize(width: self.controller.width, height: self.controller.height), contentMode: .fit) + .onAppear(perform: self.startTimer) + .onDisappear(perform: self.stopTimer) + + VStack { + Text("Next") + .font(.title) + .fontWeight(.bold) + NextTetromioesView(tetrominoes: self.controller.nextTetrominoes) + .frame(width: 100) + } + .padding(.trailing, 8) + } + } + .frame(maxWidth: 634, maxHeight: 804) + } + + func startTimer() { + self.timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { (_) in + self.controller.step() + }) + } + + func stopTimer() { + self.timer?.invalidate() + } +} + + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + let c = GameController() + c.start() + return ContentView(controller: c) + } +} diff --git a/Tetris Mac/Info.plist b/Tetris Mac/Info.plist new file mode 100644 index 0000000..d20feef --- /dev/null +++ b/Tetris Mac/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2019 Shadowfacts. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + NSSupportsAutomaticTermination + + NSSupportsSuddenTermination + + + diff --git a/Tetris Mac/Preview Content/Preview Assets.xcassets/Contents.json b/Tetris Mac/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Tetris Mac/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Tetris Mac/TetrisHostingView.swift b/Tetris Mac/TetrisHostingView.swift new file mode 100644 index 0000000..67fa7bd --- /dev/null +++ b/Tetris Mac/TetrisHostingView.swift @@ -0,0 +1,60 @@ +// +// TetrisHostingView.swift +// Tetris Mac +// +// Created by Shadowfacts on 10/16/19. +// Copyright © 2019 Shadowfacts. All rights reserved. +// + +import Cocoa +import SwiftUI +import Carbon +import TetrisKit + +class TetrisHostingView: NSHostingView { + + let gameController: GameController + + override var acceptsFirstResponder: Bool { + return true + } + + init(_ gameController: GameController) { + self.gameController = gameController + super.init(rootView: ContentView(controller: gameController)) + } + + required init(rootView: ContentView) { + fatalError("init(rootView:) has not been implemented") + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func keyDown(with event: NSEvent) { + switch Int(event.keyCode) { + case kVK_LeftArrow: + gameController.left() + case kVK_RightArrow: + gameController.right() + case kVK_UpArrow: + gameController.rotate(direction: .clockwise) + case kVK_DownArrow: + gameController.drop() + default: + super.keyDown(with: event) + } + } + + override func flagsChanged(with event: NSEvent) { + if event.modifierFlags.contains(.control) { + gameController.rotate(direction: .counterClockwise) + } else if event.modifierFlags.contains(.shift) { + gameController.hold() + } else { + super.flagsChanged(with: event) + } + } + +} diff --git a/Tetris Mac/TetrisViewController.swift b/Tetris Mac/TetrisViewController.swift new file mode 100644 index 0000000..83af39f --- /dev/null +++ b/Tetris Mac/TetrisViewController.swift @@ -0,0 +1,37 @@ +// +// TetrisViewController.swift +// Tetris Mac +// +// Created by Shadowfacts on 10/16/19. +// Copyright © 2019 Shadowfacts. All rights reserved. +// + +import Cocoa +import SwiftUI +import Carbon +import TetrisKit + +class TetrisViewController: NSViewController { + + let gameController = GameController() + + init() { + super.init(nibName: nil, bundle: nil) + preferredContentSize = NSSize(width: 634, height: 804) + } + + required init?(coder: NSCoder) { + fatalError() + } + + override func loadView() { + self.view = TetrisHostingView(gameController) + } + + override func viewDidAppear() { + super.viewDidAppear() + + gameController.start() + } + +} diff --git a/Tetris Mac/Tetris_Mac.entitlements b/Tetris Mac/Tetris_Mac.entitlements new file mode 100644 index 0000000..f2ef3ae --- /dev/null +++ b/Tetris Mac/Tetris_Mac.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + + diff --git a/Tetris/ContentView.swift b/Tetris/ContentView.swift index 10bce5e..f122425 100644 --- a/Tetris/ContentView.swift +++ b/Tetris/ContentView.swift @@ -48,7 +48,8 @@ struct ContentView: View { VStack { Text("Next") - NextTetromioesView(tetrominoes: self.controller.nextTetrominoes).frame(width: 50) + NextTetromioesView(tetrominoes: self.controller.nextTetrominoes) + .frame(width: 50) } .padding(.trailing, 8) } @@ -127,7 +128,7 @@ struct ContentView: View { } func stopTimer() { - timer?.invalidate() + self.timer?.invalidate() } func onTap() { diff --git a/TetrisUI/TetrisUI_iOS.h b/TetrisUI/TetrisUI.h similarity index 56% rename from TetrisUI/TetrisUI_iOS.h rename to TetrisUI/TetrisUI.h index bdbebb2..94ddf14 100644 --- a/TetrisUI/TetrisUI_iOS.h +++ b/TetrisUI/TetrisUI.h @@ -1,6 +1,6 @@ // -// TetrisUI_iOS.h -// TetrisUI iOS +// TetrisUI.h +// TetrisUI // // Created by Shadowfacts on 10/14/19. // Copyright © 2019 Shadowfacts. All rights reserved. @@ -9,11 +9,11 @@ #import //! Project version number for TetrisUI_iOS. -FOUNDATION_EXPORT double TetrisUI_iOSVersionNumber; +FOUNDATION_EXPORT double TetrisUIVersionNumber; //! Project version string for TetrisUI_iOS. -FOUNDATION_EXPORT const unsigned char TetrisUI_iOSVersionString[]; +FOUNDATION_EXPORT const unsigned char TetrisUIVersionString[]; -// In this header, you should import all the public headers of your framework using statements like #import +// In this header, you should import all the public headers of your framework using statements like #import