From 6e081d1f073041b373c54248a3743b66f87c730e Mon Sep 17 00:00:00 2001
From: tobias <thinkdifferent055@gmail.com>
Date: Sun, 9 Jul 2017 22:04:08 +0200
Subject: [PATCH] Improve pacman moving; Cleanup code

---
 Pacman3D-iOS.xcodeproj/project.pbxproj |  12 +-
 Pacman3D-iOS/GameViewController.swift  | 145 +++++--------------------
 Pacman3D-iOS/Level.swift               |  36 ++++++
 Pacman3D-iOS/MotionInput.swift         |  47 ++++++++
 Pacman3D-iOS/Player.swift              |  66 +++++++++++
 Pacman3D-iOS/TouchInputHandler.swift   |  25 +++++
 6 files changed, 212 insertions(+), 119 deletions(-)
 create mode 100644 Pacman3D-iOS/MotionInput.swift
 create mode 100644 Pacman3D-iOS/TouchInputHandler.swift

diff --git a/Pacman3D-iOS.xcodeproj/project.pbxproj b/Pacman3D-iOS.xcodeproj/project.pbxproj
index 7a725d6..f61ba54 100644
--- a/Pacman3D-iOS.xcodeproj/project.pbxproj
+++ b/Pacman3D-iOS.xcodeproj/project.pbxproj
@@ -7,6 +7,8 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		F6621DF41F12B09800F9E486 /* TouchInputHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6621DF31F12B09800F9E486 /* TouchInputHandler.swift */; };
+		F6621DF61F12B82200F9E486 /* MotionInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6621DF51F12B82200F9E486 /* MotionInput.swift */; };
 		F6BEB8071EF7F99B00EDAA66 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6BEB8061EF7F99B00EDAA66 /* AppDelegate.swift */; };
 		F6BEB8091EF7F99B00EDAA66 /* art.scnassets in Resources */ = {isa = PBXBuildFile; fileRef = F6BEB8081EF7F99B00EDAA66 /* art.scnassets */; };
 		F6BEB80B1EF7F99B00EDAA66 /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6BEB80A1EF7F99B00EDAA66 /* GameViewController.swift */; };
@@ -42,6 +44,8 @@
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
+		F6621DF31F12B09800F9E486 /* TouchInputHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TouchInputHandler.swift; sourceTree = "<group>"; };
+		F6621DF51F12B82200F9E486 /* MotionInput.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionInput.swift; sourceTree = "<group>"; };
 		F6BEB8031EF7F99B00EDAA66 /* Pacman3D-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Pacman3D-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		F6BEB8061EF7F99B00EDAA66 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		F6BEB8081EF7F99B00EDAA66 /* art.scnassets */ = {isa = PBXFileReference; lastKnownFileType = wrapper.scnassets; path = art.scnassets; sourceTree = "<group>"; };
@@ -116,10 +120,12 @@
 				F6FEE7141EF80AB900C1DE35 /* Level */,
 				F6FEE7191EF80C1900C1DE35 /* Uilts */,
 				F6BEB8061EF7F99B00EDAA66 /* AppDelegate.swift */,
-				F6BEB8081EF7F99B00EDAA66 /* art.scnassets */,
 				F6BEB80A1EF7F99B00EDAA66 /* GameViewController.swift */,
-				F6BEB80C1EF7F99B00EDAA66 /* Main.storyboard */,
+				F6621DF31F12B09800F9E486 /* TouchInputHandler.swift */,
+				F6621DF51F12B82200F9E486 /* MotionInput.swift */,
+				F6BEB8081EF7F99B00EDAA66 /* art.scnassets */,
 				F6BEB80F1EF7F99B00EDAA66 /* Assets.xcassets */,
+				F6BEB80C1EF7F99B00EDAA66 /* Main.storyboard */,
 				F6BEB8111EF7F99B00EDAA66 /* LaunchScreen.storyboard */,
 				F6BEB8141EF7F99B00EDAA66 /* Info.plist */,
 				F6FEE71A1EF8135200C1DE35 /* level.plv */,
@@ -305,9 +311,11 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				F6621DF61F12B82200F9E486 /* MotionInput.swift in Sources */,
 				F6E4AE451F0CF1DF004BFDBF /* Direction.swift in Sources */,
 				F6FEE7181EF80C1500C1DE35 /* StreamReader.swift in Sources */,
 				F6FEE7161EF80AD500C1DE35 /* Level.swift in Sources */,
+				F6621DF41F12B09800F9E486 /* TouchInputHandler.swift in Sources */,
 				F6BEB80B1EF7F99B00EDAA66 /* GameViewController.swift in Sources */,
 				F6BEB8071EF7F99B00EDAA66 /* AppDelegate.swift in Sources */,
 				F6E4AE431F0CEC6C004BFDBF /* Monster.swift in Sources */,
diff --git a/Pacman3D-iOS/GameViewController.swift b/Pacman3D-iOS/GameViewController.swift
index b07b55d..be8c1b6 100644
--- a/Pacman3D-iOS/GameViewController.swift
+++ b/Pacman3D-iOS/GameViewController.swift
@@ -12,7 +12,7 @@ import SceneKit
 import SpriteKit
 import CoreMotion
 
-class GameViewController: UIViewController, SKSceneDelegate ,SCNPhysicsContactDelegate, SCNSceneRendererDelegate {
+class GameViewController: UIViewController, SKSceneDelegate, SCNPhysicsContactDelegate, SCNSceneRendererDelegate {
 
     var motionManager: CMMotionManager?
     var scene: SCNScene!
@@ -22,17 +22,19 @@ class GameViewController: UIViewController, SKSceneDelegate ,SCNPhysicsContactDe
     static let monsterCollision =  0b011 //3
     static let pointsCollision =   0b100 //4
     
-    var isRotating: Bool = false
+    // MARK: - Overlay
     
-    var direction: Direction = .north
-    
-    // overlay
     var pointsLabel: SKLabelNode!
     var lifeLabel: SKLabelNode!
     
-    var player: Player = Player()
+    // MARK: - Game Objects
+    
+    var player: Player!
     var monsters: [Monster] = []
 
+    // MARK: - Input Handler
+    private var touchInputHandler: TouchInputHandler!
+    private var motionInput: MotionInput?
     
     override func viewDidLoad() {
         super.viewDidLoad()
@@ -42,6 +44,9 @@ class GameViewController: UIViewController, SKSceneDelegate ,SCNPhysicsContactDe
         // create a new scene
         scene = SCNScene(named: "art.scnassets/ship.scn")!
         
+        let pacman = scene.rootNode.childNode(withName: "Pacman", recursively: true)!
+        player = Player(node: pacman, scene: scene, level: level)
+        
         // create and add a camera to the scene
         let cameraNode = SCNNode()
         cameraNode.camera = SCNCamera()
@@ -50,42 +55,10 @@ class GameViewController: UIViewController, SKSceneDelegate ,SCNPhysicsContactDe
         // place the camera
         cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
         
-        for (x, line) in level.data.enumerated() {
-            for (z, block) in line.enumerated() {
-                if block == .wall {
-                    let box = SCNBox(width: 5, height: 2, length: 5, chamferRadius: 0)
-                    let node = SCNNode(geometry: box)
-                    node.physicsBody = SCNPhysicsBody(type: .static, shape: SCNPhysicsShape(geometry: box, options: nil))
-                    node.physicsBody?.categoryBitMask = GameViewController.wallCollision
-                    node.physicsBody?.contactTestBitMask = GameViewController.pacmanCollision
-                    node.position = SCNVector3(x: Float(x * 5), y: 1, z:Float(z * 5))
-                    node.name = "\(x) \(z)"
-                    scene.rootNode.addChildNode(node)
-                } else if block == .blank {
-                    let shere = SCNSphere(radius: 0.5)
-                    shere.firstMaterial?.diffuse.contents = UIColor.blue
-                    let node = SCNNode(geometry: shere)
-                    node.physicsBody = SCNPhysicsBody(type: .static, shape: nil)
-                    node.physicsBody?.categoryBitMask = GameViewController.pointsCollision
-                    node.physicsBody?.contactTestBitMask = GameViewController.pacmanCollision
-                    node.name = "Point"
-                    node.position = SCNVector3(x: Float(x * 5), y: 1, z:Float(z * 5))
-                    self.scene.rootNode.addChildNode(node)
-                }
-            }
-        }
-        
-        let pacman = self.scene.rootNode.childNode(withName: "Pacman", recursively: true)!
-        let pacmanBox = SCNBox(width: 5, height: 2, length: 5, chamferRadius: 0)
-        pacmanBox.firstMaterial?.diffuse.contents = UIColor.clear
-        let boxNode = SCNNode(geometry: pacmanBox)
-        pacman.addChildNode(boxNode)
-        pacman.physicsBody = SCNPhysicsBody(type: .kinematic, shape: SCNPhysicsShape(geometry: pacmanBox, options: nil))
-        pacman.physicsBody?.categoryBitMask = GameViewController.pacmanCollision
-        pacman.physicsBody?.contactTestBitMask = GameViewController.wallCollision
-        pacman.physicsBody?.isAffectedByGravity = false
         scene.physicsWorld.contactDelegate = self
         
+        level.createLevelEnviroment(scene: scene)
+        
 //        // create and add a light to the scene
 //        let lightNode = SCNNode()
 //        lightNode.light = SCNLight()
@@ -119,38 +92,14 @@ class GameViewController: UIViewController, SKSceneDelegate ,SCNPhysicsContactDe
         scnView.backgroundColor = UIColor.black
         
         // add a tap gesture recognizer
-        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
-        scnView.addGestureRecognizer(tapGesture)
+        touchInputHandler = TouchInputHandler(target: self, action: #selector(handleTap(_:)))
+        scnView.addGestureRecognizer(touchInputHandler)
         
+        self.motionInput = MotionInput(gameScene: self)
         motionManager = CMMotionManager()
         if (motionManager?.isAccelerometerAvailable)! {
             motionManager?.accelerometerUpdateInterval = 0.1
-            motionManager?.startAccelerometerUpdates(to: OperationQueue.main, withHandler: { (data, error) in
-                let rotate = data!.acceleration.y
-                //print(rotate)
-                let pacman = self.scene.rootNode.childNode(withName: "Pacman", recursively: true)!
-                let direction: Float = rotate < 0 ? 1.0 : -1.0
-                if abs(rotate) > 0.3 {
-                    if !self.isRotating {
-                        let action = SCNAction.rotateBy(x: 0, y: CGFloat(direction * Float.pi * 0.5), z: 0, duration: 0.25)
-                        pacman.runAction(action, completionHandler: { 
-                            self.isContact = false
-                        })
-                        self.isRotating = true
-                        
-                        var directionVal = self.direction.rawValue + Int(direction)
-                        if directionVal == 5 {
-                            directionVal = 1
-                        }
-                        if directionVal == 0 {
-                            directionVal = 4
-                        }
-                        self.direction = Direction(rawValue: directionVal)!
-                    }
-                } else {
-                    self.isRotating = false
-                }
-            })
+            motionManager?.startAccelerometerUpdates(to: OperationQueue.main, withHandler: motionInput!.handleMotionInput)
         }
         if (motionManager?.isDeviceMotionAvailable)! {
             motionManager?.deviceMotionUpdateInterval = 0.1
@@ -169,7 +118,7 @@ class GameViewController: UIViewController, SKSceneDelegate ,SCNPhysicsContactDe
             })
         }
         
-        for _ in 1...1 {
+        for _ in 1...10 {
             let postion = level.nextFreeSpace()
             let monster = Monster(position: SCNVector3(5 * postion.x, 1, 5 * postion.z), level: level, scene: scene)
             monster.addToScene(rootScene: self.scene)
@@ -191,8 +140,6 @@ class GameViewController: UIViewController, SKSceneDelegate ,SCNPhysicsContactDe
         }
     }
     
-    var isContact: Bool = false
-    
     func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
         if contact.nodeA.name ?? "" == "Monster" && contact.nodeB.name ?? "" == "Monster" {
             return
@@ -226,44 +173,22 @@ class GameViewController: UIViewController, SKSceneDelegate ,SCNPhysicsContactDe
                 contact.nodeB.removeFromParentNode()
             }
         }
-        
-        if(contact.nodeA == pacman && contact.nodeB.physicsBody?.categoryBitMask == GameViewController.wallCollision) || (contact.nodeA.physicsBody?.categoryBitMask == GameViewController.wallCollision && contact.nodeB == pacman){
-            
-            func block() {
-                if let box = contact.nodeA.geometry as? SCNBox {
-                    box.firstMaterial?.diffuse.contents = UIColor.blue
-                }
-                
-                if let box = contact.nodeB.geometry as? SCNBox {
-                    box.firstMaterial?.diffuse.contents = UIColor.blue
-                }
-                isContact = true
-            }
-            
-            if direction == .north {
-                if contact.contactNormal.x == 1.0 {
-                    block()
-                }
-            } else if direction == .east {
-                if contact.contactNormal.z == -1.0 {
-                    block()
-                }
-            } else if direction == .south {
-                if contact.contactNormal.x == -1.0 {
-                    block()
-                }
-            } else if direction == .west {
-                if contact.contactNormal.z == 1.0 {
-                    block()
-                }
-            }
-        }
     }
     
+    private var lastTime: TimeInterval = 0
+    
     func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
         for monster in monsters {
             monster.move()
         }
+        
+        
+        if time - lastTime > 0.25 {
+            if touchInputHandler.isTouchDown {
+                player.move()
+            }
+            lastTime = time
+        }
     }
     
     func createOverlay() -> SKScene {
@@ -283,20 +208,6 @@ class GameViewController: UIViewController, SKSceneDelegate ,SCNPhysicsContactDe
     }
 
     func handleTap(_ gestureRecognize: UIGestureRecognizer) {
-        if isContact {
-            return
-        }
-        
-        let pacman = scene.rootNode.childNode(withName: "Pacman", recursively: true)!
-        if direction == .north {
-            pacman.position.x += 5
-        } else if direction == .east {
-            pacman.position.z -= 5
-        } else if direction == .south {
-            pacman.position.x -= 5
-        } else if direction == .west {
-            pacman.position.z += 5
-        }
     }
     
     override var shouldAutorotate: Bool {
diff --git a/Pacman3D-iOS/Level.swift b/Pacman3D-iOS/Level.swift
index d0e153f..9f31ffd 100644
--- a/Pacman3D-iOS/Level.swift
+++ b/Pacman3D-iOS/Level.swift
@@ -7,6 +7,7 @@
 //
 
 import Foundation
+import SceneKit
 
 class Level {
     
@@ -44,6 +45,41 @@ class Level {
         data = [[]]
     }
     
+    func createLevelEnviroment(scene: SCNScene) {
+        for (x, line) in data.enumerated() {
+            for (z, block) in line.enumerated() {
+                if block == .wall {
+                    addBlock(toScene: scene, at: (x, z))
+                } else if block == .blank {
+                    //addPointObject(toScene: scene, at: (x, z))
+                }
+            }
+        }
+    }
+    
+    private func addBlock(toScene scene: SCNScene, at point: (x: Int, z: Int)) {
+        let box = SCNBox(width: 5, height: 2, length: 5, chamferRadius: 0)
+        let node = SCNNode(geometry: box)
+        node.physicsBody = SCNPhysicsBody(type: .static, shape: SCNPhysicsShape(geometry: box, options: nil))
+        node.physicsBody?.categoryBitMask = GameViewController.wallCollision
+        node.physicsBody?.contactTestBitMask = GameViewController.pacmanCollision
+        node.position = SCNVector3(x: Float(point.x * 5), y: 1, z: Float(point.z * 5))
+        node.name = "\(point.x) \(point.z)"
+        scene.rootNode.addChildNode(node)
+    }
+    
+    private func addPointObject(toScene scene: SCNScene, at point: (x: Int, z: Int)) {
+        let shere = SCNSphere(radius: 0.5)
+        shere.firstMaterial?.diffuse.contents = UIColor.blue
+        let node = SCNNode(geometry: shere)
+        node.physicsBody = SCNPhysicsBody(type: .static, shape: nil)
+        node.physicsBody?.categoryBitMask = GameViewController.pointsCollision
+        node.physicsBody?.contactTestBitMask = GameViewController.pacmanCollision
+        node.name = "Point"
+        node.position = SCNVector3(x: Float(point.x * 5), y: 1, z:Float(point.z * 5))
+        scene.rootNode.addChildNode(node)
+    }
+    
     func nextFreeSpace() -> (x: Int, z: Int) {
         while true {
             let x = Int(arc4random_uniform(UInt32(data.count)))
diff --git a/Pacman3D-iOS/MotionInput.swift b/Pacman3D-iOS/MotionInput.swift
new file mode 100644
index 0000000..822bdaf
--- /dev/null
+++ b/Pacman3D-iOS/MotionInput.swift
@@ -0,0 +1,47 @@
+//
+//  MotionInput.swift
+//  Pacman3D-iOS
+//
+//  Created by Tobias on 09.07.17.
+//  Copyright © 2017 Tobias. All rights reserved.
+//
+
+import Foundation
+import CoreMotion
+import SceneKit
+
+class MotionInput {
+    
+    private let gameScene: GameViewController
+    private var isRotating = false
+    
+    init(gameScene: GameViewController) {
+        self.gameScene = gameScene
+    }
+    
+    func handleMotionInput(data: CMAccelerometerData?, error: Error?) -> Swift.Void {
+        let rotate = data!.acceleration.y
+        //print(rotate)
+        let pacman = gameScene.scene.rootNode.childNode(withName: "Pacman", recursively: true)!
+        let direction: Float = rotate < 0 ? 1.0 : -1.0
+        if abs(rotate) > 0.3 {
+            if !self.isRotating {
+                let action = SCNAction.rotateBy(x: 0, y: CGFloat(direction * Float.pi * 0.5), z: 0, duration: 0.25)
+                pacman.runAction(action, completionHandler: nil)
+                self.isRotating = true
+                
+                var directionVal = gameScene.player.direction.rawValue - Int(direction)
+                if directionVal == 5 {
+                    directionVal = 1
+                }
+                if directionVal == 0 {
+                    directionVal = 4
+                }
+                gameScene.player.direction = Direction(rawValue: directionVal)!
+            }
+        } else {
+            self.isRotating = false
+        }
+
+    }
+}
diff --git a/Pacman3D-iOS/Player.swift b/Pacman3D-iOS/Player.swift
index 68af9fd..b85151f 100644
--- a/Pacman3D-iOS/Player.swift
+++ b/Pacman3D-iOS/Player.swift
@@ -7,9 +7,75 @@
 //
 
 import Foundation
+import SceneKit
 
 class Player {
     
     var points: Int = 0
     var life: Int = 3
+    
+    private let level: Level
+    
+    private let node: SCNNode
+    
+    var direction: Direction = .north
+    var position: SCNVector3
+    
+    init(node: SCNNode, scene: SCNScene, level: Level) {
+        self.node = node
+        self.position = node.position
+        self.level = level
+        
+        let pacmanBox = SCNBox(width: 5, height: 2, length: 5, chamferRadius: 0)
+        pacmanBox.firstMaterial?.diffuse.contents = UIColor.clear
+        let boxNode = SCNNode(geometry: pacmanBox)
+        node.addChildNode(boxNode)
+        node.physicsBody = SCNPhysicsBody(type: .kinematic, shape: SCNPhysicsShape(geometry: pacmanBox, options: nil))
+        node.physicsBody?.categoryBitMask = GameViewController.pacmanCollision
+        node.physicsBody?.contactTestBitMask = GameViewController.wallCollision
+        node.physicsBody?.isAffectedByGravity = false
+    }
+    
+    func move() {
+        print("\(direction)\t\(findFreeSpaces())")
+        if !findFreeSpaces().contains(direction) {
+            return
+        }
+        
+        if direction == .north {
+            position.x += 5
+        } else if direction == .east {
+            position.z += 5
+        } else if direction == .south {
+            position.x -= 5
+        } else if direction == .west {
+            position.z -= 5
+        }
+        let action = SCNAction.move(to: position, duration: 0.25)
+        node.runAction(action, completionHandler: nil)
+    }
+    
+    private func findFreeSpaces() -> [Direction] {
+        var directions: [Direction] = []
+        
+        let x: Int = Int(position.x / 5)
+        let z: Int = Int(position.z / 5)
+        
+        print("\(x) \(z)")
+        
+        if level.data[x - 1][z] == .blank {
+            directions.append(.south)
+        }
+        if level.data[x][z - 1] == .blank {
+            directions.append(.west)
+        }
+        if level.data[x + 1][z] == .blank {
+            directions.append(.north)
+        }
+        if level.data[x][z + 1] == .blank {
+            directions.append(.east)
+        }
+        
+        return directions
+    }
 }
diff --git a/Pacman3D-iOS/TouchInputHandler.swift b/Pacman3D-iOS/TouchInputHandler.swift
new file mode 100644
index 0000000..0927f2d
--- /dev/null
+++ b/Pacman3D-iOS/TouchInputHandler.swift
@@ -0,0 +1,25 @@
+//
+//  InputHandler.swift
+//  Pacman3D-iOS
+//
+//  Created by Tobias on 09.07.17.
+//  Copyright © 2017 Tobias. All rights reserved.
+//
+
+import UIKit
+import UIKit.UIGestureRecognizerSubclass
+
+import SceneKit
+
+class TouchInputHandler: UIGestureRecognizer {
+    
+    var isTouchDown: Bool = false
+    
+    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
+        self.isTouchDown = true
+    }
+    
+    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
+        self.isTouchDown = false
+    }
+}
-- 
GitLab