Invalid EventListenerTouchOneByOne! Error

Hi I’m getting this error from the console: cc._EventListenerTouchOneByOne.checkAvailable(): Invalid EventListenerTouchOneByOne! CCEventListener.js:359

I’m using Cocos2d-js v3 and I’m trying to use the new eventmanager as documented here: http://cocos2d-x.org/docs/manual/framework/html5/v3/eventManager/en

I don’t know what I’m doing wrong. Here’s my code:

    var BigGridLayer = cc.Layer.extend({
    ctor: function() {
        this._super();
        this.init();
    },
    init: function() {
        this._super();

        //create a color layer
        var gridBg = cc.LayerColor.create(cc.color(157, 155, 171, 60), 64 * 6, 768);
        gridBg.setPosition(30, 50);
        this.addChild(gridBg);

        //create a custom sprite for our blocks
        var BlockSprite = cc.Sprite.extend({
            ctor: function(filename, rect) {
                this._super(filename, rect);
                this._active = false;
                this._col;
                this._row;
                this._color;
                this.init();
                // Custom intialization

            },
            init: function() {
                this._super();
                cc.eventManager.addListener({
                    event: cc.EventListener.TOUCH_ONE_BY_ONE,
                    swallowTouches: true,
                    onTouchMoved: function(touch, event) {
                        //Move the position of current button sprite
                        console.log('touch moved');
                        var target = event.getCurrentTarget();
                        var delta = touch.getDelta();
                        target.x += delta.x;
                        target.y += delta.y;
                    },
                }, this);
            }
            // add your properties and functions
        });

        //create a block sprite
        var redBlock = new BlockSprite(res.red_png);
        redBlock.attr({
            x: 0,
            y: 0,
            anchorX: 0,
            anchorY: 0
        });
        var newRedBlock = new BlockSprite(res.red_png);
        newRedBlock.x = 64;
        newRedBlock.anchorX = 0;
        newRedBlock.anchorY = 0;
        //create a block sprite
        var blueBlock = new BlockSprite(res.blue_png);
        blueBlock.attr({
            x: 64 * 2,
            y: 0,
            anchorX: 0,
            anchorY: 0
        });
        var newBlueBlock = new BlockSprite(res.blue_png);
        newBlueBlock.x = 64 * 3;
        newBlueBlock.anchorX = 0;
        newBlueBlock.anchorY = 0;
        //create a block sprite
        var greenBlock = new BlockSprite(res.green_png);
        greenBlock.attr({
            x: 64 * 4,
            y: 0,
            anchorX: 0,
            anchorY: 0
        });
        var newGreenBlock = new BlockSprite(res.green_png);
        newGreenBlock.x = 64 * 5;
        newGreenBlock.anchorX = 0;
        newGreenBlock.anchorY = 0;


        gridBg.addChild(redBlock);
        gridBg.addChild(newRedBlock);
        gridBg.addChild(blueBlock);
        gridBg.addChild(newBlueBlock);
        gridBg.addChild(greenBlock);
        gridBg.addChild(newGreenBlock);

    }
});

Ok so I figured out what was causing that error. I did not have a “onTouchBegan” function in my listener which apparently is required.

So I added the “onTouchBegan” and it did get rid of the error. My blocks are still not being rendered on screen though. I thought that it was that error that was causing it to not be rendered.

Can anyone help?

If the rect is undefined, try to ignore it in super like this

rect ? this._super(filename, rect) : this._super(filename);

I should’ve updated this because I actually got the blocks to render but now I’m having another problem.

So here is my latest code:

var BlockSprite = cc.Sprite.extend({
    ctor: function(img, color) {
        this._super(img);
        this._color = color;
    },
    onEnter: function() {
        this._super();
        var selfPointer = this;
        var target;
        cc.eventManager.addListener({
            event: cc.EventListener.TOUCH_ONE_BY_ONE,
            swallowTouches: true,
            onTouchBegan: function(touch, event) {
                cc.log(event.getCurrentTarget());
                return true;
            },
            onTouchMoved: function(touch, event) {
//Move the position of current button sprite
                cc.log('touch moved');
                var target = event.getCurrentTarget();
                var delta = touch.getDelta();
                target.x += delta.x;
                target.y += delta.y;
            },
            onTouchEnded: function(touch, event) {
        cc.log('touch ended');
        cc.eventManager.removeListener(this._listener);
            }
        }, this);
    }

});

var BigGridLayer = cc.Layer.extend({
    onEnter: function() {
        this._super();
        //create a color layer
        var gridBg = cc.LayerColor.create(cc.color(157, 155, 171, 60), 64 * 6, 768);
        gridBg.setPosition(30, 50);
//        this.addChild(gridBg);

        var redBlock = new BlockSprite(res.red_png, 'red');
        redBlock.attr({
            x: 0,
            y: 0,
            anchorX: 0,
            anchorY: 0
        });
        this.addChild(redBlock);

        var newRedBlock = new BlockSprite(res.red_png, 'red');
        newRedBlock.x = 64;
        newRedBlock.anchorX = 0;
        newRedBlock.anchorY = 0;
        this.addChild(newRedBlock);

        //create a block sprite
        var blueBlock = new BlockSprite(res.blue_png, 'blue');
        blueBlock.attr({
            x: 64 * 2,
            y: 0,
            anchorX: 0,
            anchorY: 0
        });
        this.addChild(blueBlock);

        var newBlueBlock = new BlockSprite(res.blue_png, 'blue');
        newBlueBlock.x = 64 * 3;
        newBlueBlock.anchorX = 0;
        newBlueBlock.anchorY = 0;
        this.addChild(newBlueBlock);

        //create a block sprite
        var greenBlock = new BlockSprite(res.green_png, 'green');
        greenBlock.attr({
            x: 64 * 4,
            y: 0,
            anchorX: 0,
            anchorY: 0
        });
        this.addChild(greenBlock);

        var newGreenBlock = new BlockSprite(res.green_png, 'green');
        newGreenBlock.x = 64 * 5;
        newGreenBlock.anchorX = 0;
        newGreenBlock.anchorY = 0;
        this.addChild(newGreenBlock);    }
});

The problem that I’m having now:
1.Every time I test this on the browser , whichever block i try to move, it always moves the green block, which is the very last one that I created using my custom sprite, BlockSprite. It seems that no matter which block I try to ‘touch’ the event.getCurrentTarget() from my onTouchBegan always returns the same sprite/node, which is that green block. Why is this happening?

I’m using v3 alpha2 by the way.

After re-reading the documentation for the EventManager ( http://cocos2d-x.org/docs/manual/framework/html5/v3/eventManager/en ), I think I understand the problem now:)
I’m going to try out some stuff and maybe I’ll provide an update later.

So I figured out what the problem was.

Basically, I had created a custom Sprite called BlockSprite and inside this, I attached my listener. Since all of my blocks(sprites) was instantiated using BlockSprite, this meant that I had one listener for all of my blocks and with SceneGraphPriority pointing to a node, in this case, the BlockSprite node, every time a touch event would occur it executes that listener which is attached to all of my blocks. So no matter which block I ‘touched’, all of the blocks’ event listener would fire and would be passed the event object.

So how do I determine the actual block that was ‘touched’?
For this, I just had to look at the example code from the documentation. Inside the onTouchBegan, is this code:

onTouchBegan: function (touch, event) { 
        // event.getCurrentTarget() returns the *listener's* sceneGraphPriority node.   
        var target = event.getCurrentTarget();  

        //Get the position of the current point relative to the button
        var locationInNode = target.convertToNodeSpace(touch.getLocation());    
        var s = target.getContentSize();
        var rect = cc.rect(0, 0, s.width, s.height);

        //Check the click area
        if (cc.rectContainsPoint(rect, locationInNode)) {       
            cc.log("sprite began... x = " + locationInNode.x + ", y = " + locationInNode.y);
            target.opacity = 180;
            return true;
        }
        return false;
    },

This code basically takes care of finding out whether the current sprite is the one that’s being ‘clicked’ or ‘touched’.