I am creating a SpriteKit game which uses the CoreMotion framework to move a SKSpriteNode, userNode
, around the screen. For the scaling, I have set it to ResizeFill, and have used view.frame to store the four bounds of the view in variables:
//setting screens bounds
var rightBound = CGFloat()
var leftBound = CGFloat()
var upperBound = CGFloat()
var bottomBound = CGFloat()
rightBound = view.frame.width - (userNode.size.width / 2)
leftBound = CGRectGetMinX(view.frame) + (userNode.size.width / 2)
upperBound = view.frame.height - (userNode.size.height / 2)
bottomBound = CGRectGetMinY(self.frame) + (userNode.size.height / 2)
To attempt to keep userNode
on screen, I created a function to run in the update function:
func keepUserNodeOnScreen(){
if userNode.position.x >= rightBound{
userNode.position.x = rightBound
}
else if userNode.position.x <= leftBound{
userNode.position.x = leftBound
}
else if userNode.position.y >= upperBound{
userNode.position.y = upperBound
}
else if userNode.position.y <= bottomBound{
userNode.position.y = bottomBound
}
}
For some reason, however, when the node reaches the corners of the view, it falls out of the view. I have also tried self.physicsBody = SKPhysicsBody(edgeLoopFromRect(view.frame))
, but this didn't work either. What could it be that is causing this?
Edit: Here is the userNode generation code:
userNode.color = SKColor.redColor()
userNode.size = CGSizeMake(15, 15)
userNode.position = CGPointMake(view.frame.size.width / 2, view.frame.size.height / 2)
userNode.physicsBody = SKPhysicsBody(rectangleOfSize: userNode.size)
userNode.physicsBody?.dynamic = true
userNode.physicsBody?.allowsRotation = false
userNode.physicsBody?.categoryBitMask = userCategory
userNode.physicsBody?.contactTestBitMask = bulletCategory
self.addChild(userNode)
Here is the code for moving userNode
, set to run in the update function:
func moveUserNode(){
if motionManager.accelerometerAvailable == true{
motionManager.deviceMotionUpdateInterval = 0.001
motionManager.startDeviceMotionUpdatesToQueue(NSOperationQueue.currentQueue(), withHandler:{
deviceManager, error in
if self.gameOn == true{
var roll: CGFloat = CGFloat(self.motionManager.deviceMotion.attitude.roll)
var pitch: CGFloat = CGFloat(-self.motionManager.deviceMotion.attitude.pitch) + CGFloat(0.6)
//Keep userNode on screen
self.newPosition.x = self.userNode.position.x + CGFloat(roll) * 20
self.newPosition.y = self.userNode.position.y + CGFloat(pitch) * 20
self.userNode.position = self.newPosition
}
else if self.gameOn == false{
self.motionManager.stopDeviceMotionUpdates()
}
})
}
}
In
keepUserNodeOnScreen
, yourif/else
statements aren't testing for all the possible waysuserNode
can exit the screen. Deleting all of theelse
statements will resolve this.An alternative approach is to add an edge-loop
and move
userNode
withapplyForce
orapplyImpulse
instead of moving it by changing its position property. SpriteKit does not detect collisions if the node's position is changed, directly.