v3.0a onTouchesEnded / onTouchEnded Not working / not intercepted

In the default HelloWorld win32 application, when I try to intercept touches to the layer by adding

void onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event);

to the HelloWorld class, the function is never called when I click anywhere on the win32 emulator.

I tried using ccTouchesEnded but it says cannot override a function declared as final

helloworld.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class HelloWorld : public cocos2d::Layer
{
    private:
    cocos2d::Layer* players;
    cocos2d::Sprite* ball;
    cocos2d::Layer* tracks;
    cocos2d::Layer* flashes;
    cocos2d::Sprite* bac;
    cocos2d::Sprite* bShad;
    cocos2d::Sprite* player1;
    cocos2d::Sprite* player2;
    cocos2d::Sprite* goalie;
    cocos2d::Sprite* powerup;
    cocos2d::Sprite* powerBar;
    cocos2d::Layer* pBar;
    cocos2d::LabelTTF* labelTapPowerup;
    cocos2d::LabelTTF* labelPowerupCount;


    void onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event);
    bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);

    //void onTouchesEnded(const std::vector< cocos2d::Touch* > touches, cocos2d::Event* event);

    //void ccTouchesEnded(cocos2d::Set* touches, cocos2d::Event* event);

public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();

    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  

    // a selector callback
    void menuCloseCallback(Object* pSender);

    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);


};


class Dimen{
    public:

    int width;
    int height;
    int ballPos[2];
    int goalBase;
    int ballBase;
    int goaliePos[7][2];
    int ballSize[2];
    int bShadSize[2];
    float ballEndScale;

    int playerFrames[3][4];
    int player1Frames[2][4];
    int goalieFrames[6][4];
    int audienceArea[4];
    int ballsp[6][4];
    int ballPers[6];
    std::vector moveSteps;
    int powerup[4];
    int powerBar[6];
    int groundEnd[4];




    void initDimen();
    char* toCStr(int i);




};


#endif // __HELLOWORLD_SCENE_H__

helloworld.cpp

#include "HelloWorldScene.h"

USING_NS_CC;

Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();

    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }

    Size visibleSize = Director::getInstance()->getVisibleSize();
    Point origin = Director::getInstance()->getVisibleOrigin();
    /*
    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    auto closeItem = MenuItemImage::create(
                                           "CloseNormal.png",
                                           "CloseSelected.png",
                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

    closeItem->setPosition(Point(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                                origin.y + closeItem->getContentSize().height/2));

    // create menu, it's an autorelease object
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Point::ZERO);
    this->addChild(menu, 1);

    /////////////////////////////
    // 3. add your codes below...

    // add a label shows "Hello World"
    // create and initialize a label

    auto label = LabelTTF::create("Hello World", "Arial", 24);

    // position the label on the center of the screen
    label->setPosition(Point(origin.x + visibleSize.width/2,
                            origin.y + visibleSize.height - label->getContentSize().height));

    // add the label as a child to this layer
    this->addChild(label, 1);

    // add "HelloWorld" splash screen"
    auto sprite = Sprite::create("HelloWorld.png");

    // position the sprite on the center of the screen
    sprite->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

    // add the sprite as a child to this layer
    this->addChild(sprite, 0);
    */
    this->setTouchEnabled(true);

    // add "HelloWorld" splash screen"
    Sprite* sprite = cocos2d::Sprite::create("bac1.jpg");

    // position the sprite on the center of the screen
    sprite->setPosition(cocos2d::CCPoint(0,0));
    sprite->setAnchorPoint(cocos2d::CCPoint(0,0));

    // add the sprite as a child to this layer
    this->addChild(sprite,0);


    ball = Sprite::create("ball.png");
    players = Layer::create();

        Dimen dimen;
        dimen.initDimen();
        tracks = Layer::create();

    flashes = Layer::create();
    bac = Sprite::create("bac1.jpg");
    bShad = Sprite::create("bshad.png");

    player1=Sprite::create();
    player2=Sprite::create();
    goalie = Sprite::create("goalie.png");
    powerup = Sprite::create("powerup.png");
    powerBar = Sprite::create();
    pBar = Layer::create();
    labelTapPowerup = LabelTTF::create("Tap to powerup", "Arial", 24);
    labelPowerupCount = LabelTTF::create("Tap to powerup", "Arial", 24);

    ball->setAnchorPoint(Point(0.5,0.5));
        ball->setPosition(Point(dimen.ballPos[0],dimen.ballPos[1]));
    this->addChild(ball);
    log("start");

    this->addTouchListener();

    return true;
}


void HelloWorld::menuCloseCallback(Object* pSender)
{
    Director::getInstance()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

char* Dimen :: toCStr(int i)
{
    return "00";//itoa(i,new char[10],10);
}

void Dimen :: initDimen(){

        width=320;
        height=480;
        {int a[]={ width/2,(height*(1.0/5.0)) };  for(int i=0,n=sizeof(a)/sizeof(a[0]);igetLocationInView();
    location = Director::sharedDirector()->convertToGL(location);
    ball->setScale(1);

    ball->runAction(MoveTo::create(.5, location));// CCSequence::create(CCMoveTo::create(1, location)//,CCCallFuncN::create(this,callfuncN_selector(HelloWorld::spriteMoveFinished)),NULL) );
    ball->runAction(ScaleTo::create(.5, 0.4));
    ball->runAction(RotateBy::create(.5, 700));
    return true;
}

void HelloWorld::onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event)
{
    // Choose one of the touches to work with
    //Touch* touch = touches;
    log("touch");
    Point location = touch->getLocationInView();
    location = Director::sharedDirector()->convertToGL(location);
    ball->setScale(1);

    ball->runAction(MoveTo::create(.5, location));// CCSequence::create(CCMoveTo::create(1, location)//,CCCallFuncN::create(this,callfuncN_selector(HelloWorld::spriteMoveFinished)),NULL) );
    ball->runAction(ScaleTo::create(.5, 0.4));
    ball->runAction(RotateBy::create(.5, 700));

}

any suggestions would be very appreciated, sorry for dumping the code as it is.

thanks

  1. You don’t need to invoke this->addTouchListener();, the api is used internally.
  2. onTouchEnded is using ONE_BY_ONE dispatch mode. So you need to invoke this->setTouchMode(Touch::DispatchMode::ONE_BY_ONE.

I see a lot of people get confused by this, maybe we should enable both onTouchEnded and onTouchesEnded by default. With onTouchEnded only take one of the touch. Plus what’s the application of DispatchMode::ONE_BY_ONE anyway.

thanks for the reply James, this->addTouchListener(); was added just to see if it makes things working,
okay to get onTouchEnded working i need to set DispatchMode::ONE_BY_ONE, but what if I use onTouchesEnded do i need to set it or it should work without setting it ? sorry i am at remote place cant try it out, anyways ill reply if it works.
Thanks a lot.

finally I got the problem, I was using the different format to override,
this is the correct override in 3.0a
void onTouchesEnded(const std::vector<cocos2d::Touch*>& pTouches,cocos2d::Event *pEvent)