2

让我看看我是否能清楚地表达我正在尝试做的事情......我将把它提炼到核心问题。

我有一个objective-c 程序和ac 回调函数。上下文是我在 iphone sdk 中使用 cocos2d 和花栗鼠物理。我想做的是在子弹和怪物发生碰撞时更新“分数”。除了更新分数外,一切正常。

游戏逻辑在 obj-c 中,但实际的碰撞逻辑在 ac 函数中完成,当事情发生碰撞时会调用该函数。例如,我在那里渲染了碰撞的火焰/爆炸。我也想更新分数。

这就是问题所在:但 score 是“GAME”对象的一个​​实例变量,我无法看到该实例变量。我想我可以通过引用将另一个参数传递给 c 函数,称为 &addscore 或其他东西,但我想知道是否有更明显的方法可以做到这一点,因为除了“分数”之外可能还有一堆其他变量必须在碰撞。

网络是我需要对象中的变量才能被 c 函数看到,反之亦然:那些在函数中设置的变量才能在对象中看到。

提前致谢。

4

4 回答 4

1

您关于通过引用传递它们来访问 C 代码中的 Obj-C 实例变量的知识和想法似乎是正确的。

如果您需要传递许多变量,我假设它们共同构成某种“游戏状态”描述。也许这些可以组合成一个单独的对象或结构,并通过单个参数传递给 C 函数?

例如,以下类:

typedef struct GameState {
  int score;
  int numberOfBulletsLeft;
} GameState;

@interface GAME : NSObject {
  GameState state;
}

...

@end

可以很好地与以下 C 函数一起使用

void myCFunctionThatDoesCollisiondetectionEtc(GameState * state) {
  NSLog(@"You have %d bullets left", state->numberOfBulletsLeft);
}

如果您现有的 GAME 对象具有合适的属性或消息,您甚至可以执行以下操作,您只需传递整个 Objective-C 对象:

void myCFunctionThatDoesCollisionDetectionEtc(GAME * myGame) {
  if (...)
    [myGame increaseScore:50];
  else
    [myGame decreaseScore:50];
}

第三种选择是更改 C 函数的返回值以指示是否检测到碰撞,然后将其留给 GAME 类中的 Objective-C 代码来更新分数和可能需要发生的任何其他操作.

于 2009-12-02T22:06:33.460 回答
1

要进一步改进最后一个答案,您可以执行以下操作:

cpSpaceAddCollisionPairFunc( space, 1, 2, (cpCollFunc)functionName, game);

void functionName( cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, GameClass *game) {
    [game doSomethingToScoreSomething];
}

无需在函数内部强制转换指针,您可以改为强制转换函数指针。这就是我在内部使用 Chipmunk 源代码所做的,而且它更干净。

于 2009-12-03T14:27:56.293 回答
0

不,您不需要对象中的变量对函数可见。这破坏了封装,这是一个坏主意。当你想让一个对象做某事(比如改变一些内部值,比如分数)时,你应该提供一种方法来实现这个效果。

如果你允许你的类之外的代码改变你的实例变量,那么你就放弃了面向对象编程的一个关键优势。

于 2009-12-03T06:03:56.287 回答
0

如果游戏对象是单例,您可以从任何范围(包括您的 C 回调)访问它。如果您只希望某个对象的一个​​实例存在,您将创建一个单例。通过向类发送消息以检索单例实例,始终可以从任何地方访问单例:

[Game sharedGameInstance];

或者,花栗鼠允许您将 a 传递void * data给回调。这是为了适应程序员向回调发送他需要的信息。

您可以将指向您的游戏对象实例的指针发送void *到回调,如下所示:

cpSpaceAddCollisionPairFunc( space, 1, 2, &functionName, (void *)game );

void functionName( cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, void *data ) {
    GameClass * game = (GameClass *)data;
    // do whatever you need here. You can call messages on game as per usual.
}
于 2009-12-03T13:19:12.977 回答