【问题标题】:ObjC: Can't access ivar of custom class from outsideObjC:无法从外部访问自定义类的 ivar
【发布时间】:2012-05-14 09:55:59
【问题描述】:

我正在尝试在 cocos2d 中制作一个基本游戏,并且我已经到了尝试根据英雄精灵的位置滚动背景的地步。英雄是在名为 GameplayLayer 的类中与控件一起创建的,并且对于非滚动背景都可以正常工作。

我正在关注的书给了我一些示例代码,可以根据我的角色何时通过中点来使滚动工作,这看起来很完美,但它没有执行,我相信这是因为它正在创建另一个实例我的英雄类,并且该实例与屏幕上显示的实例之间没有链接。

我假设我可以通过从背景滚动类(称为 YrrasCoastBackgroundLayer)中访问我的英雄的工作实例来解决这个问题,但我有一个脑块,无法让它看见。我尝试了@property,但 Xcode 在其他类中看不到它。

这是来自 GameplayLayer 类的 .h 文件,其中英雄被创建/连接到控件等:

#import "CCLayer.h"
#import "cocos2d.h"
#import "CommonProtocols.h"
#import "SneakyJoystick.h"
#import "SneakyButton.h"
#import "SneakyJoystickSkinnedBase.h"
#import "SneakyButtonSkinnedBase.h"
#import "HeroMale.h"
#import "GameCharacter.h"

@interface GameplayLayer : CCLayer <GameplayLayerDelegate> {
    CCSprite *playerSprite;
    SneakyJoystick *playerJoystick;
    SneakyButton *jumpButton;  
    CCSpriteBatchNode *sceneSpriteBatchNode;
    HeroMale *heroMale;
}

@property (nonatomic, readonly) SneakyJoystick *playerJoystick;
@property (nonatomic, readonly) SneakyButton *jumpButton;
@property (nonatomic, assign) HeroMale *heroMale;

@end

YrrasCoastBackgroundLayer.h 文件肯定会导入 GameplayLayer.h,这是 YrrasCoastBackgroundLayer.m 文件中我希望能够访问该 *heroMale ivar 的方法的内容:

- (void) adjustLayer {
    float heroXPosition = heroMale.position.x;
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    float halfOfTheScreen = screenSize.width / 2.0f;
    CGSize levelSize = [[GameManager sharedGameManager] getDimensionsOfCurrentScene];

    if ((heroXPosition > halfOfTheScreen) && (heroXPosition < (levelSize.width - halfOfTheScreen))) {
        float newXPosition = halfOfTheScreen - heroXPosition;
        [self setPosition:ccp(newXPosition, self.position.y)];
    }
}

我在 float heroXPosition = heroMale.position.x 行收到 Xcode 错误,指出 heroMale 是一个未声明的标识符。我怎样才能让它在这里可用,这甚至能解决问题吗?

更新:

这是 YrrasCoastBackgroundLayer 的 .h 文件:

#import "CCLayer.h"
#import "cocos2d.h"
#import "HeroMale.h"
#import "GameplayLayer.h"

@interface YrrasCoastBackgroundLayer : CCLayer {
    // Web Tutorial
    CCParallaxNode *backgroundNode;
    CCSprite *backgroundImage;

    // Book Tutorial
    CCSpriteBatchNode *sceneSpriteBatchNode;
    CCParallaxNode *parallaxNode;
}

@property (nonatomic, assign) GameplayLayer *gameplayLayer;

@end

这里是 YrrasCoastBackgroundLayer.m:

#import "YrrasCoastBackgroundLayer.h"

@implementation YrrasCoastBackgroundLayer

@synthesize gameplayLayer;

- (id) init {
    self = [super init];

if (self != nil) {

    // Web Tutorial
    backgroundNode = [CCParallaxNode node];
    [self addChild:backgroundNode z: -1];

    backgroundImage = [CCSprite spriteWithFile:@"yrras-coast-ipad-hd.png"];

    CGPoint dustSpeed = ccp(0.1, 0.1);

    [backgroundNode addChild:backgroundImage z:0 parallaxRatio:dustSpeed positionOffset:ccp(1024, [[CCDirector sharedDirector]winSize].height / 2)];

    self.gameplayLayer = gameplayLayer;

    [self scheduleUpdate];

    }
    return self;
}

- (void)update:(ccTime)deltaTime {

    // Web Tutorial
    // CGPoint backgroundScrollVel = ccp(-1000, 0);
    // backgroundNode.position = ccpAdd(backgroundNode.position, ccpMult(backgroundScrollVel, deltaTime));

    CCArray *listOfGameObjects = [sceneSpriteBatchNode children];
    for (GameCharacter *tempChar in listOfGameObjects) {
        [tempChar updateStateWithDeltaTime:deltaTime andListOfGameObjects:listOfGameObjects];
    }
    [self adjustLayer];

}

// Book Tutorial
- (void) adjustLayer {
    float heroXPosition = gameplayLayer.heroMale.position.x;
    CCLOG(@"heroXPosition is %f", gameplayLayer.heroMale.position.x);
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    float halfOfTheScreen = screenSize.width / 2.0f;
    CGSize levelSize = [[GameManager sharedGameManager] getDimensionsOfCurrentScene];
    if ((heroXPosition > halfOfTheScreen) && (heroXPosition < (levelSize.width - halfOfTheScreen))) {
        float newXPosition = halfOfTheScreen - heroXPosition;
        [self setPosition:ccp(newXPosition, self.position.y)];
    }
}

@end

【问题讨论】:

  • 请为您的 HeroMale 类添加代码..及其属性...

标签: objective-c xcode cocos2d-iphone instance-variables undeclared-identifier


【解决方案1】:

您需要将GameplayLayer 的实例传递给YrrasCoastBackgroundLayer 层。

您可以在YrrasCoastBackgroundLayer 中声明一个可分配的属性:

@property (nonatomic, assign) GameplayLayer gamplayLayer;

当您初始化 YrrasCoastBackgroundLayer 时,传递游戏层的实例并在您的 adjustLayer 方法中执行:

float heroXPosition = gameplayLayer.heroMale.position.x;

编辑:

假设这是您创建场景的方式:

  MyScene *scene = [MyScene scene];
  gameplayLayer = [[GameplayLayer alloc] init];
  bgLayer = [[YrrasCoastBackgroundLayer alloc] init];
  bgLayer.gameplayLayer = gameplayLayer; // This is where you assign the gameplay Layer to the background layer;

  [scene addChild:bgLayer];
  [scene addChild:gameplayLayer];

  // Release both layers if you dont need them anymore here (scene addChild retains them when they are added)      
  [gameplayLayer release];
  [bgLayer release];

【讨论】:

  • 如此构建,但看起来它并没有解决我的问题,滚动代码仍然没有在应该执行的时候执行。
  • 事实上,这段代码似乎从未激活过: if ((heroXPosition > halfOfTheScreen) && (heroXPosition
  • 是否曾经达到过方法本身? (尝试调试它)
  • 是的,这个方法被调用了,但是它里面的 if 语句永远不会被执行,因为当 heroXPosition 被调用到这个类中时它总是为零——数据没有被传递。
  • 告诉我你是如何将游戏层对象传递给背景层的
【解决方案2】:

我不确定如何访问 heroMale,因为它不是 YrrasCoastBackgroundLayer 的成员,而是 GameplayLayer 的成员。您必须拥有 GameplayLayer 类的对象/实例才能访问 heroMale。这就是您获得未声明标识符的原因(heroMale 不是 YrrasCoastBackgroundLayer 类的属性)。

亲切的问候,
博

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多