diff --git a/.gitignore b/.gitignore index 164ecf8..103a118 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ PumpkinSmash.xcodeproj/xcuserdata/cranoo3.xcuserdatad/xcschemes/xcschememanagement.plist PumpkinSmash.xcodeproj/project.xcworkspace/xcuserdata/cranoo3.xcuserdatad/UserInterfaceState.xcuserstate .DS_Store +PumpkinSmash.xcodeproj/project.pbxproj +PumpkinSmash.xcodeproj/project.pbxproj diff --git a/PumpkinSmash.xcodeproj/project.pbxproj b/PumpkinSmash.xcodeproj/project.pbxproj index 4eaf097..880ce07 100644 --- a/PumpkinSmash.xcodeproj/project.pbxproj +++ b/PumpkinSmash.xcodeproj/project.pbxproj @@ -7,30 +7,34 @@ objects = { /* Begin PBXBuildFile section */ + 1DBC8C9D2AD8D50A00E75C59 /* TimerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DBC8C9C2AD8D50A00E75C59 /* TimerManager.swift */; }; + 1DBC8C9F2AD8D51700E75C59 /* Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DBC8C9E2AD8D51700E75C59 /* Helper.swift */; }; 1DFA46AA2ACEB0A700781FF4 /* GameFieldView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DFA46A92ACEB0A700781FF4 /* GameFieldView.swift */; }; + 1DFEE9182AD7D29700017E9F /* KiwiMaru-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 1DFEE9152AD7D29700017E9F /* KiwiMaru-Light.ttf */; }; + 1DFEE9192AD7D29700017E9F /* KiwiMaru-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 1DFEE9162AD7D29700017E9F /* KiwiMaru-Medium.ttf */; }; + 1DFEE91A2AD7D29700017E9F /* KiwiMaru-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 1DFEE9172AD7D29700017E9F /* KiwiMaru-Regular.ttf */; }; 6B069CEA2ACD60490027B308 /* PumpkinSmashApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B069CE92ACD60490027B308 /* PumpkinSmashApp.swift */; }; 6B069CEC2ACD60490027B308 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B069CEB2ACD60490027B308 /* ContentView.swift */; }; 6B069CEE2ACD604C0027B308 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6B069CED2ACD604C0027B308 /* Assets.xcassets */; }; 6B069CF12ACD604C0027B308 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6B069CF02ACD604C0027B308 /* Preview Assets.xcassets */; }; 6B069CF82ACD647E0027B308 /* LevelSelectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B069CF72ACD647E0027B308 /* LevelSelectView.swift */; }; - 6B75354A2AD7D1FF000EFF1A /* KiwiMaru-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6B7535472AD7D1FE000EFF1A /* KiwiMaru-Regular.ttf */; }; - 6B75354B2AD7D1FF000EFF1A /* KiwiMaru-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6B7535482AD7D1FE000EFF1A /* KiwiMaru-Light.ttf */; }; - 6B75354C2AD7D1FF000EFF1A /* KiwiMaru-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6B7535492AD7D1FF000EFF1A /* KiwiMaru-Medium.ttf */; }; 6B7907292AD6360000AB8C49 /* FontSample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B7907282AD6360000AB8C49 /* FontSample.swift */; }; 6B79073E2AD7A97700AB8C49 /* ScoreResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B79073D2AD7A97700AB8C49 /* ScoreResultsView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 1DBC8C9C2AD8D50A00E75C59 /* TimerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerManager.swift; sourceTree = ""; }; + 1DBC8C9E2AD8D51700E75C59 /* Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helper.swift; sourceTree = ""; }; 1DFA46A92ACEB0A700781FF4 /* GameFieldView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameFieldView.swift; sourceTree = ""; }; + 1DFEE9152AD7D29700017E9F /* KiwiMaru-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "KiwiMaru-Light.ttf"; path = "../../../KiwiMaru-Light.ttf"; sourceTree = ""; }; + 1DFEE9162AD7D29700017E9F /* KiwiMaru-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "KiwiMaru-Medium.ttf"; path = "../../../KiwiMaru-Medium.ttf"; sourceTree = ""; }; + 1DFEE9172AD7D29700017E9F /* KiwiMaru-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "KiwiMaru-Regular.ttf"; path = "../../../KiwiMaru-Regular.ttf"; sourceTree = ""; }; 6B069CE62ACD60490027B308 /* PumpkinSmash.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PumpkinSmash.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6B069CE92ACD60490027B308 /* PumpkinSmashApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpkinSmashApp.swift; sourceTree = ""; }; 6B069CEB2ACD60490027B308 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 6B069CED2ACD604C0027B308 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 6B069CF02ACD604C0027B308 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 6B069CF72ACD647E0027B308 /* LevelSelectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LevelSelectView.swift; sourceTree = ""; }; - 6B7535472AD7D1FE000EFF1A /* KiwiMaru-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "KiwiMaru-Regular.ttf"; path = "../../../../../../../Downloads/Kiwi_Maru/KiwiMaru-Regular.ttf"; sourceTree = ""; }; - 6B7535482AD7D1FE000EFF1A /* KiwiMaru-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "KiwiMaru-Light.ttf"; path = "../../../../../../../Downloads/Kiwi_Maru/KiwiMaru-Light.ttf"; sourceTree = ""; }; - 6B7535492AD7D1FF000EFF1A /* KiwiMaru-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "KiwiMaru-Medium.ttf"; path = "../../../../../../../Downloads/Kiwi_Maru/KiwiMaru-Medium.ttf"; sourceTree = ""; }; 6B7907272AD635C300AB8C49 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6B7907282AD6360000AB8C49 /* FontSample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontSample.swift; sourceTree = ""; }; 6B79073D2AD7A97700AB8C49 /* ScoreResultsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScoreResultsView.swift; sourceTree = ""; }; @@ -50,13 +54,32 @@ 1D8056C12AD7A85800C306BD /* fonts */ = { isa = PBXGroup; children = ( - 6B7535482AD7D1FE000EFF1A /* KiwiMaru-Light.ttf */, - 6B7535492AD7D1FF000EFF1A /* KiwiMaru-Medium.ttf */, - 6B7535472AD7D1FE000EFF1A /* KiwiMaru-Regular.ttf */, + 1DFEE9152AD7D29700017E9F /* KiwiMaru-Light.ttf */, + 1DFEE9162AD7D29700017E9F /* KiwiMaru-Medium.ttf */, + 1DFEE9172AD7D29700017E9F /* KiwiMaru-Regular.ttf */, ); path = fonts; sourceTree = ""; }; + 1DBC8C9A2AD8D11300E75C59 /* GameField */ = { + isa = PBXGroup; + children = ( + 1DFA46A92ACEB0A700781FF4 /* GameFieldView.swift */, + 6B79073D2AD7A97700AB8C49 /* ScoreResultsView.swift */, + 1DBC8C9B2AD8D4E700E75C59 /* Timer */, + ); + path = GameField; + sourceTree = ""; + }; + 1DBC8C9B2AD8D4E700E75C59 /* Timer */ = { + isa = PBXGroup; + children = ( + 1DBC8C9C2AD8D50A00E75C59 /* TimerManager.swift */, + 1DBC8C9E2AD8D51700E75C59 /* Helper.swift */, + ); + path = Timer; + sourceTree = ""; + }; 6B069CDD2ACD60480027B308 = { isa = PBXGroup; children = ( @@ -82,8 +105,7 @@ 6B069CE92ACD60490027B308 /* PumpkinSmashApp.swift */, 6B069CEB2ACD60490027B308 /* ContentView.swift */, 6B069CF72ACD647E0027B308 /* LevelSelectView.swift */, - 1DFA46A92ACEB0A700781FF4 /* GameFieldView.swift */, - 6B79073D2AD7A97700AB8C49 /* ScoreResultsView.swift */, + 1DBC8C9A2AD8D11300E75C59 /* GameField */, 6B069CED2ACD604C0027B308 /* Assets.xcassets */, 6B069CEF2ACD604C0027B308 /* Preview Content */, ); @@ -156,11 +178,11 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 1DFEE91A2AD7D29700017E9F /* KiwiMaru-Regular.ttf in Resources */, 6B069CF12ACD604C0027B308 /* Preview Assets.xcassets in Resources */, 6B069CEE2ACD604C0027B308 /* Assets.xcassets in Resources */, - 6B75354A2AD7D1FF000EFF1A /* KiwiMaru-Regular.ttf in Resources */, - 6B75354C2AD7D1FF000EFF1A /* KiwiMaru-Medium.ttf in Resources */, - 6B75354B2AD7D1FF000EFF1A /* KiwiMaru-Light.ttf in Resources */, + 1DFEE9182AD7D29700017E9F /* KiwiMaru-Light.ttf in Resources */, + 1DFEE9192AD7D29700017E9F /* KiwiMaru-Medium.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -176,7 +198,9 @@ 6B7907292AD6360000AB8C49 /* FontSample.swift in Sources */, 6B069CEC2ACD60490027B308 /* ContentView.swift in Sources */, 6B069CEA2ACD60490027B308 /* PumpkinSmashApp.swift in Sources */, + 1DBC8C9D2AD8D50A00E75C59 /* TimerManager.swift in Sources */, 1DFA46AA2ACEB0A700781FF4 /* GameFieldView.swift in Sources */, + 1DBC8C9F2AD8D51700E75C59 /* Helper.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/PumpkinSmash/Assets.xcassets/Ookawa_Pumpkin.imageset/Contents.json b/PumpkinSmash/Assets.xcassets/Ookawa_Pumpkin.imageset/Contents.json new file mode 100644 index 0000000..fefc21c --- /dev/null +++ b/PumpkinSmash/Assets.xcassets/Ookawa_Pumpkin.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Ookawa_Pumpkin.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PumpkinSmash/Assets.xcassets/Ookawa_Pumpkin.imageset/Ookawa_Pumpkin.png b/PumpkinSmash/Assets.xcassets/Ookawa_Pumpkin.imageset/Ookawa_Pumpkin.png new file mode 100644 index 0000000..4e8bdc1 Binary files /dev/null and b/PumpkinSmash/Assets.xcassets/Ookawa_Pumpkin.imageset/Ookawa_Pumpkin.png differ diff --git a/PumpkinSmash/Assets.xcassets/TapSound.dataset/Contents.json b/PumpkinSmash/Assets.xcassets/TapSound.dataset/Contents.json new file mode 100644 index 0000000..9bd65df --- /dev/null +++ b/PumpkinSmash/Assets.xcassets/TapSound.dataset/Contents.json @@ -0,0 +1,12 @@ +{ + "data" : [ + { + "filename" : "TapSound.m4a", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PumpkinSmash/Assets.xcassets/TapSound.dataset/TapSound.m4a b/PumpkinSmash/Assets.xcassets/TapSound.dataset/TapSound.m4a new file mode 100644 index 0000000..19056e7 Binary files /dev/null and b/PumpkinSmash/Assets.xcassets/TapSound.dataset/TapSound.m4a differ diff --git a/PumpkinSmash/GameField/GameFieldView.swift b/PumpkinSmash/GameField/GameFieldView.swift new file mode 100644 index 0000000..18e65d2 --- /dev/null +++ b/PumpkinSmash/GameField/GameFieldView.swift @@ -0,0 +1,166 @@ +// +// GameFieldView.swift +// PumpkinSmash +// +// Created by cranoo3 on 2023/10/05. +// + +import SwiftUI +import AVFoundation + +struct GameFieldView: View { + // グリッドの設定 + let grids = Array(repeating: GridItem(.fixed(UIScreen.main.bounds.width / 5 - 10)), count: 5) + // difficulty → 難易度。0: 簡単, 1: 普通 2: 難しい + // TODO: Bindingしよう + let difficulty: Int = 2 // switchケースに使用する + var showHole: [Int] { + // 難易度によって表示する穴の数を変更する + switch difficulty { + case 0: + return [2, 6, 8, 10, 12, 14, 16, 18, 22] + + case 1: + return [2, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 22] + + case 2: + return Array(0...24) + + default: + return [] + } + } + // ランダムでボタンを表示する + @State var buttonPosition = 0 + // ゲームがスタートしているか + @State var isGameStarted = false + // タイマーを作成 + @StateObject var timerManager = TimerManager() + + // タップサウンド + let tapSound = try! AVAudioPlayer(data: NSDataAsset(name: "TapSound")!.data) + func playSound() { + // 連打した時に音が重ならないようにする + tapSound.stop() + tapSound.currentTime = 0 + tapSound.play() + } + var body: some View { + ZStack { + //TODO: カスタム画像を作成(今週締め切り) + // タブメニューとグリッド + VStack { + // メニューバー + HStack { + // メニューボタン + Image(systemName: "slider.horizontal.3") + .opacity(0.0) + + Spacer() + + // タイマー + + Text("残り\(timerManager.secondsLeft)秒") // TODO: あとで適したものに変更しよう + .font((.custom("Kiwi Maru", size: 60))) + + Spacer() + + // ポーズボタン + Button(action: {}) { + Image(systemName: "pause.fill") + } + } + .padding() + + Spacer() + + // ゲーム画面 + ZStack { + // ゲーム画面(穴の表示) + LazyVGrid(columns: grids) { + ForEach ((0...24), id: \.self) { num in + if showHole.contains(num) { + Hole() + } else { + DummyHole() + } + } + } + // ボタン(ランダム) + LazyVGrid(columns: grids) { + ForEach ((0...24), id: \.self) { num in + if buttonPosition == num { + Button(action: { + playSound() + buttonPosition = showHole.shuffled()[0] + print("Button position is \(buttonPosition)") + }) { + Image("Ookawa_Pumpkin") + .resizable() + .aspectRatio(contentMode: .fit) + .offset(y: -15) + } + .opacity(isGameStarted ? 1.0 : 0.0) + } else { + DummyHole() + } + } + } + + // TODO: ボタンデザインを変更しよう + if !isGameStarted { + Button(action: { + isGameStarted = true // ゲームを開始しているか + buttonPosition = showHole.shuffled()[0] // ボタンの場所をシャッフルする + timerManager.start() // タイマーをスタート + }) { + ZStack { + RoundedRectangle(cornerRadius: 25.0) + .frame(maxWidth: .infinity, maxHeight: 90) + Text("Start") + .font(.title) + .fontWeight(.bold) + .foregroundStyle(.white) + } + .padding() + } + } + } + .padding(.bottom, 30) + } + } + .fullScreenCover(isPresented: $timerManager.isTimerStoped, content: { + ScoreResultsView() + }) + } +} + +struct Hole: View { + var body: some View { + ZStack { + Image("Hole") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 80, height: 90) + } + } +} + +struct DummyHole: View { + var body: some View { + ZStack { + Image("Hole") + .resizable() + .aspectRatio(contentMode: .fit) + .opacity(0.0) + .frame(width: 80, height: 90) + } + } +} + +struct GameGieldView_Previews: PreviewProvider { + static var previews: some View { + GameFieldView() + // Hole() + } +} diff --git a/PumpkinSmash/ScoreResultsView.swift b/PumpkinSmash/GameField/ScoreResultsView.swift similarity index 100% rename from PumpkinSmash/ScoreResultsView.swift rename to PumpkinSmash/GameField/ScoreResultsView.swift diff --git a/PumpkinSmash/GameField/Timer/Helper.swift b/PumpkinSmash/GameField/Timer/Helper.swift new file mode 100644 index 0000000..bc8ef64 --- /dev/null +++ b/PumpkinSmash/GameField/Timer/Helper.swift @@ -0,0 +1,14 @@ +// +// Helper.swift +// PumpkinSmash +// +// Created by cranoo3 on 2023/10/13. +// + +import Foundation + +enum TimerMode { + case running + case paused + case initial +} diff --git a/PumpkinSmash/GameField/Timer/TimerManager.swift b/PumpkinSmash/GameField/Timer/TimerManager.swift new file mode 100644 index 0000000..a796415 --- /dev/null +++ b/PumpkinSmash/GameField/Timer/TimerManager.swift @@ -0,0 +1,40 @@ +// +// TimerManager.swift +// PumpkinSmash +// +// Created by cranoo3 on 2023/10/13. +// + +import Foundation +import SwiftUI + +class TimerManager: ObservableObject { + @Published var timerMode: TimerMode = .initial + @Published var secondsLeft = 10 + @Published var isTimerStoped = false + var timer = Timer() + + func start() { + timerMode = .running + timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in + self.secondsLeft -= 1 + if self.secondsLeft == 0 { + self.timerMode = .initial + self.secondsLeft = 0 + self.isTimerStoped = true + timer.invalidate() + } + }) + } + + func pause() { + timerMode = .paused + timer.invalidate() + } + + func reset() { + timerMode = .initial + self.secondsLeft = 10 + timer.invalidate() + } +} diff --git a/PumpkinSmash/GameFieldView.swift b/PumpkinSmash/GameFieldView.swift deleted file mode 100644 index 2c92270..0000000 --- a/PumpkinSmash/GameFieldView.swift +++ /dev/null @@ -1,122 +0,0 @@ -// -// GameFieldView.swift -// PumpkinSmash -// -// Created by cranoo3 on 2023/10/05. -// - -import SwiftUI - -struct GameFieldView: View { - let grids = Array(repeating: GridItem(.fixed(UIScreen.main.bounds.width / 5 - 10)), count: 5) - - // let showHole: [Int] = [2, 6, 8, 10, 11, 12, 13, 14, 16, 18, 22] // 表示する穴の番号 - - // difficulty → 難易度。0: 簡単, 1: 普通 2: 難しい - let difficulty: Int = 1 // switchケーズに使用する - - var showHole: [Int] { - // 難易度によって表示する穴の数を変更する - switch difficulty { - case 0: - return [2, 6, 8, 10, 12, 14, 16, 18, 22] - - case 1: - return [2, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 22] - - case 2: - return Array(0...24) - - default: - return [] - } - } - - var body: some View { - ZStack { - //TODO: カスタム画像を作成(今週締め切り) - // タブメニュー? - VStack { - // 上のメニューバー - HStack { - // メニューボタン - Button(action: {}) { - Image(systemName: "slider.horizontal.3") - } - Spacer() - - // タイマー - - Text("0:00") // TODO: あとで適したものに変更しよう - - Spacer() - - // ポーズボタン - Button(action: {}) { - Image(systemName: "pause.fill") - } - } - .padding() - - Spacer() - - // ゲーム画面 - LazyVGrid(columns: grids) { - ForEach ((0...24), id: \.self) { num in - if showHole.contains(num) { - Hole() - } else { - DummyHole() - } - } - } - .padding(.bottom, 30) - - -// RoundedRectangle(cornerRadius: 20) -// .fill(.black) -// .frame(maxWidth: .infinity, minHeight: 30, alignment: .center) -// .overlay( -// Text("Game Background 🐱") -// .font(.title) -// .fontWeight(.black) -// .foregroundColor(.white) -// ) -// -// Spacer() -// } -// .padding() - } - } - } -} - -struct Hole: View { - var body: some View { - ZStack { - Image("Hole") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 80, height: 90) - } - } -} - -struct DummyHole: View { - var body: some View { - ZStack { - Image("Hole") - .resizable() - .aspectRatio(contentMode: .fit) - .opacity(0.0) - .frame(width: 80, height: 90) - } - } -} - -struct GameGieldView_Previews: PreviewProvider { - static var previews: some View { - GameFieldView() - // Hole() - } -}