Turning off detection between sprites - sprite-kit

I have two phyicsbodies in my spritekit game which are colliding and I am having a little difficulty getting them to stop.
I am posting the physics code for them below.
Problem is when the swarm touches my coins it pushes it, not exactly sure why since as far as my know my enemy is told to only contact with the player and my coin is told to only contact with the wall and the player (correct me if im wrong)
(P.S I commented out the collisionBitMask for the coin because when I dont my coins fall thru my walls )
Thanks
1St sprite
enemy = [SKSpriteNode spriteNodeWithImageNamed:#"Swarm"];
enemy.physicsBody =
[SKPhysicsBody bodyWithRectangleOfSize:enemy.size];
enemy.physicsBody.dynamic=NO;
enemy.name=#"Eagle";
enemy.physicsBody.categoryBitMask = PCFallersCategory;
// enemy.physicsBody.collisionBitMask =
// PCPlayerCategory;
enemy.physicsBody.contactTestBitMask = PCPlayerCategory;
enemy.physicsBody.restitution=0;
enemy.physicsBody.friction=0;
2nd Sprite.
self.name = #"coin";
CGFloat minDiam = MIN(self.size.width, self.size.height);
minDiam = MAX(minDiam-8, 8);
self.physicsBody =
[SKPhysicsBody bodyWithCircleOfRadius:minDiam/2.0];
self.physicsBody.dynamic=YES;
self.physicsBody.restitution =0;
self.physicsBody.friction = 0;
self.physicsBody.linearDamping = 0;
self.physicsBody.categoryBitMask = PCCollectableCategotry;
//self.physicsBody.collisionBitMask =PCPlayerCategory;
self.physicsBody.contactTestBitMask = PCPlayerCategory|PCWallCategory;

You need to explicitly set the collisionBitMask to 0.
enemy.physicsBody.collisionBitMask = 0;
According to the documentation
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).
This means that by default, an SKPhysicsBody is configured to collide with all objects.

Related

Unity object orientation in player hand changes depending on angle of object pick up

I have a character that is able to pick up the axe in the game. For some reason, if approach the item from different angles, the player picks up the axe in a different position. Why does this happen if I have made it so the axe appears in the players hand. I use the axe's center transform position and place it on the parent object which is the hand. I would of at least expected some consistency since it should not be random due to the code.
testObject = Instantiate(toCreate) as GameObject;
testObject.transform.parent = arm.transform;
testObject.transform.position = arm.transform.position;
testObject = Instantiate(toCreate) as GameObject;
testObject.transform.parent = arm.transform;
testObject.transform.localPosition = Vector3.zero;
testObject.transform.localRotation = Quaternion.identity;
Behaviour will change depending on when you make it a child of another object ( set a parent).
Probably best idea is to set position and rotation before setting a parent.

SpriteKit - Bouncing node constant speed/velocity?

Simple setup - I have bouncing ball nodes (blue) and static ball nodes (green). The grey box has Physics body SKPhysicsBody(edgeLoopFrom: box.frame), so it limits the bouncing ball from moving outside. I set the bouncing balls node (blue) velocity to a random CGVector upon creation and it starts moving. It bounces off the static ball node (green), and off the edges of the grey box.
My general SKPhysicsBody setup with all nodes is:
node.physicsBody?.restitution = 1
node.physicsBody?.friction = 0.0
node.physicsBody?.linearDamping = 0.0
node.physicsBody?.angularDamping = 0.0
My question is: How do I make sure the bouncing ball does move at a constant speed? After a couple of bounces, the node is either speeding up, or slowing down.
In order to achieve this, I normalized the vector whenever the physics engine detects a collision. So in func didBegin(_ contact: SKPhysicsContact), the following happens:
let length = hypotf(Float(node.velocity.dx), Float(node.velocity.dy))
let multiplier = (290.0 / length)
firstBody.velocity.dx *= CGFloat(multiplier)
firstBody.velocity.dy *= CGFloat(multiplier)
290.0 is an arbitrary value that determines the speed of ball.
For reference, check this answer.

How do I make Character(SCNNode) bounce off of a wall in Scenekit?

I am trying to make a simple maze game in Scenekit. I have a sphere node and wall nodes. The sphere moves by SCNActions. The actions I use on the sphere are moveByX actions. My problem is that whenever the sphere hits a wall, it just moves the wall back with it. My sphere is kinematic and my walls are dynamic. I don't have any forces in the scene, only my moveByX actions. How can I make it so my sphere bounces off of the walls?
I am using Swift.
Change walls to .static and sphere to .dynamic
One way you could do it would be to have variables for xSpeed and ySpeed, and whenever you collide with a wall make the corresponding variable negative. This is a pretty basic approach and doesn't take diagonal walls into account.
For example:
var xSpeed = 5.0 var ySpeed = 5.0
if collision with wall in x direction { xSpeed = -xSpeed }
if collision with wall in y direction { ySpeed = -ySpeed }
It might be a bit tricky to detect the collisions, you might have to look up some tutorials on SpriteKit collisions.
For Swift3
let border = SKPhysicsBody(edgeLoopFrom: self.frame)
border.friction = 0
border.restitution = 1
self.physicsBody = border

How does collisionBitMask work? Swift/SpriteKit

As far as I'm aware the default for Physics bodies is to bounce off each other when they hit each other until you set their collisionBitMask to an equal number.
However, I'm having a huge issue accomplishing what seems like it should be very simple because of collisionBitmasks I believe.
let RedBallCategory : UInt32 = 0x1 << 1
let GreenBallCategory: UInt32 = 0x1 << 2
let RedBarCategory : UInt32 = 0x1 << 3
let GreenBarCategory : UInt32 = 0x1 << 4
let WallCategory : UInt32 = 0x1 << 5
greenBall.physicsBody?.categoryBitMask = GreenBallCategory
greenBall.physicsBody?.contactTestBitMask = RedBarCategory
greenBall.physicsBody?.collisionBitMask = GreenHealthCategory
redBall.physicsBody?.categoryBitMask = RedBallCategory
redBall.physicsBody?.contactTestBitMask = GreenBarCategory
redBall.physicsBody?.collisionBitMask = RedHealthCategory
let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = borderBody
self.physicsBody?.friction = 0
borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory
borderBody.categoryBitMask = WallCategory
So here I've got my 2 balls and my border body. I can get collision detection which I want, but when I add the border body's category bit mask, it allows the balls to both go through and off the screen, which I don't want.
I also want the balls to bounce off each other, but only when I comment out one of the ball's categoryBitMasks do they bounce. Otherwise they go through each other.
That makes absolutely no sense to me because each of these items has a different collisionbitmask. I also had it sometimes where setting all the numbers equal to 5 would allow everything to pass through each other, but then setting it all to 6 would allow everything to hit each other.
How exactly do collision bitmasks work and is there a proper way to manage a lot of crisscrossing collision rules?
You can't get desired behaviour because you haven't set category, contact and collision bit masks properly. Here is an example on how you can set this to work:
greenBall.physicsBody?.categoryBitMask = GreenBallCategory //Category is GreenBall
greenBall.physicsBody?.contactTestBitMask = RedBarCategory | WallCategory //Contact will be detected when GreenBall make a contact with RedBar or a Wall (assuming that redBar's masks are already properly set)
greenBall.physicsBody?.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory //Collision will occur when GreenBall hits GreenBall, RedBall or hits a Wall
redBall.physicsBody?.categoryBitMask = RedBallCategory //Category is RedBall
redBall.physicsBody?.contactTestBitMask = GreenBarCategory | GreenBallCategory | WallCategory //Contact will be detected when RedBall make a contact with GreenBar , GreenBall or a Wall
redBall.physicsBody?.collisionBitMask = RedBallCategory | GreenBallCategory | WallCategory //Collision will occur when RedBall meets RedBall, GreenBall or hits a Wall
let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = borderBody
self.physicsBody?.friction = 0
borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory //Contact will be detected when red or green ball hit the wall
borderBody.categoryBitMask = WallCategory
borderBody.collisionBitMask = RedBallCategory | GreenBallCategory // Collisions between RedBall GreenBall and a Wall will be detected
I would recommend you to read docs about categoryBitMask which is a mask that defines which categories a physics body belongs to:
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.
contactTestBitMask - A mask that defines which categories of bodies cause intersection notifications with a current physics body.
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 nonzero 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.
collisionBitmask - A mask that defines which categories of physics bodies can collide with this physics body.
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 nonzero
value, 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.
So basically, to set up all these, you should ask your self something like:
Okay, I have a green ball, and a red ball , and wall objects on the scene. Between which bodies I want collisions to occur, or when I want to register contacts? I want a green and a red ball to collide with each other and to collide against the walls. Not a problem. I will first set up categories properly, and then I will set collision bit masks like this:
greenBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory; //greenBall will collide with greenBall, redBall and a wall
redBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory
wall.collisionBitMask = GreenBall | RedBall
Now, I want to detect when some contacts occur (in didBeginContact: method)... But I don't want to get notified about all possible contacts, but rather to be notified just about contacts between balls (contacts between balls and a wall will be ignored). So lets set contactTestBitMasks to achieve this:
greenBall.contactTestBitMask = GreenBallCategory | RedBallCategory;
redBall.contactTestBitMask = GreenBallCategory | RedBallCategory;
And that's it. The important thing is when you not using contact detection, you should not set contactTestBitMask. This is because of performance reasons. If you don't need collision detection, and you are interested only in detecting contacts, you can set collisionBitMask = 0.
Important:
Make sure you have set physics world's contact delegate in order to use didBeginContact and didEndContact methods:
self.physicsWorld.contactDelegate = self; //where self is a current scene
Hope this helps a bit.
Just want to add something here, that if the contact or collision are not able to work properly, you need to make sure that you assign the physicsBody shape first before applying the bitMasks.
Example of not working bitmask:
SKSpriteNode *bird = [SKSpriteNode spriteNodeWithImageNamed:#"bird1.png"];
bird.name = #"bird";
bird.physicsBody.categoryBitMask = birdCategory;
bird.physicsBody.contactTestBitMask = wallCategory | scoreCategory;
bird.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:bird.size.width/2.7];
bird.position = CGPointMake(_mySize.width/3.0, 2*_mySize.height/3.0);
[self addChild:bird];
And working one:
SKSpriteNode *bird = [SKSpriteNode spriteNodeWithImageNamed:#"bird1.png"];
bird.name = #"bird";
bird.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:bird.size.width/2.7];
bird.physicsBody.categoryBitMask = birdCategory;
bird.physicsBody.contactTestBitMask = wallCategory | scoreCategory;
bird.position = CGPointMake(_mySize.width/3.0, 2*_mySize.height/3.0);
[self addChild:bird];
Anyway probably just a newbie mistake, but I'd share here cause this is what caused mine not to work properly.

Make particle system only be affected by certain categories of physics fields in SceneKit?

In SceneKit, it is possible to make a SCNPhysicsBody be unaffected by a SCNPhysicsField by giving them categoryBitMasks that when compared using bitwise AND, result in a value of zero.
Bodies who's category bit mask produce a non zero value when compared with that of the field are still affected by it.
Is it possible to do the same for the particles in a SCNParticleSystem, so that the particles will be unaffected by a SCNPhysicsField (edit: and still have the particles affected by other physics fields), but certain physics bodies or even other particle systems are affected by it?
To clarify:
What I want: A SCNParticleSystem that is affected by a SCNPhysicsField (specifically a linear gravity field). This can be done by setting the particle system's affectedByPhysicsFields property to true. However, this will make the particle system affected by all physics fields in the scene. I have another field (also a linear gravity field) that I want to only affect a SCNPhysicsBody which I don't want to be affected by the particle systems's field.
As it stands both the particle system and the physics body will be affected by both fields. Unless I give them categoryBitMasks to tell them which fields to interact with. Except particle systems don't have categoryBitMasks, and if a physics field's categoryBitMask is anything other than the default, it will be ignored by any particles.
So I can set it so that one of the fields only affects the body by giving them the same category. But I can't do the same for the particles. Is there any way to accomplish this? (Using the world gravity as one of the fields doesn't work because it doesn't have a categoryBitMask either.)
I've actually figured out a workaround (for now) by just using the particle system's acceleration property instead of a physics field. But I curious to see if it actually is possible to do it using a physics field.
edit: As requested here is some sample code. This code results in a sphere affected by two physics fields, and a particle system affected by one physics field. The comments explain the problem.
let PhysicsCategorySphere = 1 << 0
let PhysicsCategoryParticles = 1 << 1
scene.physicsWorld.gravity = SCNVector3(x: 0, y: 0, z: 0)
let sphere = SCNNode(geometry: SCNSphere(radius: 1))
sphere.physicsBody = SCNPhysicsBody.dynamicBody()
sphere.physicsBody?.categoryBitMask = PhysicsCategorySphere
//only physics fields with categoryBitMasks that match the sphere's can affect it
scene.rootNode.addChildNode(sphere)
let field = SCNPhysicsField.linearGravityField()
field.strength = 9.8
field.direction = SCNVector3(x: 0, y: 1, z: 0)
field.categoryBitMask = PhysicsCategorySphere
//only things with categories that match the field's will be affected by it
let fieldNode = SCNNode()
fieldNode.physicsField = field
scene.rootNode.addChildNode(fieldNode)
let particleSystem = SCNParticleSystem(named: "particles", inDirectory: "")
particleSystem.affectedByPhysicsFields = true
//there is no way that I know of to give the particle system a physics category
let particleNode = SCNNode()
particleNode.addParticleSystem(particleSystem)
scene.rootNode.addChildNode(particleNode)
let particleField = SCNPhysicsField.linearGravityField()
particleField.strength = 20
particleField.direction = SCNVector3(x: 0, y: 0, z: 1)
//particleField.categoryBitMask = PhysicsCategoryParticles
//if the field is given a category, it will no longer affect the particles
//the default is to match all categories, thus the particle field will also affect the sphere
let particleFieldNode = SCNNode()
particleFieldNode.physicsField = particleField
scene.rootNode.addChildNode(particleFieldNode)
Ok, I don't know how I overlooked this, but the answer is right in the documentation for SCNPhysicsField's categoryBitMask property.
To determine whether a field affects the particles spawned by an
SCNParticleSystem object, SceneKit performs the same check using the
categoryBitMask property of the node containing the particle system.