You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
SwiftUiTp/DouShouQiIOS/DouShouQiIOS/Class/GameVM.swift

189 lines
6.3 KiB

//
// GameVM.swift
// DouShouQiIOS
//
// Created by Pierre FERREIRA on 12/06/2024.
//
import Foundation
import DouShouQiModel
import SpriteKit
import SwiftUI
// Gestion de la boucle de jeu par la création d'une tache async<
// On s'abonne aux événements, notament game.addPlayerNotifiedListeneren.
// Les joueurs n'ont besoin que de nom
class GameVM : ObservableObject, Identifiable {
@Published var game: Game
@Published var gameScene: GameScene
@Published var isGameOver: Bool = false
///Players (-game -> todelete)
// let player1 : Player
// let player2 : Player
// var pieces : [ Owner : [Animal : SpriteMeeple]]
// let actualRules : Rules
///Error
@Published var hasError : Bool = false
///Message
@Published var displayMessage : String = ""
//On donne directement la scene et la game à la vm
public init(withGame _game : Game, andScene _gameScene : GameScene) {
self.game = _game
self.gameScene = _gameScene
///Abonnement aux événements
self.game.addGameStartedListener(onGameStart)
self.game.addPlayerNotifiedListener(onPlayerNotified)
self.game.addMoveChosenCallbacksListener(onMoveChosen)
self.game.addInvalidMoveCallbacksListener(onInvalidMove)
self.game.addBoardChangedListener(onBoardChanged)
self.game.addGameOverListener(onGameOver)
//self.game?.addGameChangedListener({}) - //? cas persistance
self.subscribesToMeeple()
Task{
try! await self.game.start()
}
}
func onGameStart(board : Board){
displayMessage = " ==>> 🎉 GAME STARTS! 🎉 <<== "
self.gameScene.displayBoard(board)
print("GAME STARTS")
}
func onPlayerNotified(board : Board, player : Player) async{
print("PLAYER NOTIFIED")
if player is HumanPlayer {
displayMessage = "Player \(player.id == .player1 ? "🟡 1" : "🔴 2") - \(player.name), it's your turn!"
//try! await (player as! HumanPlayer).chooseMove(move)
}
else {
do{
_ = try await player.chooseMove(in: board, with: self.game.rules)
}
catch{
hasError = true
}
}
}
func onMoveChosen(board : Board, move : Move, player : Player){
///Récupération du Meeple :
let movedPiece = board.grid[move.rowOrigin][move.columnOrigin]
let meeples = gameScene.pieces[move.owner]
let meeple = meeples?.first(where: {
$0.key == movedPiece.piece?.animal
})
meeple?.value.cellPosition = CGPoint(x: move.rowDestination, y: move.columnDestination)
}
///Mouvement invalide
func onInvalidMove(board : Board, move : Move, player : Player, result : Bool){
displayMessage = "⚠️⚠️⚠️⚠️ Invalid Move detected: \(move) by \(player.name) (\(player.id))"
if result { ///* invalidité terminante
if let piece = board.grid[move.rowDestination][move.columnDestination].piece{
// Delete le meeple
let meeples = gameScene.pieces[player.id == .player1 ? .player2 : .player1]
let meeple = meeples?.first(where: {
$0.key == piece.animal
})
meeple?.value.parent?.removeChildren(in: [meeple!.value])
}
return
}
let piece = board.grid[move.rowOrigin][move.columnOrigin]
let meeples = gameScene.pieces[move.owner]
let meeple = meeples?.first(where: {
$0.key == piece.piece?.animal
})
meeple?.value.cellPosition = CGPoint(x: move.rowOrigin, y: move.columnOrigin);
print("INVALID")
}
func invalideMoveChosen(board: Board, move: Move, player: Player, result: Bool) {
if result {
if let piece = board.grid[move.rowDestination][move.columnDestination].piece{
// Delete le meeple
let meeples = gameScene.pieces[player.id == .player1 ? .player2 : .player1]
let meeple = meeples?.first(where: {
$0.key == piece.animal
})
meeple?.value.parent?.removeChildren(in: [meeple!.value])
}
return
}
let piece = board.grid[move.rowOrigin][move.columnOrigin]
let meeples = gameScene.pieces[move.owner]
let meeple = meeples?.first(where: {
$0.key == piece.piece?.animal
})
meeple?.value.cellPosition = CGPoint(x: move.rowOrigin, y: move.columnOrigin);
}
func onBoardChanged(board : Board){
/// Bruit d'un placement de pion ?
}
func onGameOver(board : Board, result : Result, winner : Player?){
displayMessage = "Game Over!!!"
isGameOver = true ///Gestion par l'appelant
}
///Meeples
func subscribesToMeeple(){
for meeple in gameScene.pieces[.player1]!{
meeple.value.observers.append(meepleMoved)
}
for meeple in gameScene.pieces[.player2]!{
meeple.value.observers.append(meepleMoved)
}
}
func meepleMoved(spriteMeeple: SpriteMeeple, startX: Int, startY: Int, endX: Int, endY: Int) async{
let owner : Owner = game.board.grid[startX][startY].piece!.owner
let otherPlayer : Owner = self.game.rules.getNextPlayer()
let move: Move = Move(of: owner, fromRow: startX, andFromColumn: startY, toRow: endX, andToColumn: endY)
if(otherPlayer != owner){ ///Mauvais Joueur pour ce jeton
print("invalide de la part de meepleMoved")
onInvalidMove(board: game.board, move: move, player: game.players[otherPlayer]!, result: false)
return
}
if let player: HumanPlayer = game.players[owner] as? HumanPlayer{
try! await player.chooseMove(move)
}
// else { ///IMPOSSIBLE DE CAST LE JOUEUR HUMAIN
// let player: HumanPlayer = game.players[.player1] as! HumanPlayer
// try! await player.chooseMove(move)
// }
print("il a bougé")
}
}