Using SKPhysicsBody(bodies:) to create one physics body from several - ios

I'm trying to create a single physics body from several other bodies using the SKPhysicsBody(bodies:) init.
I have nodes throughout my scene that have physics bodies attached to them, and I want to consolidate them into a single physics body. I'm enumerating through the nodes of the scene and picking out the nodes I want to target. I'm creating the physics body at the creation of those nodes like this:
node.physicsBody = SKPhysicsBody(rectangleOf: node.size)
node.physicsBody?.isDynamic = false
Then I add the physics body to an array of SKPhysicsBodies like this:
self.allNodePhysicsBodies.append(node.physicsBody)
I then create the conglomerate physics body like this:
let conglomeratePhysicsBody = SKPhysicsBody(bodies: self.allNodePhysicsBodies)
I've tried several different ways of adding the physics bodies to the scene: By creating an SKNode or SKSpriteNode and adding the physics bodies to it and the adding it to the scene, or setting the scene's physics body conglomeratePhysicsBody. All of these methods end up with the physics bodies all aligned at the bottom of the scene (not positioned around the scene like they should be). When I print out the conglomeratePhysicsBody to the console, I get this message: <SKPhysicsBody> type:<Compound> representedObject:[(null)]. Is there something I'm missing that is keeping the physics bodies from appearing where the nodes are?
I should add that I can see the physics bodies by using skView.showsPhysics = true.

Related

SCNPhysicsShape(shapes:transforms:) creates MULTIPLE shapes?

My goal is to create a single physics body out of several of SceneKit's SCNBox geometries.
My understanding is that when I pass an SCNPhysicsShape(shapes:transforms:) to an SCNPhysicsBody(type:shape:), it should create a single physics body.
However, I end up with something that seems suspiciously like it's not a single physics body at all, but rather several separate physics bodies -- one for each shape I passed into SCNPhysicsShape(shapes:transforms:).
When I turn on scnView.debugOptions = .showPhysicsShapes, I can clearly see red lines defining the separate bodies in question. On its own, this isn't very convincing evidence (it's conceivable that those lines could be shown for whatever reason while still being a single physics body).
But there's another piece of data, here: The project in which I'm encountering this issue features a small ball that rolls around the scene -- and when that ball rolls over the red lines in question, the ball bounces up into the air a bit. So, it's quite obvious that, whatever is actually going on, there are edges where I would expect to see none.
This behavior is clearly visible in the following GIF. In it, each colored block is a separate SCNBox geometry with its own physics body. Each block has the exact same position.z. The ball bounces considerably as it crosses the point where one geometry meets another.
Here's some code illustrating the issue. parent is an SCNNode that holds the child nodes, and is the node to which I assign the physics body. Please assume that all properties are defined; I'm omitting things that aren't terribly relevant.
let childShape1 = SCNBox(width: 6, height: 2, length: 6, chamferRadius: 0.0)
//Other child shapes defined here...
//Set up the positional translation relative to the child node's parent:
let translateMatrixShape1 = SCNMatrix4MakeTranslation(childShape1.position.x, childShape1.position.y, childShape1.position.z)
//Other child translations defined here...
let parentShape = SCNPhysicsShape(shapes: [childShape1, childShape2, childShape3, childShape4], transforms: [translateMatrixShape1, translateMatrixShape2, translateMatrixShape3, translateMatrixShape4])
parent.physicsBody = SCNPhysicsBody(type: SCNPhysicsBodyType.static, shape: parentShape)
Now, parentShape is four rectangular boxes arranged around a central point, creating a sort of picture-frame-shaped object.
The ball is an SCNNode with an SCNSphere geometry and a dynamic physics body.
Question: Does anyone have any idea what might be going on, here? Have I somehow misunderstood how this whole thing works, or is this a limitation of SceneKit?
Usually you can create one single PhysicsBody from several geometry objects by making a flattenendClone from out of your (i.Ex.) parent node. This new node will have one single geometry then. For the PhysicsBody you can then use the geometry element of the new node. In Addition I recoommend to use a concavePolyhedron for the static body type. (I hope I understood you correctly)

SpriteKit categoryBitMask issue

I'm new to Spritekit, and I'm having some trouble with something simple.
I'm making a pinball game. In order to detect collisions and award points with the ball, the bumpers have the following set:
categoryBitMask
collisionBitMask
contactTestBitMask
However, once I set categoryBitMask, the object no longer acts the same way. The ball passes through the bumper.
I've tried to set the properties in code to mirror what is set in the SKS file:
physicsBody?.isDynamic
physicsBody?.affectedByGravity
physicsBody?.allowsRotation
physicsBody?.pinned
physicsBody?.mass
But this doesn't make any difference.
How can I make a SKSpriteNode maintain it's physical properties after setting the categoryBitMask?
I found the issue. I was setting the collision on one object but not the other
ball.collisionBitMask = ...contains bumper
ball.contactTestBitMask = ... contains bumper
but not the bumper:
bumper.collisionBitMask = ...didn't contain ball
bumper.contactTestBitMask = ...didn't contain ball

Allow two sprites to intersect while still detecting contact [duplicate]

I have two SKNode objects. Their positions change when they collide.
How can I prevent that? At the same time, I still want to be able to respond to them contacting via - (void)didBeginContact;
I tried setting both their mass property to 0.0f but that didn't work.
You can achieve that by setting category, collision and contact bit masks.
uint32_t bodyABitMask = 1<<0;
uint32_t bodyBBitMask = 1<<1;
//A mask that defines which categories this physics body belongs to.
[bodyA setCategoryBitMask:bodyABitMask];
[bodyB setCategoryBitMask:bodyBBitMask];
//A mask that defines which categories of physics bodies
//can collide with this physics body.
[bodyA setCollisionBitMask:0];
[bodyB setCollisionBitMask:0];
//A mask that defines which categories of bodies cause
//intersection notifications with this physics body.
[bodyA setContactTestBitMask:bodyBBitMask];
[bodyB setContactTestBitMask:bodyABitMask];
In above case bodyA and bodyB cannot collide, but you will receive didBeginContact once they are in contact.

Keep SKNodes from applying force to each other

I have two SKNode objects. Their positions change when they collide.
How can I prevent that? At the same time, I still want to be able to respond to them contacting via - (void)didBeginContact;
I tried setting both their mass property to 0.0f but that didn't work.
You can achieve that by setting category, collision and contact bit masks.
uint32_t bodyABitMask = 1<<0;
uint32_t bodyBBitMask = 1<<1;
//A mask that defines which categories this physics body belongs to.
[bodyA setCategoryBitMask:bodyABitMask];
[bodyB setCategoryBitMask:bodyBBitMask];
//A mask that defines which categories of physics bodies
//can collide with this physics body.
[bodyA setCollisionBitMask:0];
[bodyB setCollisionBitMask:0];
//A mask that defines which categories of bodies cause
//intersection notifications with this physics body.
[bodyA setContactTestBitMask:bodyBBitMask];
[bodyB setContactTestBitMask:bodyABitMask];
In above case bodyA and bodyB cannot collide, but you will receive didBeginContact once they are in contact.

SpriteKit: SKSpriteNode containing another SKSpriteNodes but only one SKPhysicsBody

I have a character in my game, it's an SKSpriteNode with few child SKSpriteNodes so I can animate various parts of my character (hands, feet etc.), it also has 1 SKSpriteNode (tried replacing with SKNode, but it was the same) with SKPhysicsBody for a body.
When I add the character to my layer in a scene it just hang in the position and the sprite with the body falls down.
My question and problem is: How can I keep all the child sprites in my main character sprite - how can I keep my character together?
Thanks for any ideas!
EDIT: How can I keep the child sprite with the body attached to my container sprite?
Re EDIT:
Use an SKNode to control all of your character's body parts, including the main body:
SKNode (controller)
SKSpriteNode (head)
SKSpriteNode (body)
SKSpriteNode (leg1)
SKSpriteNode (leg2)
That gives you more flexibility.
To make the head the "master" position, this should do the trick:
-(void) didSimulatePhysics
{
self.parent.position = [self convertPoint:self.position toNode:self.parent.parent];
self.position = CGPointZero;
}
The body is falling because its responding to gravity, as expected. The Other body part, if they do not have physics bodies will stay where you place them.
Some options :
1.
If you want all body parts to be physics body then I suggest looking at a joints, ie a pin joint - which will work like a shoulder joint for example.
Here is an example of pin joints for making a car with wheels.
2.
If you just want it not move, for whatever reason. On your physics body, just set this.
bodyNode.physicsBody.dynamic = NO;
If I am understanding you right, you can start off by saying the gravity on the SKScene is 0, by doing
self.physicsWorld.gravity = CGVectorMake(0,0);
This will ensure that nothing causes the character of your screen to fall down into the bottom from the gravity enforced on the screen.
Possible solution: remove SKPhysicBody from child node and add it to parent node.

Resources