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];
矩形最终出现在与上次更新相同的位置(一直到屏幕右侧)
您的代码有几个问题:
lineWidth 属性,默认值为 1.0。应该是 0.0f
verticalAlignmentMode property and it's default baseline alignment. It should be SKLabelVerticalAlignmentModeCenter.
形状节点定位错误。应该是 (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
做同样的事情。重要的是 SKShapeNode
和 SKLabelNode
都不能批量绘制,也就是说,像 SKSpriteNode
那样渲染时不能在单个绘制通道中绘制。看看 。您的示例太简单了,不会产生性能问题,但通常您应该牢记所有这些。
如果您的按钮文本在游戏过程中从未改变,您应该考虑使用 SKSpriteNode
初始化纹理。如果对 SpriteKit 的预制按钮感兴趣,请查看 SKAButton.
希望对您有所帮助!
我已经为游戏的游戏结束场景编写了这段代码:
#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];
矩形最终出现在与上次更新相同的位置(一直到屏幕右侧)
您的代码有几个问题:
lineWidth 属性,默认值为 1.0。应该是 0.0f
verticalAlignmentMode property and it's default baseline alignment. It should be SKLabelVerticalAlignmentModeCenter.
形状节点定位错误。应该是 (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
做同样的事情。重要的是 SKShapeNode
和 SKLabelNode
都不能批量绘制,也就是说,像 SKSpriteNode
那样渲染时不能在单个绘制通道中绘制。看看
如果您的按钮文本在游戏过程中从未改变,您应该考虑使用 SKSpriteNode
初始化纹理。如果对 SpriteKit 的预制按钮感兴趣,请查看 SKAButton.
希望对您有所帮助!