Count rotations

Hey Guys…

I’m searching for a solution for the following problem:

I designed a stearing wheel and saved it as a sprite (by the way, the version 1.4 is awesome!). Then I imported it into a new project and wrote a code to turn it with touches (using two vectors: One for the first touch and one for the current touch and then I insert the angle between these vectors into the rotation function to turn the stearing wheel). Pretty easy so far. Now I want to count the rotations and allow only a maximum of two rotations to the left/right. This also means four rotation from maximum left to maximum right. But the “angleBetween” function jumps from -180 to 180 after a half rotation… That’s my problem. Any ideas?

Sorry for my English, I’m from Germany.

Thanks a lot,
Phil

Hi @XaXa,

English is great - I don’t know how you are drawing the steering wheel, but one way could be to take a point on the wheel and work out it’s x and y coordinates so that you can determine the extent of rotation, like:

The lowest x value of the wheel will be at the horisontal diameter level, say -radius.x and the plus will be at +radius .x which would be a mark of half a rotation or 180 degrees. You can used the y coordinates up or down (depenedent on whether radius .x is - or + to determine the direction of rotation.

I hope that makes sense. It would be easier if you have cross bars on your stee ring wheel which will give you two points as options.

Hope that helps.

Bri_G

:slight_smile:

Hi Bri_G,

thanks a lot for your fast answer. The steering wheel is a 300x300 sprite. To make it more clearly you can think of one of these example sprites like charakters, bugs, stones and so on. The code looks like this:

translate(middle of the sprite)
rotate (angle)
sprite
rotate (-angle)

To be honest, I don’t exactly understand how to work with x/y coordinates. I mean, I could calculate them with sinus/cosinus of the angle easily, but how should I count rotations?

Greets,

Phil

Hi @XaXa,

If its a sprite you’ll have to work with angles. What you can do is work out the direction of rotation yourself and work out the unsigned angle using math.absolute(angle) then if the angle gets to + or - 720 degrees ( 2 full rotations ) you can limit at that and control the sprite accordingly.

I have probably got the syntax wron, could be math.abs(angle).

Br_G

:slight_smile:

A full rotation is as large as math.pi * 2. So the number of rotations should be equal to angle / (math.pi*2). The angle is defined in radians.

I have to calculate the angle with math.deg… otherwise the rotate() function doesn’t work corretly. And this is the problem: after a half rotation, the value “jumps” from -180 to 180…

Xaxa

Try this little program I put together. I think this might be what you’re after. I selected a random sprite just to give you an example. Just rub your finger across either the left or right button to rotate the sprite. If you have any questions, just ask.

Dave.


-- Use this function to perform your initial setup
function setup()
    -- angle of rotation
    a=0
end

-- This function gets called once every frame
function draw()
    background(40, 40, 50)
    
    -- code to draw buttons
    fill(255,0,0,255)
    rect(50,800,100,50)
    rect(350,800,100,50)
    fill(255)
    text("LEFT",100,825)
    text("RIGHT",400,825)
    text(a,250,825)
    
    -- code that does rotation
    pushMatrix()
    translate(200,600)
    rotate(a)
    sprite("Small World:Observatory",1,1)
    popMatrix() 
end

function touched(t)
    -- check x value for touch location
    if CurrentTouch.x<300 then
        a=a+1
        if a>360 then
            a=360
        end
    else
        a=a-1
        if a<-360 then
          a=-360
        end  
    end
end
  

Not sure why the ~ aren’t working.

Dave

Andrew, thanks for fixing my tilde problem

(You’d left some spaces after the second fence, that breaks the syntax.)

Here’s something that might do what you want.

function setup()
    touches = {}
    touchpt = {}
    angle = 0
    sangle = 0
    iangle = 0
    watch("angle")
    watch("sangle")
    watch("pangle")
end

function draw()
    background(40,40,50)
    if touches[2] then
        local v = touchpt[touches[2]] - touchpt[touches[1]]
        if pangle then
            pangle = bratan2(v,pangle)
            angle = iangle + pangle - sangle
        else
            pangle = math.atan2(v.y,v.x)
            sangle = pangle
            iangle = angle
        end
    end
    translate(WIDTH/2,HEIGHT/2)
    rotate(math.deg(angle))
    sprite("Tyrian Remastered:Plane Boss",0,0)
end

function touched(touch)
    if touch.state == ENDED then
        touches = {}
        touchpt = {}
        pangle = false
    else
        if touch.state == BEGAN then
            table.insert(touches,touch.id)
        end
        touchpt[touch.id] = vec2(touch.x,touch.y)
    end
        
end

function bratan2(v,a)
    local b = math.atan2(v.y,v.x)
    b = b + math.floor((a - b)/(2*math.pi) + .5)*2*math.pi
    return b
end

The important bit is the bratan2 function. This ensures that the angle returned is within pi of the second argument (note that unlike the usual atan2 function, the first argument is a vector). The assumption is that when rotating the wheel, then the angle returned should be near to the previous one, so we ensure that the “branch” of the arctangent function is opposite the previously recorded angle.