Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicating a particle emitter effect in Sprite Kit

Tags:

I need to have a particle emitters effects to appear duplicated in 2 spots (For split screen purposes), I am wondering if anybody has come across a way of doing this. My goal is to have this running on iOS 10. Here is what I have tried so far.

  1. Assigning targetNode to an SKNode and then copying SKNode every frame: targetNode does not work in iOS 10 for me.
  2. Assigning the particle emitter to an SKNode, and using view.textureFromNode to make a texture to copy every frame : takes 1/120th of a frame, too slow for me.
  3. Assigning a custom action to a particle node that duplicates the node into another SKNode : Actions will not run on iOS 10
  4. Copying the existing particle node in hopes that the seed is not random : The seed is random
  5. Tried copying the particle emitter on update : Particle just spawns at origin
  6. Tried SKReferenceNode : Just a copy of the emitter, runs on its own

The only option I am left for true emitting is writing my own particle emitter, which I am trying to avoid, so I am wondering if anybody else had this problem and knew of a solution to achieve desired effect.

The other thing I could do is prerendering the emitters, but this will take up a lot of texture memory if I go this route.

Edit: To help visualize, I drew a picture, The white border shows where the Split Screen happens. The black border shows where the scene wrapping happens. enter image description here

As of right now, both Player 1 and Player 2 are on the original scene.

Player 2 is walking right and is about to hit a world wrap to move him to the left hand side of the world, but he has not hit it yet. So I need to have a copy of the scene happening so that it visually looks like one scene. Since player 1 is still on the original scene, the original emitter needs to stay in place. Player 2 is going to have to see the same image happening in the copy, otherwise once he passes that border, a "glitchy" effect will happen, and the illusion of wrapping is now gone.

Final Result:

We just said F%%% it, Player 1 and Player 2 will be looking at different emitter nodes, we will just attach the emitters to each players camera when needed.

like image 863
Knight0fDragon Avatar asked Nov 04 '16 13:11

Knight0fDragon


Video Answer


1 Answers

This just works (I guess as intended), but I have no idea how much is performant or how it fits your needs and your current game. Anyways, maybe it can help you in some way. First, in your GameViewController...Split screen :)

#import "GameViewController.h" #import "GameScene.h"  @implementation GameViewController  - (void)viewDidLoad {     [super viewDidLoad];      // Configure the view.     SKView * leftSKView = (SKView *)self.leftScene;     leftSKView.ignoresSiblingOrder = YES;     leftSKView.showsFPS = YES;     leftSKView.showsNodeCount = YES;      SKView * rightSKView = (SKView *)self.rightScene;     rightSKView.ignoresSiblingOrder = YES;     rightSKView.showsFPS = YES;     rightSKView.showsNodeCount = YES;         // Create and configure the scene.     GameScene *scene = [GameScene nodeWithFileNamed:@"GameScene"];     scene.scaleMode = SKSceneScaleModeAspectFill;      // Present the scene.     [leftSKView presentScene:scene];     [rightSKView presentScene:scene];  } 

leftScene and rightScene are UIViews defined in a storyboard using autolayout to take half of a screen each. Also a class is changed to SKView (it was UIView). Pretty trivial...

Then in your game scene just add an emitter which will be shared between these two views. Because only one emitter is used, particles emitting (how they move) will be mirrored. So in game scene, just add a particle:

-(void)didMoveToView:(SKView *)view {     /* Setup your scene here */       SKEmitterNode *emitter =  [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSBundle mainBundle] pathForResource:@"MyParticle" ofType:@"sks"]];     emitter.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidX(self.frame));     emitter.name = @"explosion";     emitter.targetNode = self;     [self addChild:emitter]; } 

I know that you don't need all this code, but if this is what you want in some way, I will post it for completeness. And here is the result: enter image description here

like image 66
Whirlwind Avatar answered Oct 21 '22 07:10

Whirlwind