【问题标题】:Sprite Kit: Anchor Point is Changing Sprite`s actual PositionSprite Kit:锚点正在改变 Sprite 的实际位置
【发布时间】:2014-07-30 07:47:02
【问题描述】:

请帮我解决这个困惑。

来自 Sprite Kit 编程指南:

sprite 节点的 anchorPoint 属性决定了节点中的哪个点 frame 位于精灵的位置。

我对此的理解是,如果我改变锚点,精灵的位置应该保持不变,只有纹理渲染应该相应地移动。

但是当我设置锚点时,我的精灵的位置实际上发生了变化!看看这个sn-p:

/* debug */
if (self.currentState == self.editState) {
    printf("B: relativeAnchorPoint = %.02f,%.02f  ", relativeAnchorPoint.x, relativeAnchorPoint.y);
    printf("position = %.02f,%.02f\n",self.position.x, self.position.y);
}

[self setAnchorPoint:relativeAnchorPoint];

/* debug */
if (self.currentState == self.editState) {
    printf("A: relativeAnchorPoint = %.02f,%.02f  ", relativeAnchorPoint.x, relativeAnchorPoint.y);
    printf("position = %.02f,%.02f\n",self.position.x, self.position.y);
}

输出:

A:relativeAnchorPoint = 0.65,0.48 位置 = 1532.00,384.00

B:relativeAnchorPoint = 0.65,0.48 位置 = 1583.00,384.00

我错过了什么?

提前致谢

*编辑:附加信息:* 只有当我的精灵将 xScale 设置为 -1 以反转图像时才会发生这种情况

【问题讨论】:

  • 精灵的位置是锚点,所以当你改变锚点时它会移动。
  • @Code Monkey 是一个误解,节点的位置是它所在的位置,anchorPoint 不会(不应该)改变节点的位置,它只确定位置 - 相对于节点的位置 -绘制节点的纹理
  • @LearnCocos2D 感谢您的澄清。
  • 也许最好避免将 xScale 设置为 -1,而是使用预览应用程序(工具 > 水平翻转)反转图像。
  • @CodeMonkey,图像反转必须即时完成,因为我不想在我的代码中拥有每个精灵的重复图像,这会浪费大量内存......跨度>

标签: ios sprite-kit anchorpoint


【解决方案1】:

我做了一个快速测试来确认你的观察,它确实是正确的。

随着 xScale 变为负值,anchorPoint 实际上会影响节点的位置

我倾向于将此视为一个错误,因为负 xScale 与 x 位置的增加之间似乎没有相关性。也不能算是正常行为。

只有在 xScale 已经为负数之后更改 anchorPoint 时才会发生这种情况。您可以设置anchorPoint,然后根据需要更改xScale,一切都会好起来的,位置不会改变。

我确认 Xcode 5.1 (iOS 7) 和 Xcode 6 beta (iOS 8 beta) 中都存在这个问题。

如果您在新创建的 Sprite Kit 项目中运行以下代码来代替其自动创建的 MyScene.m 文件,您会看到随着 anchorPoint 在 0.0 和 1.0 之间随机变化,精灵的位置始终保持不变,直到xScale 属性更改为负值。此时 position.x 开始显着增加。

#import "MyScene.h"

@implementation MyScene
{
    SKSpriteNode *sprite;
}
-(id) initWithSize:(CGSize)size
{
    if (self = [super initWithSize:size])
    {
        self.backgroundColor = [SKColor colorWithRed:0 green:0 blue:0.2 alpha:1];

        sprite = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
        sprite.position = CGPointMake(CGRectGetMidX(self.frame),
                                       CGRectGetMidY(self.frame));
        sprite.anchorPoint = CGPointMake(0.2, 0.7);
        [self addChild:sprite];

        SKAction *action = [SKAction scaleXTo:-1.0 duration:10];
        [sprite runAction:[SKAction repeatActionForever:action]];
    }
    return self;
}
-(void) update:(CFTimeInterval)currentTime
{
    sprite.anchorPoint = CGPointMake(arc4random_uniform(10000) / 10000.0,
                                     arc4random_uniform(10000) / 10000.0);

    NSLog(@"pos: {%.1f, %.1f}, xScale: %.3f, anchor: {%.2f, %.2f}",
          sprite.position.x, sprite.position.y, sprite.xScale,
          sprite.anchorPoint.x, sprite.anchorPoint.y);
}
@end

这个错误有一个解决方法:

如果 xScale 已经是负数,则反转它,然后设置锚点,然后重新反转 xScale。如果 yScale 也可能变为负数,您可能需要对它执行相同的操作。

以下更新方法包含此解决方法,我确认这可以按预期工作:

-(void) update:(CFTimeInterval)currentTime
{
    BOOL didInvert = NO;
    if (sprite.xScale < 0.0)
    {
        didInvert = YES;
        sprite.xScale *= -1.0;
    }

    sprite.anchorPoint = CGPointMake(arc4random_uniform(10000) / 10000.0,
                                     arc4random_uniform(10000) / 10000.0);

    if (didInvert)
    {
        sprite.xScale *= -1.0;
    }

    NSLog(@"pos: {%.1f, %.1f}, xScale: %.3f, anchor: {%.2f, %.2f}",
          sprite.position.x, sprite.position.y, sprite.xScale, 
          sprite.anchorPoint.x, sprite.anchorPoint.y);
}

sprite.position 现在在整个 scaleXTo 动作持续时间内保持不变。

【讨论】:

  • 您忘记在第一个 if 语句中设置 didInvert。
  • @LearnCocos2D,感谢您提供有关提示的工作。有没有办法将这种想法通知苹果?
  • 是的,这里:developer.apple.com/bug-reporting 请务必添加此帖子的链接,我认为它已经很好地解释了这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多