如何使用 iOS 7 SpriteKit 粒子向非游戏的 iOS 应用程序添加粒子效果?

Posted

技术标签:

【中文标题】如何使用 iOS 7 SpriteKit 粒子向非游戏的 iOS 应用程序添加粒子效果?【英文标题】:How to add particle effects to an iOS App that is not a game using iOS 7 SpriteKit Particle? 【发布时间】:2013-11-06 09:40:24 【问题描述】:

我需要在我的应用程序中添加雨粒子效果,我一直很难找到实际执行这个想法的方法。

我尝试遵循此 CALayer 方法教程:Link,但考虑到 Xcode 5 中提供的新 ios 7 SpriteKit 粒子发射器,我不太确定这是否是最佳方法。

我已经创建了 .sks 文件并且它在我的层次结构中,但我仍然无法将它添加到我的故事板/项目中。

话虽如此,究竟如何将 SpriteKit 粒子 (sks) 添加到我的视图中?由于我不是游戏开发人员,所以我对 SpriteKit 框架中的场景、分层等完全不熟悉。 我需要尽可能多的详细信息和示例代码,以便我能弄清楚这一点

更新: 我已按照 SO 成员的回答中提供的方向进行操作:AyatollahAndy,请在下面查看他的回答。虽然我能够在我的view 中显示SKScene,但当收到任何触摸事件时,应用程序就会崩溃。我得到以下信息:

谢谢

【问题讨论】:

我很高兴听到在我的应用程序中没有 SpriteKit 的“整个包”就可以实现这一点,话虽如此 -> 我如何将所述粒子添加到普通视图? O 已经生成了.sks 文件。 呃,是的,你必须与 SpriteKit.framework 链接,意思是“整个包”。这并不重要,因为这个库是内置在 iOS 中的,不会增加应用程序的大小。然而,要渲染粒子效果,您必须使用 SKScene 创建一个 SKView 并将粒子效果放在上面。所有其他视图都在顶部或下方,除非其他所有内容也由 Sprite Kit 节点组成。 为什么不添加一个“部分透明的雨滴覆盖”并应用一个 [UIView animationXXX:]? @dklt 因为这看起来不如从发射器随机生成的粒子。 任何人来到这个非常老的问题,我会敦促您向下滚动到我的答案(“2017”)或任何比我的答案更新的答案。幸运的是,这些天现在很容易...... 【参考方案1】:

在您的UIView 中创建SKScene 以添加SKEmitterNode 粒子效果。

一种方法:

1.在情节提要中(或以编程方式,如果您愿意)在现有视图之上添加一个视图对象,并根据您的需要调整它的大小。 2.将新视图的class改为SKView 3.在您的视图控制器.h 文件中为SKView 创建一个属性:

@property IBOutlet SKView *skView;

4.将情节提要上的 SKView 链接到 skView 属性。 5.创建一个新类,继承SKScene。 MyScene.h 看起来像:

#import <SpriteKit/SpriteKit.h>
@interface MyScene : SKScene
@end

下面的 MyScene.m 包含在任何时间和任何地方触摸 SKView 时创建粒子效果的代码。

#import "MyScene.h"

@implementation MyScene

-(id)initWithSize:(CGSize)size     
    if (self = [super initWithSize:size]) 
        /* Setup your scene here */

        self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
        SKLabelNode *myLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
        myLabel.text = @"Hello, World!";
        myLabel.fontSize = 30;
        myLabel.position = CGPointMake(CGRectGetMidX(self.frame),
                                   CGRectGetMidY(self.frame));

        [self addChild:myLabel];
    
    return self;


//particle explosion - uses MyParticle.sks
- (SKEmitterNode *) newExplosion: (float)posX : (float) posy

    SKEmitterNode *emitter =  [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSBundle mainBundle] pathForResource:@"MyParticle" ofType:@"sks"]];
    emitter.position = CGPointMake(posX,posy);
    emitter.name = @"explosion";
    emitter.targetNode = self.scene;
    emitter.numParticlesToEmit = 1000;
    emitter.zPosition=2.0;
    return emitter;


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
    /* Called when a touch begins */

    for (UITouch *touch in touches) 
        CGPoint location = [touch locationInNode:self];
        //add effect at touch location
        [self addChild:[self newExplosion:location.x : location.y]];
    


-(void)update:(CFTimeInterval)currentTime 
    /* Called before each frame is rendered */


@end

6.在您的主视图控制器中,包含您的场景类:

#import "MyScene.h"

并向 viewDidLoad 添加代码以初始化 SKView:

- (void)viewDidLoad

    [super viewDidLoad];

    // Configure the SKView
    SKView * skView = _skView;
    skView.showsFPS = YES;
    skView.showsNodeCount = YES;

    // Create and configure the scene.
    SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
    scene.scaleMode = SKSceneScaleModeAspectFill;

    // Present the scene.
    [skView presentScene:scene];

然后你应该在你的主要UIView 中有一个工作的SKScene

【讨论】:

我已经尝试过了,虽然应用程序最初启动时在我看来运行良好的“Hello World”场景,但当我“触摸”应用程序崩溃并引发错误时,请参阅更新详细问题。 ***.com/questions/19780215/… 如何去除黑色背景?我制作了 skView 和场景 backgroundColor 属性 clearColor 但我仍然得到黑色背景。 Sprite Kit 视图不能透明。如果您想将粒子效果与 UIKit 视图层次结构集成,CAEmitterLayer 是您的最佳选择 - 否则您将在 Sprite Kit 中重新实现您自己的 UI,这可能不是您时间的最佳利用。 我希望 *** 的所有答案都清晰易懂。非常感谢!!【参考方案2】:

在现代 Xcode 中:

现在这很容易。

1。在Xcode中,点击新建

“SpriteKit 粒子文件”

它将是一个 .sks 文件。

(注意:选择“SceneKit 粒子系统文件”。选择“SpriteKit 粒子文件” .)

单击一次.sks 文件。请注意右侧的许多控件

粒子实际上会移动,这是一个活生生的预览。任何可以用粒子完成的事情,你都可以做到。这就像在游戏引擎中使用粒子,只是性能提高了 180 亿倍。

2。随心所欲地拥有任何普通的 UIView:

@IBOutlet weak var teste: UIView! // totally ordinary UIView

3。只需使用以下代码链接:

下面的代码将把你的新粒子系统放在里面,普通的 UIView “teste”:

import SpriteKit ...


let sk: SKView = SKView()
sk.frame = teste.bounds
sk.backgroundColor = .clear
teste.addSubview(sk)

let scene: SKScene = SKScene(size: teste.bounds.size)
scene.scaleMode = .aspectFit
scene.backgroundColor = .clear

let en = SKEmitterNode(fileNamed: "SimpleSpark.sks")
en?.position = sk.center

scene.addChild(en!)
sk.presentScene(scene)

将此添加到您想要的任何内容中。

如果您想要一个闪闪发光的按钮,请将其添加到按钮中。

如果您希望整个屏幕呈现彩虹,请将其添加到全屏视图。

就这么简单。


SpriteKit Particle File 控件使用示例:

假设你想要迸发火花,然后结束。

将最大值设置为 50...

提示 - 如果您的效果“完成”(即,它不是循环),您似乎可以在完成后简单地摆脱 SKScene。像这样:

    ...
    scene.addChild(en!)
    sk.presentScene(scene)
    
    delay(1.5)  sk.removeFromSuperview() 

最后那一行代码似乎把一切都清理干净了。


顺便说一句,如果您想要关于粒子系统的奇妙想法,一个好主意是单击 Unity“资产商店”,各种 粒子艺术家 在这里买卖粒子系统。他们的工作会给你很棒的想法。

只需点击右侧列表中的“粒子”即可;观看视频。 (Innovative examples.)


注意! Apple 将实现它,以便您可以非常简单地在情节提要中制作 SKView,然后选择 .sks 场景。然而..

...它还不行!截至这篇文章的最后一次编辑(2020 年),它仍然被破坏。所以你需要上面的代码片段。

【讨论】:

你让我很开心。完美运行! @Fattie 绝对。!另外,你从哪里学来的。我找不到一个参考来学习这个。非常感谢,你提供了这个:) 我已经调整了速度并添加了颜色。 sks 文件的一切看起来都很好。我希望我能看到的内容显示在我添加了 SKView 的 UIView 中。我使用了确切的代码并尝试了很多东西,但我无法弄清楚为什么它没有被显示。我在代码中做其他所有事情,我删除了我的主故事板。 这是我做的第一件事。我对 safeAreaLayout 设置了一个约束,将颜色从白色更改为透明到蓝色,然后放置一个计时器,看到它被移除并且 UIView 是完美的。它必须与使用 UIView.addSubview(SKView) 显示 SKView 的 UIView 有关,或者只是添加要显示的 SKview 这很奇怪,因为那个应用程序还没有连接到任何东西。在将粒子发射器转移到我需要的地方之前,我只是在它自己的 VC 上测试粒子发射器。忘记给你点赞了,我现在就给你点赞✌?【参考方案3】:

您可以将 SKView 添加为 UIKit 层次结构中的子视图。像下面这样的函数可以工作,允许你创建一个 UIImageView 效果作为子视图,然后你可以将它添加到你的主视图中。请务必链接到 SpriteKit。

UIImageView *NewEffectUIImageViewWithFrame(CGRect frame)

    UIImageView *tempView = [[UIImageView alloc] initWithFrame:frame];

    SKView *skView = [[SKView alloc] initWithFrame:CGRectMake(0.0, 0.0, frame.size.width, frame.size.height)];
    [tempView addSubview:skView];

    SKScene *skScene = [SKScene sceneWithSize:skView.frame.size];
    skScene.scaleMode = SKSceneScaleModeAspectFill;
    skScene.backgroundColor = [UIColor clearColor];

    SKEmitterNode *emitter =  [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSBundle mainBundle] pathForResource:@"SparkParticle" ofType:@"sks"]];
    emitter.position = CGPointMake(frame.size.width*0.5,0.0);

    [skScene addChild:emitter];
    [skView presentScene:skScene];

    return tempView;

最后,如果您只需要一个发射器,那么创建CAEmitterLayer 并将其作为子层添加到您的 UIView 可能会更容易。当然,这意味着您必须以编程方式创建CAEmitterLayer,并且不能使用酷炫的 Xcode 粒子编辑器...

【讨论】:

imageview的背景是黑色的。有没有办法说清楚,以便完美地与superview合并?【参考方案4】:

这里的方法完全不同的方法来尝试。我的朋友给了我这个很酷的方法。使用CAEmitterCell。全部在代码中!看起来你需要一个 spark.png 图像。

extension UIView 
    final public func ignite() 
        let emitter = CAEmitterLayer()
        emitter.frame = self.bounds
        emitter.renderMode = kCAEmitterLayerAdditive
        emitter.emitterPosition = self.center
        self.layer.addSublayer(emitter)

        let cell = CAEmitterCell()
        let bundle = Bundle.init(for: UIColor.self)
        let image = UIImage(named: "spark", in: bundle, compatibleWith: traitCollection)

        cell.contents = image?.cgImage
        cell.birthRate = 1500
        cell.lifetime = 5.0
        cell.color = UIColor(red: 1.0, green: 0.5, blue: 0.1, alpha: 1).cgColor
        cell.alphaSpeed = -0.4
        cell.velocity = 50
        cell.velocityRange = 250
        cell.emissionRange = CGFloat.pi * 2.0

        emitter.emitterCells = [cell]
    

享受吧。

【讨论】:

【参考方案5】:

其实有一种不用SpriteKit就可以添加粒子的方法——CoreAnimation的CAEmitterCells。

通过这种方式,您可以轻松地在 UIView 中添加粒子。如果您想玩转参数并轻松获取代码,请获取此应用 (Particle X)。

它还支持 SpriteKit,所以如果你想在旅途中玩耍或设计粒子并立即获取它的代码,这个应用程序就是解决方案。

PS。如果您没有注意到,我是该应用程序的开发人员 - 在设计应用程序和游戏时自己使用它。 :)

【讨论】:

不幸的是,CAEmitterLayer 缺少很多 SpriteKit 的功能。例如,您不能创建淡入然后淡出的粒子。 CAEmitterLayer 要么全有,要么全无。您也不能使用 SpriteKit 的“advanceSimulationTime”等价物预烘焙场景的粒子。但除此之外,CAEmitterLayer 是比 SpriteKit 更好的解决方案,用于“即时”效果,如粒子爆发。【参考方案6】:

出于可见性原因将其放在这里。

关于.clearbackgroundColor 用户的答案是正确的,除了您还必须将SKView 上的allowsTransparency 属性设置为“真”。

skView.allowsTransparency = true
skView.backgroundColor = .clear  // (not nil)
scene.backgroundColor = .clear

如果您没有将allowsTransparency 设置为true,并且您将SKView 布局在UIImageView 上,那么合成引擎将很适合,并且会发送您的GPU 红线,即使只画了一个粒子。 (在模拟器中,CPU 会出现峰值。)

【讨论】:

【参考方案7】:

您不能直接在UIView 中使用粒子效果。

SKEmitterNode 必须位于使用节点场景 (SKScene) 定义的节点树中。场景节点运行一个动画循环,渲染节点树的内容以供显示。 UIView 是静态的,无法使用。

但是,您可能可以在 UIView 中创建一个场景,但我从未尝试过这样做。

【讨论】:

您可以非常轻松地在普通 UIView 中添加粒子视图!请看下面我的回答

以上是关于如何使用 iOS 7 SpriteKit 粒子向非游戏的 iOS 应用程序添加粒子效果?的主要内容,如果未能解决你的问题,请参考以下文章

使用 SpriteKit 的 Node 路径粒子效果

SpriteKit代码动态调整sks文件中粒子的颜色

在 SpriteKit 中使用 SKEmitterNode 和粒子创建轨迹

更改 spritekit 粒子颜色

SceneKit:在 SCNView 上渲染 SpriteKit 粒子系统时应用程序崩溃,当所有代码似乎都是系统代码的一部分时如何调试

是否可以在Spritekit项目中以编程方式更改纹理色调?