SKSpriteNode ignoring physics deactivation - ios

I have a node which is placed under my screen and works as a platform. As soon as another node touches the node a boolean is set to NO.
When I define my node with the SKPhysicsBody properties for the collision the node ignores the affectedByGravity property.
My code:
+ (void)addNewNodeTo:(SKNode *)parentNode
{
//Correct image size
SKSpriteNode *desertBottom = [SKSpriteNode node];
desertBottom = [[SKSpriteNode alloc] initWithImageNamed:#"Giraffe.png"];
desertBottom.position = CGPointMake(0, -200);
desertBottom.zPosition = 2;
desertBottom.physicsBody.collisionBitMask = lionType;
desertBottom.physicsBody.categoryBitMask = terrainType;
desertBottom.physicsBody.contactTestBitMask = lionType;
desertBottom.zPosition = 2;
desertBottom.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(desertBottom.size.width, desertBottom.size.height)];
desertBottom.physicsBody.dynamic = YES;
desertBottom.physicsBody.affectedByGravity = NO;
[parentNode addChild:desertBottom];
}
My collision methods:
- (void)didBeginContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (lionType | terrainType)) {
self.lionNode.lionIsJumping = NO;
NSLog(#"%i", self.lionNode.lionIsJumping);
}
}
- (void)didEndContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (lionType | terrainType)) {
self.lionNode.lionIsJumping = YES;
NSLog(#"%i", self.lionNode.lionIsJumping);
}
}

A physics body has a velocity. Gravity changes velocity over time. If the body is already traveling at a certain velocity due to gravity, and you disable gravity, it will continue to move according to its current velocity but no longer gain additional speed from gravity.
My guess is that you expect the body to stop when disabling gravity. If that's what you want you can do this manually by setting the y component of velocity to zero:
SKPhysicsBody* body = desertBottom.physicsBody;
body.velocity = CGVectorMake(body.velocity.x, 0.0);

If the platform should not move after a collision you have to set the dynamic property to false.
Maybe you have an issue with you bit masks?
Have you tried to log outside your if statement of the didBeginContact method?

I have created a new class with subclass of SKSpriteNode for the bottom and added it to my GameScene.

Related

How can one make only one side of a physics body active in SpriteKit?

I have a hero, ground and a table. I want to make a table-top active for collision and contact with hero. But hero should be able not to jump on the top and just run "through" and jump on it, if player wants it, wherever he wants. For better example of what i'm trying to achieve - think about Mario. When you are running on ground, some sky platforms appearing. You could jump on it in the middle of a platform and stay there. So I need physics body to not stop hero when he is contacting it from the bottom, but hold him if he is on top of it.
By now i'm using body with texture for table:
self.table.physicsBody = SKPhysicsBody(texture:table.texture, size:self.table.size)
self.table.physicsBody?.dynamic = false
self.table.physicsBody?.categoryBitMask = ColliderType.Table.rawValue
self.table.physicsBody?.contactTestBitMask = ColliderType.Hero.rawValue
self.table.physicsBody?.collisionBitMask = ColliderType.Hero.rawValue
It obviously, is not working. How can I implement such a thing?
The answer to this question is actually not too difficult but the implementation into a full fledged game will be much more difficult for you. This is not something for a novice programmer to start out with.
First the same code project (tap/click on screen to jump up):
#import "GameScene.h"
typedef NS_OPTIONS(uint32_t, Level1PhysicsCategory) {
CategoryPlayer = 1 << 0,
CategoryFloor0 = 1 << 1,
CategoryFloor1 = 1 << 2,
};
#implementation GameScene {
int playerFloorLevel;
SKSpriteNode *node0;
SKSpriteNode *node1;
SKSpriteNode *node2;
}
-(void)didMoveToView:(SKView *)view {
self.backgroundColor = [SKColor whiteColor];
node0 = [SKSpriteNode spriteNodeWithColor:[SKColor grayColor] size:CGSizeMake(400, 10)];
node0.position = CGPointMake(300, 200);
node0.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:node0.size];
node0.physicsBody.dynamic = NO;
node0.physicsBody.categoryBitMask = CategoryFloor0;
node0.physicsBody.collisionBitMask = CategoryPlayer;
[self addChild:node0];
node1 = [SKSpriteNode spriteNodeWithColor:[SKColor grayColor] size:CGSizeMake(400, 10)];
node1.position = CGPointMake(300, 300);
node1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:node1.size];
node1.physicsBody.dynamic = NO;
node1.physicsBody.categoryBitMask = CategoryFloor1;
node1.physicsBody.collisionBitMask = CategoryPlayer;
[self addChild:node1];
node2 = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(50, 50)];
node2.position = CGPointMake(300, 250);
node2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:node2.size];
node2.physicsBody.categoryBitMask = CategoryPlayer;
node2.physicsBody.collisionBitMask = CategoryFloor0;
[self addChild:node2];
playerFloorLevel = 0;
}
-(void)update:(CFTimeInterval)currentTime {
if(((node2.position.y-25) > (node1.position.y+10)) && (playerFloorLevel == 0)) {
node2.physicsBody.collisionBitMask = CategoryFloor0 | CategoryFloor1;
playerFloorLevel = 1;
}
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInNode:self];
//SKNode *node = [self nodeAtPoint:touchLocation];
// change 75 value to 50 to see player jump half way up through floor 1
[node2.physicsBody applyImpulse:CGVectorMake(0, 75)];
}
}
The gist of the code is the player node (node2) has to keep checking its y position (update method) in relation to the other floors. In the example, the player jumps up through floor1. Once the player is higher than floor1, the player node's physics body modifies its collision bit mask to include floor1.
Sounds easy enough. However, in a real game you will have a large number of floors and all floors might not be evenly spaced y distances. You have to keep all that in mind when coding.
I am not sure how your platforms looks like (edge based or volume based bodies) but you can consider some of these:
1. Checking positions
Check if the hero's position.y is beneath/above the platform and ignore/handle the collision.
2. Checking velocity
Or to check if player node if falling, which is indicated by a negative velocity.dy value.
I can't say if any of these can fully help you with your game or is it possible with your setup, but you can get some basic idea on where to start.
Enabling/disabling collisions can be done by changing player's and platform's collision bitmasks. If possible try to avoid tracking states like isInTheAir, isOnPlatform, isFaling, isJumping and similar because it can become messy as number of states grows. For example, instead of adding custom boolean variable called "isFalling" and constantly maintaining its state, you can check if velocity.dy is negative to see if player is falling.
I tried changing the platforms collision bitmask but wasn't working fine. I found a different solution.
Inside the update() function you can check the following
if player.physicsBody?.velocity.dy <= 0 {
player.physicsBody?.collisionBitMask = PhysicsCategory.Platform
} else {
player.physicsBody?.collisionBitMask = PhysicsCategory.None
}
In this way, every time the player is going up, it can pass through rocks, and every time it is falling, it can stand.
Using swift you can create a sprite node subclass like this:
class TableNode: SKSpriteNode {
var isBodyActivated: Bool = false {
didSet {
physicsBody = isBodyActivated ? activatedBody : nil
}
}
private var activatedBody: SKPhysicsBody?
init(texture: SKTexture) {
super.init(texture: texture, color: SKColor.clearColor(), size: texture.size())
// physics body setup. Assuming anchorPoint = (0.5, 0.5)
let bodyInitialPoint = CGPoint(x: -size.width/2, y: +size.height/2)
let bodyEndPoint = CGPoint(x: +size.width/2, y: +size.height/2)
activatedBody = SKPhysicsBody(edgeFromPoint: bodyInitialPoint, toPoint: bodyEndPoint)
activatedBody!.categoryBitMask = ColliderType.Table.rawValue
activatedBody!.collisionBitMask = ColliderType.Hero.rawValue
physicsBody = isBodyActivated ? activatedBody : nil
name = "tableNode"
}
}
Then, update all tableNodes in the gameScene:
override func didSimulatePhysics() {
self.enumerateChildNodesWithName("tableNode") {
node, stop in
if let tableNode = node as? TableNode {
// Assuming anchorPoint = (0.5, 0.5) for table and hero
let tableY = tableNode.position.y + tableNode.size.height/2
let heroY = hero.position.y - hero.size.height/2
tableNode.isBodyActivated = heroY > tableY
}
}
}

Sprite Kit - Make SKPhysicsBody with restitution only on sides

I am trying to create a complex SKPhysicsBody that does not bounce on the top, but does allow bouncing on the sides and bottom. Currently I am creating two nodes. One that has the image of the Sprite and a no restitution PhysicsBody on the top.
My second node matches the first node, but is clear with the same size as the first node It just has a PhysicsBody on the front and bottom and has a restitution. to allow my main character to bounce off the bottom and front.
Here is the code for my current setup:
//This is the top part.
- (void)nodePhysicsBodySetup:(SKSpriteNode *)node
{
CGPoint topStart = CGPointMake(0, node.size.height);
CGPoint topEnd = CGPointMake(node.size.width, node.size.height);
SKPhysicsBody *topEdge = [SKPhysicsBody bodyWithEdgeFromPoint:topStart toPoint:topEnd];
node.physicsBody = topEdge;
//[SKPhysicsBody bodyWithBodies:#[topEdge, frontEdge, bottomEdge]]
//node.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:node.frame.size];
node.physicsBody.dynamic = NO;
node.physicsBody.restitution = 0.0;
node.physicsBody.affectedByGravity = NO;
node.physicsBody.categoryBitMask = groundCategory;
node.physicsBody.collisionBitMask = mainHeroCategory;
node.physicsBody.contactTestBitMask = mainHeroCategory;
}
//This is the bottom physicsbody that matches up with the image of the main node.
- (void)bottomNodePhysicsBodySetup:(SKSpriteNode *)node
{
CGPoint topStart = CGPointMake(0, node.size.height);
CGPoint frontEnd = CGPointMake(0,0);
CGPoint bottomEnd = CGPointMake(node.size.width,0);
SKPhysicsBody *frontEdge = [SKPhysicsBody bodyWithEdgeFromPoint:topStart toPoint:frontEnd];
SKPhysicsBody *bottomEdge = [SKPhysicsBody bodyWithEdgeFromPoint:frontEnd toPoint:bottomEnd];
bottomNode.physicsBody = [SKPhysicsBody bodyWithBodies:#[frontEdge, bottomEdge]];
bottomNode.physicsBody.dynamic = NO;
bottomNode.physicsBody.affectedByGravity = NO;
bottomNode.physicsBody.restitution = 0.5;
bottomNode.physicsBody.categoryBitMask = otherCategory;
bottomNode.physicsBody.collisionBitMask = mainHeroCategory;
bottomNode.physicsBody.contactTestBitMask = mainHeroCategory;
}
Picture as screenshots are under NDA:
Currently, the Green PhysicsBody is attached to the node, and the red PhysicsBody is attached to a transparent second node with the same position as the first node.
This does not really work. My main character (mainHeroCategory) gets stuck sometimes on the node corner where the PhysicsBody with restitution and the one without meet. What is a better way to do this?
I would try to do this using only one physics body and look at the contact delegate methods to determine where the contact occurred and what the normal vector is (that information is in the SKPhysicsContact object passed in the delegate method).
Once I got that information I would apply an impulse to the mainHeroCategory object, or not, depending on where the contact occurred.
I suggest you join the physics bodies with an SKPhysicsJointFixed or by constraining the bodies with an SKConstraint or two. SpriteKit only uses the shape when merging two or more bodies with bodyWithBodies. From the docs...
The properties on the children, such as mass or friction, are ignored.
Only the shapes of the child bodies are used.
The restitution property is ignored.

How to have my character "ride" along with moving platforms?

Im experiencing a problem with my Hero Character, when he lands on a moving platform, rather then moving along with it, he literally stands on the same X position until the platform moves offscreen. I searched many answers with no avail.
Here is my methods for my hero character and the moving platforms.
-(void)HeroAdd
{
_Hero = [SKSpriteNode spriteNodeWithImageNamed:#"Hero-1"];
_Hero.name = #"Daniel";
_Hero.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_Hero.size];
_Hero.physicsBody.categoryBitMask = fPlayerCategory;
_Hero.physicsBody.contactTestBitMask = fPlatformCategory | fEnemyCategory;
_Hero.physicsBody.usesPreciseCollisionDetection = YES;
_Hero.physicsBody.affectedByGravity = YES;
_Hero.physicsBody.dynamic = YES;
_Hero.physicsBody.friction = .9;
_Hero.physicsBody.restitution = 0;
_Hero.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
_Hero.position = CGPointMake(_Hero.position.x - 252, _Hero.position.y + 50);
if (self.size.width == 480) {
_Hero.position = CGPointMake(_Hero.position.x + 44, _Hero.position.y);
}
[self addChild:_Hero];
}
My moving platform code
-(void)createPlatform {
SKTexture *objectTexture;
switch (arc4random_uniform(2)) {
case (0):
objectTexture = [SKTexture textureWithImageNamed:#"shortPlatform"];
break;
case (1):
objectTexture = [SKTexture textureWithImageNamed:#"highPlatform"];
default:
break;
}
SKSpriteNode *variaPlatform = [SKSpriteNode spriteNodeWithTexture:objectTexture];
variaPlatform.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
variaPlatform.position = CGPointMake(variaPlatform.position.x + 500, variaPlatform.position.y - 140);
variaPlatform.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:variaPlatform.size];
variaPlatform.physicsBody.usesPreciseCollisionDetection = YES;
variaPlatform.physicsBody.categoryBitMask = fPlatformCategory;
variaPlatform.physicsBody.contactTestBitMask = fPlatformCategory |fPlayerCategory | fEnemyCategory;
variaPlatform.physicsBody.dynamic = NO;
variaPlatform.physicsBody.affectedByGravity = NO;
SKAction *moveLeft = [SKAction moveTo:CGPointMake(180, variaPlatform.position.y) duration:3];
SKAction *moveDown = [SKAction moveTo:CGPointMake(180, -700) duration:4];
SKAction *removeFromParent = [SKAction removeFromParent];
SKAction *AllThree = [SKAction sequence:#[moveLeft, moveDown, removeFromParent]];
[self addChild:variaPlatform];
[variaPlatform runAction:AllThree];
}
Any type of information would be truly appreciated.
I ran into the same issue when I added conveyer belts into a game. Sprite Kit does not drag objects no matter how much resistance is added. You currently have 2 options.
Option 1 - Add a ledge at each end of your platform. This is the easiest to implement but is less graceful and still allows the player to slide off if he lands on the ledge.
Option 2 -
Step 1: Add code which makes the player move in sync with the horizontal moving platform. You can either use something like self.physicsBody.velocity = CGVectorMake(-50, self.physicsBody.velocity.dy); or use self.position = CGPointMake(self.position.x+10, self.position.y);. You will have to play around with the x values to sync them to the platform's speed.
Step 2: Activate the above code whenever the player makes contact with the platform and deactivate when contact is lost.
Step 3: In case the platform switches directions, set up left and right limits which notify you via contact when the platform switches direction. Depending on the platform's direction you apply either +x or -x movement values to your player.
I know this option sounds complicated but it is not. You just need to go step by step.
* EDIT to provide sample code *
This is the logic I have behind the horizontal moving platforms:
PLATFORMS
If you have more than 1 horizontal moving platform, you will need to store them in an array in the GameScene (my Levels). I have created my own class for them but you do not have to do this.
You will have to set left and right limits (invisible SKNodes with contacts) to set a BOOL property for the platform which tells the player class which way to push as each platform will probably not be the same length. This is why you need to keep a reference to each platform (hence the array).
PLAYER
When the player jumps on the platform, set a Player class property BOOL to TRUE which activates the constant left or right push depending on which way the platform is currently moving. On the flip side, losing the contact cancels the push.
// This code in my "Levels class" which is the default GameScene class.
- (void)didBeginContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (CategoryPlatformHorizontal | CategoryPlayer))
{
[_player setPlatformHorizontalContact:true];
for(Platform *platformObject in platformArray)
{
if(([platformObject.name isEqualToString:contact.bodyB.node.name]) || ([platformObject.name isEqualToString:contact.bodyA.node.name]))
{
_player.currentPlatform = platformObject;
}
}
}
}
- (void)didEndContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (CategoryPlatformHorizontal | CategoryPlayer))
{
[_player setPlatformHorizontalContact:false];
}
}
// This code is in Player.h
#property (strong) Platform *currentPlatform;
#property BOOL platformHorizontalContact;
// This code is in Player.m
- (void)update:(NSTimeInterval)currentTime
{
if(self.platformHorizontalContact == true)
{
if(self.currentPlatform.movingLeft == true)
{
self.physicsBody.velocity = CGVectorMake(-75, self.physicsBody.velocity.dy); // set your own value depending on your platform speed
} else {
self.physicsBody.velocity = CGVectorMake(75, self.physicsBody.velocity.dy); // set your own value depending on your platform speed
}
}
}

How to test if 2 SKSpriteNodes collide

Hi I am a newbie in IOS Dev.
I would like to text if my hull node and my fallingObject node collide.
Once it collided, I want to remove that fallingObject node.
In my code I created a basket in my Scene. then on a Random point on the screen it creates a fallingObject node.
My goal is once the fallingObject collides (or catched) by the hull (imaginary box inside the basket node). the fallingObject would disappear or removed from the Scene.
Please see my code below:
static const uint32_t boxCategory = 0x1 << 0;
static const uint32_t fallingObjectCategory = 0x1 << 1;
#import "MyScene.h"
- (SKSpriteNode *)newBasket
{
SKSpriteNode *basketImage = [[SKSpriteNode alloc] initWithImageNamed:#"basket-01.png"];
basketImage.size = CGSizeMake(150,120);
SKSpriteNode *hull = [[SKSpriteNode alloc] initWithColor:[SKColor grayColor] size:CGSizeMake(64,32)];
[basketImage addChild:hull];
hull.alpha = 0.0;
hull.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:hull.size];
hull.physicsBody.dynamic = NO;
hull.physicsBody.categoryBitMask = boxCategory;
hull.physicsBody.contactTestBitMask = fallingObjectCategory;
hull.physicsBody.collisionBitMask = boxCategory | fallingObjectCategory;
_basket = basketImage;
_box =hull;
return basketImage;
}
- (void)addFallingObject
{
SKSpriteNode *fallingObject = [[SKSpriteNode alloc] initWithImageNamed:[self getRandomFallingObject]];
//Configure the Size
switch (randomNumber) {
case 0:
fallingObject.size = CGSizeMake(70,45);
break;
case 1:
fallingObject.size = CGSizeMake(30,45);
break;
case 2:
fallingObject.size = CGSizeMake(40,90);
break;
default:
fallingObject.size = CGSizeMake(50,50);
break;
}
fallingObject.position = CGPointMake(skRand(0, self.size.width), self.size.height-50);
fallingObject.name = #"fallingObject";
fallingObject.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:fallingObject.size];
self.physicsWorld.speed = 0.30;
fallingObject.physicsBody.categoryBitMask = fallingObjectCategory;
fallingObject.physicsBody.contactTestBitMask = boxCategory;
fallingObject.physicsBody.collisionBitMask = fallingObjectCategory | boxCategory;
[self addChild:fallingObject];
}
-(void)didBeginContact:(SKPhysicsContact *)contact
{
NSLog(#"contact detected");
SKPhysicsBody *boxBody;
SKPhysicsBody *fallingObjectBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
boxBody = contact.bodyA;
fallingObjectBody = contact.bodyB;
}
else
{
boxBody = contact.bodyB;
fallingObjectBody = contact.bodyA;
}
if ((boxBody.categoryBitMask & boxCategory) !=0 && (fallingObjectBody.categoryBitMask & fallingObjectCategory) !=0)
{
//do whatever you want like remove a node
}
}
thank you for all your help. :D
I have a sprite kit game with two things that collide. One is the player and one is the charge. I set up a category for both like this before all my code. This is before all my imports and stuff.
static const uint32_t playerCategory = 0x1 << 4;
static const uint32_t chargeCategory = 0x1 << 5;
Then when I make each node I use the following.
self.player.physicsBody.categoryBitMask = playerCategory;
self.player.physicsBody.contactTestBitMask = chargeCategory;
self.player.physicsBody.collisionBitMask = chargeCategory | selfCategory;
and for the charge.
_chargedBall.physicsBody.categoryBitMask = chargeCategory;
_chargedBall.physicsBody.contactTestBitMask = playerCategory;
_chargedBall.physicsBody.collisionBitMask = playerCategory | selfCategory | chargeCategory;
This tells the player it can collide with a charge and something I called self, but that is not necessary right now.
Then in didBeginContact I use.
SKPhysicsBody *playerBody, *chargeBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
playerBody = contact.bodyA;
chargeBody = contact.bodyB;
}
else
{
playerBody = contact.bodyB;
chargeBody = contact.bodyA;
}
if ((playerBody.categoryBitMask & playerCategory) !=0 && (chargeBody.categoryBitMask & chargeCategory) !=0)
{
//do whatever you want like remove a node
}
EDIT #1
I actually make my objects in initWithSize.
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size])
{ // a bunch of code
self.player = [[Player alloc] initWithImageNamed:#"character"];
self.player.name = #"MyPlayer";
self.player.position = CGPointMake(self.frame.size.width / 2.0f, 120);
self.player.zPosition = 15;
self.player.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.player.frame.size];
self.player.physicsBody.dynamic = YES;
self.player.physicsBody.affectedByGravity = NO;
self.player.physicsBody.mass = 0.25;
self.player.physicsBody.allowsRotation = NO;
self.player.physicsBody.friction = 0.5;
self.player.physicsBody.restitution = 0.3;
self.player.physicsBody.categoryBitMask = playerCategory;
self.player.physicsBody.contactTestBitMask = chargeCategory;
self.player.physicsBody.collisionBitMask = chargeCategory | selfCategory;
[self.map addChild:self.player];
}
Then I make the other obj in a method.
- (void)spawnChargesWithNumber:(int)number
{ // some code
_chargedBall.position = (CGPointMake(_randomX, random));
_chargedBall.name = [NSString stringWithFormat:#"chargeNumber%i", number];
_chargedBall.zPosition = 15;
_chargedBall.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:13.0f];
_chargedBall.physicsBody.dynamic = YES;
_chargedBall.physicsBody.affectedByGravity = NO;
_chargedBall.physicsBody.mass = 0.1;
_chargedBall.velocity = CGPointMake(0.0, 0.0); //changed actualVelocityX to 0
_chargedBall.physicsBody.categoryBitMask = chargeCategory;
_chargedBall.physicsBody.contactTestBitMask = playerCategory;
_chargedBall.physicsBody.collisionBitMask = playerCategory | selfCategory | chargeCategory;
[self.map addChild:_chargedBall];
}
EDIT #2
This might clear some things up. It is from the Apple Docs.
***categoryBitMask
A mask that defines which categories this physics body belongs to.
#property(assign, nonatomic) uint32_t categoryBitMask
Discussion
Every physics body in a scene can be assigned to up to 32 different categories, each corresponding to a bit in the bit mask. You define the mask values used in your game. In conjunction with the collisionBitMask and contactTestBitMask properties, you define which physics bodies interact with each other and when your game is notified of these interactions.
The default value is 0xFFFFFFFF (all bits set).
Availability
Available in iOS 7.0 and later.
See Also
#property collisionBitMask
#property contactTestBitMask
Declared In
SKPhysicsBody.h
***collisionBitMask
A mask that defines which categories of physics bodies can collide with this physics body.
#property(assign, nonatomic) uint32_t collisionBitMask
Discussion
When two physics bodies contact each other, a collision may occur. This body’s collision mask is compared to the other body’s category mask by performing a logical AND operation. If the result is a non-zero value, then this body is affected by the collision. Each body independently chooses whether it wants to be affected by the other body. For example, you might use this to avoid collision calculations that would make negligible changes to a body’s velocity.
The default value is 0xFFFFFFFF (all bits set).
Availability
Available in iOS 7.0 and later.
See Also
#property categoryBitMask
Declared In
SKPhysicsBody.h
***contactTestBitMask
A mask that defines which categories of bodies cause intersection notifications with this physics body.
#property(assign, nonatomic) uint32_t contactTestBitMask
Discussion
When two bodies share the same space, each body’s category mask is tested against the other body’s contact mask by performing a logical AND operation. If either comparison results in a non-zero value, an SKPhysicsContact object is created and passed to the physics world’s delegate. For best performance, only set bits in the contacts mask for interactions you are interested in.
The default value is 0x00000000 (all bits cleared).
Availability
Available in iOS 7.0 and later.
See Also
#property categoryBitMask
Declared In
SKPhysicsBody.h

Issue with removing physics body from physics world (spritekit)

I have one sprite and my code is:
sprite.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:sprite.size.width/2];
sprite.physicsBody.dynamic = YES;
sprite.physicsBody.affectedByGravity = YES;
sprite.physicsBody.mass = 550.0f;
sprite.physicsBody.categoryBitMask = 1;
sprite.physicsBody.collisionBitMask = 1;
sprite.physicsBody.contactTestBitMask = 1;
I can detect collision in:
- (void)didBeginContact:(SKPhysicsContact *)contact {
// destroy contact.bodyA , contact.bodyB
}
But how can I destroy/remove these bodies from physics world?
I'm not sure if I completely understand, but if you're looking for a way of removing your sprites upon collision, you have to access each physics body's node property, and call its removeFromParent function.
[contact.bodyA.node removeFromParent];
[contact.bodyB.node removeFromParent];
Of course, you'll want to add additional logic to determine whether the bit masks of the colliding sprites are the same as the ones you wish to destroy during collision.

Resources