【发布时间】:2015-01-20 22:44:11
【问题描述】:
我使用 Sprite Kit 开发了一款 iOS 游戏,其中有很多敌人和障碍物,我制作了动画。每次第一次加载动画帧时,游戏都会滞后一点,然后运行良好。
例如我的一个敌人是这样的:
Fox 实现文件:
- (id)initWithTexture:(SKTexture *)nodetexture
{
self = [super initWithTexture:nodetexture];
if (self) {
//Initialization code
[self setScale:0.2];
[self setSpeed:20];
self.physicsBody.allowsRotation = false;
self.physicsBody.contactTestBitMask = 0x1 << 1 | 0x1 << 3;
self.physicsBody.categoryBitMask = 0x1 << 2;//enemy
self.physicsBody.collisionBitMask = 0x1 << 1 | 0x1 << 3;
[self animateSelf];
}
return self;
}
- (void) animateSelf{
[super animateSelf];
NSMutableArray *textures = [NSMutableArray arrayWithCapacity:16];
for (int i = 1; i < 5; i++) {
NSString *textureName = [NSString stringWithFormat:@"fox%d.png", i];
SKTexture *texture =[SKTexture textureWithImageNamed:textureName];
[textures addObject:texture];
}
[self removeActionForKey:[NSString stringWithFormat:@"animate %@", self.class]];
[self runAction:[SKAction sequence:@[[SKAction repeatAction:[SKAction sequence:@[[SKAction runBlock:^{
self.xScale = -0.2;
[self jumpEntity];
[self setSpeed:40];
[self impulseEntityRight];
[self setSpeed:20];
self.runAnimation = [SKAction animateWithTextures:textures timePerFrame:3];
}], [SKAction waitForDuration:20], [SKAction runBlock:^{
self.xScale = 0.2;
[self jumpEntity];
[self setSpeed:40];
[self impulseEntityLeft];
[self setSpeed:20];
[self runAction:[SKAction repeatActionForever:self.runAnimation]];
}], [SKAction waitForDuration:20]]] count:5]]] withKey:[NSString stringWithFormat:@"animate %@", self.class]];
}
帧存储在 .atlas 文件中,我认为延迟的原因是第一次运行 for 循环,但这只是一个假设。
我尝试按照这些思路在 GameViewController 中预加载帧:
GameViewController 实现文件:
- (void)viewDidLoad
{
[super viewDidLoad];
//Load new game
[self initialiseGameScene];
[self.gamescene.physicsWorld setContactDelegate:self];
[self checkTiltBool];
self.gamestarted = false;
self.startedbytilt = false;
[self addListenersToButtons];
[self instantiateGestureRecognizers];
self.spawnedobjects = [[NSMutableArray alloc] init];
if (self.tiltbool == true){
[self startGame];
}
[self updateLifeIcons];
NSMutableArray *frames = [[NSMutableArray alloc]init];
for (int i=0; i<[SKTextureAtlas atlasNamed:@"fox"].textureNames.count; i++) {
[frames addObject:[SKTexture textureWithImageNamed:[SKTextureAtlas atlasNamed:@"fox"].textureNames[i]]];
}
[SKTexture preloadTextures:frames withCompletionHandler:^{NSLog(@"Complete");}];
}
我走对了吗?理想情况下,我想在游戏开始之前预加载所有动画,以便动画顺利运行。
【问题讨论】:
-
您正在预加载。你只需要让你的代码以预加载完成的方式流动,然后你的游戏才开始。例如,使用 BOOL 变量让您的 NSLog “完成”在加载完成时通知您。您可以在更新方法中测试 BOOL 变量,以了解何时开始运行您的游戏。
-
您不应该在每次运行动画时都创建新的纹理数组。而是为您拥有的每个动画存储一个纹理数组并重复使用每个纹理数组。
-
纹理预加载代码相当浪费。每次在循环中,您都会让狐狸图集从中获取所有纹理名称两次,一次在 for 循环中,一次在循环内。
-
那么我可以在 GameViewController 中加载帧,然后在我的 Fox 类中使用预加载的帧吗?
-
我会将其设为共享类变量,并在加载场景数据时加载动画。您绝对应该有一种加载/准备场景的方法。我个人会将数据加载到您的场景类中,但这完全取决于您。 GameViewController 也可以工作。
标签: ios objective-c animation sprite-kit