Background music not working when physicsWorld added - swift

This is my code. The music is not playing for some reason and it started when I added my physicsWorld function. I already checked my sound mp3 file and it seems to be working. I even ran a previous version (same but without the physicsWorld stuff) and the music works perfectly. I'm not sure why this is happening... Your help would be greatly appreciated :)
import UIKit
import QuartzCore
import SceneKit
var ballNode = SCNNode()
var floorNode = SCNNode()
class GameViewController: UIViewController, SCNPhysicsContactDelegate {
let categoryFloor = 2
var scene: SCNScene!
override func viewDidLoad() {
super.viewDidLoad()
scene = SCNScene(named: "art.scnassets/main.scn")!
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = .ambient
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
scene.rootNode.addChildNode(lightNode)
let ball = scene.rootNode.childNode(withName: "ball", recursively: true)!
ballNode = scene.rootNode.childNode(withName: "ball", recursively: true)!
ballNode.physicsBody = SCNPhysicsBody.dynamic()
ballNode.physicsBody!.contactTestBitMask = 1
floorNode = scene.rootNode.childNode(withName: "floor", recursively: true)!
floorNode.physicsBody = SCNPhysicsBody.static()
floorNode.physicsBody!.contactTestBitMask = 1
scene.rootNode.addChildNode(ballNode)
scene.rootNode.addChildNode(floorNode)
let camera = scene.rootNode.childNode(withName: "camera", recursively: true)!
ball.runAction(SCNAction.repeatForever(SCNAction.moveBy(x: 0, y: 0, z: 10, duration: 1)))
camera.runAction(SCNAction.repeatForever(SCNAction.moveBy(x: 0, y: 0, z: 10, duration: 1)))
let scnView = self.view as! SCNView
scnView.scene = scene
scnView.scene?.physicsWorld.contactDelegate = self
scnView.allowsCameraControl = false
scnView.showsStatistics = true
if let source = SCNAudioSource(fileNamed: "art.scnassets/gameMusic.mp3") {
let action = SCNAction.playAudio(source, waitForCompletion: false)
ball.runAction(action)
} else {
print("cannot find file")
}
addSwipeGestureRecognizers()
}
func addSwipeGestureRecognizers() {
let gestureDirections: [UISwipeGestureRecognizerDirection] = [.right, .left, .up, .down]
for gestureDirection in gestureDirections {
let gestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector((handleSwipe)))
gestureRecognizer.direction = gestureDirection
self.view?.addGestureRecognizer(gestureRecognizer)
}
}
func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
if (contact.nodeA == ballNode || contact.nodeA == floorNode) && (contact.nodeB == ballNode || contact.nodeB == floorNode) {
ballNode.removeFromParentNode()
}
}
#objc func handleSwipe(gesture:UIGestureRecognizer) {
let jumpUpAction = SCNAction.moveBy(x: 0, y: 10, z: 0, duration: 0.2)
let jumpDownAction = SCNAction.moveBy(x: 0, y: -10, z: 0, duration: 0.2)
let up = SCNAction.sequence([jumpUpAction, jumpDownAction])
let right = SCNAction.moveBy(x: -10, y: 0, z: 0, duration: 0.2)
let left = SCNAction.moveBy(x: 10, y: 0, z: 0, duration: 0.2)
let down = SCNAction.moveBy(x: 0, y: 0, z: 0, duration: 0.2)
if let gesture = gesture as? UISwipeGestureRecognizer{
switch gesture.direction {
case .up:
ballNode.runAction(up)
case .right:
ballNode.runAction(right)
case .left:
ballNode.runAction(left)
case .down:
ballNode.runAction(down)
default:
print("No Swipe")
}
}
}
override var shouldAutorotate: Bool {
return false
}
override var prefersStatusBarHidden: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

Related

Trying to load images from the assets folder in xcode into an array but having hard time

import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate{
var picsArray = [String]()
var scoreLabel: SKLabelNode!
var editLabel: SKLabelNode!
var editingMode = false{
didSet{
if editingMode{
editLabel.text = "Done"
}
else{
editLabel.text = "Edit"
}
}
}
var score = 0 {
didSet{
scoreLabel.text = " score: \(score)"
}
}
override func didMove(to view: SKView) {
let fm = FileManager.default
let path = Bundle.main.resourcePath!
let items = try! fm.contentsOfDirectory(atPath: path)
for item in items {
if item.hasPrefix("ball"){
picsArray.append(item)
}
print(picsArray.count)
}
physicsWorld.contactDelegate = self
let background = SKSpriteNode(imageNamed: "background")
background.position = CGPoint(x: 512, y: 384)
background.blendMode = .replace
background.zPosition = -1
addChild(background)
scoreLabel = SKLabelNode(fontNamed: "chalkduster")
scoreLabel.text = "Score: 0"
scoreLabel.horizontalAlignmentMode = .right
scoreLabel.position = CGPoint(x: 980, y: 700)
addChild(scoreLabel)
editLabel = SKLabelNode(fontNamed: "chalkduster")
editLabel.text = "Edit"
editLabel.position = CGPoint(x: 80, y: 700)
addChild(editLabel)
physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
makeSlots(at: CGPoint(x: 128, y: 0), isGood: true)
makeSlots(at: CGPoint(x: 384, y: 0), isGood: false)
makeSlots(at: CGPoint(x: 640, y: 0), isGood: true)
makeSlots(at: CGPoint(x: 896, y: 0), isGood: false)
makeBouncer(at: CGPoint(x: 0, y: 0))
makeBouncer(at: CGPoint(x: 256, y: 0))
makeBouncer(at: CGPoint(x: 512, y: 0))
makeBouncer(at: CGPoint(x: 768, y: 0))
makeBouncer(at: CGPoint(x: 1024, y: 0))
// Get label node from scene and store it for use later
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else{return}
let location = touch.location(in: self)
let objects = nodes(at: location)
if objects.contains(editLabel){
editingMode.toggle()
}
else{
if editingMode{
let size = CGSize(width: Int.random(in: 16...128), height: 16)
let box = SKSpriteNode(color: UIColor(red: CGFloat.random(in: 0...1), green: CGFloat.random(in: 0...1), blue: CGFloat.random(in: 0...1), alpha: 1), size: size)
box.zRotation = CGFloat.random(in: 0...3)
box.position = location
box.physicsBody = SKPhysicsBody(rectangleOf: box.size)
box.physicsBody?.isDynamic = false
addChild(box)
}
else{
let ball = SKSpriteNode(imageNamed: "ballRed")
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width/2.0)
ball.physicsBody?.restitution = 0.4
ball.physicsBody?.contactTestBitMask = ball.physicsBody?.collisionBitMask ?? 0
ball.position = location
ball.name = "ball"
addChild(ball)
}
}
}
func makeBouncer(at position: CGPoint){
let bouncer = SKSpriteNode(imageNamed: "bouncer")
bouncer.position = position
bouncer.physicsBody = SKPhysicsBody(circleOfRadius: bouncer.size.width/2)
bouncer.physicsBody?.isDynamic = false
addChild(bouncer)
}
func makeSlots(at position: CGPoint, isGood: Bool){
var slotBase: SKSpriteNode
var slotGlow: SKSpriteNode
if isGood{
slotBase = SKSpriteNode(imageNamed: "slotBaseGood")
slotGlow = SKSpriteNode(imageNamed: "slotGlowGood")
slotBase.name = "good"
} else{
slotBase = SKSpriteNode(imageNamed: "slotBaseBad")
slotGlow = SKSpriteNode(imageNamed: "slotGlowBad")
slotBase.name = "bad"
}
slotGlow.position = position
slotBase.position = position
slotBase.physicsBody = SKPhysicsBody(rectangleOf: slotBase.size)
slotBase.physicsBody?.isDynamic = false
addChild(slotGlow)
addChild(slotBase)
let spin = SKAction.rotate(byAngle: .pi, duration: 1)
let spinforever = SKAction.repeatForever(spin)
slotGlow.run(spinforever)
}
func collision(between ball: SKNode, object: SKNode){
if object.name == "good"{
destroy(ball: ball)
score+=1
}
else{
if object.name == "bad"{
destroy(ball: ball)
score-=1
}
}
}
func destroy(ball: SKNode){
ball.removeFromParent()
}
func didBegin(_ contact: SKPhysicsContact) {
guard let nodeA = contact.bodyA.node else{return}
guard let nodeB = contact.bodyB.node else{return}
if nodeA.name == "ball"{
collision(between: nodeA, object: nodeB)
}
else if nodeB.name == "ball"{
collision(between: nodeB, object: nodeA)
}
}
}

Room texture isn't fully rendered when I move SCNCamera around SCNBox inside the virtual room using SceneKit

I have tried to create a virtual room using SceneKit and put into it a box.
Also I have created a separate node with camera called ‘cameraOrbitNode’ (camera locates between the wall of room and the box). The main goal is to move ‘cameraOrbitNode’ around the box inside the room. I implemented it via pan gesture recognizer.
import UIKit
import SceneKit
enum WallType {
case left
case right
case top
case bottom
case forward
case back
}
class ViewController: UIViewController {
//MARK: - Outlets
#IBOutlet fileprivate weak var sceneView: SCNView!
//MARK: - Properties
fileprivate let roomLength: CGFloat = 12
fileprivate let cubeLength: CGFloat = 1
fileprivate var cameraOrbitNode: SCNNode?
fileprivate let panModifier: CGFloat = 100
//MARK: - Life cycle
override func viewDidLoad() {
super.viewDidLoad()
setupSceneView()
setupRoom()
setupCameraOrbitNode()
setupGestures()
}
func setupSceneView() {
sceneView.scene = SCNScene()
sceneView.autoenablesDefaultLighting = true
}
func setupRoom() {
let roomNode = SCNNode()
roomNode.position = SCNVector3(0, 0, 0)
for wallType in Array<WallType>([.left, .right, .top, .bottom, .forward, .back]) {
roomNode.addChildNode(getWallNodeWith(wallType: wallType))
}
roomNode.addChildNode(getCubeNode())
sceneView.scene?.rootNode.addChildNode(roomNode)
}
func getWallNodeWith(wallType: WallType) -> SCNNode {
let wallGeometrySize = getWallSize()
let wallGeometry = SCNPlane(width: wallGeometrySize.width, height: wallGeometrySize.height)
wallGeometry.firstMaterial?.diffuse.contents = UIColor.darkGray
let wallNode = SCNNode(geometry: wallGeometry)
wallNode.position = getWallPositionWith(wallType: wallType)
wallNode.eulerAngles = getWallEulerAnglesWith(wallType: wallType)
return wallNode
}
func getWallSize() -> CGSize {
return CGSize(width: roomLength, height: roomLength)
}
func getWallPositionWith(wallType: WallType) -> SCNVector3 {
switch wallType {
case .left:
return SCNVector3(-roomLength / 2, 0, 0)
case .right:
return SCNVector3(roomLength / 2, 0, 0)
case .forward:
return SCNVector3(0, 0, -roomLength / 2)
case .back:
return SCNVector3(0, 0, roomLength / 2)
case .top:
return SCNVector3(0, roomLength / 2, 0)
case .bottom:
return SCNVector3(0, -roomLength / 2, 0)
}
}
func getWallEulerAnglesWith(wallType: WallType) -> SCNVector3 {
switch wallType {
case .left, .right:
return SCNVector3(0, CGFloat.pi / 2, 0)
case .forward, .back:
return SCNVector3(0, 0, 0)
case .top, .bottom:
return SCNVector3(CGFloat.pi / 2, 0, 0)
}
}
func getCubeNode() -> SCNNode {
let cubeGeometry = SCNBox(width: cubeLength, height: cubeLength, length: cubeLength, chamferRadius: 0)
cubeGeometry.firstMaterial?.diffuse.contents = UIColor.blue
let cubeNode = SCNNode(geometry: cubeGeometry)
cubeNode.position = SCNVector3(0, 0, 0)
return cubeNode
}
func setupCameraOrbitNode() {
let camera = SCNCamera()
camera.zNear = 0
camera.zFar = Double(roomLength)
let cameraNode = SCNNode()
cameraNode.position = SCNVector3(0, 0, (roomLength + cubeLength) / 4)
cameraNode.camera = camera
cameraOrbitNode = SCNNode()
guard let cameraOrbitNode = cameraOrbitNode else { return }
cameraOrbitNode.addChildNode(cameraNode)
cameraOrbitNode.position = SCNVector3(0, 0, 0)
sceneView.scene?.rootNode.addChildNode(cameraOrbitNode)
}
#objc func actionPan(gesture: UIPanGestureRecognizer) {
let translation = gesture.velocity(in: gesture.view)
cameraOrbitNode?.eulerAngles.y -= Float(translation.x/CGFloat(panModifier)) * .pi / 180
cameraOrbitNode?.eulerAngles.x -= Float(translation.y/CGFloat(panModifier)) * .pi / 180
}
func setupGestures() {
sceneView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(actionPan(gesture:))))
}
}
But in some cases you can see transparent walls of the room (basically room texture isn't fully rendered when I move the camera around the box). I was changing some camera properties (zNear, zFar) but nothing helped. Please see the links on images attached below. Thanks a lot for any help.
https://www.dropbox.com/s/ihxjrsgjfzidoff/IMG_0187.PNG?dl=0
https://www.dropbox.com/s/wd23xepcir3wggk/IMG_0188.PNG?dl=0
set isDoubleSdided to true
node.geometry?.firstMaterial?.isDoubleSided = true

How to make shape not to go to GameOver? -SpriteKit

I am creating a game where there is a square shape and every time the player taps on the square, it goes to GameOver scene. All I want to do is when the square shape is tapped, it will be allotted different position of the screen to be tapped on the squares.
Here is my code:
let touch:UITouch = touches.first!
let positionInScene = touch.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if let name = touchedNode.name
{
//The first ball that shows up
if name == "startball"
{
print("Touched", terminator: "")
addBall(ballSize)
self.addChild(score)
}
else if name == "shape"{
scoreCount += 1
addBall(ballSize)
audioPlayer.play()
}
}
else {
let scene = GameOver(size: self.size)
scene.setMyScore(0)
let skView = self.view! as SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .resizeFill
scene.size = skView.bounds.size
scene.setMessage("You Lost!")
scene.setEndGameMode(va)
gameTimer.invalidate()
shownTimer.invalidate()
print(" timers invalidated ", terminator: "")
ran = true
skView.presentScene(scene, transition: SKTransition.crossFade(withDuration: 0.25))
}
if firstTouch {
shownTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(GameScene.decTimer), userInfo: nil, repeats: true)
gameTimer = Timer.scheduledTimer(timeInterval: TIME_INCREMENT, target:self, selector: Selector("endGame"), userInfo: nil, repeats: false)
firstTouch = false
}
if touchCount > 5 {
for touch: AnyObject in touches {
let skView = self.view! as SKView
skView.ignoresSiblingOrder = true
var scene: Congratz!
scene = Congratz(size: skView.bounds.size)
scene.scaleMode = .aspectFill
skView.presentScene(scene, transition: SKTransition.doorsOpenHorizontal(withDuration: 1.0))
}
}
touchCount += 1
}
override func update(_ currentTime: TimeInterval) {
super.update(currentTime)
}
func endGame(){
shownTimer.invalidate()
gameTimer.invalidate()
let scene = GameOver(size: self.size)
scene.setMyScore(scoreCount)
if let skView = self.view {
skView.ignoresSiblingOrder = false
scene.scaleMode = .resizeFill
scene.size = skView.bounds.size
scene.setMessage("Times up")
skView.presentScene(scene, transition: SKTransition.crossFade(withDuration: 0.25))
}
}
override func addBall(_ size: Int) {
// Add the ball
let currentBall = SKShapeNode(circleOfRadius: CGFloat(size))
let viewMidX = view!.bounds.midX
let viewMidY = view!.bounds.midY
currentBall.fillColor = pickColor()
currentBall.position = randomBallPosition()
if scoreCount != 0{
if scoreCount == 1{
self.addChild(score)
self.addChild(timeLeftLabel)
self.childNode(withName: "welcome")?.removeFromParent()
}
self.childNode(withName: "ball")?.run(getSmaller)
self.childNode(withName: "ball")?.removeFromParent()
}
currentBall.name = "ball"
self.addChild(currentBall)
}
func addSquare(_ size: Int) {
// Add the square
let shape = SKShapeNode(rectOf: CGSize(width:CGFloat(size), height:CGFloat(size)))
shape.path = UIBezierPath(roundedRect: CGRect(x: 64, y: 64, width: 160, height: 160), cornerRadius: 50).cgPath
shape.fillColor = pickColor()
shape.position = randomBallPosition()
shape.name = "shape"
self.addChild(shape)
}
func randomBallPosition() -> CGPoint {
let xPosition = CGFloat(arc4random_uniform(UInt32((view?.bounds.maxX)! + 1)))
let yPosition = CGFloat(arc4random_uniform(UInt32((view?.bounds.maxY)! + 1)))
return CGPoint(x: xPosition, y: yPosition)
}
What I would suggest would be to make something like an enum for the different shapes, so you can keep track of what shape you're using.
enum GameShape: Int {
case circle = 0
case square = 1
}
Then create a GameShape property at the top of your GameScene:
var currentShape: GameShape = .circle
Then you could create some sort of updateShape method, which you could call in your touchesBegan method instead of just addBall
func updateShape(shapeSize: CGSize) {
switch currentShape {
case .circle:
addCircle(shapeSize)
case .square:
addSquare(shapeSize)
default:
break
}
// However you want to setup the condition for changing shape
if (condition) {
currentShape = .square
}
}
func addBall(_ size: CGSize) {
// Add the ball
}
func addSquare(_ size: CGSize) {
// Add the square
}
Now in your touchesBegan method, instead of calling addBall(size, you could call updateShape:
override func touchesBegan(_ touches: Set<UITouch>!, with event: UIEvent?) {
// Setup your code for detecting position for shape origin
updateShape(shapeSize)
}
EDIT - Your code is a mess. You really should take the time to make sure it's properly formatted when you submit it, otherwise it's really hard to help you. Indentation helps to see where a closure begins and ends. From what I can tell, it looks like you have two or more functions nested within your addBall method. This is not good. I tried my best to clean it up for you. You'll still need to write the code to make the shape a square, but I've lead you in the right direction to start to make that happen:
func addBall(_ size: CGSize) {
// Add the ball
let currentBall = SKShapeNode(circleOfRadius: CGFloat(size))
let viewMidX = view!.bounds.midX
let viewMidY = view!.bounds.midY
currentBall.fillColor = pickColor()
shape.path = UIBezierPath(roundedRect: CGRect(x: 64, y: 64, width: 160, height: 160), cornerRadius: 50).cgPath
shape.fillColor = pickColor()
currentBall.position = randomBallPosition()
shape.position = randomBallPosition()
self.addChild(shape)
if scoreCount != 0{
if scoreCount == 1{
self.addChild(score)
self.addChild(timeLeftLabel)
self.childNode(withName: "welcome")?.removeFromParent()
}
self.childNode(withName: "ball")?.run(getSmaller)
self.childNode(withName: "ball")?.removeFromParent()
}
currentBall.name = "ball"
shape.name = "ball"
self.addChild(currentBall)
}
func addSquare(_ size: CGSize) {
// Add the square
}
func randomBallPosition() -> CGPoint {
let xPosition = CGFloat(arc4random_uniform(UInt32((view?.bounds.maxX)! + 1)))
let yPosition = CGFloat(arc4random_uniform(UInt32((view?.bounds.maxY)! + 1)))
return CGPoint(x: xPosition, y: yPosition)
}
Now the above code assumes you have some property named shape because from what I could tell you never explicitly instantiated that, but you begin manipulating it.

Swift Issue with SCNSceneRenderer ---Trouble getting protocol to work

I'm working to implement a Zig Zag game and following a set of instructions from an on-line course. I have a swift UIViewController, and I am trying now to use also SCNSceneRenderer (to do the game logic of keeping the game character on the zig-zag path). The code looks like this:
import UIKit
import QuartzCore
import SceneKit
class GameViewController: UIViewController, SCNSceneRenderer{
let scene = SCNScene()
let cameraNode = SCNNode()
var person = SCNNode()
let firstBox = SCNNode()
var goingLeft = Bool()
var tempBox = SCNNode()
var boxNumber = Int()
var prevBoxNumber = Int()
override func viewDidLoad() {
print("Yes -- view did load")
self.createScene()
}
func renderer(render: SCNSceneRenderer, updateAtTime time: TimeInterval){
let deleteBox = self.scene.rootNode.childNode(withName: "\(prevBoxNumber)", recursively: true )
if (deleteBox?.position.x)! > (person.position.x + 1) || (deleteBox?.position.z)! > (person.position.z + 1) {
prevBoxNumber += 1
deleteBox?.removeFromParentNode()
createBox()
}
}
func createBox(){
tempBox = SCNNode(geometry: firstBox.geometry)
let prevBox = scene.rootNode.childNode(withName: "\(boxNumber)", recursively: true )
boxNumber += 1
tempBox.name = "\(boxNumber)"
let randomNumber = arc4random() % 2
switch randomNumber {
case 0:
tempBox.position = SCNVector3Make((prevBox?.position.x)! - firstBox.scale.x, (prevBox?.position.y)!, (prevBox?.position.z)!)
break
case 1:
tempBox.position = SCNVector3Make((prevBox?.position.x)! , (prevBox?.position.y)!, (prevBox?.position.z)! - firstBox.scale.z)
break
default:
break
}
self.scene.rootNode.addChildNode(tempBox)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if goingLeft == false {
person.removeAllActions()
person.runAction(SCNAction.repeatForever(SCNAction.move(by: SCNVector3Make(-100, 0, 0), duration: 20)))
goingLeft = true
} else {
person.removeAllActions()
person.runAction(SCNAction.repeatForever(SCNAction.move(by: SCNVector3Make(0, 0, -100), duration: 20)))
goingLeft = false
}
print("boxNumber is \(boxNumber)")
}
func createScene(){
boxNumber = 0
prevBoxNumber = 0
self.view.backgroundColor = UIColor.orange
let sceneView = self.view as! SCNView
sceneView.delegate = self
sceneView.scene = scene
//Create Person
let personGeo = SCNSphere(radius: 0.2)
person = SCNNode (geometry : personGeo)
let personMat = SCNMaterial()
personMat.diffuse.contents = UIColor.red
personGeo.materials = [personMat]
person.position = SCNVector3Make(0, 1.1, 0)
scene.rootNode.addChildNode(person)
//Create Camera
cameraNode.camera = SCNCamera()
cameraNode.camera?.usesOrthographicProjection = true
cameraNode.camera?.orthographicScale = 3
cameraNode.position = SCNVector3Make(20,20,20)
cameraNode.eulerAngles = SCNVector3Make(-45,45,0)
//let constraint = SCNLookAtConstraint(target: firstBox)
let constraint = SCNLookAtConstraint(target: person)
constraint.isGimbalLockEnabled = true
self.cameraNode.constraints = [constraint]
scene.rootNode.addChildNode(cameraNode)
person.addChildNode(cameraNode)
//Create Box
let firstBoxGeo = SCNBox(width: 1.0, height: 1.5, length: 1.0, chamferRadius: 0)
firstBox.geometry = firstBoxGeo
let boxMaterial = SCNMaterial()
boxMaterial.diffuse.contents = UIColor(red: 0.2, green: 0.8, blue: 0.9, alpha: 1.0)
firstBoxGeo.materials = [boxMaterial]
firstBox.position = SCNVector3Make(0,0,0)
scene.rootNode.addChildNode(firstBox)
firstBox.name = "\(boxNumber)"
for _ in 0...6{
createBox()
}
//Create light
let light = SCNNode()
light.light = SCNLight()
light.light?.type = SCNLight.LightType.directional
light.eulerAngles = SCNVector3Make(-45, 45, 0)
scene.rootNode.addChildNode(light)
//Create light2
let light2 = SCNNode()
light2.light = SCNLight()
light2.light?.type = SCNLight.LightType.directional
light2.eulerAngles = SCNVector3Make(45, 45, 0)
scene.rootNode.addChildNode(light2)
}
}
When I added SCNSceneRenderer I get the following error:
"Type 'GameViewController' cannot conform to protocol 'SCNSceneRenderer' because it has requirements that cannot be satisfied"
Since my GameViewController isn't recognized as a SCNSceneRenderer, I also get an error at this line:
sceneView.delegate = self
the error is "Cannot assign value of type 'GameViewController' to type 'SCNSceneRendererDelegate'
I'm new to swift programming, but this seems like I am trying to implement an interface like in Java, I've been looking at the Swift documentation but don't see what I need to do to make my class be functional as an SCNSceneRenderer. I would appreciate help to solve this problem. Thanks!

SceneKit Swift 2.0 Collision Detections (SCNPhysicsContactDelegate)

I already build an application with collision detection using delegate SCNPhysicsContactDelegate. Right now I'm using Swift 2.0 and Xcode 7 and I try to detect collision with SCNPhysicsContactDelegate delegate but it doesn't work.
What I'm doing wrong? Below the code:
let CubeType = 1
let PlayerType = 2
class GameViewController: UIViewController, SCNSceneRendererDelegate,SCNPhysicsContactDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let scnView = self.view as! SCNView
scnView.scene = SCNScene()
scnView.scene?.physicsWorld.contactDelegate = self
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(x: 0, y: 0, z: 5)
scnView.scene?.rootNode.addChildNode(cameraNode)
scnView.autoenablesDefaultLighting = true
scnView.allowsCameraControl = true
scnView.showsStatistics = true
scnView.backgroundColor = UIColor.blackColor()
let g = SCNBox(width: 0.5, height: 0.5, length: 0.5, chamferRadius: 0)
let n = SCNNode(geometry: g)
n.physicsBody = SCNPhysicsBody(type: .Kinematic, shape: SCNPhysicsShape(geometry: g, options: nil))
n.physicsBody?.categoryBitMask = CubeType
n.physicsBody?.collisionBitMask = PlayerType
n.position = SCNVector3Make(5, 0, 0)
scnView.scene?.rootNode.addChildNode(n)
let playerGeometry = SCNSphere(radius: 1)
let playerNode = SCNNode(geometry: playerGeometry)
playerNode.position = SCNVector3Zero
playerNode.physicsBody = SCNPhysicsBody(type: .Kinematic, shape: SCNPhysicsShape(geometry: playerGeometry, options:nil))
playerNode.physicsBody?.categoryBitMask = PlayerType
playerNode.physicsBody?.collisionBitMask = CubeType
scnView.scene?.rootNode.addChildNode(playerNode)
let moveAction = SCNAction.moveTo(n.position, duration: 3)
playerNode.runAction(moveAction)
}
func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact) {
print("-> didBeginContact")
}
func physicsWorld(world: SCNPhysicsWorld, didEndContact contact: SCNPhysicsContact) {
print("-> didEndContact")
}
func physicsWorld(world: SCNPhysicsWorld, didUpdateContact contact: SCNPhysicsContact) {
print("-> didupdatecontact")
}
The .contactTestBitMask property is missing for both nodes:
n.physicsBody?.contactTestBitMask = PlayerType
playerNode.physicsBody?.contactTestBitMask = CubeType