我一直在构建“学习Cocos2D”一书中描述的SpaceViking项目。当我开始遇到问题时,我得到了关于Box2D的第10章。然后我尝试将cocos2D从版本1升级到版本2.0。在进行必要的更改以修复弃用之后,代码将不再起作用。具体来说,我发现当创建游戏对象或敌对对象时,不再调用它们的init方法。例如,执行以下行时:
RadarDish *radarDish = [[RadarDish alloc] initWithSpriteFrameName:@"radar_1.png"];
未调用RadarDish init方法。然后,我查看了版本1和版本2中initWithSpriteFrameName的执行情况,发现CCSprite.m已更改,因此不再调用init方法。在版本2源代码中,initWithSpriteFrameName方法调用initWithSpriteFrame,它调用initWithTexture调用:
-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect rotated:(BOOL)rotated
{
if( (self = [super init]) ) {
因此,不调用RadarDish init方法。而是调用CCNode init方法。但是在版本1中,initWithSpriteFrameName调用initWithSpriteFrame,它调用具有以下代码的initWithTexture:
// IMPORTANT: [self init] and not [super init];
if( (self = [self init]) ){
[self setTexture:texture];
[self setTextureRect:rect];
}
这允许调用RadarDish init方法。
我该怎么做才能解决这个问题?这本书似乎不太可能需要改变以支持升级到cocos2d v2.0,所以我怀疑我必须遗漏其他东西。但如果我错了,那么更改此代码以便调用RadarDish init方法的方法是什么?
答案 0 :(得分:3)
好的,我错了。 “cocos2d 2.x与v1.x的许多细节不同,所以不能指望v1.x代码只能在2.x下工作”。如果您打算阅读“学习Cocos2D”一书,我建议您加载cocos2d-iphone版本1.0.1。否则,您将面临许多不兼容性以及需要修复的大量弃用。
但是如果你真的想使用最新的cocos2d,那么你应该做一些事情。 1)按照this link中的说明进行操作。 2)您将需要修改许多弃用和更改,因此请使用this link了解如何修复这些弃用和更改。 3)您还需要更新操纵杆类,所以转到this link进行更改,4)您必须谷歌其余的以找到解决方案。
现在至于我在这里提到的问题的解决方案,可能有多种解决方案,但我会在下面提供一个(感谢Sylvan的答案):
在每个GameObjects,EnemyObjects和PowerUps中,我添加了一个覆盖initWithFrameName的方法。这将绕过对象init方法的使用。例如,对于RadarDish,我添加了以下内容:
-(id) initWithSpriteFrameName:(NSString*)frameName {
if( (self=[super init]) ) {
if ((self = [super initWithSpriteFrameName:frameName])) {
CCLOG(@"### RadarDish initialized");
[self initAnimations]; // 1
characterHealth = 100.0f; // 2
gameObjectType = kEnemyTypeRadarDish; // 3
[self changeState:kStateSpawning]; // 4
}
}
return self;
}
这允许GameObject和GameCharacter init方法在CCSprite的initWithSpriteFrameName方法运行之前运行。
Viking GameObject必须有一个稍微不同的解决方案,因为它是用initWithSpriteFrame而不是initWithSpriteFrameName初始化的。但覆盖实现与上面的RadarDish示例基本相同。
(除了克服弃用所需的所有更改)上述更改允许“学习Cocos2D”示例中的其他所有内容保持不变。
祝你好运。
答案 1 :(得分:2)
我认为你遇到了麻烦,因为你保持你的init方法并没有修改它。您在RadarDish类上调用方法initWithSpriteFrameName:但该类没有该方法名称,因此它查找其超类。我想你可以简单地将你的init方法重命名为initWithSpriteFrameName:你会没事的。像这样:
// RadarDish.m
-(id) initWithSpriteFrameName:(NSString*)frameName {
if ((self = [super initWithSpriteFrameName:frameName])) {
// init anything here
}
return self;
}
只是不要有一个名为init的方法,并期望它被调用。