Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
How does globalToLocal and localToGlobal really work? — Gideros Forum

How does globalToLocal and localToGlobal really work?

MikeHartMikeHart Guru
edited March 2012 in General questions
Hi folks,

I have a problem understanding Sprite:globalToLocal and Sprite:localToGlobal. Here is the code:
local ns = Sprite.new()
stage:addChild(ns)
ns:setPosition(150,0)
 
stage:setPosition(-150,0)
 
print (ns:getPosition())       --prints 150 0
print (ns:localToGlobal(ns:getPosition()))    --prints 150 0
print (ns:globalToLocal(ns:getPosition()))    --prints 150 0
1) I create a sprite and make it the child of the stage.
2) I set the X-position of the sprite to 150
3) I set the X-Position of the stage to -150

Why do all positions, converted or not print then X=150? I would have expected at least localToGlobal to print 0 0.

Comments

  • I agree with you Mike. That was my understanding.
  • When I first read this, I thought it was because the stage was the world. But, if you replace stage with some other sprite, the program still prints the same numbers.
  • stage is the first sprite that is automatically created by Gideros when the app starts. Everything has to become a child in/directly to stage so it can be displayed. So you could say that stage=world. But not when you talk about Box2D. :)
  • ndossndoss Guru
    edited March 2012
    Everything seems to work as expected if you do:
    stage:setScale(0.5,0.5)
    localToGlobal always seems to multiply the results by 2?
  • I was wondering that too. But your solution is not one, as you want to be able to scale the stage.
    @Atilim: this seems to be a bug, or?
  • avoavo Member
    If you pass 0,0 it works.

    By passing the coordinates of the ns sprite you are getting that position in ns sprite converted. So it's adding 150 to 150 etc.

    At least I think that's whats going on here.
  • avoavo Member
    Now I think I'm wrong :P

    I believe that globalToLocal and localToGlobal don't care about parent sprites and returns the x,y relative to the logical resolution.

    I could be wrong again though :) I'm trying to create a detailed example for my own understanding.
  • I believe that globalToLocal and localToGlobal don't care about parent sprites and returns the x,y relative to the logical resolution.
    Changing logical resolution in the player (I tried doubling and halving) doesn't seem to change the result. Also tried changing hardware resolution and no luck there either.
  • avoavo Member
    edited March 2012
    What I meant to say was the distance of your sprite to the top left of the screen (for localToGlobal), not logical resolution sorry. Anyway I don't think I should speculate more until I'm 100% sure I understand.
  • avoavo Member
    edited March 2012
    Ok this works I think. It's not the same example but it moves an image from one sprite to another and keeps the display position:

    edit: updated and cleaned example to not confuse anyone:
    local ns = Sprite.new()
    local blue = Bitmap.new(Texture.new("Blue.png")) -- use any image here
    stage:addChild(ns)
    ns:addChild(blue)
    ns:setPosition(150,150)
    blue:setPosition(50,50)
    stage:setPosition(-100,-100)
     
    --Move blue to stage but keep the same relative display position
    local x,y = blue:localToGlobal(0,0)
    ns:removeChild(blue)
    stage:addChild(blue)
    blue:setPosition(stage:globalToLocal(x,y))
  • Isn't Global the display? In your latest example if you run it, the blue ends up in position 50,50 on the display.

    So it doesn't matter what sprite manipulation you do by setPosition (which takes place relative to the parent sprite) - Global means where it actually appears to the user on the device.
  • avoavo Member
    edited March 2012
    blue actually ends up at 100,100 on the display, (stage -100, blue + 200)

    I'm not sure what you mean that setPosition doesn't matter since you need to use it to keep the image in the same position after moving between sprites?

    I think Gideros knows what you want to do when you combine setPosition and globalToLocal together?
  • evsevs Member
    Hello,
    print(blue:globalToLocal(x,y)) -- This is only 50,50 so what happens in the setPosition above to make it 200,200?
    is just
    print(blue:globalToLocal(150,150))
    so it prints the 50, 50 which is 150, 150 adjusted by the global -100, -100 stage offset

    so you get 50 (I think)


    cheers

    evs

    Likes: avo

    +1 -1 (+1 / -0 )Share on Facebook
  • CarolineCaroline Guru
    edited March 2012
    It seems to me that on your 'magic' line, the coordinates 150, 150 are changed to be globally 200,200, because at that point the blue sprite is physically -50, -50 off screen.

    Something that does bother me is that if you do:
    print ("blue:localToGlobal:", blue:localToGlobal(blue:getPosition()))
    just after adding blue to the stage, then it prints out 0,0. To me, it should print out -50, -50.
  • I'm not sure what you mean that setPosition doesn't matter since you need to use it to keep the image in the same position after moving between sprites?
    Actually, the image isn't in the same position.

    If you stop the program after adding blue to the stage, then it does not appear on the device, because it's at -50,-50.


  • Oh, sorry - you mean you have to set the position again because it's disappeared? Yes, in that way setPosition is important of course. But that's because you changed the relative position of the stage to go offscreen.
  • avoavo Member
    edited March 2012

    Actually, the image isn't in the same position.

    If you stop the program after adding blue to the stage, then it does not appear on the device, because it's at -50,-50.
    Well yes.. the goal of the example was to display the image on one sprite, and then move it to another but use gTL/lTG to not have the visual position change. So if you just add blue back to stage it will of course have the original position and appear offscreen.

    edit: oh I think I should have used "visual position" earlier when I was saying it was in the "same position" I meant when you look at the actual device.
  • I'm confused now - did we sort out the question? Because your example demonstrates gTL/lTG well.

    To me it's working as it should, apart from that one print statement where I think it should be -50, and not 0.

  • avoavo Member
    edited March 2012
    Haha yes it works I was just confused on the details a bit. I think I get it all now.. I think..

    The magic bit I had there was just because I was printing the gTL function after I had already changed the images position, duh #-o
  • avoavo Member
    edited March 2012
    print ("blue:localToGlobal:", blue:localToGlobal(blue:getPosition()))
    just after adding blue to the stage, then it prints out 0,0. To me, it should print out -50, -50.
    If what I put above is true then: the position of blue is 50,50 the distance from there to the top left is 50,50 so 50-50 = 0

    edit: I think this might also hopefully explain the issue that started this thread.

    And now I must apologize to everyone for posting so many times in this thread, I hope some of it is coherent at least :P

  • atilimatilim Maintainer
    edited March 2012
    Hi,

    I think the real confusion is this usage:
    local x, y = blue:localToGlobal(blue:getPosition()))
    The correct usage should be:
    local x, y = blue:localToGlobal(0, 0)

    Likes: Holonist

    +1 -1 (+1 / -0 )Share on Facebook
  • avoavo Member
    haha next time I'm just waiting for atilim to show up. That was my first guess way at the beginning but I was convinced you were supposed to pass the position for some reason since I think you recommend doing it that way here: http://www.giderosmobile.com/forum/discussion/comment/856#Comment_856

    So I made it work and then tried to figure out why exactly it worked that way #-o

    anyway thank you atilim. I think I'll edit a couple of my posts so as not to confuse future readers.
  • atilimatilim Maintainer
    Oh.. sorry.. that post is (totally) wrong :\"> The correct one is localToGlobal(0, 0)
    I don't know what I was thinking. I'll also correct that post.

    thank you avo.
  • avoavo Member
    hmm.. except the example doesn't work like that?

    Is there something else I'm doing wrong, because it does seem like you need to pass in the position like I was doing?
  • atilimatilim Maintainer
    which example? Your example or mine? :)

    Passing the position uses the position of sprite twice while doing the calculations. Therefore this usage should always give wrong results.
  • Thanks guys for all the input. I was confused by the input parameters. But if you cann localToGlobal with 0,0, then I get what I need.
  • avoavo Member
    edited March 2012
    this code here:
    local ns = Sprite.new()
    local blue = Bitmap.new(Texture.new("Blue.png")) -- use any image here
    stage:addChild(ns)
    ns:addChild(blue)
    ns:setPosition(150,150)
    blue:setPosition(50,50) -- position relative to stage is: (200,200) 150+50
    stage:setPosition(-100,-100)
     
    --Now Trying to move the image to a different sprite but keep the same position on device
    local x,y = blue:localToGlobal(0,0)
    print(x,y) -- 150,150
    ns:removeChild(blue)
    stage:addChild(blue)
    blue:setPosition(blue:globalToLocal(x,y))
    worked when I used blue:getPosition() inside localToGlobal
  • atilimatilim Maintainer
    edited March 2012
    I think you should call globalToLocal with the parent sprite of blue

    What is the result if you change the line:
    blue:setPosition(blue:globalToLocal(x,y))
    with
    blue:setPosition(blue:getParent():globalToLocal(x,y))
    ?
  • avoavo Member
    ah yes that works, thanks. It seems like the other way does also work though it just makes things more complicated for no reason.

    thank you for clearing this up atilim. :)

    Here is a cleaned up example if anyones curious or seeing this later:
     
    aSprite = Sprite.new()
    bSprite = Sprite.new()
    stage:addChild(aSprite)
    aSprite:addChild(bSprite)
    aSprite:setPosition(50,50)
    bSprite:setPosition(200,200)
    stage:setPosition(25,25)
     
    --Move bSprite to stage from aSprite and keep same relative display position
    local x,y = bSprite:localToGlobal(0,0)
    aSprite:removeChild(bSprite)
    stage:addChild(bSprite)
    bSprite:setPosition(stage:globalToLocal(x,y))
    If I could suggest you may want to add a couple of lines to the reference file about usage for these functions. You can use that example if you think it explains it well enough.

  • atilimatilim Maintainer
    I've also updated the example here http://www.giderosmobile.com/forum/discussion/comment/856#Comment_856

    Improving the reference manual is good idea. I'll do it.

    thanks

    Likes: avo, seppsepp

    +1 -1 (+2 / -0 )Share on Facebook
Sign In or Register to comment.