What is the equivalent to SetParent keep position true?

HI, i am learning cocos creator using typscript.
i am making a stacking game, so when two objects collide the falling object attach to the parent. It moves with the parent but the location changes far from the collision point. really far like middle of screen.
Cocos has a function called setParent like Unity but in unity exists SetParent(Transform parent, bool worldPositionStays);
what is the equivalent to World POsition stays in cocos?

I think that there is not anything like this in cocos. Is there any chance for removing the child from his parent, and avoid the relative positioning?

The objetive is to stack sprite and move together as if they were glued each other.
How can it be implemented using your solution?

I didnt understand what you want to do.
I just understand it: Cocos has a function called setParent like Unity but in unity exists SetParent(Transform parent, bool worldPositionStays);

We talk about the parent child relationship in our Programmers Guide.

http://cocos2d-x.org/docs/cocos2d-x/en/basic_concepts/parent_child.html

When you use setParent() this should do what you want. Also you could do something like parent->addChild(another sprite, zorder);

1 Like

https://lh3.googleusercontent.com/qbkg5scj9jYDo4e_3tDueNQniBj_1KLEZCkbnU1jxVaLC7hJJQ-oEERIDHgG-JFnzIBz=h900-rw
(using cocos creator)

what i want is this:
i have falling balls and a base on the bottom platform movable left to right.
if a ball hits the bottom it become attached to the moving platform. Then the platform moves with the ball . if another ball hits, it get attached and when the platform moves it moves the two balls sticked. and so on.

When i use setparent, the ball DOES NOT keep in the las position, the position of the impact.
It changes to the center of the screen.
When i move the platform the balls move left right but from the center of the screen.

Ball

onLoad () {

  
 } 
 onCollisionEnter(other, self)
 {
  
   let pc =other.getComponent("PlayerController");

    if(pc!=null )
    {
        
       this.node.stopAction(this.action);
       pc.addSnowBall(this.node);


    }

 }
moveDown()
{
   
    this.action=cc.moveTo(2,cc.p(this.node.x,-100));
    this.node.runAction(this.action);

}
start () {

}

init()
{
    let randomX=Math.floor(Math.random()*500 )+1;
    this.node.setPosition(cc.p(randomX,1100));
    this.moveDown();

}

and the code of the platform

addSnowBall(_snowBall)
{

    _snowBall.removeFromParent();
    let pos = _snowBall.getPosition();

    _snowBall.setParent(this.node);
    
}

UpdateLocation(_dt)
{
   
    if(!this.bIsPressed)return;
    var xLoc=this.node.x;
 
    if( Math.abs(  Math.round(this.lastTouchLocation.x-xLoc))<=11)return;

    
    if( this.lastTouchLocation.x > xLoc)
    {
       this.node.x=(xLoc+ this.moveSpeed);
     

    }else
    if( this.lastTouchLocation.x < xLoc)
    {
        this.node.x=(xLoc- this.moveSpeed);
    
    }

}

 update (dt) {
    this.UpdateLocation(dt);


 }

I understand the problem now. I have a node positioned in 0.0 called gameplay area.
Gameplayarea has a child.platform.
Balls are spawned and made child of gameplayarea.otherwise they are not visible by the camera.
If a ball is on 100.100 when it collides with the platform and it becomes child of the platform it moves to 100.100 relative to the new parent. The platform. So it is not 100.100 world anymore
It is platform position+100.100
That is why i asked how to setparentkeeping world position

I dont know how to fix it

An excelent explanation that helped me before:

1 Like

thank you. it was hard to understand but finally got it working. If most people has this problem at the beginning (because is the expected behaviour after parenting) setParent should keep world position by default, just like unity ue4 and any other engine in general.

I had similar problem. Cocos creator doesn’t give the possibility to work with node matrices. Half of the functions are hidden inside cc classes.
I wrote helper class that can change parent and leave world position the same:

export default class NodeHelper
{
    public static copyWorldPosition(node: cc.Node, copyFrom: cc.Node, withScale?: boolean, withRotation?: boolean, withAnchor?: boolean): void
    {
        let parent = node.parent;
        let worldPos = copyFrom.parent.convertToWorldSpaceAR(copyFrom.position);
        let locPos = parent.convertToNodeSpaceAR(worldPos);
        node.setPosition(locPos);

        if (withScale)
        {
            let parentScale = NodeHelper.getGlobalScale(parent);
            let copyScale = NodeHelper.getGlobalScale(copyFrom);
            node.scale = copyScale / parentScale;
        }

        if (withRotation)
        {
            let parentRotation = NodeHelper.getGlobalRotation(parent);
            let copyRotation = NodeHelper.getGlobalRotation(copyFrom);
            node.angle = copyRotation - parentRotation;
        }
        if (withAnchor)
        {
            node.setAnchorPoint(copyFrom.getAnchorPoint());
        }
    }

    public static setParentWorldPosStays(node: cc.Node, newParent: cc.Node, withScale?: boolean, withRotation?: boolean): void
    {
        let oldParent = node.parent;
        let worldPos = oldParent.convertToWorldSpaceAR(node.position);
        node.parent = newParent;
        node.position = newParent.convertToNodeSpaceAR(worldPos);
        
        if (withScale)
        {
            let oldScale = NodeHelper.getGlobalScale(oldParent);
            let newScale = NodeHelper.getGlobalScale(newParent);
            if (Math.abs(oldScale - newScale) > Number.EPSILON)
            {
                node.scale = node.scale * oldScale / newScale;
            }
        }

        if (withRotation)
        {
            let oldRotation = NodeHelper.getGlobalRotation(oldParent);
            let newRotation = NodeHelper.getGlobalRotation(newParent);
            if (Math.abs(oldRotation - newRotation) > Number.EPSILON)
            {
                node.angle = node.angle + oldRotation - newRotation;
            }
        }
    }

    public static getGlobalScale(node: cc.Node): number
    {
        let scale = 1.0;

        let cur = node;
        while (cur)
        {
            scale *= cur.scale;
            cur = cur.parent;    
        }
        return scale;
    }

    public static getGlobalRotation(node: cc.Node): number
    {
        let r = node.angle;
        let cur = node.parent;
        while(cur)
        {
            r += cur.angle;
            cur = cur.parent;
        }
        return r;
    }
}``
3 Likes