Jules
Jules

Reputation: 7766

Swift: SKEmitterNode affected by PhysicsWorld gravity?

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.

Upvotes: 1

Views: 317

Answers (2)

Confused Vorlon
Confused Vorlon

Reputation: 10446

By default, your particles are not effected by physics fields, but you can change that with the fieldBitMask

I added a radial gravity field (you could use a linear one)

    let fieldNode = SKFieldNode.radialGravityField();
    fieldNode.position = center
    fieldNode.falloff = 0;
    fieldNode.strength = -0.03;
    fieldNode.animationSpeed = 5;
    fieldNode.categoryBitMask = 1

then in my emitter node, I simply set fieldBitMask = 1

class MyNode:SKEmitterNode{
    
    override init() {
  
        super.init()

        //Snip   

        fieldBitMask = 1
    }

}

Upvotes: 1

Fabrizio Scarano
Fabrizio Scarano

Reputation: 106

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

Upvotes: 1

Related Questions