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

我想在iOS使用sprite工具包创build一个粒子系统,在这里我定义了每个粒子的颜色。 据我所知,现有的SKEmitterNode是不可能的。 看来我能做的最好的是指定一般行为。 有什么办法可以指定每个粒子的起始颜色和位置吗?

这可以给你一个基本的想法,我的意思是在我的意见。 但请记住,它是未经testing的,我不知道如果帧速率下降将如何performance。

这个例子每秒创build5个粒子,沿着给定圆的周边顺序(逆时针方向)添加它们。 每个粒子将具有不同的预定义颜色。 您可以使用设置结构属性来改变粒子产卵速度,或者增加或减less要发射的粒子数量。

几乎所有的东西都评论,所以我想你会没事的:

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") } } } 

添加橙色点仅用于debugging目的,如果您愿意,可以删除该部分。

就我个人而言,我想说的是,你正在反思这个问题,但是我可能是错的,因为没有明确的描述你正在做什么以及如何使用它。 请记住,SpriteKit可以以非常高效的方式在一次绘制调用中渲染一组精灵。 如果谨慎使用,则与SKEmitterNode一样。 另外,不要低估SKEmitterNode …实际上它是非常可configuration的。

这里是粒子发射器编辑器的设置:

粒子发射器编辑器

无论如何,这是最后的结果:

发射器

请注意,节点数来自用于debugging的橙色SKSpriteNodes。 如果删除它们,您将看到只有一个节点添加到场景(发射器节点)。

你想要的是完全可能的,甚至可能是实时的。 不幸的是要做这样的事情,你所描述的移动粒子作为每个像素的粒子的方式最好用像素着色器来完成。 我不知道一个干净的方法,它可以让你用像素着色器在场景的顶部绘制,否则你只需要一个像素着色器,将像素和像素着色器从中心移出。 我个人不会尝试这样做,除非我用我自己的自定义游戏引擎来代替spritekit构build游戏。

这就是说,我不知道在大多数情况下,每像素扩散的像素是最好的。 特别是如果你有卡通艺术。 许多stream行的游戏实际上会为他们期望着色的物体碎片制造精灵。 所以就像是一架飞机,你可能会有一个翅膀的精灵,甚至可能有电线挂在这个。 然后,当飞机破碎的时候,把它从场景中移出,用与飞机形状相同的部件来代替这个区域… Sorta就像一个拼图。 这可能需要一些调整。 然后你可以将skphysicsbodies添加到所有这些作品中,并且有力量将它们推向四面八方。 这也并不意味着每个像素都得到一个节点。 我会build议创造性地把它分成10块以下。

而旋风说,你可以通过各种方式使事情看起来像“像”,它实际上是通过使用发射器节点解体。 只是使产卵区域更大,尽量模仿颜色。 为了使船消失,你可能会淡化? 还是马布爆炸精灵呢? 通常使用实时特效和物理,或者使用vfx,更多的是使它看起来像现实,然后模拟真实。 有时你必须使用欺骗手段才能使事情看起来很好,并且能够实时运行。

如果你想看看这可能看起来,我会build议看像jetpac兜风游戏。

祝你好运!