Absolute screen coordinates for nested CCNode tree - cocos2d-x

I tried to get real coordinates (like on iPad screen) for all elements on active scene using
CCARRAY_FOREACH(node->getChildren(), obj)
for each Node I tried
CCPoint realCoordinates = node->getParent()->convertToWorldSpace(node->getPosition());
or this
CCPoint realCoordinates = node->convertToWorldSpace(node->getPosition());
or
CCPoint realCoordinates = node->convertToWorldSpaceAR(CCPointZero);
In result: For some node from my elements tree I have wrong coordinates.
Element tree is big in deep nested with anchors.
May be somthing can help me how can I calculate valid absolute (1024х768) screen coordinates for all elements from my CCNode tree.
Thanks

The solution is
node->getParent()->convertToWorldSpace(node->getPosition())
This worked for me for a button as a child of a listview in a child of a layout in the scene.
Seems like it should be working with you, too.

Related

AS3 - Finding an objects x and y position relative to the stage

I'm new to ActionScript 3 and I have a character which you can control, the screen scrolls right along the stage and he can fire missiles.
The problem I'm getting is the missiles are created via these co-ords:
bullet.x = hero.mc.x;
bullet.y = hero.mc.y
These work fine untill the screen has scrolled to the right. I assume it's because the bullets are being spawned as a result of them using the canvas x,y and not the stages x,y
So i'm wondering how to find out the x and y of my hero in relative to the canvas so i can spawn the missiles on top of him!
Thanks, and if you need any more information let me know, I'm new to all this. Thank you.
You can do that with localToGlobal and globalToLocal. Your solution would be something like:
bulletPos = bullet.parent.localToGlobal(new Point(bullet.x, bullet.y));
Beware, though, as those are last resort functions. Normally, you'd have all your elements using the same 'layer', so comparisons are easier and faster.

ActionScript 3: Zoom into movieclip while not scaling its childrens

I've included a zoom functionality similar to the one explained at this website:
http://www.flashandmath.com/howtos/zoom/
This works perfectly on my background image(a map, that is), but I want to keep the symbols on my map the same size while zooming in.
I probably could work this out by changing all the children's size when calling the zoom-function, but I am hoping there is some kind of easy code adapt in my children class to make the size of the instances unchangable. Is there?
Thanks!
One crude way, so you don't have to calculate the symbols scale, would be to remove the symbols from the mapDisplayObject so they're no longer a child and instead put symbol placeholders. Then match each symbol's x and y to each place holder, using localToGlobal...
If your children are not scaled or skewed or rotated you can iterate all of them and set transformation matrix to 1/parentScale. Something like:
for each (var child:DisplayObject in parent) {
var matrix:Matrix = child.transform.matrix;
matrix.a = 1/parentScale;
matrix.d = 1/parentScale;
child.transform.matrix = marix;
}

cocos2dx - sub layer that covers its parent partially keep capturing all touches

In my cocos2dx game, I have a CCLayer that contains another CCLayer. The sublayer just cover part of the container layer. I 'think' I achieve this through:
this->setContentSize( CCSizeMake( 100, 200 ) );
however, the sublayer always capture touches even though it is outside its size and position area... Is it common?
I can filter through the touches position by comparing it inside the ccTouch** functions, but I think it is a hack, what is the proper way to set the sublayer to properly cover just the partial area of its parent?
The only thing i can think of straight away is making this inner layer a CCNODE and also extent it with CCTouchDelegate.
Now with this, when u register with the TouchDispatcher, you make sure it doesn't Swallowtouches(the boolean value given as the last parameter)...
This way when you receive a touch ... just see if it is within the boundary of this inner layer of urs and if it is not, send let the parent class use this touch.
Hope this helps.

localToGlobal/globalToLocal AS3 confusion

I want to move a display object from one container to another, but have it appear in the same place on screen.
I thought I'd understood this years ago, but the following does not work:
function moveToNewContainer(obj:DisplayObject, newParent:DisplayObjectContainer):void {
var pos:Point = new Point(obj.x, obj.y);
var currentParent:DisplayObjectContainer = obj.parent;
pos = currentParent.localToGlobal(pos);
currentParent.removeChild(obj);
newParent.addChild(obj);
pos = newParent.globalToLocal(pos);
obj.x = pos.x;
obj.y = pos.y;
}
This doesn't position the object in the same place as I would have expected.
Does anyone know what I am doing wrong, please?
Thanks,
James
Using localToGlobal/globalToLocal and setting the x and y properties like you showed calculates the correct position for the object in its new parent, but does not adjust for other aspects of the transformation such as scaling or rotation. In other words, the object's registration point will indeed remain in the same place, but the object may be rotated, scaled, or sheared differently.
The solution to your problem will need to take into account the transform.concatenatedMatrix properties of the old and new parents--you'll need to multiply the object's transformation matrix by one and then by the inverse of the other, or something along those lines. Leave a comment if you need help working out the math.
There is nothing wrong with your code, provided that both containers have no transformations applied. If your clips are scaled, rotated, etc.. you need to handle that in addition to the coordinate space transformations that localToGlobal and globalToLocal do.
You have to check if your containers are actually placed on stage. If your new container isn't added as a child to stage, function globalToLocal fails, just because it doesnt know how to correctly calculate that data.

AS3 - Using Matrix3D objects for reordering display

I'm working with about 20 objects that are moving around in 3D space. Adobe recommends "Using Matrix3D objects for reordering display":
Use the getRelativeMatrix3D() method of the Transform object to get the relative z-axes of the child 3D display objects.
Use the removeChild() method to remove the objects from the display list.
Sort the display objects based on their relative z-axis values.
Use the addChild() method to add the children back to the display list in reverse order.
Great. That's fine if the objects aren't moving. But what if there are animations happening and one object comes in front of another in z-space? The objects are displayed accoring to the position in the display list, not according to their z-order. How can you make objects respect z-order while animating (make object A appear in front of object B if object A's z-value becomes smaller than object B)? Obviously you can't clear the display list during an animation.
It's practically the same as adobe's docs says... and it works perfectly for moving objects.
The simplest way, so you have some code reference, and given you have all of your 3d objects in an array, would go something like this:
function zSort(objects:Array) {
objects.sortOn("z", Array.DESCENDING | Array.NUMERIC); // sort the array on the "z" property
for each(var clip:DisplayObject in objects) { //loop the array and add the childs in the corrected order...
addChild(clip);
}
}