Spritekit and OpenGL: Smooth Smoke Trail

I want to achieve this effect in my Spritekit game, where the character is smooth .

See the coin trail in the helicopter: enter image description here

And this trace of the hero in Jupiter. Jump: enter image description here

Or this super smooth track of the hero in Ski Safari: enter image description here

Perhaps this is a standard feature in other games? I think the spritekit particle emitter will only provide a locked trace, not a smooth trace. Should I use some special sprite shader? Any other thought ideas?

+5
source share
1 answer

Your question does not include the key question, which is the type of movement used. My answer is based on touching the screen for the destination, but another alternative is to use kernel movement. No matter which method is used, the basic principles of the code remain unchanged. Only the implementation will change.

I used the rectangle tail image in my example because I wanted you to be able to copy and run the sample code. You should replace the rectangle with a circle image / texture to give smoother sides of the tail.

Changing the fadeOutDuration value will result in a longer or shorter long tail.

Modifying stepDivider will result in more or less nodes in the tail.

#import "GameScene.h" @implementation GameScene { SKSpriteNode *playerNode; CGPoint destinationPoint; NSMutableArray *myArray; NSMutableArray *myDiscardArray; BOOL working; int numberOfSteps; float xIncrement; float yIncrement; float fadeOutDuration; int stepsDivider; } -(void)didMoveToView:(SKView *)view { self.backgroundColor = [SKColor blackColor]; playerNode = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(30, 30)]; playerNode.position = CGPointMake(200, 200); [self addChild:playerNode]; myArray = [[NSMutableArray alloc] init]; myDiscardArray = [[NSMutableArray alloc] init]; working = false; fadeOutDuration = 0.5; stepsDivider = 10; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch *touch in touches) { CGPoint location = [touch locationInNode:self]; if(working == false) { destinationPoint = location; if(fabsf(location.x - playerNode.position.x) > fabsf(location.y - playerNode.position.y)) { numberOfSteps = fabsf(location.x - playerNode.position.x) / 10; } else { numberOfSteps = fabsf(location.y - playerNode.position.y) / 10; } xIncrement = (location.x - playerNode.position.x) / numberOfSteps; yIncrement = (location.y - playerNode.position.y) / numberOfSteps; working = true; } } } -(void)update:(CFTimeInterval)currentTime { if (working == true) { // create trail node at current player position SKSpriteNode *myNode = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(30, 30)]; myNode.position = playerNode.position; [self addChild:myNode]; [myArray addObject:myNode]; [myNode runAction:[SKAction fadeOutWithDuration:fadeOutDuration]]; // check array for any nodes with zero alpha for(SKSpriteNode *object in myArray) { if(object.alpha == 0) { [myDiscardArray addObject:object]; } } // remove zero alpha nodes if([myDiscardArray count] > 0) { [myArray removeObjectsInArray:myDiscardArray]; [myDiscardArray removeAllObjects]; } // update player new position playerNode.position = CGPointMake(playerNode.position.x+xIncrement, playerNode.position.y+yIncrement); // check if player has arrived at destination if(((int)playerNode.position.x == (int)destinationPoint.x) && ((int)playerNode.position.y == (int)destinationPoint.y)) { working = false; } } } @end 
+4
source

Source: https://habr.com/ru/post/1215646/


All Articles