0

I have 9 blocks on screen (BlockView is just a subclass of view with some properties to keep track of things), and I want to add a smoke particle emitter behind the top of each block to add some smoke rising from the tops of each block. I create a view to hold the block and the particle emitter, and bring the block in front of the subviews so the block is in front. However, this causes my device (iphone 6) to be incredibly laggy and very difficult to move the blocks with a pan gesture.

SmokeParticles.sks: birthrate of 3 (max set to 0), lifetime of 10 (100 range), position range set in code.

My code for adding a particle emitter to each view is below (I'm not very good with particle emitters so any advice is appreciated! :D)

    - (void)addEffectForSingleBlock:(BlockView *)view
{
    CGFloat spaceBetweenBlocksHeight = (self.SPACE_TO_WALLS * self.view.frame.size.height + self.SPACE_BETWEEN_BLOCKS*self.view.frame.size.width + self.WIDTH_OF_BLOCK*self.view.frame.size.height) - (self.HEIGHT_OF_BLOCK*self.view.frame.size.height + self.SPACE_TO_WALLS * self.view.frame.size.height);
    view.alpha = 1.0;
    CGRect frame2 = [view convertRect:view.bounds toView:self.view];
    UIView * viewLarge = [[UIView alloc] initWithFrame:frame2];
    [self.view addSubview:viewLarge];
    CGRect frame1 = [view convertRect:view.bounds toView:viewLarge];
    view.frame = frame1;
    [viewLarge addSubview:view];
    SKEmitterNode *burstNode = [self particleEmitterWithName:@"SmokeParticles"];
    CGRect frame = CGRectMake(view.bounds.origin.x-self.SPACE_BETWEEN_BLOCKS*self.view.frame.size.width, view.bounds.origin.y-self.SPACE_BETWEEN_BLOCKS_HEIGHT, view.bounds.size.width+self.SPACE_BETWEEN_BLOCKS*self.view.frame.size.width, view.bounds.size.height/2);
    SKView *skView = [[SKView alloc] initWithFrame:frame];
    [viewLarge addSubview:skView];
    SKScene *skScene = [SKScene sceneWithSize:skView.frame.size];
    [skScene addChild:burstNode];
    [viewLarge bringSubviewToFront:view];
    [burstNode     setParticlePositionRange:CGVectorMake(skView.frame.size.width/5, skView.frame.size.height/100.0)];
    skView.allowsTransparency = YES;
    skScene.backgroundColor = [UIColor clearColor];
    skView.backgroundColor = [UIColor clearColor];
    [skView presentScene:skScene];
    [burstNode setPosition:CGPointMake(skView.frame.size.width/2, -skView.frame.size.height*0.25)];
}
jbug123
  • 33
  • 6
  • Well, start by reducing particle count. If I calculate 3 * 60 fps * 10 seconds I get a total count of 1800 particles per emitter, unless the max particle count limit is set lower than that. That's *a frickin' lot of particles*. A couple hundred particles total (all emitters added together) will have to do. – CodeSmile Feb 19 '15 at 10:07
  • Thanks for the response! Sorry but I'm really new to this particle stuff. If it's a birth rate of 3, lifetime of 10 (though I guess the range may make it way more), and there's 9 blocks, wouldn't it be 3*10*9 particles after 10 seconds? Why do you multiply the number of particles by 60? – jbug123 Feb 19 '15 at 10:42
  • Also, if I make a general flame.sks file in Xcode, its default settings are 455 birthrate and lifetime of 2.5 --> doesn't that mean that there's 1100 particles on screen after 2.5 seconds for one default flame emitter? Are the default settings not feasible to implement in an app, especially if I want 2 flames? – jbug123 Feb 19 '15 at 10:45
  • Try using the background as an SKView and adding a single Scene to it. Then add the emitter nodes to this scene. – rakeshbs Feb 19 '15 at 14:17
  • I thought the birthRate is measured in frames but docs say it's particles per second, so I was wrong there. – CodeSmile Feb 20 '15 at 08:39
  • SceneKit is a hungry beast... Can you work it so you only have one instance of it and overlay it over the whole screen and add nodes that match the positions of the blocks? – Chris Jun 13 '15 at 09:47

1 Answers1

0

I realize that this is an old question, but I recently learned something that could be helpful to others and decided to share it here because it is relevant (I think).

I'll assume your BlockView is a subclass of UIView (if it is not, this will not help you, sorry). A view performs a lot of unnecessary calculations each frame (for example, each view checks if someone tapped on it). When creating a game you should use as fewer UIViews as possible (that's why all other commenters recommended you to use only one SKView and make each Block a SKSpriteNode, which is not a view). But, if you need to use some other kind of object or you do not want to use SpriteKit (or SceneKit for 3D objects), then try using CALayers inside one single UIView (for example, one case where you would prefer to use CALayers instead of SpriteKit is to increase backwards compatibility with older iOS versions as SpriteKit needs iOS 7).

Mr. John Blanco explains the CALayer approach very well in his View vs. Layers (including Clock Demo).

RoberRM
  • 883
  • 9
  • 18