0

我一直在构建《学习 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 方法的方法是什么?

4

2 回答 2

3

好吧,我错了。“cocos2d 2.x 在很多细节上都与 v1.x 不同,所以不能指望 v1.x 代码只能在 2.x 下工作”。如果你打算跟着《学习 Cocos2D》这本书,我建议加载 cocos2d-iphone 1.0.1 版本。否则,您将面临许多不兼容问题以及需要修复的大量弃用。

但是如果你真的想使用最新的cocos2d,那么你应该做一些事情。1) 按照此链接中的说明进行操作。2) 您将有很多弃用和更改需要修复,因此请使用此链接了解如何修复这些弃用和更改。3)您还需要更新操纵杆类,因此请访问此链接以获取这些更改,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”示例中的其他所有内容保持不变。

祝你好运。

于 2013-01-19T16:34:33.997 回答
2

我认为您遇到了麻烦,因为您将 init 方法保持原样而不是对其进行修改。您在 RadarDish 类上调用方法 initWithSpriteFrameName: 但该类没有该方法名称,因此它查找其超类。我认为你可以简单地将你的 init 方法重命名为 initWithSpriteFrameName: 并且你会没事的。像这样:

// RadarDish.m

-(id) initWithSpriteFrameName:(NSString*)frameName {
   if ((self = [super initWithSpriteFrameName:frameName])) {
      // init anything here
   }
   return self;
}

只是没有一个名为 init 的方法并期望它被调用。

于 2013-01-19T18:07:27.303 回答