Mouse and Touch reporting different positions

Hello all,

I’m currently developing an isometric html5, and i’m trying to get the touched/clicked tile so I can perform some actions as item placement, open an edit menu etc.

When I use onTouchesBegan to retrieve the clicked position, everything works like a charm, with the touch object returning it’s position that when used with convertTouchToNodeSpace correctly converts to the tiled map coordinates.
But when I use onMouseMoved, the mouse object returns the mouse’s screen coordinates, that, when used with convertTouchToNodeSpace doesn’t correctly maps to the tile map coordinates…

I need to use onMouseMoved so I can place an indicator for the player so she knows where she will place an item for example…

Please, take a look at the code and if you know what i’m doing wrong or what I need to do, please enlighten me :stuck_out_tongue:

Thanks in advance!

Here’s the code:

cc.TMXTiledMap.prototype.tilePosToScreenPos = function(posX, posY) {
    point.x += this._tileSize.width * this._mapSize.width / 2;
    point.y = this._tileSize.height * this._mapSize.height - point.y;*/
    var point = cc.p(this._tileSize.width / 2 * (this._mapSize.width - posX + posY),
        this._tileSize.height * ( this._mapSize.height - (posX + posY) / 2));
    return point;
};

cc.TMXTiledMap.prototype.ScreenPosToTilePos = function(posX, posY) {
    var point = cc.p(this._mapSize.width / 2 + this._mapSize.height - posX / this._tileSize.width - posY / this._tileSize.height,
        this._mapSize.height - this._mapSize.width / 2 - posY / this._tileSize.height + posX / this._tileSize.width);
    point.x = Math.floor(point.x);
    point.y = Math.floor(point.y);
    return point;
};

var testLayer = cc.Layer.extend({
/* initializer stuff here... */
    onTouchesBegan : function(touches, event) {
        var touch = touches[0];
        var position = this.tmxMap.convertTouchToNodeSpace(touch);
        cc.log("Position: " + position.x + ", " + position.y);
        var tilePosition = this.tmxMap.ScreenPosToTilePos(position.x, position.y);
        cc.log("TilePos: " + tilePosition.x + ", " + tilePosition.y);
        var selectedPos = this.tmxMap.tilePosToScreenPos(tilePosition.x, tilePosition.y);
        selectedPos.y -= this.tmxMap.getTileSize().height / 2;
        this.selectedTileSprite.setPosition(selectedPos);
        return true;

    },
    onMouseMoved : function(mouse) {
        var position = this.tmxMap.convertTouchToNodeSpace(mouse);
        cc.log("Position: " + position.x + ", " + position.y);
        var tilePosition = this.tmxMap.ScreenPosToTilePos(position.x, position.y);
        cc.log("TilePos: " + tilePosition.x + ", " + tilePosition.y);
        var selectedPos = this.tmxMap.tilePosToScreenPos(tilePosition.x, tilePosition.y);
        selectedPos.y -= this.tmxMap.getTileSize().height / 2;
        this.selectedTileSprite.setPosition(selectedPos);
        return true;
    }
});

An example of touch and mouse coordinates (using just a mouse on firefox):
Touch Raw Position: 640.8411214953271, 561.8691588785047 Mouse Raw Position: 677, 334

After playing around with the codes I’ve found the problem:
Touch object automatically applies content scaling and viewport offset to it’s location, while mouse object returns it’s raw position related to browser’s screen.

The following sample code correctly converts mouse’s location to the viewport:

onMouseMoved : function(mouse) { 
        //var location = mouse.getLocation();
        cc.log("Mouse Raw Position: " + mouse.getLocation().x + ", " + mouse.getLocation().y);
        var origin = cc.EGLView.getInstance().getViewPortRect();
        cc.log("WinOrigin: " + origin.origin.x + ", " + origin.origin.y);
        mouse.getLocation().x -= origin.origin.x;
        mouse.getLocation().y -= origin.origin.y;
        mouse.getLocation().x /= Constants.scale; // Constants.scale === cc.Director.getInstance().getContentScaleFactor()
        mouse.getLocation().y /= Constants.scale;
        cc.log("Mouse Position: " + mouse.getLocation().x + ", " + mouse.getLocation().y);
        var position = this.tmxMap.convertTouchToNodeSpace(mouse);
        var tilePosition = this.tmxMap.ScreenPosToTilePos(position.x, position.y);
        var selectedPos = this.tmxMap.tilePosToScreenPos(tilePosition.x, tilePosition.y);
        selectedPos.y -= this.tmxMap.getTileSize().height / 2;
        this.selectedTileSprite.setPosition(selectedPos);
        return true;
    }

Anyway, I think this might be a bug, so I won’t flag the thread as solved for now…

Indeed this is annoying, and I can’t see why this would be intended. Would you mind filing an issue?

PS: I’m getting strange behaviour with your code for some reason: when the mouse is near p(0,0) it works about fine, but the further away you move the reported position increases too much.

I use Guilherme Maia’s solution, but it still have the same problem. Later I checked Ben Wheatcroft’s post, and it works. see: http://www.cocos2d-x.org/forums/19/topics/34532?r=38882