[SOLVED] Anchor point madness!

@stevetranby That is very true. This does seem like a useful feature that won’t be easily solvable by people who haven’t done this sort of thing before.

I’m surprised cocos2d doesn’t have gestures built-in in some way, considering tapping, pinch-to-zoom and 2-finger rotation are pretty common in mobile apps. Unless they are in the code somewhere and I just haven’t looked lol

1 Like

I agree @stevetranby!

Here’s what I’ve learnt:

  1. A node’s position is relative to it’s parent node. If it is added to a scene’s root node then it is likely to be relative screen co-ordinates.

  2. DO NOT calculate a node’s absolute position with just the node’s information ie content size and/or bounding box. Always calculate new position or size relative to existing position or size.

  3. To calculate anchor point, scale is irrelevant. Use a local point within the node ie within the node’s co-ordinate space against it’s content size. getContentSize() always returns unscaled size. ie scale = 1.0

  4. A node’s position is always on it’s parent node’s co-ordinate space.

  5. Use a node’s bounding box and anchor point to calculate it’s position in it’s parent node’s co-ordinate space.

1 Like

@grimfate, @stevetranby there is no gesture recognizer in cocos2-dx base or extensions. I got super lucky and got the code from the link I provided above.

At the moment there is a problem with double tap recognition with this code. Long ways before I get to ship my game!

Yeah so both an example (one doesn’t need gesture recognizer for pinch-to-zoom capabilities) and gesture support (cross-platform fallback with platform-specific wrapper where possible, e.g. apple’s API).

hey guys,

I’m now trying to limit the pan/zoom to the viewport. I’m a lil off on the scaling side. I thought I might run it by you guys for any ideas. Here’s pan that works:

bool CoordsTest::onGesturePan(TGesturePan *gesture) {
    Vec2 delta = gesture->getTranslation();

    auto contentBoundingBox = _contentNode->getBoundingBox();
    contentBoundingBox.origin += delta;

    auto parent = _contentNode->getParent();
    auto minPointInParent = parent->convertToNodeSpace(contentBoundingBox.origin);
    auto maxPointInParent = parent->convertToNodeSpace(contentBoundingBox.origin + contentBoundingBox.size);
    auto parentBoundingBox = parent->getBoundingBox();

    if (minPointInParent.x <= parentBoundingBox.getMinX() && minPointInParent.y <= parentBoundingBox.getMinY() &&
            maxPointInParent.x >= parentBoundingBox.getMaxX() && maxPointInParent.y >= parentBoundingBox.getMaxY()) {
        _contentNode->setPosition(_contentNode->getPosition() + delta);
    }
    return true;
}

Here’s pinch but stops too late, not sure how should I adjust the target bounding box of _contentNode:

bool CoordsTest::onGesturePinch(TGesturePinch *gesture) {
    // scale
    float scale = _scaleStart * gesture->getScale();
    auto loc = gesture->getLocation();

    auto oldAnchor = _contentNode->getAnchorPoint();
    auto oldPosition = _contentNode->getPosition();

    auto point = _contentNode->convertToNodeSpace(loc);
    auto contentSize = _contentNode->getContentSize();
    auto contentBoundingBox = _contentNode->getBoundingBox();
    auto bbSize = contentBoundingBox.size;

    auto newAnchor = Vec2(point.x / contentSize.width, point.y / contentSize.height);
    auto anchorChange = newAnchor - oldAnchor;
    auto newPosition = Vec2(oldPosition.x + bbSize.width * anchorChange.x, oldPosition.y + bbSize.height * anchorChange.y);

    auto minPointInParent = _contentNode->getParent()->convertToNodeSpace(contentBoundingBox.origin);
    auto maxPointInParent = _contentNode->getParent()->convertToNodeSpace(contentBoundingBox.origin + contentBoundingBox.size);

    auto parentBoundingBox = _contentNode->getParent()->getBoundingBox();

    if (minPointInParent.x <= parentBoundingBox.getMinX() && minPointInParent.y <= parentBoundingBox.getMinY() &&
            maxPointInParent.x >= parentBoundingBox.getMaxX() && maxPointInParent.y >= parentBoundingBox.getMaxY()) {
        _contentNode->setAnchorPoint(newAnchor);
        _contentNode->setPosition(newPosition);
        _contentNode->setScale(scale);
    }
    return true;
}

Thanks a lot!