Spritekit和OpenGL:流畅的烟雾痕迹

时间:2015-03-19 05:42:03

标签: opengl-es sprite-kit glsl skemitternode

我希望在我的Spritekit游戏中实现此效果,其中角色背后有平滑曲目。

在jetpack兜风中看到硬币背后的踪迹: enter image description here

在木星跳跃中英雄身后的这条小道: enter image description here

或者在Ski Safari中英雄背后的超级平滑路径: enter image description here

这似乎是其他游戏引擎的标准功能吗?我认为spritekit粒子发射器只会提供块状/标记的跟踪,而不是平滑的跟踪。我应该使用某种精灵自定义着色器吗?还有其他创造性的想法吗?

1 个答案:

答案 0 :(得分:4)

您的问题没有包含一个关键问题,即使用的移动类型。我的答案是基于触摸目标点的屏幕,但另一种选择是使用核心运动。无论使用哪种方法,基本代码主体都保持不变。只有实施才会改变。

我在我的示例中使用了矩形尾部图像,因为我希望您能够复制并运行示例代码。您应该用圆形图像/纹理替换矩形,以使尾部更平滑。

修改fadeOutDuration值将导致更长或更短的尾部。

修改stepsDivider会在尾部产生更多或更少的节点。

#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's 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's 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