我有这个游戏,当一个精灵触及两侧,你得到一个点。我想出了每次精灵触及侧面时增加分数的代码。我通过NSLog消息得到正确的输出。
但是,当我通过将代码从NSLog更改为SKLabelNode来尝试相同的代码时,我得到了超过一千个节点(我认为这将影响性能并减慢游戏速度)。此外,当分数增加时,它与旧分数重叠,而不仅仅是增加分数。我在框架中添加了更新中的代码。
下面是代码:
- (void)printScore {
NSString *text = [NSString stringWithFormat:@"%ld",(long)userScore];
SKLabelNode *score = [SKLabelNode labelNodeWithText:text];
score.fontName = @"chalkduster";
score.fontSize = 45;
score.fontColor = [SKColor whiteColor];
score.position = CGPointMake(CGRectGetMidX(self.frame) + 175 ,CGRectGetMidY(self.frame) + 350);
[self addChild:score];
}
-(void)update:(CFTimeInterval)currentTime {
[self printScore];
}
如何解决这个问题,以便在没有添加太多精灵的情况下更新分数?
对不起,如果这是一个非常愚蠢的问题,我就是诺布。
答案 0 :(得分:2)
您获得如此多节点的原因是您不断向场景添加新标签。请注意,在printScore
方法中,您要创建新的SKLabelNode
个实例,然后将其添加到场景中。
为了纠正这个问题,您需要维护对单个SKLabelNode
的引用,然后更新其文本。
此外,您可能希望将调用移至printScore
仅在实际评分事件发生时调用,而不是为每个帧调用update
。我当然假设你没有每一帧都有得分事件。
答案 1 :(得分:2)
只添加一个属性:
@property (nonatomic, strong) SKLabelNode *scoreLabel;
在viewDidLoad
init
方法中只创建一次:
_scoreLabel = [SKLabelNode initWithFontNamed:@"chalkduster"];
_scoreLabel.fontSize = 45;
_scoreLabel.fontColor = [SKColor whiteColor];
_scoreLabel.position = CGPointMake(CGRectGetMidX(self.frame) + 175 ,CGRectGetMidY(self.frame) + 350);
[self addChild:_scoreLabel];
然后仅在精灵触及de侧时调用printScore
方法,而不是像在update
方法中那样在每个帧上调用:
- (void)printScore
{
NSString *text = [NSString stringWithFormat:@"%ld",(long)userScore];
self.scoreLabel.text = text;
}
我希望这会有所帮助。
答案 2 :(得分:0)
您的printScore方法每次调用时都会创建一个新的SKLabelNode,并且您通过更新方法每秒调用60次。您应该设置BOOL以通知您只有在需要时才会调用printScoreMethod(如分数已更改)。
答案 3 :(得分:0)
创建一个全局布尔值,并且只在第一次添加标签:
BOOL firsttime = YES;
- (void)printScore {
NSString *text = [NSString stringWithFormat:@"%ld",(long)userScore];
SKLabelNode *score = [SKLabelNode labelNodeWithText:text];
if( firsttime )
{
score.fontName = @"chalkduster";
score.fontSize = 45;
score.fontColor = [SKColor whiteColor];
score.position = CGPointMake(CGRectGetMidX(self.frame) + 175, CGRectGetMidY(self.frame) + 350);
[self addChild:score];
firsttime = NO;
}
}
-(void)update:(CFTimeInterval)currentTime {
[self printScore];
}
答案 4 :(得分:0)
有几种方法可以解决这个问题。我更喜欢一种隐藏了底层实现的方法。理想情况下,我实际上会创建一个代表HUD分数的类。从“应用程序代码的其余部分”的角度来看,其他游戏代码与HUD的合同是通过分数属性来反映分数。
有些人会说它是一个标签,看起来很麻烦。但是如果你改变了它的实现方式(例如,假设它变成了一个带有填充条的分数,或者你可能会有一个特殊的效果伴随着分数的变化),你会发现它使它变得非常容易处理。或者如果你突然有一个2人游戏并且两个玩家跟踪得分怎么办?您可以通过添加分数类的新实例轻松添加新分数。
这是我的意思的一个简单例子。
ScoreHUD.h
@interface ScoreHUD : NSObject
@property (nonatomic, assign) NSInteger score;
- (instancetype)initWithScene:(SKScene *)scene x:(CGFloat)x y:(CGFloat)y;
@end
ScoreHUD.m
@interface ScoreHUD()
@property (nonatomic, strong) SKLabelNode *scoreLabel;
@end
@implementation ScoreHUD
- (instancetype)initWithScene:(SKScene *)scene x:(CGFloat)x y:(CGFloat)y
{
self = [super init];
if (self) {
_scoreLabel = [SKLabelNode initWithFontNamed:@"chalkduster"];
_scoreLabel.fontSize = 45;
_scoreLabel.fontColor = [SKColor whiteColor];
_scoreLabel.position = CGPointMake(x, y);
[scene addChild:_scoreLabel];
// Setting initial label value to the default value of the score
_scoreLabel.text = [@(_score) stringValue];
}
return self;
}
- (void)setScore:(NSInteger)score
{
if (_score != score) {
_score = score;
self.scoreLabel.text = [@(score) stringValue];
}
}
@end
请注意,我没有测试代码或检查它是否会编译。
所以要使用它,你可以在你的场景中创建一个这样的实例,如:
// Property in the scene
@property (nonatomic, strong) ScoreHUD *score;
// Initialize where you need to
self.score = [[ScoreHUD alloc] initWithScene:self x:CGRectGetMidX(self.frame) + 175 y:CGRectGetMidY(self.frame) + 350];
您可以在场景initWithSize
中执行此操作。
当分数发生变化时,您只需执行以下操作:
self.score.score += 1;
如果它看起来很讨厌,你总是可以用另一种方法包装它。
这种方法有一个缺点。假设你的分数在一帧中得到了很多更新。这意味着您的文本将每帧设置多次。根据您拥有的游戏类型,这可能是也可能不是一个问题。有一些方法仍然可以使用这个基本设置并解决它。但对于绝大多数游戏来说,这不会是一个问题。