ios - 适用于 iOS 的自定义粒子系统

标签 ios sprite-kit particle-system skemitternode

我想在 iOS 上创建一个粒子系统使用 Sprite 套件,我在其中定义每个粒子的颜色。据我所知,现有的 SKEmitterNode 不可能做到这一点。 .
似乎我能做的最好的事情就是指定一般行为。有什么办法可以指定每个粒子的起始颜色和位置吗?

最佳答案

这可以让您基本了解我在评论中的意思。但请记住,它未经测试,如果发生帧速率下降,我不确定它会如何表现。
此示例每秒创建 5 个粒子,沿给定圆的周长按顺序(逆时针方向)添加它们。每个粒子都有不同的预定义颜色。您可以使用设置结构属性来更改粒子生成速度或增加或减少要发射的粒子数量。
几乎所有内容都被评论了,所以我想你会没事的:
swift 2

import SpriteKit

struct Settings {
    
    static var numberOfParticles = 30
    static var particleBirthRate:CGFloat = 5   //Means 5 particles per second, 0.2 means one particle in 5 seconds etc.
}

class GameScene: SKScene {
    
    var positions       = [CGPoint]()
    var colors          = [SKColor]()
    
    var emitterNode:SKEmitterNode?
    
    var currentPosition = 0
    
    override func didMoveToView(view: SKView) {
        
        backgroundColor = .blackColor()
        
      
        emitterNode = SKEmitterNode(fileNamed: "rain.sks")
      
        if let emitter = emitterNode {
            
            emitter.position =  CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
            emitter.particleBirthRate = Settings.particleBirthRate
            addChild(emitter)
            
            
            let radius = 50.0
            let center = CGPointZero
            
            for var i = 0; i <= Settings.numberOfParticles; i++ {
                
                //Randomize color
                colors.append(SKColor(red: 0.78, green: CGFloat(i*8)/255.0, blue: 0.38, alpha: 1))
                
                //Create some points on a perimeter of a given circle (radius = 40)
                let angle = Double(i) * 2.0 * M_PI / Double(Settings.numberOfParticles)
                let x = radius * cos(angle)
                let y = radius * sin(angle)
                
                
                let currentParticlePosition = CGPointMake(CGFloat(x) + center.x, CGFloat(y) + center.y)
                
                positions.append(currentParticlePosition)
                
                if i == 1 {
                    /*
                    Set start position for the first particle.
                    particlePosition is starting position for each particle in the emitter's coordinate space. Defaults to (0.0, 0,0).
                    */
                    emitter.particlePosition = positions[0]
                    emitter.particleColor = colors[0]
                    
                    self.currentPosition++
                }
                
            }
            
            // Added just for debugging purposes to show positions for every particle.
            for particlePosition in positions {
                
                let sprite = SKSpriteNode(color: SKColor.orangeColor(), size: CGSize(width: 1, height: 1))
                sprite.position = convertPoint(particlePosition, fromNode:emitter)
                sprite.zPosition = 2
                addChild(sprite)
            }
            
            
            let block = SKAction.runBlock({
                
                // Prevent strong reference cycles.
                [unowned self] in
                
                if self.currentPosition < self.positions.count {
                    
                    // Set color for the next particle
                    emitter.particleColor = self.colors[self.currentPosition]
                    
                    // Set position for the next particle. Keep in mind that particlePosition is a point in the emitter's coordinate space.
                    emitter.particlePosition = self.positions[self.currentPosition++]
                    
                }else {
                    
                    //Stop the action
                    self.removeActionForKey("emitting")
                    emitter.particleBirthRate = 0
                }
                
           })
            
            
            // particleBirthRate is a rate at which new particles are generated, in particles per second. Defaults to 0.0.
            
            let rate = NSTimeInterval(CGFloat(1.0) / Settings.particleBirthRate)
            
            let sequence = SKAction.sequence([SKAction.waitForDuration(rate), block])
            
            let repeatAction = SKAction.repeatActionForever(sequence)
            
            
            runAction(repeatAction, withKey: "emitting")
        }
        
    }
}
swift 3.1
import SpriteKit

struct Settings {

    static var numberOfParticles = 30
    static var particleBirthRate:CGFloat = 5   //Means 5 particles per second, 0.2 means one particle in 5 seconds etc.
}

class GameScene: SKScene {

    var positions = [CGPoint]()
    var colors = [SKColor]()

    var emitterNode: SKEmitterNode?

    var currentPosition = 0

    override func didMove(to view: SKView) {

        backgroundColor = SKColor.black


        emitterNode = SKEmitterNode(fileNamed: "rain.sks")

        if let emitter = emitterNode {

            emitter.position = CGPoint(x: frame.midX, y: frame.midY)
            emitter.particleBirthRate = Settings.particleBirthRate
            addChild(emitter)


            let radius = 50.0
            let center = CGPoint.zero

            for var i in 0...Settings.numberOfParticles {

                //Randomize color
                colors.append(SKColor(red: 0.78, green: CGFloat(i * 8) / 255.0, blue: 0.38, alpha: 1))

                //Create some points on a perimeter of a given circle (radius = 40)
                let angle = Double(i) * 2.0 * Double.pi / Double(Settings.numberOfParticles)
                let x = radius * cos(angle)
                let y = radius * sin(angle)


                let currentParticlePosition = CGPoint.init(x: CGFloat(x) + center.x, y: CGFloat(y) + center.y)

                positions.append(currentParticlePosition)

                if i == 1 {
                    /*
                    Set start position for the first particle.
                    particlePosition is starting position for each particle in the emitter's coordinate space. Defaults to (0.0, 0,0).
                    */
                    emitter.particlePosition = positions[0]
                    emitter.particleColor = colors[0]

                    self.currentPosition += 1
                }

            }

            // Added just for debugging purposes to show positions for every particle.
            for particlePosition in positions {

                let sprite = SKSpriteNode(color: SKColor.orange, size: CGSize(width: 1, height: 1))
                sprite.position = convert(particlePosition, from: emitter)
                sprite.zPosition = 2
                addChild(sprite)
            }


            let block = SKAction.run({

                // Prevent strong reference cycles.
                [unowned self] in

                if self.currentPosition < self.positions.count {

                    // Set color for the next particle
                    emitter.particleColor = self.colors[self.currentPosition]

                    // Set position for the next particle. Keep in mind that particlePosition is a point in the emitter's coordinate space.
                    emitter.particlePosition = self.positions[self.currentPosition]

                    self.currentPosition += 1

                } else {

                    //Stop the action
                    self.removeAction(forKey: "emitting")
                    emitter.particleBirthRate = 0
                }

            })


            // particleBirthRate is a rate at which new particles are generated, in particles per second. Defaults to 0.0.

            let rate = TimeInterval(CGFloat(1.0) / Settings.particleBirthRate)

            let sequence = SKAction.sequence([SKAction.wait(forDuration: rate), block])

            let repeatAction = SKAction.repeatForever(sequence)


            run(repeatAction, withKey: "emitting")
        }

    }
}
添加橙色点只是为了调试目的,如果您愿意,可以删除该部分。
就我个人而言,我会说你想得太多了,但我可能是错的,因为没有明确描述你想要做什么以及如何使用它。请记住,SpriteKit 可以以非常高效的方式在单个绘制调用中渲染一堆 Sprite 。如果谨慎使用,SKEmitterNode 也是如此。还有,不要小看SKEmitterNode ...实际上它是非常可配置的。
这是Particle Emitter Editor的设置:
Particle Emitter Editor
无论如何,这是最终结果:
emitter
请注意,节点数来自用于调试的橙色 SKSpriteNodes。如果删除它们,您将看到只有一个节点添加到场景中(发射器节点)。

关于ios - 适用于 iOS 的自定义粒子系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34900203/

相关文章:

javascript - 粒子(用构造函数创建)在碰撞时扩展和消失

ios - 在 OSX : IOBluetooth or CoreBluetooth? 上模拟 HID

ios - 更新 UITableViewCell labelText 文字问题

ios - 如何根据 Sprite Kit 中的设备更改屏幕大小?

c++ - 将粒子位置(glm vec3s)顶点传递给顶点缓冲区对象

c# - 更改粒子系统 Material Unity 3D脚本

ios - 带有旋转表面的 OpenGL ES 2.0 工件

ios - 在拖动期间暂时禁用 UITableView 滚动

ios - SKShapeNode : How to set String to name of SKShapeNode

swift - 将 SKSpriteNode 旋转到另一个 SKSpriteNode