2012-04-05 101 views
2

我根据在网上找到的一些教程创建了一个简单的2帧精灵动画。我拿走了我的2张图片,用plist和png文件创建了一个精灵图表,并将它们合并到我的代码中,如下所示。这个设置在Cocos2d V 1.0.1中运行正常。我刚刚将我的项目升级到2.0rc0a,现在我的应用程序在第一帧切换到第二帧时出现以下错误:'CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteBatchNode'从Cocos2d 1.0.1升级到2.0后,Sprite Sheet动画失败

我看着这个SO question,但我不确定是否这是我做错了一样的事情,因为我对Cocos2d还很陌生,我不确定如何正确调整我的代码。这是2.0版本中改变的东西,我在笔记中没有看到,我应该报告的错误,还是只是编码不正确?我仍然拥有1.0.1项目的副本,其代码相同,并且动画可以正常工作。

//CHAMELEON 
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"front page/mainchameleon.plist"]; 
mainChameleon = [CCSpriteBatchNode batchNodeWithFile:@"front page/mainchameleon.png"]; 
[self addChild:mainChameleon z:7]; 
NSMutableArray *chameleonFrames = [NSMutableArray array]; 
for (int i = 1; i <= 2; ++i) 
{ 
    [chameleonFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"chameleon%d.png", i]]]; 
} 

CCAnimation *mouthAnim = [CCAnimation animationWithSpriteFrames:chameleonFrames delay:0.3f]; 
chameleon = [CCSprite spriteWithSpriteFrameName:@"chameleon1.png"]; 
CCAnimate *chameleonAction = [CCAnimate actionWithAnimation:mouthAnim]; 
CCDelayTime *chameleonDelay = [CCDelayTime actionWithDuration:10]; 
CCRepeatForever *chameleonRepeat = [CCRepeatForever actionWithAction:[CCSequence actions:chameleonDelay, chameleonAction, chameleonDelay, nil]]; 
[chameleon runAction:chameleonRepeat]; 
[mainChameleon addChild:chameleon]; 

如果我注释掉chameleon = [CCSprite spriteWithSpriteFrameName:@"chameleon1.png"];然后应用程序不会崩溃,但变色龙不会出现所有的,因为会与代码是如何写的当前预期。

或者,如果我注释掉[chameleon runAction:chameleonRepeat];然后出现变色龙表示帧,chameleon1.png,但很明显,通过动画不走。

好的,所以为了让我更加困惑,因为我肯定错过了一些东西,我试着将代码底部改为这个,动画从第1帧开始到第2帧,然后无限期地停留在第2帧。但是,如果延迟时间超过1.0,我会收到与之前相同的错误。如果我在重复永久声明之前重新包含chameleonDelay,我也会遇到相同的崩溃。看起来,如果应用程序必须等待1秒以上才能执行切换,该应用程序会崩溃。我需要的是第1帧放置一段时间(10秒),然后切换到第2帧0.3秒,然后切换回第1帧并再坐一会儿。

试图代码#2:

CCAnimation *mouthAnim = [CCAnimation animationWithSpriteFrames:chameleonFrames delay:0.3f]; //<--- maxes out at 1.0. Anything more causes crash 
chameleon = [CCSprite spriteWithSpriteFrameName:@"chameleon1.png"]; 
CCAnimate *chameleonAction = [CCAnimate actionWithAnimation:mouthAnim];  
[chameleon runAction:chameleonAction]; 
[mainChameleon addChild:chameleon]; 

使用restoreOriginalFrame语句YvesLeBorg建议,但在版本2.0弃用。我试着用

CCAnimation *mouthAnim = [CCAnimation animationWithAnimationFrames:chameleonFrames delayPerUnit:0.3f loops:5];

并且得到错误'-[CCSpriteFrame delayUnits]: unrecognized selector sent to instance'。我不确定为什么这不起作用,或者从这里尝试其他方法。

编辑:所以现在的工作......但不能有效编码,因为我想:

新代码:

//CHAMELEON 
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"front page/mainchameleon.plist"]; 
mainChameleon = [CCSpriteBatchNode batchNodeWithFile:@"front page/mainchameleon.png"]; 
[self addChild:mainChameleon z:7]; 
NSMutableArray *chameleonFrames = [NSMutableArray array]; 

//Frame 1 - closed mouth 
[chameleonFrames addObject:[CCSpriteFrame frameWithTexture:mainChameleon.texture rect:CGRectMake(0, 124, 149, 122)]]; 
//Frame 2 - Open Mouth 
[chameleonFrames addObject:[CCSpriteFrame frameWithTexture:mainChameleon.texture rect:CGRectMake(0, 0, 149, 122)]]; 
//Frame 1 - closed mouth 
[chameleonFrames addObject:[CCSpriteFrame frameWithTexture:mainChameleon.texture rect:CGRectMake(0, 124, 149, 122)]]; 

CCAnimation *mouthAnim = [CCAnimation animationWithSpriteFrames:chameleonFrames delay:0.9f]; 
    chameleon = [CCSprite spriteWithTexture:mainChameleon.texture rect:CGRectMake(0,124,149,122)]; 
CCAnimate *chameleonAction = [CCAnimate actionWithAnimation:mouthAnim]; 
CCDelayTime *chameleonDelay = [CCDelayTime actionWithDuration:10]; 
CCRepeatForever *chameleonRepeat = [CCRepeatForever actionWithAction:[CCSequence actions:chameleonDelay, chameleonAction, nil]]; 
[chameleon runAction:chameleonRepeat]; 
[mainChameleon addChild:chameleon]; 

我真的很喜欢,我是这样做的方式在1.0.1中,因为如果我有2帧或100帧,我只需要对if语句进行小调整。这种方式需要编码每个单独的框架,这似乎与使用plist相反。如果没有人能够在未来几天内提供更好的解决方案或“真实”答案,我会将其作为答案发布,并接受它来解决问题。

回答

3

这是我结束了与该代码工作正常。不知道为什么我必须做出这些改变,但它是。 (有些名字已经改变了,因为我开始了一个新的项目来解决这个问题,但是我原来的代码和这个之间的区别很明显)。对于其他人发现此线程,我的原始代码基于Ray Wenderlich's sprite sheet tutorial

CCSpriteBatchNode *chameleonBN = [CCSpriteBatchNode batchNodeWithFile:@"chameleonimages.png"]; 
    [self addChild:chameleonBN]; 

//ADDED the texture part to resolve: 'CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteBatchNode' 
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"chameleonplist.plist" texture:chameleonBN.texture]; 

NSMutableArray *chameleonframes = [NSMutableArray array]; 

for (int i = 1; i <= 2 ; i++) 
{ 
    [chameleonframes addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"chameleon%d.png", i]]]; 
} 

CCAnimation *mouthAnim = [CCAnimation animationWithSpriteFrames:chameleonframes delay:0.9f]; 

//ADDED this sprite frame to resolve texture id assert error 
CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:chameleonBN.texture rect:CGRectMake(0, 0, 149, 122)]; 
CCSprite *chameleon = [CCSprite spriteWithSpriteFrame:frame]; 
chameleon.position = ccp(512,384); 
CCAnimate *chameleonAnimate = [CCAnimate actionWithAnimation:mouthAnim]; 

CCDelayTime *chameleonDelay = [CCDelayTime actionWithDuration:10]; 
CCDelayTime *chameleonDelay2 = [CCDelayTime actionWithDuration:0.1];//Had to use this to ge tthe mouth to close. Using restore original frame doesn't work for me. 
CCRepeatForever *chameleonRepeat = [CCRepeatForever actionWithAction:[CCSequence actions:chameleonDelay, chameleonAnimate, chameleonDelay2, nil]]; 
[chameleon runAction:chameleonRepeat]; 
[chameleonBN addChild:chameleon]; 
+0

你好。首先感谢详细的问题+答案。今天我偶然发现了同样的问题,但我用不同的方式解决了这个问题。现在我不知道哪一个是最好的,或者即使我所做的都是正确的。在我的其中一次尝试中,我注意到精灵尺寸裁剪出现问题,所以我添加了对Retina的检查并根据该检查加载了文件。和粉扑!问题(似乎是)解决了。那么你如何处理视网膜? – mokagio 2012-08-03 14:13:26

+0

如果您有兴趣,我可以在这里发布我的代码作为答案。 – mokagio 2012-08-03 14:14:22

+0

最后一件事,我的是一个非常简单的动画,只是为了框架。这可能是相关的。不幸的是,我现在没有时间用更多的框架来测试:( – mokagio 2012-08-03 14:15:29

0

不确定这是否是2.0问题,但我注意到你正在使用相同序列中的两倍chameleonDelay对象。这真的是你试图完成,即

延迟,行动,延迟,延迟,行动,延迟,延迟,行动等。

试试这个,看看它的工作原理:

CCRepeatForever *chameleonRepeat = [CCRepeatForever actionWithAction:[CCSequence actions:chameleonDelay, chameleonAction, nil]]; 
+0

是的,那是故意的。这是问题的组合。我发现如果不添加它,出于某种原因,这些动作不会做我想要的,从第1帧开始到第2帧,然后快速回到第1帧。如果没有第二次延迟,它会停留在第2帧。我确定这是我处理它的方式,但实际上时机正好符合我想要完成的任务。感谢您指出了这一点。 – BobbyScon 2012-04-05 17:18:11

+0

为了防止快速回到第一帧,您可能需要使用[CCAnimate actionWithAnimation:mouthAnim restoreOriginalFrame:NO]。但是,无论如何,如果您有两个使用相同的序列,请尝试创建另一个CCDelayTime实例。 – YvesLeBorg 2012-04-05 17:36:12

+0

对不起,我可能没有正确说出它。我希望它回到第一帧。这是一个开口和关闭的嘴。我在结束这段代码之前尝试了restoreOriginalFrame:YES,它实际上并没有返回到第一帧。不知道为什么。这种编码的工作方式正是我想要的,所以我只是把它放在一边。关于创建第二个实例的观点,我会这样做。 – BobbyScon 2012-04-05 17:45:59