Child SkShapeNode定位混乱

Child SkShapeNode positioning confusion

我已经为游戏的游戏结束场景编写了这段代码:

#import "GameOverScene.h"
#import "SharedInfo.h"
@implementation GameOverScene

-(void)didMoveToView:(SKView *)view {
    /* Setup your scene here */

    [self setupView];

}

-(void)showGameEndingWithGameInformation:(NSDictionary *)gameEndingInformation{

}
-(void)setupView{
    SKLabelNode *GOTitle = [SKLabelNode labelNodeWithFontNamed:@"Generica Bold"];
    GOTitle.fontSize = 40.f;
    NSString* text = [NSString stringWithFormat:@"GAME OVER"];
    [GOTitle setText:text];
    GOTitle.position = CGPointMake(CGRectGetMidX(self.frame), self.frame.size.height- GOTitle.frame.size.height*1.5);
    [GOTitle setFontColor:[[SharedInfo sharedManager]colorFromHexString:@"#2EB187"]];
    [self addChild: GOTitle];


    SKLabelNode *replayButton = [SKLabelNode labelNodeWithFontNamed:@"Quicksand-Bold"];
    replayButton.fontSize = 25.f;
    NSString* replayText = [NSString stringWithFormat:@"Play Again"];
    [replayButton setText:replayText];
    replayButton.name = kGOSceneReplayButton;
    replayButton.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)- self.frame.size.height/5);
    [replayButton setFontColor:[SKColor whiteColor]];
    SKShapeNode *bgNode = [SKShapeNode shapeNodeWithRectOfSize:replayButton.frame.size];
    [bgNode setFillColor:[UIColor redColor]];

    [replayButton addChild:bgNode];
    [self addChild:replayButton];

    NSLog(@"replay dimensions: %@",NSStringFromCGRect(replayButton.frame));
    SKLabelNode *returnButton = [SKLabelNode labelNodeWithFontNamed:@"Quicksand-Bold"];
    returnButton.fontSize = 25.f;

    NSString* returnText = [NSString stringWithFormat:@"Return To Main Menu"];
    [returnButton setText:returnText];
    returnButton.name = kGOSceneReturnToMainButton;
    returnButton.position = CGPointMake(CGRectGetMidX(self.frame), replayButton.position.y -self.frame.size.height/7  );
    [returnButton setFontColor:[SKColor whiteColor]];

    [self addChild:returnButton];

}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];
    SKNode *sprite = [self nodeAtPoint:location];

    NSLog(@"sprite name: %@",sprite.name);

    if ([sprite.name isEqualToString:kGOSceneReturnToMainButton]||[sprite.name isEqualToString:kGOSceneReturnToMainButton]) {
        //return to main menu or retry

        [self.gameEndingSceneDelegate goToScene:sprite.name withOptions:nil]; //Sort out the options later on. 

    }

}
@end

当我 运行 它时,我明白了:

有两个问题我真的很困惑。首先,为什么我在场景中有 8 个节点,而我实际上应该有 4 个节点?我认为有些东西正在加倍节点,但这只是一个猜测。

比较混乱的问题是红色SKShapeNode的定位。我读过缩放父节点可能会给子 SKShapeNode 带来问题,但我没有缩放任何东西。另外,为什么它把我的红色矩形放在一个随机位置(它不是父元素的中间,也不是与底部对应)。

非常感谢您提前提供的所有帮助。

更新 1:所以按照建议,我检查了我的方法是否被调用了两次,从而创建了重复项。运气不好,因为它只被调用一次。谜团依旧强大!

至于定位恶作剧,我稍微更改了代码以设置红色矩形的位置以匹配其父节点:

SKLabelNode *replayButton = [SKLabelNode labelNodeWithFontNamed:@"Quicksand-Bold"];
replayButton.fontSize = 25.f;
NSString* replayText = [NSString stringWithFormat:@"Play Again"];
[replayButton setText:replayText];
replayButton.name = kGOSceneReplayButton;
replayButton.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)- self.frame.size.height/5);
[replayButton setFontColor:[SKColor whiteColor]];
SKShapeNode *bgNode = [SKShapeNode shapeNodeWithRectOfSize:replayButton.frame.size];
[bgNode setFillColor:[UIColor redColor]];


[self addChild:replayButton];
bgNode.position = replayButton.position;
[replayButton addChild:bgNode];

但是更新后,我得到了这个:

如果有帮助,我就是这样做来呈现场景的:

SKView * skView = (SKView *)self.view;
skView.showsFPS = YES;
skView.showsNodeCount = YES;
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = YES;
scene = [GameOverScene sceneWithSize:self.view.frame.size];
[(GameOverScene*)scene setGameEndingSceneDelegate:self];
[(GameOverScene*)scene setScaleMode: SKSceneScaleModeAspectFill];
[(GameOverScene*)scene showGameEndingWithGameInformation:self.gameEndingInfo];

// Present the scene.
[skView presentScene:scene transition:sceneTransition];

此外,这是我的 NSLog 的输出:

replay dimensions: {{221, 91}, {127, 25}

我有一种感觉,因为我设置了场景的 setScaleMode,它变得很奇怪,但没有其他异常,所以不知道该怎么做。我在想也许只是为我的标签创建一个图像并将 SKLabelNode 更改为 SKSpriteNode 并设置图像,所以我跳过添加红色矩形作为标签节点的背景。我想添加矩形的原因实际上是为了在点击 'Button' 时提供更大的命中目标,所以如果有人知道更简单、更直接的方法,我将不胜感激。

更新 3:

我还尝试设置矩形的位置以匹配父标签节点的位置:

bgNode.position = [replayButton convertPoint:CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)- self.frame.size.height/5) fromNode:self];

矩形最终出现在与上次更新相同的位置(一直到屏幕右侧)

您的代码有几个问题:

  1. lineWidth 属性,默认值为 1.0。应该是 0.0f

  2. verticalAlignmentMode property and it's default baseline alignment. It should be SKLabelVerticalAlignmentModeCenter.

  3. 形状节点定位错误。应该是 (0,0)

要修复它,请更改标签的垂直对齐方式:

replayButton.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;

将 shapenode 的线宽 属性 设置为 0.0f:

bgNode.lineWidth = 0.0f;

并删除这一行:

//bgNode.position should be CGPointZero which is (0,0)
bgNode.position = replayButton.position; 

不过,我会远离这种方法。 SKShapeNode 在这种情况下不需要。你可以用 SKSpriteNode 做同样的事情。重要的是 SKShapeNodeSKLabelNode 都不能批量绘制,也就是说,像 SKSpriteNode 那样渲染时不能在单个绘制通道中绘制。看看 。您的示例太简单了,不会产生性能问题,但通常您应该牢记所有这些。

如果您的按钮文本在游戏过程中从未改变,您应该考虑使用 SKSpriteNode 初始化纹理。如果对 SpriteKit 的预制按钮感兴趣,请查看 SKAButton.

希望对您有所帮助!