[SOLVED] How to make an object rotate or move forever?

Hi,

I have a player’s head who I want to move up/down and rotate a bit to make it look like they’re alive/breathing. What is the best way to go about that?

Here is my player (car_object + head_object) and I want to make his head “bob” back and forth.

I’ve looked at the Corona APIs and Coronto Tutorials but I’m not exactly sure what the best way to achieve this is. Let’s say I want to rotate the head 20 degrees clockwise over the span of 2 seconds and then rotate it back continuously. Do I use a timer.performWithDelay() call and make it move 1 degree every 100ms? Or is there a built-in transition that already does this?

Thanks in advance!

There are many ways to do that.

  1. Use a sprite.  You can make a sprite that plays this animation and if you want to modify the rate over time  you can also do that.

  2. Use a timer as you suggested.

  3. Use enterFrame listener() (Timer is actually using this under the hood).

  4. transition.to() - I forgot this, but am adding this now.  Credit to @XeduR below.

Tip: If you use this method, make sure the onComplete objects are fields on the object and then the transition will be stopped automatically.

  1. Make the head a physics object with low density, plus a little bit of angular damping,  and attach it to the rest of the image (also a body) with a pivot joint that has a limited rotation angle.  Then, motion of the second body will cause the head to bobble.

  2. maybe… transition2 an external lib might… have a built-in feature for this too.  Maybe.

If your game has physics (and some slopes), then I would definitely look into joints, like roaminggamer already suggested. It would probably result in the most dynamic effect.

If joints aren’t your thing, then I would probably solve this by creating two functions that both contain transitions with onComplete for each other. Something along the lines of this pseudo-code:
 

local transition1, transition2 function transition1() transition.to( object, { time=1000, rotation=object.rotation+20, transition=easing.inOutBack, onComplete=transition2 } ) end function transition2() transition.to( object, { time=1000, rotation=object.rotation-20, transition=easing.inOutBack, onComplete=transition1 } ) end transition1()

Tip: Extending above example to make it self-cancelling (in case object is removed)

local transition1, transition2 --function transition1(self) transition1 = function(self) self.onComplete = transition2 transition.to( self, { time=1000, rotation=self.rotation+20, transition=easing.inOutBack, onComplete=self } ) end --function transition2(self) transition2 = function(self) self.onComplete = transition1 transition.to( self, { time=1000, rotation=self.rotation-20, transition=easing.inOutBack, onComplete=self } ) end transition1(object)

Thanks for the suggestions guys. I don’t use physics in my game, I should have mentioned that in the post.

Xedur, I like your solution, it makes sense to me but I’m getting this error: **Attempt to index field ‘?’ (a nil value) **when transition2 runs.

See update to solution above.

Thank you guys! I did not expect a response/solution this fast haha thanks again, really appreciate it!

Roaminggamer, what’s the point of putting self.onComplete = transition2 as opposed to just sticking transition2 into the transition.to() option parameters?

Ex:

transition.to( self, { time=1000, rotation=self.rotation+20,transition=easing.inOutBack, onComplete=transition2 } )

In addition, I am trying to make players “breath” at different times. I display 4 players on the screen and each time I display a player, I begin the transitions on them. I don’t always want all 4 players to be “breathing” the same way at the exact same time every time.

I am trying to do this:

M.normalBreathing = function(object) local transition1, transition2 function transition1(self) self.onComplete = transition2 transition.to( self, { time=1000, rotation=self.rotation+20, transition=easing.inOutBack, onComplete=self } ) end function transition2(self) self.onComplete = transition1 transition.to( self, { time=1000, rotation=self.rotation-20, transition=easing.inOutBack, onComplete=self } ) end local function startTransitions() transition1(object) end timer.performWithDelay(math.random(0, 10) \* 100, startTransitions); end

And I get an Error: Attempt to index local ‘self’ (a nil value)

  1. I made a small mistake in my update to @XeduR’s original code.  See my update above.

In the original versions, those functions  were global not local. i.e. The local statement at the top had no effect.

  1. If that change doesn’t fix the problem, try this and see what prints out:

    local function startTransitions() print( "Object nil? ", object ) if( object ) then print( "Actually a display object? ", object.displayRemove ) end transition1(object) end

You pasted the wrong code above. I did originally typo it, but this is the final version I posted:

transition.to( self, { time=1000, rotation=self.rotation+20, transition=easing.inOutBack, onComplete=self } )

What I’ve done is ‘attached’ the function directly to the object and then had the transition look at the object for an onComplete method.

Your code could well have worked fine, but it has been my practice for years to use local functions instead of global ones.  My technique above makes the function local (to the object).

Because there are effectively ‘two’ onComplete methods, I simply swap them on each call.

There are many ways to do that.

  1. Use a sprite.  You can make a sprite that plays this animation and if you want to modify the rate over time  you can also do that.

  2. Use a timer as you suggested.

  3. Use enterFrame listener() (Timer is actually using this under the hood).

  4. transition.to() - I forgot this, but am adding this now.  Credit to @XeduR below.

Tip: If you use this method, make sure the onComplete objects are fields on the object and then the transition will be stopped automatically.

  1. Make the head a physics object with low density, plus a little bit of angular damping,  and attach it to the rest of the image (also a body) with a pivot joint that has a limited rotation angle.  Then, motion of the second body will cause the head to bobble.

  2. maybe… transition2 an external lib might… have a built-in feature for this too.  Maybe.

If your game has physics (and some slopes), then I would definitely look into joints, like roaminggamer already suggested. It would probably result in the most dynamic effect.

If joints aren’t your thing, then I would probably solve this by creating two functions that both contain transitions with onComplete for each other. Something along the lines of this pseudo-code:
 

local transition1, transition2 function transition1() transition.to( object, { time=1000, rotation=object.rotation+20, transition=easing.inOutBack, onComplete=transition2 } ) end function transition2() transition.to( object, { time=1000, rotation=object.rotation-20, transition=easing.inOutBack, onComplete=transition1 } ) end transition1()

Tip: Extending above example to make it self-cancelling (in case object is removed)

local transition1, transition2 --function transition1(self) transition1 = function(self) self.onComplete = transition2 transition.to( self, { time=1000, rotation=self.rotation+20, transition=easing.inOutBack, onComplete=self } ) end --function transition2(self) transition2 = function(self) self.onComplete = transition1 transition.to( self, { time=1000, rotation=self.rotation-20, transition=easing.inOutBack, onComplete=self } ) end transition1(object)

Thanks for the suggestions guys. I don’t use physics in my game, I should have mentioned that in the post.

Xedur, I like your solution, it makes sense to me but I’m getting this error: **Attempt to index field ‘?’ (a nil value) **when transition2 runs.

See update to solution above.

Thank you guys! I did not expect a response/solution this fast haha thanks again, really appreciate it!

Roaminggamer, what’s the point of putting self.onComplete = transition2 as opposed to just sticking transition2 into the transition.to() option parameters?

Ex:

transition.to( self, { time=1000, rotation=self.rotation+20,transition=easing.inOutBack, onComplete=transition2 } )

In addition, I am trying to make players “breath” at different times. I display 4 players on the screen and each time I display a player, I begin the transitions on them. I don’t always want all 4 players to be “breathing” the same way at the exact same time every time.

I am trying to do this:

M.normalBreathing = function(object) local transition1, transition2 function transition1(self) self.onComplete = transition2 transition.to( self, { time=1000, rotation=self.rotation+20, transition=easing.inOutBack, onComplete=self } ) end function transition2(self) self.onComplete = transition1 transition.to( self, { time=1000, rotation=self.rotation-20, transition=easing.inOutBack, onComplete=self } ) end local function startTransitions() transition1(object) end timer.performWithDelay(math.random(0, 10) \* 100, startTransitions); end

And I get an Error: Attempt to index local ‘self’ (a nil value)

  1. I made a small mistake in my update to @XeduR’s original code.  See my update above.

In the original versions, those functions  were global not local. i.e. The local statement at the top had no effect.

  1. If that change doesn’t fix the problem, try this and see what prints out:

    local function startTransitions() print( "Object nil? ", object ) if( object ) then print( "Actually a display object? ", object.displayRemove ) end transition1(object) end