Merge branch 'dev_views_Game'

Conflicts:
	DouShouQi_App/DouShouQi_App.xcodeproj/project.pbxproj
	DouShouQi_App/DouShouQi_App/Views/Game/GameView.swift
	DouShouQi_App/DouShouQi_App/Views/Player/SelectPlayerView.swift
dev_vm_saveHistorique
Nathan VERDIER 10 months ago
commit 631ae89c11

@ -7,6 +7,8 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
6437FF132C25846F009D0EAF /* PlayingGameVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6437FF122C25846F009D0EAF /* PlayingGameVM.swift */; };
6437FF142C25870C009D0EAF /* DSQ.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC62C5322C1C188F0048CD0B /* DSQ.xcframework */; };
6458345C2BF5F92300E18321 /* DouShouQi_AppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6458345B2BF5F92300E18321 /* DouShouQi_AppApp.swift */; }; 6458345C2BF5F92300E18321 /* DouShouQi_AppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6458345B2BF5F92300E18321 /* DouShouQi_AppApp.swift */; };
6458345E2BF5F92300E18321 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6458345D2BF5F92300E18321 /* ContentView.swift */; }; 6458345E2BF5F92300E18321 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6458345D2BF5F92300E18321 /* ContentView.swift */; };
645834602BF5F92500E18321 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6458345F2BF5F92500E18321 /* Assets.xcassets */; }; 645834602BF5F92500E18321 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6458345F2BF5F92500E18321 /* Assets.xcassets */; };
@ -30,6 +32,7 @@
649B59AE2BF64EAB002BAE38 /* AppImages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649B59AD2BF64EAB002BAE38 /* AppImages.swift */; }; 649B59AE2BF64EAB002BAE38 /* AppImages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649B59AD2BF64EAB002BAE38 /* AppImages.swift */; };
649B59B22BF65392002BAE38 /* TextStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649B59B12BF65392002BAE38 /* TextStyles.swift */; }; 649B59B22BF65392002BAE38 /* TextStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649B59B12BF65392002BAE38 /* TextStyles.swift */; };
649B59B42BF653E1002BAE38 /* ViewTitleTextStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649B59B32BF653E1002BAE38 /* ViewTitleTextStyle.swift */; }; 649B59B42BF653E1002BAE38 /* ViewTitleTextStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649B59B32BF653E1002BAE38 /* ViewTitleTextStyle.swift */; };
64D2D74E2C25D380009BD010 /* Animals.Symbols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D2D74D2C25D380009BD010 /* Animals.Symbols.swift */; };
64D992722C06281B002ACBC6 /* SystemIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D992712C06281B002ACBC6 /* SystemIcons.swift */; }; 64D992722C06281B002ACBC6 /* SystemIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D992712C06281B002ACBC6 /* SystemIcons.swift */; };
64FC4D692C09C78000D08B8B /* SelectPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64FC4D682C09C78000D08B8B /* SelectPlayerView.swift */; }; 64FC4D692C09C78000D08B8B /* SelectPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64FC4D682C09C78000D08B8B /* SelectPlayerView.swift */; };
64FC4D6B2C09C7C900D08B8B /* SelectPlayerButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64FC4D6A2C09C7C900D08B8B /* SelectPlayerButtonView.swift */; }; 64FC4D6B2C09C7C900D08B8B /* SelectPlayerButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64FC4D6A2C09C7C900D08B8B /* SelectPlayerButtonView.swift */; };
@ -56,7 +59,6 @@
EC62C5252C0F68830048CD0B /* PlayerVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC62C5242C0F68830048CD0B /* PlayerVM.swift */; }; EC62C5252C0F68830048CD0B /* PlayerVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC62C5242C0F68830048CD0B /* PlayerVM.swift */; };
EC62C5292C1974000048CD0B /* PlayersVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC62C5282C1974000048CD0B /* PlayersVM.swift */; }; EC62C5292C1974000048CD0B /* PlayersVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC62C5282C1974000048CD0B /* PlayersVM.swift */; };
EC62C52D2C197ED10048CD0B /* Player.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC62C52C2C197ED10048CD0B /* Player.swift */; }; EC62C52D2C197ED10048CD0B /* Player.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC62C52C2C197ED10048CD0B /* Player.swift */; };
EC62C5332C1C188F0048CD0B /* DSQ.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC62C5322C1C188F0048CD0B /* DSQ.xcframework */; };
EC62C5382C1C64EE0048CD0B /* CoreManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC62C5372C1C64EE0048CD0B /* CoreManager.swift */; }; EC62C5382C1C64EE0048CD0B /* CoreManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC62C5372C1C64EE0048CD0B /* CoreManager.swift */; };
EC62C53D2C1C69200048CD0B /* DouShouQi_App.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = EC62C53B2C1C69200048CD0B /* DouShouQi_App.xcdatamodeld */; }; EC62C53D2C1C69200048CD0B /* DouShouQi_App.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = EC62C53B2C1C69200048CD0B /* DouShouQi_App.xcdatamodeld */; };
EC62C53F2C1C6D1A0048CD0B /* CDPlayerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC62C53E2C1C6D1A0048CD0B /* CDPlayerExtension.swift */; }; EC62C53F2C1C6D1A0048CD0B /* CDPlayerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC62C53E2C1C6D1A0048CD0B /* CDPlayerExtension.swift */; };
@ -98,6 +100,7 @@
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
6437FF122C25846F009D0EAF /* PlayingGameVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayingGameVM.swift; sourceTree = "<group>"; };
645834582BF5F92300E18321 /* DouShouQi_App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DouShouQi_App.app; sourceTree = BUILT_PRODUCTS_DIR; }; 645834582BF5F92300E18321 /* DouShouQi_App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DouShouQi_App.app; sourceTree = BUILT_PRODUCTS_DIR; };
6458345B2BF5F92300E18321 /* DouShouQi_AppApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DouShouQi_AppApp.swift; sourceTree = "<group>"; }; 6458345B2BF5F92300E18321 /* DouShouQi_AppApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DouShouQi_AppApp.swift; sourceTree = "<group>"; };
6458345D2BF5F92300E18321 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; }; 6458345D2BF5F92300E18321 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
@ -125,6 +128,7 @@
649B59AD2BF64EAB002BAE38 /* AppImages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppImages.swift; sourceTree = "<group>"; }; 649B59AD2BF64EAB002BAE38 /* AppImages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppImages.swift; sourceTree = "<group>"; };
649B59B12BF65392002BAE38 /* TextStyles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextStyles.swift; sourceTree = "<group>"; }; 649B59B12BF65392002BAE38 /* TextStyles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextStyles.swift; sourceTree = "<group>"; };
649B59B32BF653E1002BAE38 /* ViewTitleTextStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewTitleTextStyle.swift; sourceTree = "<group>"; }; 649B59B32BF653E1002BAE38 /* ViewTitleTextStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewTitleTextStyle.swift; sourceTree = "<group>"; };
64D2D74D2C25D380009BD010 /* Animals.Symbols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Animals.Symbols.swift; sourceTree = "<group>"; };
64D992712C06281B002ACBC6 /* SystemIcons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemIcons.swift; sourceTree = "<group>"; }; 64D992712C06281B002ACBC6 /* SystemIcons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemIcons.swift; sourceTree = "<group>"; };
64FC4D682C09C78000D08B8B /* SelectPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectPlayerView.swift; sourceTree = "<group>"; }; 64FC4D682C09C78000D08B8B /* SelectPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectPlayerView.swift; sourceTree = "<group>"; };
64FC4D6A2C09C7C900D08B8B /* SelectPlayerButtonView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectPlayerButtonView.swift; sourceTree = "<group>"; }; 64FC4D6A2C09C7C900D08B8B /* SelectPlayerButtonView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectPlayerButtonView.swift; sourceTree = "<group>"; };
@ -174,7 +178,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
EC62C5332C1C188F0048CD0B /* DSQ.xcframework in Frameworks */, 6437FF142C25870C009D0EAF /* DSQ.xcframework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -322,6 +326,7 @@
children = ( children = (
646FA83D2C072340001466BA /* GameVM.swift */, 646FA83D2C072340001466BA /* GameVM.swift */,
646FA8422C0730D6001466BA /* HistoricVM.swift */, 646FA8422C0730D6001466BA /* HistoricVM.swift */,
6437FF122C25846F009D0EAF /* PlayingGameVM.swift */,
); );
path = Game; path = Game;
sourceTree = "<group>"; sourceTree = "<group>";
@ -455,6 +460,7 @@
children = ( children = (
EC62C53E2C1C6D1A0048CD0B /* CDPlayerExtension.swift */, EC62C53E2C1C6D1A0048CD0B /* CDPlayerExtension.swift */,
ECF3FD302C2722C600F5E62B /* CDHistoriqueExtension.swift */, ECF3FD302C2722C600F5E62B /* CDHistoriqueExtension.swift */,
64D2D74D2C25D380009BD010 /* Animals.Symbols.swift */,
); );
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
@ -672,6 +678,7 @@
649B59B22BF65392002BAE38 /* TextStyles.swift in Sources */, 649B59B22BF65392002BAE38 /* TextStyles.swift in Sources */,
EC99D5C12C089F6B00731B62 /* GameResumeFrame.swift in Sources */, EC99D5C12C089F6B00731B62 /* GameResumeFrame.swift in Sources */,
EC05BFCB2C05F470000F7B19 /* GameScene.swift in Sources */, EC05BFCB2C05F470000F7B19 /* GameScene.swift in Sources */,
64D2D74E2C25D380009BD010 /* Animals.Symbols.swift in Sources */,
6458345C2BF5F92300E18321 /* DouShouQi_AppApp.swift in Sources */, 6458345C2BF5F92300E18321 /* DouShouQi_AppApp.swift in Sources */,
ECB636512C046379007CD5E2 /* MusicPlayer.swift in Sources */, ECB636512C046379007CD5E2 /* MusicPlayer.swift in Sources */,
ECB6364E2C04628E007CD5E2 /* SpriteMeeple.swift in Sources */, ECB6364E2C04628E007CD5E2 /* SpriteMeeple.swift in Sources */,
@ -709,6 +716,7 @@
646F04BE2C0F54C0003C8600 /* SettingsVM.swift in Sources */, 646F04BE2C0F54C0003C8600 /* SettingsVM.swift in Sources */,
EC62C52D2C197ED10048CD0B /* Player.swift in Sources */, EC62C52D2C197ED10048CD0B /* Player.swift in Sources */,
EC62C5292C1974000048CD0B /* PlayersVM.swift in Sources */, EC62C5292C1974000048CD0B /* PlayersVM.swift in Sources */,
6437FF132C25846F009D0EAF /* PlayingGameVM.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

@ -0,0 +1,34 @@
//
// Animals.Symbols.swift
// DouShouQi_App
//
// Created by Rémi REGNAULT on 21/06/2024.
//
import Foundation
import DouShouQiModel
extension Animal {
public var symbol: String {
switch self{
case .rat:
return "🐭"
case .cat:
return "🐱"
case .dog:
return "🐶"
case .wolf:
return "🐺"
case .leopard:
return "🐆"
case .tiger:
return "🐯"
case .lion:
return "🦁"
case .elephant:
return "🐘"
@unknown default:
return "🐥"
}
}
}

@ -13,4 +13,6 @@ public struct Colors {
static let Button = Color("ButtonColor") static let Button = Color("ButtonColor")
static let MeepleP1 = UIColor(named: "MeepleP1") static let MeepleP1 = UIColor(named: "MeepleP1")
static let TextButton = Color("ButtonTextColor") static let TextButton = Color("ButtonTextColor")
static let MeepleP2 = UIColor(named: "MeepleP2")
static let WinnerBackground = Color("WinnerBackground")
} }

@ -23,9 +23,9 @@
"color-space" : "srgb", "color-space" : "srgb",
"components" : { "components" : {
"alpha" : "1.000", "alpha" : "1.000",
"blue" : "1.000", "blue" : "0.765",
"green" : "1.000", "green" : "0.855",
"red" : "1.000" "red" : "0.000"
} }
}, },
"idiom" : "universal" "idiom" : "universal"

@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "1.000",
"green" : "0.150",
"red" : "0.150"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "1.000",
"green" : "0.150",
"red" : "0.150"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "0.800",
"blue" : "1.000",
"green" : "1.000",
"red" : "1.000"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "1.000",
"green" : "1.000",
"red" : "1.000"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -6,20 +6,23 @@
// //
import SwiftUI import SwiftUI
import DouShouQiModel
struct TopGameBoard: View { struct TopGameBoard: View {
@ObservedObject var gameVM: PlayingGameVM
var body: some View { var body: some View {
VStack { VStack {
HStack { HStack {
Circle() Circle()
.fill(Color.white) .fill(Color.white)
.frame(width: 40, height: 40) .frame(width: 40, height: 40)
Text("Player 1 Turn") Text("\(gameVM.currentPlayerName)'s Turn")
.font(.title) .font(.title)
.foregroundColor(.white) .foregroundColor(.white)
} }
.padding() .padding()
.background(Color.red) .background(Color(gameVM.currentPlayerColor))
.cornerRadius(10) .cornerRadius(10)
Spacer().frame(height: 20) Spacer().frame(height: 20)
@ -37,14 +40,14 @@ struct TopGameBoard: View {
Spacer() Spacer()
HStack { HStack {
Text("Last moove :") Text("Last move :")
.font(.title2) .font(.title2)
.foregroundColor(.black) .foregroundColor(.black)
/*Image(systemName: "cheetah") /*Image(systemName: "cheetah")
.resizable() .resizable()
.frame(width: 30, height: 30)*/ .frame(width: 30, height: 30)*/
Text("🦁") Text(gameVM.lastPieceMoved)
Text("2.3") Text(gameVM.lastMove)
.font(.title2) .font(.title2)
.foregroundColor(.black) .foregroundColor(.black)
} }
@ -60,8 +63,8 @@ struct TopGameBoard: View {
} }
} }
struct TopGameBoard_Previews: PreviewProvider { //struct TopGameBoard_Previews: PreviewProvider {
static var previews: some View { // static var previews: some View {
TopGameBoard() // TopGameBoard(gameVM: vm)
} // }
} //}

@ -6,43 +6,43 @@
// //
import Foundation import Foundation
import SwiftUI
import SpriteKit import SpriteKit
import DouShouQiModel import DouShouQiModel
class GameScene : SKScene { class GameScene : SKScene {
var player1: HumanPlayer = HumanPlayer(withName: "Rémi", andId: .player1)! var player1: DouShouQiModel.Player?
var player2: HumanPlayer = HumanPlayer(withName: "Rayhan", andId: .player2)! var player2: DouShouQiModel.Player?
var game: Game var game: Game?
let pieces: [Owner : [Animal:SpriteMeeple]] = [ let pieces: [Owner : [Animal:SpriteMeeple]] = [
.player1: [ .player1: [
.rat: SpriteMeeple(imageNamed: AppImages.Rat, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!), .rat: SpriteMeeple(imageNamed: AppImages.Rat, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!, imageRotation: 180),
.cat: SpriteMeeple(imageNamed: AppImages.Cat, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!), .cat: SpriteMeeple(imageNamed: AppImages.Cat, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!, imageRotation: 180),
.dog: SpriteMeeple(imageNamed: AppImages.Dog, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!), .dog: SpriteMeeple(imageNamed: AppImages.Dog, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!, imageRotation: 180),
.wolf: SpriteMeeple(imageNamed: AppImages.Wolf, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!), .wolf: SpriteMeeple(imageNamed: AppImages.Wolf, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!, imageRotation: 180),
.leopard: SpriteMeeple(imageNamed: AppImages.Leopard, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!), .leopard: SpriteMeeple(imageNamed: AppImages.Leopard, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!, imageRotation: 180),
.lion: SpriteMeeple(imageNamed: AppImages.Lion, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!), .lion: SpriteMeeple(imageNamed: AppImages.Lion, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!, imageRotation: 180),
.tiger: SpriteMeeple(imageNamed: AppImages.Tigger, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!), .tiger: SpriteMeeple(imageNamed: AppImages.Tigger, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!, imageRotation: 180),
.elephant: SpriteMeeple(imageNamed: AppImages.Elephant, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!), .elephant: SpriteMeeple(imageNamed: AppImages.Elephant, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP1!, imageRotation: 180),
], ],
.player2: [ .player2: [
.rat: SpriteMeeple(imageNamed: AppImages.Rat, size: CGSize(width: 100, height: 100), backgroundColor: .blue, imageRotation: 180), .rat: SpriteMeeple(imageNamed: AppImages.Rat, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP2!),
.cat: SpriteMeeple(imageNamed: AppImages.Cat, size: CGSize(width: 100, height: 100), backgroundColor: .blue, imageRotation: 180), .cat: SpriteMeeple(imageNamed: AppImages.Cat, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP2!),
.dog: SpriteMeeple(imageNamed: AppImages.Dog, size: CGSize(width: 100, height: 100), backgroundColor: .blue, imageRotation: 180), .dog: SpriteMeeple(imageNamed: AppImages.Dog, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP2!),
.wolf: SpriteMeeple(imageNamed: AppImages.Wolf, size: CGSize(width: 100, height: 100), backgroundColor: .blue, imageRotation: 180), .wolf: SpriteMeeple(imageNamed: AppImages.Wolf, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP2!),
.leopard: SpriteMeeple(imageNamed: AppImages.Leopard, size: CGSize(width: 100, height: 100), backgroundColor: .blue, imageRotation: 180), .leopard: SpriteMeeple(imageNamed: AppImages.Leopard, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP2!),
.lion: SpriteMeeple(imageNamed: AppImages.Lion, size: CGSize(width: 100, height: 100), backgroundColor: .blue, imageRotation: 180), .lion: SpriteMeeple(imageNamed: AppImages.Lion, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP2!),
.tiger: SpriteMeeple(imageNamed: AppImages.Tigger, size: CGSize(width: 100, height: 100), backgroundColor: .blue, imageRotation: 180), .tiger: SpriteMeeple(imageNamed: AppImages.Tigger, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP2!),
.elephant: SpriteMeeple(imageNamed: AppImages.Elephant, size: CGSize(width: 100, height: 100), backgroundColor: .blue, imageRotation: 180), .elephant: SpriteMeeple(imageNamed: AppImages.Elephant, size: CGSize(width: 100, height: 100), backgroundColor: Colors.MeepleP2!),
], ],
] ]
let imageBoard: SKSpriteNode = SKSpriteNode(imageNamed: AppImages.boardGame) let imageBoard: SKSpriteNode = SKSpriteNode(imageNamed: AppImages.boardGame)
override init(size: CGSize) { override init(size: CGSize) {
game = try! Game(withRules: ClassicRules(), andPlayer1: player1, andPlayer2: player2)
super.init(size: size) super.init(size: size)
imageBoard.size = size imageBoard.size = size
//self.scaleMode = .aspectFit //self.scaleMode = .aspectFit
@ -50,48 +50,41 @@ class GameScene : SKScene {
self.backgroundColor = .white self.backgroundColor = .white
self.addChild(imageBoard) self.addChild(imageBoard)
}
convenience init(size: CGSize, gameVM: PlayingGameVM) {
self.init(size: size)
self.game = gameVM.game
self.player1 = self.game?.players[.player1]
self.player2 = self.game?.players[.player2]
for piece in pieces.flatMap({owner, pieces in pieces.values}) { for piece in pieces.flatMap({owner, pieces in pieces.values}) {
self.addChild(piece) self.addChild(piece)
//piece.setOnMove(onMove: onMeepleMove) piece.setOnMove(onMove: gameVM.onMeepleMove)
} }
initializeBoard(game.board) initializeBoard(game!.board)
gameVM.game.addPieceRemovedListener { _, _, piece in
self.pieces[piece.owner]![piece.animal]?.removeFromParent()
}
gameVM.start()
} }
func initializeBoard(_ board: Board) { func initializeBoard(_ board: Board) {
for (lineIndex, currentLine) in game.board.grid.enumerated() { for (lineIndex, currentLine) in game!.board.grid.enumerated() {
for (cellIndex, currentCell) in currentLine.enumerated() { for (cellIndex, currentCell) in currentLine.enumerated() {
if let piece = currentCell.piece { if let piece = currentCell.piece {
pieces[piece.owner]?[piece.animal]?.cellPosition = CGPoint(x: cellIndex-3, y: lineIndex-4) pieces[piece.owner]?[piece.animal]?.cellPosition = CGPoint(x: cellIndex, y: lineIndex)
pieces[piece.owner]?[piece.animal]?.cellPosition = CGPoint(x: 0, y: 0) pieces[piece.owner]?[piece.animal]?.cellPosition = CGPoint(x: 0, y: 0)
print("line :", lineIndex, " cologne: ", cellIndex)
} }
} }
} }
} }
required init?(coder aDecoder: NSCoder) { required init?(coder aDecoder: NSCoder) {
game = try! Game(withRules: ClassicRules(), andPlayer1: player1, andPlayer2: player2) game = try! Game(withRules: ClassicRules(), andPlayer1: DouShouQiModel.Player(withName: "P1", andId: .player1)!, andPlayer2: DouShouQiModel.Player(withName: "P2", andId: .player2)!)
super.init(coder: aDecoder); super.init(coder: aDecoder);
} }
func onMeepleMove(_ start: CGPoint, _ end: CGPoint) async {
let owner = game.rules.getNextPlayer()
let player = game.players[owner]
let move = Move(of: owner, fromRow: Int(start.x), andFromColumn: Int(start.y), toRow: Int(end.x), andToColumn: Int(end.y))
print("Meeple moved")
try! await (player as! HumanPlayer).chooseMove(move)
}
public func start() async throws {
try await game.start()
}
} }

@ -10,8 +10,8 @@ import SpriteKit
class SpriteMeeple : SKNode { class SpriteMeeple : SKNode {
static let offset = CGPoint(x: 0, y: 0) static let offset = CGPoint(x: -300, y: 400)
static let direction = CGVector(dx: 100, dy: 100) static let direction = CGVector(dx: 100, dy: -100)
let imageNode : SKSpriteNode let imageNode : SKSpriteNode
var ellipseNode : SKShapeNode var ellipseNode : SKShapeNode
@ -19,15 +19,21 @@ class SpriteMeeple : SKNode {
var originalSize: CGSize var originalSize: CGSize
var originalEllipseSize: CGSize var originalEllipseSize: CGSize
var onMove: ((CGPoint, CGPoint) async -> ())? var onMove: ((SpriteMeeple, CGPoint, CGPoint) -> ())?
var cellPosition: CGPoint{ var cellPosition: CGPoint{
didSet(cellPosition){ didSet(cellPosition){
self.position.x = SpriteMeeple.offset.x + SpriteMeeple.direction.dx*cellPosition.x self.position.x = SpriteMeeple.offset.x + SpriteMeeple.direction.dx*cellPosition.x
self.position.y = SpriteMeeple.offset.y + SpriteMeeple.direction.dx*cellPosition.y self.position.y = SpriteMeeple.offset.y + SpriteMeeple.direction.dy*cellPosition.y
} }
} }
private var oldCellPosition: CGPoint?
func getCellPosition() -> CGPoint {
return CGPoint(x: Int((self.position.x - SpriteMeeple.offset.x)/SpriteMeeple.direction.dx), y: Int((self.position.y - SpriteMeeple.offset.y)/SpriteMeeple.direction.dy))
}
init(imageNamed imageName: String, size: CGSize, backgroundColor: UIColor, imageRotation : Double = 0){ init(imageNamed imageName: String, size: CGSize, backgroundColor: UIColor, imageRotation : Double = 0){
imageNode = SKSpriteNode(imageNamed: imageName) imageNode = SKSpriteNode(imageNamed: imageName)
originalSize = CGSize(width: 80, height: 65) originalSize = CGSize(width: 80, height: 65)
@ -59,7 +65,7 @@ class SpriteMeeple : SKNode {
super.init(coder: aDecoder) super.init(coder: aDecoder)
} }
public func setOnMove(onMove: @escaping (CGPoint, CGPoint) -> ()) { self.onMove = onMove } public func setOnMove(onMove: @escaping (SpriteMeeple, CGPoint, CGPoint) -> ()) { self.onMove = onMove }
override var isUserInteractionEnabled: Bool{ override var isUserInteractionEnabled: Bool{
set { } set { }
@ -67,6 +73,8 @@ class SpriteMeeple : SKNode {
} }
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){ override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){
self.oldCellPosition = getCellPosition()
imageNode.size = CGSize(width: imageNode.size.width * 1.1, height: imageNode.size.height * 1.1) imageNode.size = CGSize(width: imageNode.size.width * 1.1, height: imageNode.size.height * 1.1)
ellipseNode.path = SKShapeNode(ellipseOf: CGSize(width: originalEllipseSize.width*1.1, height: originalEllipseSize.height*1.1)).path ellipseNode.path = SKShapeNode(ellipseOf: CGSize(width: originalEllipseSize.width*1.1, height: originalEllipseSize.height*1.1)).path
self.zPosition = 1 self.zPosition = 1
@ -88,13 +96,12 @@ class SpriteMeeple : SKNode {
imageNode.size = originalSize imageNode.size = originalSize
ellipseNode.path = SKShapeNode(ellipseOf: originalEllipseSize).path ellipseNode.path = SKShapeNode(ellipseOf: originalEllipseSize).path
if let onMove: (CGPoint, CGPoint) async -> () = onMove { if let onMove: (SpriteMeeple, CGPoint, CGPoint) -> () = onMove {
//onMove(CGPoint(x: 100, y: 100), CGPoint(x: 200, y: 100)) onMove(self, self.oldCellPosition!, self.getCellPosition())
} }
self.zPosition = 0 self.zPosition = 0
} }
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){ override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){
self.position = touches.first?.location(in: parent!) ?? CGPoint(x: 0, y: 0) self.position = touches.first?.location(in: parent!) ?? CGPoint(x: 0, y: 0)

@ -0,0 +1,136 @@
//
// PlayingGameVM.swift
// DouShouQi_App
//
// Created by Rémi REGNAULT on 21/06/2024.
//
import Foundation
import SwiftUI
import DouShouQiModel
class PlayingGameVM: ObservableObject {
// Properties
@Published var game: Game
// Computed properties
public var currentPlayerName: String { game.players[game.rules.getNextPlayer()]?.name ?? (game.rules.getNextPlayer() == .player1 ? "P1" : "P2") }
public var lastMove: String {
if let move: Move = game.rules.historic.last {
return "\(move.columnDestination).\(move.rowDestination)"
}
else {
return ""
}
}
public var lastPieceMoved: String {
if let move: Move = game.rules.historic.last {
return game.board.grid[move.rowDestination][move.columnDestination].piece?.animal.symbol ?? ""
} else {
return ""
}
}
public var currentPlayerColor: UIColor {
return game.rules.getNextPlayer() == .player1 ? Colors.MeepleP1! : Colors.MeepleP2!
}
public var winner: String {
guard self.game.isOver else {
return ""
}
guard let lastMove: Move = self.game.rules.historic.last else {
return ""
}
guard let winner: DouShouQiModel.Player = game.players[lastMove.owner] else {
return ""
}
return winner.name
}
// Inits
init(withGame game: Game) {
self.game = game
}
init?(withRules rules: Rules, andPlayer1 p1: DouShouQiModel.Player, andPlayer2 p2: DouShouQiModel.Player) {
do {
self.game = try Game(withRules: rules, andPlayer1: p1, andPlayer2: p2)
self.game.addInvalidMoveCallbacksListener { _, move, player, result in
if result {
return
}
print("**************************************")
print("⚠️⚠️⚠️⚠️ Invalid Move detected: \(move) by \(player.name) (\(player.id))")
print("**************************************")
}
self.game.addGameOverListener { board, result, player in
switch(result){
case .notFinished:
print("⏳ Game is not over yet!")
case .winner(winner: let o, reason: let r):
print(board)
print("**************************************")
print("Game Over!!!")
print("🥇🏆 and the winner is... \(o == .player1 ? "🟡" : "🔴") \(player?.name ?? "")!")
switch(r){
case .denReached:
print("🪺 the opponent's den has been reached.")
case .noMorePieces:
print("🐭🐱🐯🦁🐘 all the opponent's animals have been eaten...")
case .noMovesLeft:
print("⛔️ the opponent can not move any piece!")
case .tooManyOccurences:
print("🔄 the opponent seem to like this situation... but enough is enough. Sorry...")
default:
print("Reason unknown...")
}
print("**************************************")
default:
break
}
}
} catch {
print("Error")
return nil
}
}
// Customs funcs
func onMeepleMove(_ sender: SpriteMeeple, _ start: CGPoint, _ end: CGPoint) {
let owner = game.rules.getNextPlayer()
let player: DouShouQiModel.Player = game.players[owner]!
let move = Move(of: owner, fromRow: Int(start.y), andFromColumn: Int(start.x), toRow: Int(end.y), andToColumn: Int(end.x))
if (game.rules.isMoveValid(onBoard: game.board, withMove: move)) {
print("Meeple moved = ", start, " -> ", end)
Task {
try! await (player as! HumanPlayer).chooseMove(move)
}
self.objectWillChange.send()
} else {
sender.cellPosition = start
sender.cellPosition = start
}
}
public func start() {
Task {
try await self.game.start()
}
}
}

@ -7,21 +7,53 @@
import SwiftUI import SwiftUI
import SpriteKit import SpriteKit
import DouShouQiModel
struct GameView: View { struct GameView: View {
var gameScene: GameScene = GameScene(size: CGSize(width: 700, height: 900)) var gameScene: GameScene = GameScene(size: CGSize(width: 700, height: 900))
@StateObject var gameVM: PlayingGameVM
@State private var showHome = false
var body: some View { var body: some View {
VStack { ZStack {
TopGameBoard().frame(maxHeight: 200) VStack {
SpriteView(scene: gameScene) TopGameBoard(gameVM: gameVM).frame(maxHeight: 200)
} SpriteView(scene: GameScene(size: CGSize(width: 700, height: 900), gameVM: gameVM))
.onAppear { }
playSound(named: "Fight") .onAppear {
playSound(named: "Fight")
//MusicPlayer.shared.playBackgroundMusic(music: "GameMusic")
//MusicPlayer.shared.playBackgroundMusic(music: "GameMusic")
DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) {
MusicPlayer.shared.playBackgroundMusic(music: "GameMusic")
}
}
.onDisappear {
MusicPlayer.shared.stopBackgroundMusic()
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) { if (gameVM.game.isOver) {
MusicPlayer.shared.playBackgroundMusic(music: "GameMusic") HStack {
Spacer()
VStack(alignment: .center) {
Text("Game Over")
.font(.title2)
Text("Winner: \(gameVM.winner)")
}
.background(Colors.WinnerBackground)
Spacer()
}
.onAppear {
Timer.scheduledTimer(withTimeInterval: 10, repeats: false) { _ in
// Il faut retourner au home
}
}
} }
} }
.onDisappear { .onDisappear {
@ -31,8 +63,8 @@ struct GameView: View {
} }
} }
struct GameView_Previews: PreviewProvider { /*struct GameView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
GameView() GameView()
} }
} }*/

@ -7,6 +7,7 @@
import SwiftUI import SwiftUI
import SpriteKit import SpriteKit
import DouShouQiModel
struct SelectPlayerView: View { struct SelectPlayerView: View {
@ -26,8 +27,9 @@ struct SelectPlayerView: View {
HStack { HStack {
VStack(alignment: .trailing) VStack(alignment: .trailing)
{ {
MainMenuButton(text: "Start", destination: GameView(), sound: "Start", horizontalAlignment: .trailing, topLeftCorner: 10, bottomLeftCorner: 10) MainMenuButton(text: "Start", destination: GameView(gameVM: PlayingGameVM(withRules: ClassicRules(), andPlayer1: HumanPlayer(withName: player1.player.name, andId: .player1)!, andPlayer2: HumanPlayer(withName: player2.player.name, andId: .player2)!)!), sound: "Start", horizontalAlignment: .trailing, topLeftCorner: 10, bottomLeftCorner: 10)
MainMenuButton(text: "Settings", destination: ContentView(), sound: "TitleScreenButtonSound", horizontalAlignment: .trailing, topLeftCorner: 10, bottomLeftCorner: 10) MainMenuButton(text: "Settings", destination: ContentView(), sound: "TitleScreenButtonSound", horizontalAlignment: .trailing, topLeftCorner: 10, bottomLeftCorner: 10)
} }
} }

Loading…
Cancel
Save