Rotate changing the X and Y of sprites

Trying to rotate a sprite 90 degrees, but it keeps changing my x and y of the sprite drastically. It is also making an ellipse further down the code disappear entirely. Tried using pushStyle() and popStyle() to isolate the rotate, but it is messing with all of my graphics. Does anyone know why rotate performs this way?

@jrohanian Without seeing your code I can’t say exactly what you’re doing. Normally to rotate something, you use translate to set the rotation point and then give the sprites an offset from the rotation point. In the example below, I’m rotating around an x,y point of 300,300. Since I want the one sprite to rotate at that point, I gave it an offset of 0,0. The second sprite has an offset of 100,100 so it rotates around the center point but farther out.


function setup()
    a=0
end

function draw()
    background(40,40,50)
    pushMatrix()
    translate(300,300)
    rotate(a)
    sprite("Planet Cute:Character Boy",0,0)
    sprite("Planet Cute:Character Pink Girl",100,100)
    a = a + 1   
    popMatrix() 
end

As Dave said, rotate should be paired with translate to get an image to rotate around its center.

Also, pushStyle and popStyle will not work to isolate the rotate, you need to use pushMatrix and popMatrix

@jrohanian -

Codea rotates around 0,0

You want it to rotate around x,y, the centre of your sprite

So you have to move (“translate”) 0,0 so it is at x,y, then rotate

Then you need to put 0,0 back where it was.

pushMatrix() --remembers position of 0,0 so we can put it back
translate(x,y) -- move rotation point to centre of sprite
rotate(a) -- rotate by a degrees
sprite(image,0,0) --draw sprite at 0,0 ( remember, it is at x,y now)
popMatrix() -- put 0,0 back where it was

Not clear? Imagine drawing on a big sheet of paper. You want to draw something up at top right, tilted on its side? Do you stretch your arm and try to draw at an odd angle? No. You pull the paper towards you so the drawing place is under your pencil (translate), rotate so you can draw the image the right way up, draw the image, then put the paper back as it was (popMatrix).

I explain all this in an ebook, here

https://www.dropbox.com/s/t5im6tl14ky5t08/Codea%20for%20beginners.pdf

@jrohanian Here’s an example of rotating 3 sprites around 3 different points.


function setup()
    a=0
end

function draw()
    background(40, 40, 50)

    pushMatrix()
    translate(300,100)
    rotate(a)
    sprite("Planet Cute:Character Boy",0,0)
    popMatrix()
    
    pushMatrix()
    translate(300,300)
    rotate(a)
    sprite("Planet Cute:Character Cat Girl",0,0)
    popMatrix()
    
    pushMatrix()
    translate(300,500)
    rotate(a)
    sprite("Planet Cute:Character Horn Girl",0,0)
    popMatrix()
    
    a=a+1

end

To sum up (and just to add to @Ignatz and @JakAttak s explanation) - the order of your transformations within your push/popMatrix() block is really important.

rotate() followed by translate()

is very different to:

translate() followed by rotate()

The effect is cumulative and would give a very different result!

The same goes for scale()

I like to think backwards, so I always read it backwards to make sure it works. For instance:

pushMatrix()
translate(x,y)
rotate(angle)
sprite(image)
popMatrix()

I would read the above backwards to ensure it would work. 1 draw the sprite, 2 rotate it, 3 move it to where I want it. Which while not what it actually does, results in what I want to have happen.

@MrScience101 that is a very good trick (if it works, not checked). Thanks.

@MrScience101 - while it works in this case, I wouldn’t rely on it for too many things in graphics programming, which can get strange pretty quickly. I prefer to think of real life equivalents, as I did above, because I think they are reliable analogies for how it works.

Translate it into normal mathematical function syntax and it works as you’d expect. If we do f(g(x)) then that means “apply g to x and then apply f to the result”. So if you think of it as:

translate(x,y) (
    rotate(angle) (
        sprite(image)
    )
)

then the logic is right.

@jrohanian

--Rotation
function setup()
    a=0
    b=0
    parameter.integer("speed",1,10,5)
    parameter.integer("go",1,10)
    spriteMode(CENTER)
end

function draw()
    background(40, 40, 50)
    
    pushMatrix()
    translate(90 + b,100)
    rect(0,0,200,50)
    popMatrix()

    pushMatrix()
    translate(120 + b,100)
    rotate(-a)
    sprite("Space Art:UFO",0,0,60,60)
    popMatrix()
    
    pushMatrix()
    translate(260 + b,100)
    rotate(-a)
    sprite("Space Art:UFO",0,0,60,60)
    popMatrix()   
    a=a+speed
    b=b+go
    if b > 1100 then b = -400 end
end

ok cool i get it now. thanks.

@jmv38 someone on these forums taught it to me so I can’t take credit for it.

@ignatz you are correct.