@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// ArKitView.swift
|
||||||
|
// ArkitDoushiQi
|
||||||
|
//
|
||||||
|
// Created by Enzo JOLYS on 12/06/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import DouShouQiModel
|
||||||
|
import Foundation
|
||||||
|
import ARKit
|
||||||
|
import RealityKit
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class ArKitView : ARView {
|
||||||
|
|
||||||
|
|
||||||
|
required init(frame frameRect: CGRect) {
|
||||||
|
super.init(frame: frameRect)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder decoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
convenience init() {
|
||||||
|
self.init(frame: UIScreen.main.bounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyConfiguration() {
|
||||||
|
let configuration = ARWorldTrackingConfiguration()
|
||||||
|
session.run(configuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
func defineAnchors() -> AnchorEntity {
|
||||||
|
let anchor = AnchorEntity(.plane(.horizontal, classification: .any, minimumBounds: SIMD2<Float>(0.2, 0.2)))
|
||||||
|
scene.addAnchor(anchor)
|
||||||
|
return anchor
|
||||||
|
}
|
||||||
|
|
||||||
|
func addGesture(_ pieces:[Owner : [ Animal : Entity?]]){
|
||||||
|
for piece in pieces.flatMap({ animal,values in return values })
|
||||||
|
{
|
||||||
|
if piece.self.value != nil {
|
||||||
|
self.installGestures([.all], for: piece.self.value as! Entity & HasCollision).forEach { gestureRecognizer in
|
||||||
|
gestureRecognizer.addTarget(self, action: #selector(handleGesture(_:)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var initialTransform: Transform = Transform()
|
||||||
|
|
||||||
|
@objc private func handleGesture(_ recognizer: UIGestureRecognizer) {
|
||||||
|
guard let translationGesture = recognizer as? EntityTranslationGestureRecognizer, let entity = translationGesture.entity else { return }
|
||||||
|
|
||||||
|
switch translationGesture.state {
|
||||||
|
case .began:
|
||||||
|
self.initialTransform = entity.transform
|
||||||
|
case .ended:
|
||||||
|
entity.move(to: initialTransform, relativeTo: entity.parent, duration: 1)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// ArKitViewRepresentable.swift
|
||||||
|
// ArkitDoushiQi
|
||||||
|
//
|
||||||
|
// Created by Enzo JOLYS on 12/06/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
import DouShouQiModel
|
||||||
|
|
||||||
|
struct ArKitViewRepresentable : UIViewRepresentable {
|
||||||
|
|
||||||
|
var vm:VMArkit
|
||||||
|
|
||||||
|
init(_ game:Game){
|
||||||
|
vm = VMArkit(game)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeUIView(context: Context) -> ArKitView {
|
||||||
|
let arView = ArKitView()
|
||||||
|
let anchor = arView.defineAnchors()
|
||||||
|
vm.setup(anchor)
|
||||||
|
arView.addGesture(vm.pieces)
|
||||||
|
return arView
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIView(_ uiView: UIViewType, context: Context) { }
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// UIViewArKit.swift
|
||||||
|
// ArkitDoushiQi
|
||||||
|
//
|
||||||
|
// Created by Enzo JOLYS on 12/06/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import DouShouQiModel
|
||||||
|
|
||||||
|
struct ContentArkit: View {
|
||||||
|
|
||||||
|
//var vm:VMArkit = VMArkit(try! Game(withRules: ClassicRules(), andPlayer1: RandomPlayer(withName: "Bot1", andId: .player1)!, andPlayer2: RandomPlayer(withName: "Bot2", andId: .player2)!))
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
Text("toto")
|
||||||
|
ArKitViewRepresentable(try! Game(withRules: ClassicRules(), andPlayer1: RandomPlayer(withName: "Bot1", andId: .player1)!, andPlayer2: RandomPlayer(withName: "Bot2", andId: .player2)!))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct UIViewArKit_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
ContentArkit()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,192 @@
|
|||||||
|
//
|
||||||
|
// VMArkit.swift
|
||||||
|
// ArkitDoushiQi
|
||||||
|
//
|
||||||
|
// Created by Enzo JOLYS on 14/06/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import DouShouQiModel
|
||||||
|
import ARKit
|
||||||
|
import RealityKit
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
struct VMArkit {
|
||||||
|
|
||||||
|
static let offset = CGPoint(x: -0.458 * 0.3 , y: -0.3435 * 0.3 )
|
||||||
|
static let direction = CGVector(dx: 0.1145 * 0.3, dy: 0.1145 * 0.3)
|
||||||
|
|
||||||
|
var game:Game
|
||||||
|
|
||||||
|
var pieces: [Owner : [ Animal : Entity?]] = [.player1: [.cat:nil,
|
||||||
|
.elephant:nil,
|
||||||
|
.dog:nil,
|
||||||
|
.leopard:nil,
|
||||||
|
.lion:nil,
|
||||||
|
.rat:nil,
|
||||||
|
.tiger:nil,
|
||||||
|
.wolf:nil],
|
||||||
|
.player2: [.cat:nil,
|
||||||
|
.elephant:nil,
|
||||||
|
.dog:nil,
|
||||||
|
.leopard:nil,
|
||||||
|
.lion:nil,
|
||||||
|
.rat:nil,
|
||||||
|
.tiger:nil,
|
||||||
|
.wolf:nil]]
|
||||||
|
|
||||||
|
init(_ game:Game){
|
||||||
|
self.game = game
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup(_ anchor:AnchorEntity){
|
||||||
|
addBoard(anchor)
|
||||||
|
generatePieces(anchor)
|
||||||
|
displayBoard(game.board)
|
||||||
|
}
|
||||||
|
|
||||||
|
func addBoard(_ anchor:AnchorEntity){
|
||||||
|
let board = try? Entity.load(named: "board")
|
||||||
|
board?.scale = [0.3,0.3,0.3]
|
||||||
|
if let board {
|
||||||
|
print("Ajout du board")
|
||||||
|
anchor.addChild(board)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Crée les pieces
|
||||||
|
func generatePieces(_ anchor:AnchorEntity) {
|
||||||
|
|
||||||
|
// Position - X,Y,Z
|
||||||
|
for var piece in pieces.flatMap({ animal,values in return values })
|
||||||
|
{
|
||||||
|
var entity:Entity?
|
||||||
|
switch piece.self.key {
|
||||||
|
case .cat :
|
||||||
|
entity = try? Entity.loadModel(named: "cat")
|
||||||
|
case .elephant :
|
||||||
|
entity = try? Entity.loadModel(named: "elephant")
|
||||||
|
case .dog :
|
||||||
|
entity = try? Entity.loadModel(named: "dog")
|
||||||
|
case .leopard :
|
||||||
|
entity = try? Entity.loadModel(named: "leopard")
|
||||||
|
case .lion :
|
||||||
|
entity = try? Entity.loadModel(named: "lion")
|
||||||
|
case .rat :
|
||||||
|
entity = try? Entity.loadModel(named: "rat")
|
||||||
|
case .tiger :
|
||||||
|
entity = try? Entity.loadModel(named: "tiger")
|
||||||
|
case .wolf :
|
||||||
|
entity = try? Entity.loadModel(named: "wolf")
|
||||||
|
|
||||||
|
default:
|
||||||
|
fatalError("Animal non compris")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if let entityNotNull = entity {
|
||||||
|
entityNotNull.scale = [0.3,0.3,0.3]
|
||||||
|
anchor.addChild(entityNotNull)
|
||||||
|
entityNotNull.position = SIMD3<Float>(0,0.02,0)
|
||||||
|
|
||||||
|
entityNotNull.generateCollisionShapes(recursive:true)
|
||||||
|
|
||||||
|
piece.self.value = entityNotNull
|
||||||
|
print("Piece \(piece.self.key) a été crée !")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print("La pièce \(piece.self.key) n'a pas été crée !")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -- Affiche les pieces à la bonne positions
|
||||||
|
func displayBoard(_ board:Board) {
|
||||||
|
for ligne in 0..<board.grid.count {
|
||||||
|
for col in 0..<board.grid[ligne].count {
|
||||||
|
if let piece = board.grid[ligne][col].piece {
|
||||||
|
print("Piece detected !!")
|
||||||
|
if let element = pieces[piece.owner]![piece.animal]{
|
||||||
|
if (element != nil ){
|
||||||
|
print("Change position !!")
|
||||||
|
element!.position = convertPosModeleIntoWorldPos(pos:CGPoint(x: ligne, y: col))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print("WARNING !!! -> Element vide ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertPosModeleIntoWorldPos(pos:CGPoint) -> SIMD3<Float> {
|
||||||
|
return SIMD3<Float>(Float(VMArkit.offset.x + VMArkit.direction.dx * pos.x),Float(VMArkit.offset.y + VMArkit.direction.dy * pos.y),10)
|
||||||
|
}
|
||||||
|
func converWorldPosIntoPosModele(pos:SIMD3<Float>) -> CGPoint {
|
||||||
|
let posX = Int(round((CGFloat(pos.x) - (VMArkit.offset.x)) / VMArkit.direction.dx))
|
||||||
|
let posY = Int(round((CGFloat(pos.y) - (VMArkit.offset.y)) / VMArkit.direction.dy))
|
||||||
|
return CGPoint(x: posX, y: posY)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------ Listener -------- //
|
||||||
|
func defineListeners(){
|
||||||
|
self.game.addGameStartedListener { board in startGame()}
|
||||||
|
self.game.addGameOverListener { board, result, player in gameOver()}
|
||||||
|
self.game.addGameChangedListener { game in gameChange() }
|
||||||
|
self.game.addBoardChangedListener { board in boardChange() }
|
||||||
|
self.game.addMoveChosenCallbacksListener { board, move, player in moveChose(board: board, move: move, player: player) }
|
||||||
|
self.game.addInvalidMoveCallbacksListener { board,move,player,bool in invalidMove(board: board, move: move, player:player, bool:bool)}
|
||||||
|
self.game.addPieceRemovedListener { _,_,piece in removePiece(piece: piece) }
|
||||||
|
|
||||||
|
self.game.addPlayerNotifiedListener { board, player in
|
||||||
|
print("Player notif : \(player.id) à toi de jouer ")
|
||||||
|
//msg = "Player notif : \(player.id) à toi de jouer !"
|
||||||
|
if (player is IAPlayer ){
|
||||||
|
try! await player.chooseMove(in: board, with: game.rules)
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func startGame() { print("Start game !")
|
||||||
|
//self.msg = "Start !!"
|
||||||
|
}
|
||||||
|
func gameOver() { print("Game over !")
|
||||||
|
//msg = "Game over !!"
|
||||||
|
}
|
||||||
|
func gameChange() { print("Game change !") }
|
||||||
|
func boardChange() {
|
||||||
|
print("Board change !")
|
||||||
|
self.displayBoard(self.game.board)
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveChose(board:Board,move:Move,player:Player) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func invalidMove(board:Board,move:Move,player:Player,bool:Bool) {
|
||||||
|
if (bool){ // Valid
|
||||||
|
print("Move valid de \(player.id)")
|
||||||
|
print("Move : \(move.description)")
|
||||||
|
}
|
||||||
|
else { // Invalid
|
||||||
|
print("Move invalid de \(player.id)")
|
||||||
|
print("Move : \(move.description)")
|
||||||
|
self.displayBoard(self.game.board)
|
||||||
|
}
|
||||||
|
print("------------")
|
||||||
|
}
|
||||||
|
|
||||||
|
func removePiece(piece:Piece){
|
||||||
|
print("Remove piece")
|
||||||
|
if let entity = pieces[piece.owner]![piece.animal] {
|
||||||
|
if let x = entity {
|
||||||
|
x.removeFromParent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------- //
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue