How to pass the e pointer in the onMouseDown function to the popScene function?

the code as follows:

bool HelloWorld::init()
{
   this->schedule(CC_CALLBACK_1(HelloWorld::popScene,this),0.1f,"aaa");
}

void HelloWorld::onMouseDown(Event *event){
   i=0;
   EventMouse *e=(EventMouse*)event;
}

void HelloWorld::onMouseUp(Event *event){
   i=1;
}

void HelloWorld::popScene(float t)
{
if(i==0){
	Sprite* node3=Sprite::create("ty.png");
	node3->setPosition(node2->getPosition());
	this->addChild(node3);
	auto moveTo = MoveTo::create(1, Vec2(e->getCursorX(),e->getCursorY()));
	node3->runAction(moveTo);
   }
}

change the scope from local to something HelloWorld:: can access? Then use it in popScene()?

It looks like “i” is a member of Helloworld (although perhaps bool mouseIsDown would be a better name?)

Why not use an EventMouse* in HelloWorld instead (EventMouse* mouseDownEvent;)?
Set it to null normally and in onMouseUp(), and to event in onMouseDown().
Now when the mouse is down, you have access to the event

void HelloWorld::popScene(float t)
{
if(mouseDownEvent){
	Sprite* node3=Sprite::create("ty.png");
	node3->setPosition(node2->getPosition());
	this->addChild(node3);
	auto moveTo = MoveTo::create(1, Vec2(mouseDownEvent->getCursorX(),mouseDownEvent->getCursorY()));
	node3->runAction(moveTo);
   }
}

(Assuming MouseEvent is reference counted, or you may need to handle persistence and release your self, one way would be to store getcursor x and y in a hellowworld member vec2, then clear that in mouse up.)

Note this is single threaded and assumes mouseup can’t happen while you are inside popScene() - if it can you need to make sure event is not set to null while you are inside popScene()

Further note, I am not sure how mouse down/up will handle

  1. click and hold in app
  2. move mouse “off” app and release button
  3. move mouse back.
    You may loose the mouse up event and need to handle mouse entering and leaving app area too.

And it shows error.

Is it modify like this?

The head file as follows:

 #ifndef __HELLOWORLD_SCENE_H__
 #define __HELLOWORLD_SCENE_H__

 #include "cocos2d.h"
 using namespace cocos2d;
 class HelloWorld : public cocos2d::Scene
 {
 private:
     int i,j;
     EventMouse* mouseDownEvent;
 public:
       HelloWorld::HelloWorld(){
	     i=2;
	     j=2;
       }
static cocos2d::Scene* createScene();
virtual bool init();
cocos2d::Sprite* node2;
cocos2d::Sprite* node3;
cocos2d::Sprite* node4;
void onMouseDown(cocos2d::EventMouse* mouseDownEvent);
void onMouseUp(cocos2d::EventMouse* mouseDownEvent);
CREATE_FUNC(HelloWorld);
void popScene(float t);
};

#endif // __HELLOWORLD_SCENE_H__

Thi sourse file as follows:

bool HelloWorld::init(){
	node2=Sprite::create("ty.png");
	node2->setPosition(Vec2(200,200));
	this->addChild(node2);

	auto _mouseListener=EventListenerMouse::create();
	_mouseListener->onMouseDown=CC_CALLBACK_1(HelloWorld::onMouseDown,this);
	_mouseListener->onMouseUp=CC_CALLBACK_1(HelloWorld::onMouseUp,this);
	_eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener,this);
	SimpleAudioEngine::getInstance()->playBackgroundMusic("yingyue.mp3",true);

	this->schedule(CC_CALLBACK_1(HelloWorld::popScene,this),2.1f,"aaa");
	return true;
}
void HelloWorld::onMouseDown(EventMouse* event){
	Sprite* node3=Sprite::create("ty.png");
	node3->setPosition(node2->getPosition());
	this->addChild(node3);
	SimpleAudioEngine::getInstance()->playEffect("yingxiao.mp3", false, 1.0, 1.0, 1.0);
	EventMouse *mouseDownEvent=(EventMouse*)event;
	auto moveTo = MoveTo::create(1, Vec2(mouseDownEvent->getCursorX(),mouseDownEvent->getCursorY()));
	node3->runAction(moveTo);
	auto pDelayTime=DelayTime::create(0.2f);
	node3->runAction(pDelayTime);
}

void HelloWorld::onMouseUp(EventMouse* event){
    EventMouse *mouseDownEvent=(EventMouse*)event;
}

void HelloWorld::popScene(float t)
{
if(mouseDownEvent){
	SimpleAudioEngine::getInstance()->playEffect("yingxiao.mp3", false, 1.0, 1.0, 1.0);
	Sprite* node3=Sprite::create("ty.png");
	node3->setPosition(node2->getPosition());
	this->addChild(node3);
	auto moveTo = MoveTo::create(1, Vec2(mouseDownEvent->getCursorX(),mouseDownEvent->getCursorY()));
	node3->runAction(moveTo);
	auto pDelayTime=DelayTime::create(0.2f);
	node3->runAction(pDelayTime);
   }
 }

Real close I think :slight_smile:

Some things to consider

  1. Initialize mouseDownEvent to nullptr.
    In debug mode you may be ok, if compiler defaults to zero, but in release mode it will be a random address and you will be in for a world of hurt debugging it.
    ALWAYS (well almost always) initialize your variables.

  2. Unless I am misreading code you are setting mouseDownEvent in both onMouseDown() and onMouseUp(). If you want your code to work like it did initially, where “i” indicated if you’re up or down, and popScene() uses if(mouseDownEvent) for that logic, THEN onMouseUp() should set mouseDownEvent to nullptr, not (EventMouse*)event

  3. In general a pointer either points to a location in memory (an address) or nullptr (i.e. zero). If zero / nullptr if(pointer) will be false. IF the location it points to is not actually the location of a thing (i.e. not initialized), you will have a lot of random bugs.
    Once you get a bit more comfortable in C++ I suggest you read up on pointers - very powerful, but tricky until you get the hang of it.
    You may find the distinction between passing these 3 ways useful:

func(int foo); // By value - foo is a copy of the int value passed
func(int& foo); // By reference  - foo lets you access the int but foo cannot be nullptr (or zero)
func(int* foo); // By pointer - foo is address of int, but may be nullptr (i.e.zero) indicating no int

In general prefer by value or reference, UNLESS the concept of none (i.e. nullptr / zero) has meaning. Like above where we could use no mouseDownEvent (nullptr) in logic of popScene.
(I often ask C++ programmers I interview to explain the difference and when they would use each one - shows me who has actually done some C++ :wink:)

There has still an proplem after modification, After the program runs, when I click the left mouse button then the program terminates.I found that this line in the popScene function was causing the problem:

auto moveTo = MoveTo::create(1, Vec2(mouseDownEvent->getCursorX(),mouseDownEvent->getCursorY()));

I uploaded the demo file.
demo.zip (1.1 MB)

The modified with the code as follows:
The head file as follows:

 #ifndef __HELLOWORLD_SCENE_H__
 #define __HELLOWORLD_SCENE_H__

 #include "cocos2d.h"
 using namespace cocos2d;
 class HelloWorld : public cocos2d::Scene
 {
 private:
     int i,j;
     EventMouse* mouseDownEvent;
 public:
 HelloWorld::HelloWorld(){
     i=2;
     j=2;
     EventMouse* mouseDownEvent=nullptr;
   }
static cocos2d::Scene* createScene();
virtual bool init();
cocos2d::Sprite* node2;
cocos2d::Sprite* node3;
cocos2d::Sprite* node4;
void onMouseDown(cocos2d::Event* event);
void onMouseUp(cocos2d::Event* event);
CREATE_FUNC(HelloWorld);
void popScene(float t);
};

#endif // __HELLOWORLD_SCENE_H__

The sourse file as follows:

bool HelloWorld::init(){
	node2=Sprite::create("ty.png");
	node2->setPosition(Vec2(200,200));
	this->addChild(node2);

	auto _mouseListener=EventListenerMouse::create();
	_mouseListener->onMouseDown=CC_CALLBACK_1(HelloWorld::onMouseDown,this);
	_mouseListener->onMouseUp=CC_CALLBACK_1(HelloWorld::onMouseUp,this);
	_eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener,this);
	SimpleAudioEngine::getInstance()->playBackgroundMusic("yingyue.mp3",true);

	this->schedule(CC_CALLBACK_1(HelloWorld::popScene,this),2.1f,"aaa");
	return true;
}
void HelloWorld::onMouseDown(Event* event){
    i=0;
	Sprite* node3=Sprite::create("ty.png");
	node3->setPosition(node2->getPosition());
	this->addChild(node3);
	SimpleAudioEngine::getInstance()->playEffect("yingxiao.mp3", false, 1.0, 1.0, 1.0);
	EventMouse *mouseDownEvent=(EventMouse*)event;
	auto moveTo = MoveTo::create(1, Vec2(mouseDownEvent->getCursorX(),mouseDownEvent->getCursorY()));
	node3->runAction(moveTo);
	auto pDelayTime=DelayTime::create(0.2f);
	node3->runAction(pDelayTime);
}

void HelloWorld::onMouseUp(Event* event){
    i=1;
	EventMouse *mouseDownEvent=nullptr;
}

void HelloWorld::popScene(float t)
{
if(mouseDownEvent&&i==0){
	SimpleAudioEngine::getInstance()->playEffect("yingxiao.mp3", false, 1.0, 1.0, 1.0);
	Sprite* node3=Sprite::create("ty.png");
	node3->setPosition(node2->getPosition());
	this->addChild(node3);
    //The following line has an error
	auto moveTo = MoveTo::create(1, Vec2(mouseDownEvent->getCursorX(),mouseDownEvent->getCursorY()));
	node3->runAction(moveTo);
	auto pDelayTime=DelayTime::create(0.2f);
	node3->runAction(pDelayTime);
   }
 }

It still has a problem.

Hm, at first I was wondering about

if(mouseDownEvent&&i==0){

Personally I always use braces to make explicit what I want, even if not needed.
But == is evaluated before &&
Operators Precedence in C (tutorialspoint.com)
So we have

if(mouseDownEvent&&(i==0))

Which means mouseDownEvent is true, i.e. not null, so that should be ok.

I think I found problem, you are using a local variable, not the member

void HelloWorld::onMouseDown(Event* event){
    i=0;
	Sprite* node3=Sprite::create("ty.png");
	node3->setPosition(node2->getPosition());
	this->addChild(node3);
	SimpleAudioEngine::getInstance()->playEffect("yingxiao.mp3", false, 1.0, 1.0, 1.0);
	// EventMouse *mouseDownEvent=(EventMouse*)event; BUG this is local to function variable
    mouseDownEvent = (EventMouse*)event; // this is the member variable - you might have seen a waring from compiler about this.
   // Alternate you can use "this->mouseDownEvent  = (EventMouse*)event;"  if you want to be specific
	auto moveTo = MoveTo::create(1, Vec2(mouseDownEvent->getCursorX(),mouseDownEvent->getCursorY()));
	node3->runAction(moveTo);
	auto pDelayTime=DelayTime::create(0.2f);
	node3->runAction(pDelayTime);
}

and

void HelloWorld::onMouseUp(Event* event){
    i=1;
    // EventMouse *mouseDownEvent=nullptr; BUG
   mouseDownEvent=nullptr;
}

Looking at code you may also want to get rid of “i” since mouseDownEvent serves same purpose as i=0 or 1. Unless there is more that I am not seeing

No error was reported this time,

However, the expected function cannot be achieved.

I hope that the timer can continuously move the node3 node in the popScene function to the position of the cursor.

But after the program runs, when I click the left mouse button, it moves only once.

I uploaded the file.
demo.zip (1.1 MB)

The modified code is as follows:
head file:

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
using namespace cocos2d;
class HelloWorld : public cocos2d::Scene
{
private:
	int i,j;
	EventMouse* mouseDownEvent;
	cocos2d::Sprite* node2;
public:
	HelloWorld::HelloWorld(){
		mouseDownEvent=nullptr;
		node2=nullptr;
	}
    static cocos2d::Scene* createScene();
    virtual bool init();
	void onMouseDown(cocos2d::Event* event);
	void onMouseUp(cocos2d::Event* event);
    CREATE_FUNC(HelloWorld);
	void popScene(float t);
};

#endif // __HELLOWORLD_SCENE_H__

source file:

bool HelloWorld::init()
{
    node2=Sprite::create("ty.png");
	node2->setPosition(Vec2(200,200));
	this->addChild(node2);

	auto _mouseListener=EventListenerMouse::create();
	_mouseListener->onMouseDown=CC_CALLBACK_1(HelloWorld::onMouseDown,this);
	_mouseListener->onMouseUp=CC_CALLBACK_1(HelloWorld::onMouseUp,this);
	_eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener,this);
	SimpleAudioEngine::getInstance()->playBackgroundMusic("yingyue.mp3",true);

	this->schedule(CC_CALLBACK_1(HelloWorld::popScene,this),2.1f,"aaa");
	return true;
}
void HelloWorld::onMouseDown(Event* event){
		Sprite* node3=Sprite::create("ty.png");
		node3->setPosition(node2->getPosition());
		this->addChild(node3);
		SimpleAudioEngine::getInstance()->playEffect("yingxiao.mp3", false, 1.0, 1.0, 1.0);
		this->mouseDownEvent=(EventMouse*)event;
		auto moveTo = MoveTo::create(1, Vec2(mouseDownEvent->getCursorX(),mouseDownEvent->getCursorY()));
		node3->runAction(moveTo);
		auto pDelayTime=DelayTime::create(0.2f);
		node3->runAction(pDelayTime);
}

void HelloWorld::onMouseUp(Event* event){
	mouseDownEvent=nullptr;
}

void HelloWorld::popScene(float t)
{
	if(mouseDownEvent){
		SimpleAudioEngine::getInstance()->playEffect("yingxiao.mp3", false, 1.0, 1.0, 1.0);
		Sprite* node3=Sprite::create("ty.png");
		node3->setPosition(node2->getPosition());
		this->addChild(node3);
		auto moveTo = MoveTo::create(1, Vec2(mouseDownEvent->getCursorX(),mouseDownEvent->getCursorY()));
		node3->runAction(moveTo);
		auto pDelayTime=DelayTime::create(0.2f);
		node3->runAction(pDelayTime);
	   }
}

Glad it runs :slight_smile:
Now it will be a bit trickier for me to help, but I can suggest some tings to try.

  1. Perhaps add log messages to functions to give you an idea what is / is not happening.
    Specifically I am wondering if popScene is called more than once. I used something like this
void LairLichLordScene::onMouseDown(cocos2d::Event*)
{
    cc::log("onMouseDown"); // log to output window so easier to debug
    Jump();
}
  1. As I discovered recently Help Please: Sprite::SetPosition() does not seem to work in onContact callbacks for Chipmunk physics engine - cocos2d-x / C++ - Cocos Forums
    sometimes sePosition seems to be ignored.
    Try using an action instead, I used something like this which fixed my problem
// hole is Sprite*
auto action = cocos2d::MoveTo::create(0.0, cocos2d::Vec2(pos)); // works, UNLESS setPosition() was also called in which case it fails (?)
hole->runAction(action);   
  1. Try asking around on forum, I am good at C++, but working on learning cocos, I have been surprised / confounded trying to get stuff working my self

Good luck dfgfgh345

I know too little of the details of cocos2d-x yet, but in my game based of the hello world template I have a call to “this->scheduleUpdate();”
I think this is what actually creates a game loop that regularly runs all the stuff that need running in a loop including processing messages etc. I am wondering is your delay never gets a chance to be evaluated without the gameloop being updated. But you really need to ask someone who know more of cocos2d-x I think :slight_smile:

Or maybe your delay means that the mouse up event clears the mouseDownEvent before popScene has a chance to act.

  1. What happens if you press and hold mouse button down the second time?
  2. What happens if you move the mouseDownEvent=nullptr; from onMouseUp() to popScene() and null it when you are done with it (before the pauses)
if(mouseDownEvent){
		SimpleAudioEngine::getInstance()->playEffect("yingxiao.mp3", false, 1.0, 1.0, 1.0);
		Sprite* node3=Sprite::create("ty.png");
		node3->setPosition(node2->getPosition());
		this->addChild(node3);
		auto moveTo = MoveTo::create(1, Vec2(mouseDownEvent->getCursorX(),mouseDownEvent->getCursorY()));
     mouseDownEvent=nullptr;
		node3->runAction(moveTo);
		auto pDelayTime=DelayTime::create(0.2f);
		node3->runAction(pDelayTime);
	   }