Noah Covey
Noah Covey

Reputation: 161

Make SKSpriteNode running an action collide with edge of screen

I have an SKSpriteNode which is controlled by the accelerometer to move left and right like so:

var destX = myNode.position.x

override func update(currentTime: CFTimeInterval) {
    if let data = motionManager.accelerometerData {

        let currentX = self.myNode.position.x

        if data.acceleration.x < 0 {
            self.destX = currentX + CGFloat(data.acceleration.x * 2000)
        } else if data.acceleration.x > 0 {
            self.destX = currentX + CGFloat(data.acceleration.x * 2000)
        }
        else if data.acceleration.x == 0 {
            self.destX = currentX
        }
    }
}

Then, also in the update method, I create an SKAction to move the SpriteNode to destX:

if alive {

        let action = SKAction.moveToX(destX, duration: 1)
        self.myNode.runAction(action)

    }

The right - left movement works fine. What I need to do now, though is to make the node so that it can't leave the screen. I tried putting a physics body around the edge of the screen:

self.physicsBody = SKPhysicsBody(edgeLoopFromRect: CGRectMake(0, 0, self.size.width, self.size.height))
self.physicsBody?.categoryBitMask = PhysicsCategory.ScreenEdge

myNode.physicsBody?.collisionBitMask = PhysicsCategory.ScreenEdge

I have the physics bodies themselves running fine, but the reason the collision is not working between the sprite node and the edge of the screen is that the node is running an action, and actions kind of 'override' physics. Is there any way to make the the node stop at the edge of the screen while still keeping the acceleration from the accelerometer's data? I know that currently, destX is a very high or low number, but that is to cause the sprite node to move side to side quickly.

Basically, I need a way to either a) allow collisions even with an SKAction running on the node, or b) make the moveToX action stop when the sprite node gets off the screen, and make it start again once the node is back on the screen.

Thanks!

Upvotes: 0

Views: 523

Answers (1)

Pro Blaster
Pro Blaster

Reputation: 491

Maybe this can help:
(sorry for the Objective C, I am not a swift programmer but will still try to explain how you could do this in your own language)

-(BOOL)isNode:(*SKnode)theNode outOfScene:(*SKScene)theScene
{
BOOL isIt = NO;
if (theNode.position.x > theScene.frame.size.width + (theNode.frame.size.width / 2)){isIt = YES;}
if (theNode.position.x < -(theNode.frame.size.width / 2)){isIt = YES;}
if (theNode.position.y > theScene.frame.size.height + (theNode.frame.size.height / 2)){isIt = YES;}
if (theNode.position.y < -(theNode.frame.size.height / 2)){isIt = YES;}
return isIt;
}

Here is how it works

-(BOOL)isNode:(*SKnode)theNode outOfScene:(*SKScene)theScene new funtion,
input variables are: theNode a node, and theScene the scene to see if it is in in the bounds of.

BOOL isIt = NO; creates a new Boolean variable, it's default value is NO

if (theNode.position.x > theScene.frame.size.width){isIt = YES;}
if (theNode.position.x < 0){isIt = YES;}
if (theNode.position.y > theScene.frame.size.height){isIt = YES;}
if (theNode.position.y < 0){isIt = YES;}

check to see if theNode is not within theScene's visible bounds.
Sets isIt to Yes if it is out of theScene's bounds.
This assumes that theNode's orientation is (0,0) -if you do not know what this means than you should probably ignore it.


return isIt return isIt to the sender (thing who 'called' the function)


That is how it is.

Note: This code has not been tested, please leave a comment if it is faulty.


Edit: if theNode is not a child of theScene you may have to convert the position of theNode's coordinate space to that of theScene.

Upvotes: 1

Related Questions