# How to calculate absolute world x/y without using world xy property?

## Recommended Posts

I have strong suspicions that the world x/y property on Phaser.Sprite (which I think replaced the old toGlobal method) is buggy and would like to figure out a way to manually calculate the absolute position of a sprite. Suppose I have a sprite child of a sprite child of a sprite child of the world.

spriteA ([0,0], rotation: 0) > spriteB ([0,0], rotation: 0) > spriteC ([0,0], rotation: 0) > world.

We all know if the sprites have no rotations, you can easily calculate the absolute positions by adding the parent positions, e.g. the absolute world position of spriteA would be:

var xValue = spriteA.x + spriteB.x + spriteC.x;

var yValue = spriteA.y + spriteB.y + spriteC.y;

But what about when the child sprites have rotations and offsets. e.g.:

spriteA ([15,34], rotation: 2.3) > spriteB ([30,0], rotation: 0) > spriteC ([1400,1000], rotation: .6) > world.

How then will you calculate absolute world positions? Because simply adding the x/y won't work as it doesn't take rotation into account. I suspect using Phaser.Point.rotate will be involved but I'm not sure exactly how to solve this and I ran out of patience testing different parameters.  Someone please help me figure this out!

##### Share on other sites

Not sure if this is what you're looking for, but let's say we have these:

parent {x: 100, y:100, rotation: Math.PI*0.5}

child {x: 50, y: 50, rotation: 0}

so you want to get the global cords of the child right?,

``````var childDisFromParent = Math.sqrt(child.x*child.x + child.y*child.y)

var childRotFromParent = Math.atan2(child.y, child.x)

var childActualPos = {

x: Math.cos(childRotFromParent + Parent.rotation) * childDisFromParent + parent.x,

y: Math.sin(childRotFromParent + Parent.rotation) * childDisFromParent + parent.y

}``````

I'm quite sure there's probably a lot better way of doing this, but this thing is first that I had in mind

##### Share on other sites

This looks promising ... I will try it and report back, thanks!

##### Share on other sites

Here's my implementation. Unfortunately, it doesn't work ... bullets are beginning somewhere near the sprites though. Bug guess what? Where the bullets start are affected by the camera position once again!

``````function getAbsolutePosition(sprite) {

var child = sprite;
var spriteParent = child.parent;

var absPosition;

while (spriteParent.name != '_stage_root') {

var childDisFromParent = Math.sqrt(child.x * child.x + child.y * child.y)

var childRotFromParent = Math.atan2(child.y, child.x)
var absX = Math.cos(childRotFromParent + spriteParent.rotation) * childDisFromParent + spriteParent.x;
var absY = Math.sin(childRotFromParent + spriteParent.rotation) * childDisFromParent + spriteParent.y;

if (absPosition == undefined) {
absPosition = {

x: absX,
y: absY

}

} else {

absPosition.x += absX,
absPosition.y += absY

}
child = spriteParent;
spriteParent = spriteParent.parent;

}

return absPosition;

}``````

P.S. Just changed parent to spriteParent because parent is a global variable used by the window.

##### Share on other sites

hmm, It feels like maybe you don't use anchor in the middle for sprite or bullet? Also I can't see why camera position should affect bullets position any way. how exactly does camera position affect it?

##### Share on other sites

It's truly bizarre. I have a mini map which shows where all the bullets are starting from and going on the map. When I move the camera away from the sprites, the start x/y position of the bullets changes drastically as if they are relative to the camera. It's the same exact thing that was happening when I was using .world.

And yes, I have checked - all my sprites are using .5 as an anchor.

##### Share on other sites

Oh! got it, camera position changes Phaser.World position, if you move camera to x: 20, y:10, then Phaser.World position will be x:-20, y-10, and in that while loop you're also considering in the Phaser.World which probably is the cause of this issue. So use while(spriteParent.name !=  "__world" ) { //code here } instead

##### Share on other sites

hmm, the positions are no longer affected by the camera. However, They are way further down the map then they should. If I had to guess, their x/y properties are twice as far, as if they are unnecessarily adding the unit position relative to the world.

##### Share on other sites

If I do this at the very end:

absPosition.x = absPosition.x * .5;
absPosition.y = absPosition.y * .5;

I get results that are close. The bullets are still offset from the muzzle flashes. I suspect chopping the number in half isn't a solution :).

##### Share on other sites

``````function getAbsolutePosition(sprite) {

var child = sprite;
var spriteParent = child.parent;

var absPosition;

while (spriteParent.name != '__world') {

var childDisFromParent = Math.sqrt(child.x * child.x + child.y * child.y)

var childRotFromParent = Math.atan2(child.y, child.x)
var absX = Math.cos(childRotFromParent + spriteParent.rotation) * childDisFromParent;
var absY = Math.sin(childRotFromParent + spriteParent.rotation) * childDisFromParent;

if (absPosition == undefined) {
absPosition = {

x: absX,
y: absY

}

} else {

absPosition.x += absX,
absPosition.y += absY

}
child = spriteParent;
spriteParent = spriteParent.parent;

}

return absPosition;

}``````

Try this, I have a suspicion that this should work

Edited by TickleMeElmo
##### Share on other sites

7 minutes ago, TickleMeElmo said:
```
```function getAbsolutePosition(sprite) {

var child = sprite;
var spriteParent = child.parent;

var absPosition;

while (spriteParent.name != '_stage_root') {

var childDisFromParent = Math.sqrt(child.x * child.x + child.y * child.y)

var childRotFromParent = Math.atan2(child.y, child.x)
var absX = Math.cos(childRotFromParent + spriteParent.rotation) * childDisFromParent + spriteParent.x;
var absY = Math.sin(childRotFromParent + spriteParent.rotation) * childDisFromParent + spriteParent.x;

if (absPosition == undefined) {
absPosition = {

x: absX,
y: absY

}

} else {

absPosition.x += spriteParent.x,
absPosition.y += spriteParent.y

}
child = spriteParent;
spriteParent = spriteParent.parent;

}

return absPosition;

}``````

Try this, I have a suspicion that this should work(in case you only have on parent of that sprite rotated)

Hmm, now the bullets are starting from the very top left of the map, so it seems to be the opposite problem (before bullets were starting at bottom right). The bullets should be starting near the center of the map as that's where the test sprites are.

Btw, I very much appreciate the help and will send you a free copy of my game once it's finished. I never imagined I would be spending 2 days trying to get the absolute position of a child sprite. That's one of those things you assume the framework will handle.

P.S. Why does Phaser take the camera location into account on the world property? How does the camera have anything to do with the absolute position of a sprite in the world. Is that intentional?

##### Share on other sites

oh yeah, sorry, I just edited the code try again now, (getting a bit late so I'm starting to produce not the brightest codes, night coding isn't for everyone you know)

##### Share on other sites

8 minutes ago, TickleMeElmo said:

oh yeah, sorry, I just edited the code try again now, (getting a bit late so I'm starting to produce not the brightest codes, night coding isn't for everyone you know)

Just tried it now. The results mirror the results using .world x/y on the muzzle flash (lowest child in hierarchy). The only difference is the results are no longer skewed by camera movement, which is a good thing. However, they bullet start x/y doesn't rotate perfectly along with the muzzle flash.  Of course, everything is where it's supposed to be if nothing is rotated. But pretty much every child/parent is rotated in my case.

##### Share on other sites

Send me the child parent tree(include just the cords and rotation, and the bullet start pos) at some random test, or show me the part of code about the childs parents etc.

##### Share on other sites

Top of tree to bottom (all objects are anchored by .5):

world

group ("game objects" [0,0], rotation = 0)

sprite ("unit", [345,600],rotation = .785)

sprite ("gun", [-7,0],rotation = 2.486)

sprite ("muzzleFlash", [32,-23],rotation = 1.5)

The bullet is in a separate group which is the child of the world. So when I fire the bullet, I'm trying to get it to start exactly where the muzzle flash sprite is. I should note that the muzzle flash moves to arbitrary coordinates based on which gun is firing (these are double and triple guns), like so:

msprite.x = unit.guns[gunIndex].multi[currentMulti][0];
msprite.y = unit.guns[gunIndex].multi[currentMulti][1];

unit.guns[gunIndex].currentMulti++

So the first time the gun fires, it will be at:

[32, -23],
And the second time:

[32, 22]

Then currentMulti is reset to zero and it goes back to [32, -23].

It's just dawned on my that may be where the miscalculation is, because those arbitrary movements assume 0 rotations. But how can I calculate the x/y, taking all the world transforms into account?

##### Share on other sites

and what is the code output for this(the bullet cords)? Don't have the time right now to test it myself

##### Share on other sites

Here are some example results:

unit position:  {x: 4361.8046108200615, y: 4299.997671575902, type: 25}

unit rotation: -0.014180800172453928

gun position {x: 50, y: 15, type: 25}

gun rotation: 2.440526462913298

muzzle flash position: {x: 20, y: 0, type: 25}

muzzle flash rotation: 0

gun bullet start (results): {x: 4396.729190524387, y: 4327.1878029138115, type: 25}

##### Share on other sites

and the desired result is?

##### Share on other sites

the only way I know it's not the desired result is because the bullet is not starting where the muzzle flash is. but I don't know the actual x/y of what is desired.

##### Share on other sites

btw, here are some more test results (everything is in the same order):

game2.js:1864 P…r.Point {x: 4356.86049998745, y: 4300, type: 25} -0.012042771838760834 P…r.Point {x: 50, y: 15, type: 25} 2.3884880298189324 P…r.Point {x: 20, y: 0, type: 25} 0 P…r.Point {x: 4392.446129251321, y: 4328.0749300625785, type: 25}

game2.js:1864 P…r.Point {x: 4356.86049998745, y: 4300, type: 25} -0.012042771838760834 P…r.Point {x: 50, y: -15, type: 25} 2.1412993755593033 P…r.Point {x: 20, y: 0, type: 25} 0 P…r.Point {x: 4395.875127157528, y: 4301.23155181026, type: 25}

game2.js:1864 P…r.Point {x: 3592.809754647056, y: 3687.190245352944, type: 25} -0.7853981633974483 P…r.Point {x: -7, y: 0, type: 25} 2.917026544114841 P…r.Point {x: 32, y: 22, type: 25} 0 P…r.Point {x: 3551.764466450548, y: 3677.8182631932104, type: 25}

game2.js:1864 P…r.Point {x: 5165.6067975568885, y: 4285.995071426674, type: 25} 0.12767083478338517 P…r.Point {x: 50, y: 15, type: 25} 2.9450681640327123 P…r.Point {x: 20, y: 0, type: 25} 0 P…r.Point {x: 5193.674967799077, y: 4311.144440777133, type: 25}

game2.js:1864 P…r.Point {x: 5165.6067975568885, y: 4285.995071426674, type: 25} 0.12767083478338517 P…r.Point {x: 50, y: -15, type: 25} 2.910269127507492 P…r.Point {x: 20, y: 0, type: 25} 0 P…r.Point {x: 5197.642442777036, y: 4282.0686882863665, type: 25}

##### Share on other sites

could you send a picture of that bullet firing, so that the muzzle is also there

##### Share on other sites

Top is example of start x/y of bullet being wrong and bottom is correct:

Note that the bottom has nothing rotated. See how with the top, the bullet is starting behind the gun, because it isn't starting at the correct x/y.

##### Share on other sites

I had this wacky solution a while back which worked perfectly about 95% of the time. Unfortunately, it was affected by camera movement. about 5% of the time, if you moved the camera, it would offset everything incorrectly. msprite is muzzleflash sprite, startPosition is bullet start x/y:

var position = msprite.toGlobal(msprite);
position.x = game.camera.x + position.x;
position.y = game.camera.y + position.y;
unit.guns.startPosition = position;

But with that, the bullet always started right on top of the muzzle flash sprites, as intended.

##### Share on other sites

okey, I'm quite confused right now, will continue looking into this tomorrow

##### Share on other sites

3 minutes ago, TickleMeElmo said:

okey, I'm quite confused right now, will continue looking into this tomorrow

You and me both. Okay, thanks :).