How Do I Rotate An Object Around A Specific Axis?

Hiho,

For my game I’ve been thinking of a game mechanic where an object (image) will rotate around a specific axis, but I’m not sure how to pull this off, to show you what I mean I made this picture:

LUagxtM.jpg

Where the blue block would be the image I want to rotate around the red dot (axis), is it possible?

Help is much appreciated  :slight_smile:

Hello,

you can consider changing the reference point of your display object (e.g. rectangle/image) to the bottom-center of it, here is an example :

--The Dot local dot --The Rectangle (could be an image) local rect --In case you need physics local physics = require "physics" physics.start() physics.setGravity( 0, 0 ) physics.setDrawMode( "hybrid" ) local doTurn = function(event) rect.rotation = rect.rotation + 5 end dot = display.newCircle(display.contentWidth/2,display.contentHeight/2,5) dot:setFillColor(200,0,0) rect = display.newRect(0,0,20,40) physics.addBody(rect) --Change the reference point to the botton center of your rect rect:setReferencePoint(display.BottomCenterReferencePoint) --Set the coords. of your rect rect.y = dot.y rect.x = dot.x --Run the animation Runtime:addEventListener( "enterFrame", doTurn )

Hope this helps,

Best,

Jérôme.

Hello again,

other option, could be to use maths, as :

--The Dot local dot --The Rectangle local rect --In case you need physics local physics = require "physics" physics.start() physics.setGravity( 0, 0 ) physics.setDrawMode( "hybrid" ) --Math functions local Cos = math.cos local Sin = math.sin local Rad = math.rad local Atan2 = math.atan2 local Deg = math.deg -- local radius = 10 local angle = 90 --Start angle local doTurn = function(event) rect.x = dot.x + Cos(Rad(angle)) \* radius rect.y = dot.y + Sin(Rad(angle)) \* radius local angleBetween = Atan2(dot.y-rect.y, dot.x-rect.x) rect.rotation = Deg(angleBetween) angle = angle + 5 end dot = display.newCircle(display.contentWidth/2,display.contentHeight/2,5) dot:setFillColor(200,0,0) --The rectangle (could be an image) rect = display.newRect(0,0,20,40) rect:setReferencePoint(display.BottomLeftReferencePoint) physics.addBody(rect) --Run the animation Runtime:addEventListener( "enterFrame", doTurn )

Best,

Jérôme.

Hi Jérôme,

Wow! I’m astonished how easy this could be solved, your examples work great and I can definitely work on this to make it fit what I look for in my project.

Thank you.

-Pierre

For more control of how far away from the red dot you want your object to go you can use the xReference and yReference.

I have slightly changed the above code which allow you greater control of position of your object.  Simply change:

rect.yReference = 50 to any value you want

--The Dot local dot --The Rectangle (could be an image) local rect --In case you need physics local physics = require "physics" physics.start() physics.setGravity( 0, 0 ) physics.setDrawMode( "hybrid" ) local doTurn = function(event)     rect.rotation = rect.rotation + 5 end dot = display.newCircle(display.contentWidth/2,display.contentHeight/2,5) dot:setFillColor(200,0,0) rect = display.newRect(0,0,20,40) physics.addBody(rect) --Change the reference point to anything rect.yReference = 50 --Set the coords. of your rect rect.y = dot.y rect.x = dot.x --Run the animation Runtime:addEventListener( "enterFrame", doTurn )  

Thanks Icy,
That will be alot more convenient for simulating an anchor point for an image, perfect!

You learn new things everyday :slight_smile:

-Pierre

You are welcome Pierre.  Glad to help :slight_smile:

If i want move the object using acelerometer around the circle?

Instead of this:

local doTurn = function(event) rect.rotation = rect.rotation + 5 end Runtime:addEventListener( "enterFrame", doTurn )

Try this:

local onAccelerate = function( event ) --yGravity as an example for tilts in landscape rect.rotation = rect.rotation + event.yGravity\*10 end Runtime:addEventListener( "accelerometer", onAccelerate )

You can fine tune event.yGravity by editing the numerical value (10) to whatever you feel works the best

Thanks Nerolyn is working like i need

Now im trying to use this in a side view car with joints and gravity

here the code with acelerometer

[lua]

–In case you need physics
local physics = require “physics”
physics.start()
physics.setGravity( 0, 0 )
physics.setDrawMode( “hybrid” )
system.setAccelerometerInterval( 50 );

 

–local doTurn = function(event)
–    rect.rotation = rect.rotation + 5
–end

    local onAccelerate = function( event )
    --yGravity as an example for tilts in landscape
    rect.rotation = rect.rotation + event.yGravity*10
    end
     
    Runtime:addEventListener( “accelerometer”, onAccelerate )

rect = display.newRect(0,0,88,40)
physics.addBody(rect)

dot = display.newCircle(display.contentWidth/2,display.contentHeight/2,5)
dot:setFillColor(200,0,0)

–Change the reference point to the botton center of your rect
dot:setReferencePoint(display.CenterReferencePoint)

–Set the coords. of your rect
rect.y = dot.y
rect.x = dot.x

–dot.x = rect.x
–dot.y = rect.y

–Run the animation
–Runtime:addEventListener( “accelerometer”, doTurn )

[/lua]
 

I’ve encountered a pretty tricky problem.

Assume I place a circle on top of the rectangle like so:

AK6Co60.jpg

To match rectangle rotation, assume circle properties to be:

circle.yReference = 50 circle.y = dot.y circle.x = dot.x

Now reference points is only visible by corona and not by box2D physics, so creating a normal collision filter with the circle and a player object is pretty worthless, because the physics assume the circle reference point to be the center of the circle at the original position (dot.x, dot.y).

I’ve been trying my best with using physics, but it doesn’t seem to be a viable option, I guess it would be possible if you somehow created a circular path for the little circle to follow in the same rythm as the rotating image(rectangle) - but I’m not sure if that’s possible

Hello Nerolyn,

please have a look on this post, you will find the answer : http://forums.coronalabs.com/topic/32895-using-eg-topleftalign-on-a-physics-body-only-applies-to-its-appearance-not-its-body-help/

Hope this helps,

Best,

Jérôme.

Thank you Jérôme,

basic issue solved but another one occured, here’s my code:
 

local dot local circle doTurn = function(event) circle.rotation = circle.rotation + 5 end dot = display.newCircle(display.contentWidth/2,display.contentHeight/2,5) dot:setFillColor(200,0,0) circle = display.newCircle(dot.x,dot.y,15) physics.addBody( circle, "static", { friction=0.3, radius=15, filter=objectCollisionFilter } ) circle.yReference = 50 circle.rotation = 3 local circleContentX, circleContentY = circle:localToContent( 0, 0 ) circle.rotation = 0 circle.yReference = 50 circle.x, circle.y = circleContentX, circleContentY circle.rotation = 3

So what happens is that the physical property of “circle”, doesn’t move from its initial position, image:

Ueo42Ff.jpg

Suggestions?

Hello,

you can consider changing the reference point of your display object (e.g. rectangle/image) to the bottom-center of it, here is an example :

--The Dot local dot --The Rectangle (could be an image) local rect --In case you need physics local physics = require "physics" physics.start() physics.setGravity( 0, 0 ) physics.setDrawMode( "hybrid" ) local doTurn = function(event) rect.rotation = rect.rotation + 5 end dot = display.newCircle(display.contentWidth/2,display.contentHeight/2,5) dot:setFillColor(200,0,0) rect = display.newRect(0,0,20,40) physics.addBody(rect) --Change the reference point to the botton center of your rect rect:setReferencePoint(display.BottomCenterReferencePoint) --Set the coords. of your rect rect.y = dot.y rect.x = dot.x --Run the animation Runtime:addEventListener( "enterFrame", doTurn )

Hope this helps,

Best,

Jérôme.

Hello again,

other option, could be to use maths, as :

--The Dot local dot --The Rectangle local rect --In case you need physics local physics = require "physics" physics.start() physics.setGravity( 0, 0 ) physics.setDrawMode( "hybrid" ) --Math functions local Cos = math.cos local Sin = math.sin local Rad = math.rad local Atan2 = math.atan2 local Deg = math.deg -- local radius = 10 local angle = 90 --Start angle local doTurn = function(event) rect.x = dot.x + Cos(Rad(angle)) \* radius rect.y = dot.y + Sin(Rad(angle)) \* radius local angleBetween = Atan2(dot.y-rect.y, dot.x-rect.x) rect.rotation = Deg(angleBetween) angle = angle + 5 end dot = display.newCircle(display.contentWidth/2,display.contentHeight/2,5) dot:setFillColor(200,0,0) --The rectangle (could be an image) rect = display.newRect(0,0,20,40) rect:setReferencePoint(display.BottomLeftReferencePoint) physics.addBody(rect) --Run the animation Runtime:addEventListener( "enterFrame", doTurn )

Best,

Jérôme.

Hi Jérôme,

Wow! I’m astonished how easy this could be solved, your examples work great and I can definitely work on this to make it fit what I look for in my project.

Thank you.

-Pierre

For more control of how far away from the red dot you want your object to go you can use the xReference and yReference.

I have slightly changed the above code which allow you greater control of position of your object.  Simply change:

rect.yReference = 50 to any value you want

--The Dot local dot --The Rectangle (could be an image) local rect --In case you need physics local physics = require "physics" physics.start() physics.setGravity( 0, 0 ) physics.setDrawMode( "hybrid" ) local doTurn = function(event)     rect.rotation = rect.rotation + 5 end dot = display.newCircle(display.contentWidth/2,display.contentHeight/2,5) dot:setFillColor(200,0,0) rect = display.newRect(0,0,20,40) physics.addBody(rect) --Change the reference point to anything rect.yReference = 50 --Set the coords. of your rect rect.y = dot.y rect.x = dot.x --Run the animation Runtime:addEventListener( "enterFrame", doTurn )  

Here I am with an update:

I’ve somehow got it to work by combining the example I was given and added parts of it to the doTurn function. However, some parts I can’t even imagine how box2D/corona calculates because they’re just over-the-top-of-the-highest-roof-on-planet-earth-weird.

local dot local rect local circle, circleOriginal dot = display.newCircle(display.contentCenterX,175,5) dot:setFillColor(200,0,0) rect = display.newImage("img/rect.png") rect:setReferencePoint( display.BottomCenterReferencePoint ) rect.x = dot.x; rect.y = dot.y --Only way to really get them 'synced' in the circular movement around the 'dot' is to place the circle at dot.x+2, but it really should be dot.x circle = display.newCircle(dot.x+2,dot.y - 47.5,12.5) physics.addBody( circle, "static", { friction=0.3, radius=12.5, filter=objectCollisionFilter } ) local circleContentX, circleContentY = circle:localToContent( 0, 0 ) circle.rotation = 90 circle.x, circle.y = circleContentX, circleContentY doTurn = function(event) circleContentX, circleContentY = circle:localToContent( 0, 0 ) --Why 4.15?? circle.yReference = 4.15 circle.x, circle.y = circleContentX, circleContentY circle.rotation = circle.rotation + 5 rect.rotation = rect.rotation + 5 end

This code actually works, the circle with its physical body updates its new center point every frame with the movement. However I can’t really understand how the circle.yReference must be 4.15 (or a number very close to that) when it should actually be 47.5?

I need to be doing something very wrong somewhere

EDIT: after a while (several minutes) the circle comes ahead of the rect picture in rotation, more than the 2 pixels from dot.x + 2, probably the 4.15 reference being off somewhat

Thanks Icy,
That will be alot more convenient for simulating an anchor point for an image, perfect!

You learn new things everyday :slight_smile:

-Pierre

You are welcome Pierre.  Glad to help :slight_smile: