I have nodes (sand) falling downwards.
I have other nodes (walls) that are static.
How do I make the walls not move when the sand collides with it?
let wall = SKSpriteNode(texture: chosen)
wall.position = location
wall.physicsBody = SKPhysicsBody(circleOfRadius: sprite.frame.width)
wall.physicsBody?.affectedByGravity = false
wall.physicsBody!.categoryBitMask = BLOCK
self.addChild(wall)
//////////
let sand = SKSpriteNode (imageNamed: img)
var randLoc = arc4random_uniform(26)
sand.position = CGPointMake(location.x - CGFloat(10) + CGFloat(randLoc), location.y)
self.addChild(sand)
//gravity
sand.physicsBody = SKPhysicsBody(circleOfRadius: sand.frame.width)
sand.physicsBody?.affectedByGravity = true
//contact
sand.physicsBody!.categoryBitMask = self.PARTICLE
sand.physicsBody?.collisionBitMask = self.BLOCK | self.PARTICLE
if you have wall.physicsBody?.dynamic = false & sand.physicsBody?.dynamic = true then you should be able to detect the contact without the walls being pushed/moved by the sand. - Daniel Mihaila
https://stackoverflow.com/users/4963031/daniel-mihaila
Related
I have tree that is built out of a series of joints. The anchor is the base/stump of the tree. My hero is currently not able to walk through the anchor. Setting collisionBitMask = 0 isn't working for the anchor but that approach does work for the individual joint segments.
So, essentially I just want to avoid this collision. Here is the code:
//code for anchor
let chunkHolder = SKSpriteNode(imageNamed: ImageName.ChunkHolder)
chunkHolder.position = anchorPoint
chunkHolder.physicsBody = SKPhysicsBody(circleOfRadius: chunkHolder.size.width / 2)
chunkHolder.physicsBody?.isDynamic = false
chunkHolder.physicsBody?.categoryBitMask = PhysicsCategory.chunkAnchor.rawValue
chunkHolder.physicsBody?.collisionBitMask = 0
addChild(chunkHolder)
//individual tree segements where hero correctly passes through:
for i in 0..<length {
let treeSegment = SKSpriteNode(imageNamed: ImageName.ChunkTexture)
let offset = treeSegment.size.height * CGFloat(i + 1)
treeSegment.position = CGPoint(x: anchorPoint.x, y: anchorPoint.y - offset)
treeSegment.name = "tree" + String(i)
treeSegments.append(treeSegment)
addChild(treeSegment)
treeSegment.physicsBody = SKPhysicsBody(rectangleOf: treeSegment.size)
treeSegment.physicsBody?.collisionBitMask = 0
}
//joints
for i in 1..<length {
let nodeA = treeSegments[i - 1]
let nodeB = treeSegments[i]
let joint = SKPhysicsJointPin.joint(withBodyA: nodeA.physicsBody!, bodyB: nodeB.physicsBody!, anchor: CGPoint(x: nodeA.frame.midX, y: nodeA.frame.minY))
scene.physicsWorld.add(joint)
}
//for reference here is Hero's physics body:
self.physicsBody?.categoryBitMask = PhysicsCategory.hero.rawValue
self.physicsBody?.contactTestBitMask = PhysicsCategory.ground.rawValue
Also setting hero's collisionBitMask to 0 will not currently help because then hero will also fall through the ground / floor.
This was resolved by also setting the categoryBitMask to 0.
chunkHolder.physicsBody?.categoryBitMask = 0
chunkHolder.physicsBody?.collisionBitMask = 0
I am making a game where when the character lands on the cloud, the cloud fades out. I put in code to determine when it is hit, there are multiple clouds registered under the same SKSpriteNode, but when it lands on the cloud, the wrong cloud is fading away, it is the most recently added SKSpriteNode that is being removed, not the one it is colliding with.
Is there any way to do it so it only removes the one that the character has collided with, not the earliest one that spawns? Here is the code:
func didBeginContact(contact: SKPhysicsContact)
{
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch(contactMask)
{
case BodyType.PersonCategory.rawValue | BodyType.CloudCategory.rawValue:
let CheckDelay = delay(0.02)
{
self.Cloud.runAction(self.FadeAway)
}
default:
return
Person.physicsBody?.usesPreciseCollisionDetection = true
Person.size = CGSizeMake(self.frame.size.width / 25, self.frame.size.height / 16.25)
Person.physicsBody = SKPhysicsBody(rectangleOfSize: Person.size)
Person.physicsBody?.restitution = 0
Person.physicsBody?.friction = 0
Person.physicsBody?.allowsRotation = false
Person.physicsBody?.affectedByGravity = true
Person.physicsBody?.dynamic = true
Person.physicsBody?.linearDamping = 0
Person.zPosition = 5
Person.physicsBody?.categoryBitMask = BodyType.PersonCategory.rawValue
Person.physicsBody?.contactTestBitMask = BodyType.CloudCategory.rawValue
Person.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame) * 1.7)
self.addChild(Person)
Cloud = SKSpriteNode(texture: NormalCloudTexture)
Cloud.zPosition = 7
Cloud.physicsBody?.usesPreciseCollisionDetection = true
Cloud.physicsBody?.affectedByGravity = false
Cloud.physicsBody?.allowsRotation = false
Cloud.size = CGSizeMake(self.frame.size.width / 8.05, self.frame.size.height / 40)
Cloud.physicsBody = SKPhysicsBody(rectangleOfSize: Cloud.size)
Cloud.physicsBody?.friction = 0
Cloud.physicsBody?.restitution = 0
Cloud.physicsBody?.dynamic = false
Cloud.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) / 7.60)
addChild(Cloud)
You need to remove the cloud represented by the physicsBody actually making the contact. so bodyA is either the player, or the cloud, and then bodyB is either the player or the cloud. Then get the actual SKSpriteNode from the physics body. It can be referenced via the node property on the SKPhysics body. So either bodyA.node, or bodyB.node.
this may be a duplicate of
Static Physics body still moving with contact
but I have not the reputation to add a comment.
My problem is with collisions and static bodies. I'm working on a little game and I have a player, so configured (from sks file):
player = worldNode.childNodeWithName("player") as! SKSpriteNode
let playerBodyTexture = SKTexture(imageNamed: "player_physicBody_mask")
player.physicsBody = SKPhysicsBody(texture: playerBodyTexture, size: CGSizeMake(player.size.width, player.size.height))
player.physicsBody!.usesPreciseCollisionDetection = true
player.physicsBody!.categoryBitMask = PhysicsCategory.player
player.physicsBody!.collisionBitMask = PhysicsCategory.ground | PhysicsCategory.enemies
player.physicsBody!.contactTestBitMask = PhysicsCategory.enemies
player.physicsBody!.restitution = 0
player.physicsBody!.friction = 0
player.physicsBody!.allowsRotation = false}
an enemy:
worldNode.enumerateChildNodesWithName("enemy") { node, _ in
let enemy = node as! SKSpriteNode
enemy.name = "enemy"
enemy.physicsBody = SKPhysicsBody(circleOfRadius: 17)
enemy.physicsBody!.dynamic = true
enemy.physicsBody!.mass = 0.4
enemy.physicsBody!.restitution = 0
enemy.physicsBody!.categoryBitMask = PhysicsCategory.enemies
enemy.physicsBody!.collisionBitMask = PhysicsCategory.ground | PhysicsCategory.player
enemy.physicsBody!.contactTestBitMask = PhysicsCategory.player}
and I have the platfrom brick, so configured:
worldNode.enumerateChildNodesWithName("fixedBlock") { node, _ in
let fixedBlock = node as! SKSpriteNode
fixedBlock.name = "fixedBlock"
let fixedBlockBodyTexture = SKTexture(imageNamed: "tripleBlocks_physicBody_mask")
fixedBlock.physicsBody = SKPhysicsBody(texture: fixedBlockBodyTexture, size: CGSizeMake(fixedBlock.size.width, fixedBlock.size.height))
fixedBlock.physicsBody!.categoryBitMask = PhysicsCategory.ground
fixedBlock.physicsBody!.collisionBitMask = PhysicsCategory.player | PhysicsCategory.enemies
fixedBlock.physicsBody!.contactTestBitMask = 0
fixedBlock.physicsBody!.dynamic = false
fixedBlock.physicsBody!.affectedByGravity = false
fixedBlock.physicsBody!.allowsRotation = false
fixedBlock.physicsBody!.pinned = false
fixedBlock.physicsBody!.friction = 0.3
fixedBlock.physicsBody!.restitution = 0}
When the player jumps on the enemies, he has an impulse (like Super Mario :-)), so I have this:
func didBeginContact(contact: SKPhysicsContact) {
let collision: UInt32 = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
if collision == PhysicsCategory.player | PhysicsCategory.enemies {
self.player.physicsBody!.applyImpulse(CGVectorMake(0, 500))}}
Ok... sometimes, often, when the player jumps on enemy, the impulse appens correctly, but the ground tile moves down, also if its dynamic propriety is set on false. I tried to apply a JointFixed on the ground tile but when it is pushed down, its physic body "glitch"; I tried to print the physicsBody velocity propierty of the ground tile and when the problem occours, the velocity's dx vector is >100, but should static bodies not be affected by forces?
Any idea?
Many thanks
I'm creating a simple game. I'm trying to set the frame as an physicsBody so the plane, never falls below the screen. The function below stops it from falling all the way off, but the SKSpriteNode falls just out of view before stopping.
func setBoundry(view: SKView) {
// Create ground
var boundry = SKNode()
boundry.physicsBody = SKPhysicsBody(edgeLoopFromRect: view.frame)
boundry.physicsBody?.dynamic = false
boundry.physicsBody?.contactTestBitMask = PhysicsCategory.Plane
boundry.physicsBody?.categoryBitMask = PhysicsCategory.Boundry | PhysicsCategory.Collidable
self.addChild(boundry)
}
Plane is being created like this...
func createPlane(sceneView: SKView) {
let planeTexture = SKTexture(imageNamed: "planeRed1")
let planeTexture1 = SKTexture(imageNamed: "planeRed2")
let planeTexture2 = SKTexture(imageNamed: "planeRed3")
// Animate plans propeller
let animation = SKAction.animateWithTextures([planeTexture, planeTexture1, planeTexture2], timePerFrame: 0.05)
let makePropellerSpin = SKAction.repeatActionForever(animation)
// Set planes position
plane = SKSpriteNode(texture: planeTexture)
plane.position = CGPointMake(size.width/4, size.height/2)
plane.runAction(makePropellerSpin)
plane.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(plane.size.width, plane.size.height))
plane.physicsBody?.dynamic = true
plane.physicsBody?.allowsRotation = false
plane.physicsBody?.categoryBitMask = PhysicsCategory.Plane
plane.physicsBody?.collisionBitMask = PhysicsCategory.Collidable | PhysicsCategory.Boundry
plane.physicsBody?.contactTestBitMask = PhysicsCategory.Collidable | PhysicsCategory.Boundry
// Set elevation
plane.zPosition = 5
self.addChild(plane)
}
You need to set the contactTestBitMask for your boundry node and also set the physics for your plane-node:
boundry.physicsBody?.contactTestBitMask = PhysicsCategory.YourPlayerEnum
Also check out the collisionBitMask property of the physicsbody.
I'm trying to implement a rope in Swift SpriteKit and to add physics to it, the position is good for all, but they won't attach, when I hit play they all fall except the first one which is the "holder". Here is my code:
// create rope holder
let chainHolder = SKSpriteNode(imageNamed: "chainHolder")
chainHolder.position.y = self.frame.maxY - chainHolder.size.height
chainHolder.physicsBody = SKPhysicsBody(circleOfRadius: chainHolder.size.width / 2)
chainHolder.physicsBody?.dynamic = false
//chainHolder.physicsBody?.allowsRotation = true
chains.append(chainHolder)
addChild(chainHolder)
// add each of the rope parts
for i in 0...5 {
let chainRing = SKSpriteNode(imageNamed: "chainRing")
let offset = chainRing.size.height * CGFloat(i + 1)
chainRing.position = CGPointMake(chainHolder.position.x, chainHolder.position.y - offset)
chainRing.name = String(i)
chainRing.physicsBody = SKPhysicsBody(rectangleOfSize: chainRing.size)
//chainRing.physicsBody?.allowsRotation = true
chains.append(chainRing)
addChild(chainRing)
}
// set up joints between rope parts
for i in 1...5 {
var nodeA = chains[i - 1]
var nodeB = chains[i]
var joint = SKPhysicsJointPin.jointWithBodyA(nodeA.physicsBody, bodyB: nodeB.physicsBody,
anchor: CGPointMake(CGRectGetMidX(nodeA.frame), CGRectGetMinY(nodeA.frame)))
physicsWorld.addJoint(joint)
}
I found out that the problem was because I was setting the anchor point for the scene in (0.5, 0.5). If I leave it in (0, 0) everything is ok.