【问题标题】:SpriteKit conveyor beltSpriteKit 传送带
【发布时间】:2014-01-10 09:14:58
【问题描述】:

我正在尝试像这样使用 SpriteKit 创建传送带效果

我的第一反应是创建一个比屏幕更大的传送带图像,然后通过动作不断地反复移动它。但这似乎不太好,因为它取决于屏幕尺寸。

有没有更好的方法来做到这一点?

很明显,我想把东西(它会独立移动)放在传送带上,所以节点是一个 SKNode,其中有一个正在移动的子精灵节点。

更新:我希望传送带“视觉”移动;所以线条会朝着一个方向移动,给人一种运动的印象。

【问题讨论】:

    标签: ios iphone objective-c ios7 sprite-kit


    【解决方案1】:

    physicsBody 应用于所有需要在传送带上移动的精灵,并将affectedByGravity 属性设置为NO。

    在本例中,我假设代表传送带的 spriteNode 名为 conveyor。此外,所有需要移动的精灵节点都具有字符串“moveable”作为它们的name 属性。

    然后,在您的 -update: 方法中,

    -(void)update:(CFTimeInterval)currentTime
    {
        [self enumerateChildNodesWithName:@"moveable" usingBlock:^(SKNode *node, BOOL *stop{ 
            if ([node intersectsNode:conveyor])
            {
                [node.physicsBody applyForce:CGVectorMake(-1, 0)];
                //edit the vector to get the right force. This will be too fast.
            }
        }];
    }
    

    在此之后,只需将所需的精灵添加到正确的位置,您就会看到它们自己移动。

    对于动画,最好使用可以在精灵上循环的纹理数组。

    或者,您可以添加和删除一系列带有截面图像的小精灵,并像在传送带上移动精灵一样移动它们。

    【讨论】:

    • 您好,感谢您的反馈。我更新了我的问题。我正在寻找的效果是使传送带看起来像是在移动。就像这样randomfeature.co.uk/files/gimgs/47_quartet01.gif。什么是获得这种效果的好方法?
    • 在不同纹理之间循环时,可能很难使动画和对象同步(因此它们似乎以相同的速度移动)。但是这个效果用CoreAnimation很容易实现(有几种方法可以实现,搜索StackOverflow)。这个想法是设置view width = screen width + texture width,将x = -texture width移动到x = 0并重复。
    • @DarkDust 如果我理解正确,这种情况下的纹理必须大于屏幕才能正常工作,因此需要大图像(这就是我在想)
    • @akashg 有一个更好的解决方案,即小的重复截面图像;一个实现会很棒;理想情况下,我认为我们可以仅垂直应用重复纹理,然后每帧将其偏移一个增量;我不确定这是否可能
    • @TiborUdvari:不,纹理应该尽可能小,以使其可重复,然后您的视图应该重复绘制它。所以 view 会比屏幕大,texture 不会。
    【解决方案2】:

    @akashg 指出了在传送带上移动物体的解决方案,我给出的答案是如何使传送带看起来好像在移动

    一个建议和我最初的直觉是在场景中放置一个比屏幕更大的矩形并反复移动它。经过反思,我认为这不是一个好的解决方案,因为如果我们想在中间放置一条传送带,在某种程度上我们可以看到它的两端,如果没有额外的剪贴蒙版,这将是不可能的。

    理想的解决方案是将SKTexture 平铺在SKSpriteNode 上并仅偏移此纹理;但这似乎不适用于 Sprite Kit(无平铺机制)。

    所以基本上我所做的就是从类似 [tile][tile](2 次可重复的 tile)的纹理创建子纹理,我只是一个接一个地显示这些子纹理以创建动画。

    代码如下:

    - (SKSpriteNode *) newConveyor
    {
        SKTexture *conveyorTexture = [SKTexture textureWithImageNamed:@"testTextureDouble"];
        SKTexture *halfConveyorTexture = [SKTexture textureWithRect:CGRectMake(0.5, 0.0, 0.5, 1.0) inTexture:conveyorTexture];
    
        SKSpriteNode *conveyor = [SKSpriteNode spriteNodeWithTexture:halfConveyorTexture size:CGSizeMake(conveyorTexture.size.width/2, conveyorTexture.size.height)];
    
        NSArray *textureArray = [self horizontalTextureArrayForTxture:conveyorTexture];
        SKAction *moveAction = [SKAction animateWithTextures:textureArray timePerFrame:0.01 resize:NO restore:YES];
        [conveyor runAction:[SKAction repeatActionForever:moveAction]];
    
        return conveyor;
    }
    
    - (NSArray *) horizontalTextureArrayForTxture : (SKTexture *) texture
    {
        CGFloat deltaOnePixel = 1.0 / texture.size.width;
        int countSubtextures = texture.size.width / 2;
    
        NSMutableArray *textureArray = [[NSMutableArray alloc] initWithCapacity:countSubtextures];
    
        CGFloat offset = 0;
        for (int i = 0; i < countSubtextures; i++)
        {
            offset = i * deltaOnePixel;
            SKTexture *subTexture = [SKTexture textureWithRect:CGRectMake(offset, 0.0, 0.5, 1.0) inTexture:texture];
            [textureArray addObject:subTexture];
        }
    
        return [NSArray arrayWithArray:textureArray];
    }
    

    现在这仍然不理想,因为需要手动制作具有 2 个图块的图像。我们还可以编辑带有CIFilter 变换的SKTexture,它可能被用来创建这个带有2 个图块的纹理。

    除此之外,我认为这个解决方案更好,因为它不依赖于屏幕的大小并且内存效率高;但为了在整个屏幕上使用它,我必须创建更多 SKSpriteNode 对象,这些对象共享我使用过的 moveAction,因为根据此来源,Sprite Kit 无法进行平铺: How do you set a texture to tile in Sprite Kit

    我将尝试更新代码,以便可以使用多个SKSpriteNode 对象进行平铺。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-10
      • 2023-03-14
      • 1970-01-01
      • 2021-02-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多