c and objective-c variables
Let me see if I can articulate what I'm trying to do... I'll distill it to the core issue.
I have an objective-c program and a c callback function. The context is I am using cocos2d and chipmunk physics with the iphone sdk. What I am trying to do is update "score" upon a collision between a bullet and a monster. Everything works fine except for updating the score.
the game logic is in obj-c but the actual collision logic is done in a c function that gets called when things collide. For example, it is there that I render the flames/explosion of the collision. It is also there that I want to update the score.
Here's the problem: But score is an instance variable of the "GAME" object and I do not have visibility into that instance variable. I suppose I can pass into the c function another parameter by reference called &addscore or something, but was wondering if there is a more obvious way to do it since there might be a bunch of other variables beyo开发者_运维知识库nd 'score' that must be updated upon the collission.
the net is I need variables in the object to be seen by the c function, and vice versa: those variables set in the function to be seen in the object.
thanks in advance.
Your knowledge and thoughts about gaining access to Obj-C instance variables within C code by passing them by reference seems correct.
If you need to pass a number of variables I assume they collectively make up some kind of "game state" description. Perhaps these could be grouped into a seperate object or structure and passed into the C function via a single parameter?
As an example, the following class:
typedef struct GameState {
int score;
int numberOfBulletsLeft;
} GameState;
@interface GAME : NSObject {
GameState state;
}
...
@end
Would work well with a C function such as the following
void myCFunctionThatDoesCollisiondetectionEtc(GameState * state) {
NSLog(@"You have %d bullets left", state->numberOfBulletsLeft);
}
If your existing GAME object has suitable properties or messages, you may even be able to do something like the following, where you simply pass your entire Objective-C object:
void myCFunctionThatDoesCollisionDetectionEtc(GAME * myGame) {
if (...)
[myGame increaseScore:50];
else
[myGame decreaseScore:50];
}
A third alternative would be to change the return value of your C function to indicate if a collision has been detected and then leave it up to the Objective-C code within the GAME class to update the score and any other actions which may need to occur.
To improve on that last answer a bit more, you can do the following:
cpSpaceAddCollisionPairFunc( space, 1, 2, (cpCollFunc)functionName, game);
void functionName( cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, GameClass *game) {
[game doSomethingToScoreSomething];
}
No need to cast the pointer inside of the function, you can cast the function pointer instead. That's what I've done internally with the Chipmunk source and it's a lot cleaner.
No, you do not need variables in your object to be visible by the function. That breaks encapsulation, and it's a bad idea. When you want an object to do something (like changing some internal value such as the score) you should provide a method to accomplish that effect.
If you allow code outside your class to alter your instance variables, then you're throwing away a key advantage of object-oriented programming.
If the game object is a singleton you can access it from any scope (which includes your C callback). You would make a singleton if you only ever want one instance of some object to exist. A singleton can always be reached from anywhere by sending a message to the class to retrieve the singleton instance:
[Game sharedGameInstance];
Alternatively, chipmunk allows for you to pass a void * data
to the callback. This is to accommodate the programmer to send information he needs to the callback.
You can send a pointer to your game object instance in that void *
to the callback, like so:
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.
}
精彩评论