Two button problems

I have two problems with a button in my game.

The first one is that the button does not seem to work in frame sizes above 1047x1047. It works fine when it is 1047x1047 and below but as soon as I make it any bigger, it does not work.

My other problem is that I’m trying to hide the button once I press it. However as soon as I set the opacity to 0, it crashes the program.

Here is my code:

auto play = Button::create("play.png");
play->setPosition(Vec2(visibleSize.width/2, visibleSize.height/2));
this->addChild(play);
play->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type) {
    switch (type) {
        case Widget::TouchEventType::ENDED:
            log("ended");
            play->setOpacity(0); //crashes program
            break;
    }
});

I’m using cocos2d-x v3.10 and Microsoft Visual Studio Express 2015 for Windows Desktop (if that matters).

Any help would be appreciated.

Hi @xxYxx
The crash problem is related do bad lambda definition.
You catch variable play by reference, but play is a local variable and will be destroyed when program exit from its scope.
This means that when you press the button play variable does not exist anymore!
To make invisible the button I suggest to use setVisible(false), with setOpacity(0) the button should continue to work even if invisible!
Try this code:

auto play = Button::create("play.png");
play->setPosition(Vec2(visibleSize.width/2, visibleSize.height/2));
this->addChild(play);
play->addTouchEventListener([=](Ref* sender, Widget::TouchEventType type) {
    switch (type) {
        case Widget::TouchEventType::ENDED:
            log("ended");
            play->setVisible(false);
            break;
    }
});
1 Like

Hi @drakon99
Thanks for the fast reply.

I declared the play variable in my header file so now it works. Also thanks for the setVisible(false).

@xxYxx I’m glad this worked for you! :smile:
Anyway I strongly suggest to avoid global variable if you can.

You can still catch local variables in lambda by copy in two ways:

  • using [=] (catch all variables in lambda by copy, see code I posted before)
  • using [play] (catch by copy the variables you specify inside brackets)

Why do you recommend not using global variables? (Sorry if this sounds really newb, I’m pretty new to C++)

@xxYxx
Having a global variable containing a pointer is really dangerous because it can easily became a dangling pointer.
Namely when the object (the Button in your case) contained in the variable is destroyed (maybe because you change Scene), you have to remember that the pointer in the global variable is invalid.
If you try to access to the variable after destruction you get a crash!