physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
let dodge = childNodeWithName(Dodge) as! SKSpriteNode
dodge.physicsBody!.applyImpulse(CGVector(dx: 100.0, dy: -100))
When the ball touches the boundaries that I set, it slows down or it just stops moving.
Allows Rotation Unchecked,
Friction to 0,
Restitution to 1,
linear Damping to 0,
Angular Damping to 0
Have you tried setting the friction to 0 on your edge based physics body? (The edge of the screen) This could be causing the problem. Even though your volume based physics body has no friction (The ball) friction will still be caused unless your edge based boundary (the edge of the screen) also has no friction set.
Have you tried applyforce instead of applyimpulse?
dodge.physicsBody!.applyForce(CGVector(dx: 100, dy: -100))
Related
I have a SpriteKit game in which balls bounce around, interacting with other objects.
One of those other objects is a spinner that should rotate around its center, but NOT change its x/y position. It should be stationary except for the rotation.
According to Apple's documentation, node.physicsBody.pinned = true should do exactly what I want, making it so that:
"the node’s position is fixed relative to its parent. The node’s position cannot be changed by actions or physics forces. The node can freely rotate around its position in response to collisions or other forces."
However, that's not what's happening. What's happening is that the spinner's y-axis position changes when a ball hits it squarely -- briefly moving down and then popping back into the correct position.
My code for the spinner (please assume all variables are defined):
for i in 0..<spinners.count {
let spinnerNode = SKSpriteNode(texture: texture)
spinnerNode.position = CGPoint(x: spinners[i].minX, y: spinners[i].minY)
spinnerNode.size = CGSize(width: spinners[i].width, height: spinners[i].height)
spinnerNode.physicsBody = SKPhysicsBody(texture: spinnerNode.texture!, size: CGSize(width: spinners[i].width, height: spinners[i].height))
spinnerNode.physicsBody?.isDynamic = true
spinnerNode.physicsBody?.affectedByGravity = false
spinnerNode.physicsBody?.pinned = true
addChild(spinnerNode)
}
Why on earth is my spinner node moving vertically when a ball collides with it? Why isn't .pinned working as advertised?
Thank you for your help!
I solved the problem by setting the spinner node's mass to a value slightly greater than that of the ball nodes.
node.physicsBody?.mass = 6.0
I'm trying to have a rain particles which are affected by wind aka physicsWorld gravity.
I can see that the gravity does has an affect on my SKSpriteNodes but I can't achieve the same affect on an SKEmitterNode.
I'm just wondering if it's possible.
Here's what I've been trying...
override func didMove(to view: SKView) {
if let rainParticles = SKEmitterNode(fileNamed: "Rain.sks") {
rainParticles.position = CGPoint(x: size.width/2, y: size.height)
rainParticles.name = "rainParticle"
rainParticles.targetNode = scene
rainParticles.particlePositionRange =
CGVector(dx: frame.size.width, dy: frame.size.height)
rainParticles.zPosition = -1
// I don't think this is right
rainParticles.physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
rainParticles.physicsBody?.affectedByGravity = true
addChild(rainParticles)
}
physicsWorld.contactDelegate = self
// gravity is pushing to the right here
physicsWorld.gravity = CGVector(dx: 20, dy: 0)
physicsWorld.speed = 0.85
}
Yes I have added SKPhysicsContactDelegate.
Obviously I want to ignore collisions so I haven't set collisionBitMask, also I don't want to have rain bouncing off anything with contactTestBitMask. I don't believe I need to set a categoryBitMask.
Particles are not represented by objects in SpriteKit. This means you cannot perform node-related tasks on particles, nor can you associate physics bodies with particles to make them interact with other content. Although there is no visible class representing particles added by the emitter node, you can think of a particle as having properties like any other object.
This is straight from SKEmitterNode documentation. Particles won't get any gravity acceleration from the physicsWorld of the scene.
Also rainParticles.physicsBody refers to the SKEmitterNode physicsBody, not its particles.
If you simply want the particles to simulate the current physicsWorld's gravity:
rainParticles.xAcceleration = self.physicsWorld.gravity.dx
rainParticles.yAcceleration = self.physicsWorld.gravity.dy
I have a construction crane that has a joint with an object. The joint works fine if the crane is stationary.
But I added the ability for the crane to move left to right and whenever the crane is about to leave the view with the object, the object hits the edge of the screen and gets stuck while the crane keeps going. The joint also stops working even after the crane has come back to the view.
Here's an image. The yellow line at the top represents the path the hook follows forever. It goes left to right. The gold block that's around the blue rectangle is what's getting stuck. That's the block that's originally jointed with the crane's gray hook. But when the hook moves to right side of the view, the gold block hits the edge of the screen and stays there forever.
What doesn't make sense to me is that the edge of the view has a category bit mask of 0 while the gold block is at 64. In other levels, the gold blocks NEVER collide with the edge. But here when the crane moves to the edge, the gold block collides with the edge and gets stuck. As you can see, the joints are still there based on the light blue physic lines.
This is the code of the joint being called from the scene and configuring it. Like I said, joint works fine if the hook is stationary.
craneBase.alpha = 0
let path = CGMutablePath()
path.move(to: CGPoint(x: craneBase.position.x, y: craneBase.position.y))
path.addLine(to: CGPoint(x: craneBase.size.width - 100, y: craneBase.position.y + 10))
path.addLine(to: CGPoint(x: craneBase.position.x, y: craneBase.position.y))
craneHook.initializeMovingJoint(withObject: childNode(withName: "HookedObject") as! SKSpriteNode)
hook.run(SKAction.repeatForever(SKAction.follow(path, asOffset: false, orientToPath: false, duration: 10)))
physicsWorld.add(craneHook.joint)
This is the code of the crane's hook class that adds the joint to the block.
private func initHook() {
self.hookSize = CGSize(width: 10, height: 10)
self.physicsBody = SKPhysicsBody(rectangleOf: hookSize)
self.physicsBody?.categoryBitMask = PhysicsBit.none
self.physicsBody?.isDynamic = false
self.physicsBody?.affectedByGravity = false
}
//Creates the joint between the object and the hook
func initializeJoint(withObject object: SKSpriteNode) {
initHook()
hookedObject = object
jointAnchor = CGPoint(x: self.anchorPoint.x, y: self.anchorPoint.y)
joint = SKPhysicsJointFixed.joint(withBodyA: physicsBody!, bodyB: hookedObject.physicsBody!, anchor: jointAnchor)
doesHaveHookedObject = true
}
And the gold block's settings are assigned from the scene editor to a category mask of 64. I've tested the gold blocks and they don't collide with the edge. I'm not sure why it collides with the edge while moving.
I realized it was not working because the joint and the physicsWorld had the same category bit mask. Even though the gold block had a different bit mask, it was part of the joint and thus collided with the same category bit mask as none.
I have a SKAction that changes the y position of a sprite. The sprite is affected by gravity towards the right, and when i set the x position in the SKAction to the sprite's position the sprite movement is slowing down while the Action is running.
How can i change this so that the x movement is not effected by the action running?
let moveDown = SKAction.moveTo(CGPoint(x: player.position.x, y: 0), duration: 0.3)
player.runAction(moveDown)
You could try using linearDamping. I'm not sure this is exactly what you're looking for, but it's a property that reduces the body’s linear velocity.
player.physicsBody!.linearDamping = 0.0
Let me know if this works for you or if this wasn't what you were looking for!
Solved it using this code:
let moveDown = SKAction.moveToY(0, duration: 0.3)
player.runAction(moveDown)
I am trying to create a impenetrable border at the edge of the game scene frame.
In Swift I have attempted to re-write this as:
override func didMoveToView(view: SKView) {
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: CGRect(x: 0,y: 100,width: self.frame.size.width,height: self.frame.size.height-200))
}
Instead of giving me a clear boundary at the edge of frame it is providing a weak border, which my player (with no specified mass) can pass over.
I'm also not sure why I am having to subtract and add to the y axis to get the correct border but this is less of a concern. Any help would be much appreciated.
The key is to move your sprites by applying a force/impulse or by setting the velocity property so that they respond correctly to
collisions with other physics bodies (such as an edge loop)
forces such as linear/angular damping, friction, and force fields.
You should first define a bitmask category to represent the physics body of your game scene. I typically use the 32-bit binary value 00000000000000000000000000000001, which I define as a constant:
let SCENE_EDGE_CATEGORY: UInt32 = 0x1
With that constant defined, you can now define the scene's physics body in a very readable way:
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody!.categoryBitMask = SCENE_EDGE_CATEGORY
For any sprite that you want to be constrained by the edge of the scene, set its physics body's collision bitmask to the scene's category bitmask. You're telling Sprite Kit that you want the physics engine to handle collisions between that sprite and the scene's edge:
someSprite.physicsBody!.collisionBitMask = SCENE_EDGE_CATEGORY
Hope this helps!
Try this:
override init(size: CGSize)
{
super.init(size: size)
physicsBody = SKPhysicsBody(edgeLoopFromRect: CGRectMake(0, 0, size.width, size.height))
anchorPoint = CGPointMake(0.0, 0.0)
}
works fine for me.
This will definitely help you to define the edge of the screen in Swift.
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)