Getting transformed screen coordinates

Hi All,
I have a quick question and I feel I should know the answer but for the life of me I can’t find the solution.

I’ve been playing with a new prototype and I wanted to use some of the Codea transform management functions to position items on the screen. For instance I have a small circle ('ship") orbiting a central “planet” and instead of all the fiddly 2D transforms in Lua I simply do the following

translate(cx,cy)  -- centre of the screen
rotate(angle)
ellipse(radius,0,width)

Then all I do is update angle each frame and bingo, nice easy rotation around a point, however the next stage is on a touch event fire off a “bullet” from the circles current position to the touch location.

Now if I’d rotated the ship by hand I’d know the screen space coords to start the bullet from (it’d be the point I drew the ship at), but using the inbuilt transforms is it possible to get the final 2D screen position or do I still need to do the transform it long hand.

Well since e ellipse will always be at coordinates (0,0) (because of the translate) with this code, the bullet just needs made at (0,0) to be at the location of the ellipse, if that’s what you are asking.

Actually the ellipse is at (radius,0) - edited the OP

I can see why you’d think that - but before I draw the ellipse I push the matrix and then change the translate, do the rotate and then pop the matrix ready for the next object to render.

If I just used the coord then the rotation for the ellipse would continue to effect the bullet and it wouldn’t fly straight :slight_smile:

Another way to think of it - is that the ship is operating in it’s own little world coord system and the bullet would be in the screen coord system, when the ship is drawn Codea handles the translation into screen coords - I’d like to be able to grab those values if possible.

Ah, seem I didn’t know exactly what you wanted done, but I think I get it now :slight_smile:

The best way to do it would be to take off the translation and rotation and find the exact location of the ellipse using sin and cos, then putting the bullet there.

bulletx = cx+radius*math.cos(math.rad(angle))
bullety = cy+radius*math.sin(math.rad(angle))

Then to move to the bullets new location:

translate(bulletx-cx,bullety-cy) --translates (0,0) to the new location without having to reset the translation
rotate(-angle)

And always remember that rotate() takes degrees and math.sin and math.cos take radians. The code above converts it to radians to do the math and leaves it in degrees for the rotations

You would still need to rotate after translating, if the bullet needs to be pointed at its target

@Monkeyman32123 - Hmmm, looks like I was right in the first case, I was hoping to avoid having to redo the 2D geom in Lua - I thought it’d be cleaner and more efficient to use the native functionality :frowning: but I guess if I’m doing the geom anyway I might as well position the ellipse myself.

@TechDojo perhaps there is a way, but I’m no mathematician, and I cannot help you there, unfortunately. :frowning: geometry is quite painful at times, I agree.
@Ignatz, oh, yes, thank you for the correction

@TechDojo, unfortunately you’ll have to get used to it, if you expect to program graphics.

@TechDojo Here’s an example of what I think you’re after.

EDIT: Added code to remove the bullet from the table when it goes off screen.


displayMode(FULLSCREEN)

function setup()
    bullets={}
    angleSpeed=1
    bulletSpeed=5
    shipDistance=350
    centerX=WIDTH/2
    centerY=HEIGHT/2
    angle=0
end

function draw()
    background(40, 40, 50)
    fill(255)
    text("Tap screen multiple times for bullet direction.",WIDTH/2,HEIGHT-50)
    sprite("Tyrian Remastered:Eye Mecha",centerX,centerY,50)
    
    pushMatrix()
    translate(centerX,centerY)
    rotate(angle)
    sprite("Space Art:UFO",shipDistance,0,30)
    popMatrix()
    
    for _,bullet in pairs(bullets) do
        sprite("Tyrian Remastered:Explosion Ball",bullet.x,bullet.y,10)
        bullet.x=bullet.x-bullet.z*bulletSpeed
        bullet.y=bullet.y-bullet.w*bulletSpeed
    end
    
    for index,bullet in pairs(bullets) do
        if bullet.x<0 or bullet.x>WIDTH or bullet.y<0 or bullet.y>HEIGHT then
            table.remove(bullets,index)
        end
    end
    
    shipX=centerX+math.cos(math.rad(angle))*shipDistance
    shipY=centerY+math.sin(math.rad(angle))*shipDistance
    angle=angle+angleSpeed
end

function touched(t)
    if t.state==BEGAN then
        local direction=vec2(shipX-t.x,shipY-t.y):normalize()
        table.insert(bullets,vec4(shipX,shipY,direction.x,direction.y))
    end
end

Thanks guys for all the help, @dave1707 that’s a great demo thanks, it’s pretty much what I’d already got - however in mine I couldn’t see the benefit of using the translate and rotate functions if I’d already worked out the coords as it’s just being repeated.

@Ignatz :slight_smile: I’m well used to the maths behind this - I’ve been programming graphics for years :slight_smile:

I was hoping that there might be back door way of getting the values back from Codea but that’s obviously not possible. However I’m sure many people will benefit from dave1707’s example.

@TechDojo I think you’re looking for a way to read back the transformation matrix. If so, what you want is modelMatrix(). With no argument this returns the current model matrix. (You might also need viewMatrix() and projectionMatrix() which return the view and projection matrices respectively, but I think that just modelMatrix() will do for you.) This is actually a 4x4 matrix as we’re working with 3-dimensional homogeneous coordinates so need a 4-vector to represent a point in space, but you can read off the required transformation from it quite easily.

I’m not on my iPad at the moment so don’t want to post some code that might be wrong. If you’re used to the maths you should be okay (though be warned that the matrix is the transpose of what mathematicians would normally use). It might be at the wrong level for you, but you might find my write-up on matrices of some use.

@LoopSpace - I think that’s exactly what I was looking for. I’ll give it a shot later, thanks.

I knew there’d be some little ninja trick somewhere :slight_smile: