I am developing game in cocos2dx.In Cocos2d for calling parent layer method from NSObject i had used this:
-(void)EnableTouch
{
CCScene *current = [[CCDirector sharedDirector] runningScene];
if (current) {
id layer = [current getChildByTag:8];
if (layer) {
[indicator stopAnimating];
[layer EnableTouch];
}
}
}
and i can call EnableTouch method of my parent layer...Now same thing i want to do with cocos2dx.
Here I have called Myclass.mm which is NSObject type(Objective C++ Source) from Info.cpp which has same type(Objective C++ Source) by making object like this:
Myclass *object=[[Myclass alloc]init];
[object temp];
Now,I want to call parent layer method(Info.cpp) after completion of process in temp function for that what I have to do? I have tried this:
CCScene *current=CCDirector::sharedDirector()->getRunningScene();
CCLayer *layer=(CCLayer *)current->getChildByTag(88);
Info *gamescene=dynamic_cast<Info *>(layer);
gamescene->temp();
But it gives error...What I have to change here?Please suggest if anyone know.
Related
I try to make a Code Connection with my game object (which is located in Enemy.ccb) in SpriteBuilder.
It works perfect when I just load my object and add it to the stage.
CCNode *enemy = [CCBReader load:#"Enemy"];
[self addChild:enemy];
Unfortunately it will not work when I set the custom class of the object to 'Enemy'. The asset is loading and its custom class is initializing, but it is not shown. What I am doing wrong?
EDIT:
Here's my simple implementation of the Enemy class. It is subclassed from CCSprite:
#implementation Enemy
- (id)init {
self = [super init];
if (self) {
CCLOG(#"Enemy created");
}
return self;
}
#end
is there a reason why when you use CCTransitionFade this way.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[director_ pushScene:[CCTransitionFade transitionWithDuration:1
scene:[FirstScene node]]];
return YES;
}
and then the Second Scene is called inside the FirstScene's init to advance like a regular brand presentation of the game, why is it that if I don't put a scheduler that is a bit longer than the first CCTransitionFade timer why does it get stuck?
//in FirstScene Class
-(void) onEnter {
self = [super init];
if (self) {
[[CCDirector sharedDirector] replaceScene:
[CCTransitionFade transitionWithDuration:1.2 scene:[SecondScene node]]];
}
return self;
}
I mean I understand the reason why, but does this mean I have been doing this the wrong way? Is there a more acceptable way to do this CCTransitionFades or is it correct to use the Scheduler this way?
//in FirstScene Class
-(void) onEnter {
self = [super init];
if (self) {
[self scheduleOnce:#selector(makeTransition:) delay:1.2];
}
return self;
}
-(void)makeTransition:(ccTime)dt {
[[CCDirector sharedDirector] replaceScene:
[CCTransitionFade transitionWithDuration:1 scene:[SecondScene node]]];
}
By doing it the second way with SchedulerOnce I am able to sucessfully get what I want.
so, am I doing something wrong? Is this just a bad workaround from my side? Or is there a correct way to this situation?
Note: Made a correction because Currently I do have the code with onEnter method. but I have tried it with init and it does have the same behavior as well.
In first case when you call replaceScene from init, the order of calling functions looks something like that:
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
[FirstScene node]
FirstSceneInit
[[CCDirector sharedDirector] replaceScene: ..
...
[director_ pushScene
The problem is because you call replaceScene when there aren't scene on screen, so the director try change the actual scene, which is NULL to FirstScene. The first scene appear on the screen after pushScene
In the second mostly works, but theoretically this solution is dangerous, because when you call init and set scheduler, then can be 2 seconds lag for example. I don't know that this is possible on cocos2d, which operate in one thread, but i think that putting replace scene in onEnter function is more elegant solution
A lot of example CCLayer subclasses I see have code that looks like this:
+(CCScene *) scene{
CCScene *scene = [CCScene node];
HelloWorldLayer *layer = [HelloWorldLayer node];
[scene addChild: layer];
return scene;
}
Who calls that method and what purpose does it serve? Does it need to be there? Is it convenient for some future purpose?
Yes, it is needed. This method is called in applicationDidFinishLaunching method of ApplicationDelegate. For example in the HellowWorld template it is called in this line in AppDelegate:
[[director_ pushScene: [HelloWorldLayer scene]]
The ccDirector can run only CCScene, and it can run only one CCScene at a time. That is why CCLayer creates a CCScene first and then adds itself as a child to it.
As an alternative, you can subclass CCScene and add your CCLayers and etc to it by overriding its init method like this:
-(id) init {
if (self = [super init]){
CCLayer *aLayer = [CCLayer node];
[self addChild: aLayer];
....
}
return self;
}
and replace this line [[director_ pushScene: [HelloWorldLayer scene]] with this [[director_ pushScene: [myScene node]] in the applicationDidFinishLaunching method of AppDelegate.
All I know is that it isn't needed, I've wondered the same thing. I think it is because they want to encourage the use of scenes a bit. Your scenes should consist of layers and you should switch between scenes.
How do you handle the setAction message in Objective-C++? (Not Objective-C.)
For example, suppose I have:
my_class.mm
NSSegmentedControl *segmented = [[NSSegmentedControl alloc] init];
[segmented setSegmentCount:5];
// etc.
[segmented setAction:???];
Application: I am programming in Qt (C++) and need a wrapper around some Cocoa widgets I want to use directly. I am inheriting from QMacCocoaViewContainer but can't figure out how to handle the "clicks" of the NSSegmentedControl I am wrapping. Eventually this will emit a standard Qt signal.
action is just a selector - it is used in tandem with target. so write an objc method for target+action which calls through or does what you really want. actions' arguments are the sender, but you can omit that if you don't need it. the sender will be whatever is sending the message (e.g. the control). it's no different in ObjC++ - this has to be wrapped in an objc method because the target must be an objc object.
so it would look like this:
obj.action = #selector(pressDoStuff:);
and the method is:
- (void)pressDoStuff:(id)sender
#Justin has the right answer; I'll accept it, but also include the final solution in case it helps others. The trick is you need a proxy class, as #smparkes noted.
Ignoring the .h files for brevity:
mac_control.mm
MacControl::MacControl(QWidget *parent) : QMacCocoaViewContainer(NULL, parent) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSSegmentedControl *segmented = [[NSSegmentedControl alloc] init];
// Set up NSSegmentedControl...
// The proxy class marshalls between Objective-C and C++.
proxy_ = [[MacControlProxy alloc] init];
[proxy_ setTarget:this];
[segmented setTarget:proxy_];
[segmented setAction:#selector(handleToggle:)];
setCocoaView(segmented);
[segmented release];
[pool release];
}
MacControl::~MacControl() {
delete proxy_;
}
void MacControl::TriggerAction(int index) {
// Trigger the action in Qt/C++.
}
mac_control_proxy.mm
#implementation MacControlProxy
- (id)init {
[super init];
target_ = NULL;
return self;
}
-(void) handleToggle: (id)sender {
if (target_) {
target_->TriggerAction([sender selectedSegment]);
}
}
-(void) setTarget: (MacToolbarButtonControlImpl*)target {
target_ = target;
}
#end
I'm following up on Dave Mateer's answer (which was super helpful!).
I was having issues setting the C++ target (from within a objective-C++ class) and used [NSValue valueWithPointer:theTargetCxxClass] to pass the target to the Proxy.mm class.
So, inside of my Objective-C++ class, rather than doing this:
[proxy_ setTarget:this];
I did this:
[proxy_ setTarget:[NSValue valueWithPointer:this]];
or
[proxy_ setTarget:[NSValue valueWithPointer:ptrToMyCxxObject]];
And doing this got rid of an error about passing a C++ class (which does not extend type "id") to the Objective-C++ proxy class.
Inside of the proxy class, you then need to use NSValue's pointerValue method and then cast back to the C++ class in order to send a message to it.
-(void) myButtonAction: (id)sender {
((MyCxxClass*)[target pointerValue])->someMethodInMyCxxClass();
}
I first was alerted to the "valueWithPointer" trick in this post.
I'm confused with the addChild: behavior in Cocos2D, because of the following:
I have a CCNode subclass that owns a CCSprite and a Box2DBody.
Im the -init method of this subclass, i add the sprite to a CCSpriteBatchNode of the main GameScene, like this:
//Ball class, CCNode subclass with a CCSprite and a b2Body
-(id)initBallInWorld:(b2World *)word spriteFile:(NSString *)file
{
//self = [super init] blablabla
CCSpriteBatchNode *batch = [GameScene getSpriteBatch]; //singleton
//create Box2dBody inside the world
//create a CCSprite
[batch addChild:sprite]; //Here is the confusion!
}
In the main GameScene i do:
Ball *ball = [Ball ballInWorld...]
If i do [self addChild:ball], the physics works as expected, but if i don't, the ballSprite gets stuck at (0, 0)..why is that? The batch is already added to the GameScene, and the ballSprite is already added to the batch, this extra addChild seems weird to me!
Thanks!
Thanks for the comments, but i figure it out.
When i call the static [Ball ballInWorld:] the CCSprite is not retained in the Ball class, but only inside the CCSpriteBatchNode, so i have to use addChild:ball or use [[Ball alloc]init ...]to keep the sprite reference alive.
GameScene is a CCLayer, i think thats ok to use it as a singleton.