如何使用 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】:出于可见性原因将其放在这里。
关于.clear
backgroundColor
用户的答案是正确的,除了您还必须将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 中使用 SKEmitterNode 和粒子创建轨迹
SceneKit:在 SCNView 上渲染 SpriteKit 粒子系统时应用程序崩溃,当所有代码似乎都是系统代码的一部分时如何调试