using transition.to and enterFrame to move a display object

When I used the transition.to function, I don’t see the display object move when I expect it. I’ve read that that transition time s 500 msec but in my app I don’t see the movement until much later.

The ShowCoverBlocks() function below is called from my enterFrame handler, every 16 msec. I expected to see the blocks move after 4 seconds and then again at 6 seconds. Originally, I saw no movement of the blocks at all. After I commented out the lines that reset the blocks’ position (at the end of the function) I discovered that the transition.to function had moved the blocks, but I didn’t see the new position until 10’s of seconds later, after the blocks had been made invisible, then visible again (by the operation of the CoverFlags).

Does transition.to work with some kind of display update scheduler? Maybe I shouldn’t call transition.to from an enterFrame handler? 

Dan

Sample code:

     – Decide if we should see any cover blocks

     local function ShowCoverBlocks()

          

           – handle each cover block

           for i = 1, 10 do

               

                if ((CoverFlags[i]) and (CoverKeepAwayTimes[i] == 0)) then

                     – make it visible. Also, time to move it?

                     if (CoveredTimes[i] > 6000) then

                           – move it

                           transition.to(CoverBlocks[i], {

                                x = ScreenWidth*5/8,

                                width = ScreenWidth*3/4})

                                CoverBlocks[i].isVisible = true

                     elseif (CoveredTimes[i] > 4000) then

                           – move it

                           transition.to(CoverBlocks[i], {

                                x = ScreenWidth*3/4,

                                width = ScreenWidth/2})

                                CoverBlocks[i].isVisible = true

                               

                     elseif (CoveredTimes[i] > 2000) then

                           – just make it visible

                           CoverBlocks[i].isVisible = true

                     end

                else

                     – make it invisible

                     CoverBlocks[i].isVisible = false

                     – and reset its position

                     --transition.to(CoverBlocks[i], {

                           --x = ScreenWidth*7/8, 

                           --width = ScreenWidth/4})

                end

           end

     end

1.  Thanks for trying to format your code, but there is a tool on the editor bar for that.  It will make your life much easier. :slight_smile:

  1. NO.  Do not call transition.to in enterFrame.  At least don’t do it every frame.  That will just stack up a bunch of transition calls that will fight each other.

formatyourcode.jpg

  1. Ah ha! I’ll find that code formatting tool next time. :slight_smile:

  2. I found that I could get my object to move the way I wanted it to move (this time) by just setting object.x = and object.width = , but I was hoping to use the transition.to special effects sometime in the future.

I’m used to a display model where you move around objects and set their properties, THEN call a “repaint” or updateDisplay function to actually paint the display. Corona doesn’t seem to work that way, but 

I haven’t found a tutorial or guide about when the display gets updated in Corona. Do you know if there is any documentation on that? 

In any case, thanks for your answer! 

Dan

Dan,
 
 
Guides and Tuts
I can’t point you to a specific guide or tutorial, but I can get you started in a more general way:

How Corona Works
In Corona, you don’t set up a draw, then update to make the draw happen.  It is more immediate. For example if I type this:

local tmp = display.newRect( 100, 100, 10, 10 ) tmp:setFillColor(1,0,0)

The very next frame, a red square will be drawn at <100,100>.
 
Also, It will continue to be drawn every frame after that till it is destroyed by you, or as a side-effect of some game action.
 
( Tip: If you’re a previous LÖVE user, you will be used to setting up a draw, then forcing a draw each game loop.  That is NOT how Corona works.)
 
Speaking of game loops and frames, how does that work?  How do you control the game loop?
 
Game Loops
If you’re a prior LÖVE user, or some other engine that has a ‘manual’ game loop, you may be used to the idea of putting all your game code in a big loop.  i.e. The Game Loop.
 
The Game Loop code is run every frame or maybe even more often.  Again, this is not how Corona works.
 
Corona DOES have a game loop, but you don’t generally use it directly.  Instead all of the code you write in Corona is essentially ‘event’ based.
 
If you’re familiar with the concept, Corona is essentially an ‘event based simulator’ that executes game and app code as a result.
 
When Corona starts up, it does the following:

  • Magic device & OS dependent stuff we don’t care about and can’t control.
  • Reads config.lua and sets up the ‘content area’.  
  • Reads and executes the code in main.lua

For a really simple game/app, that may be it.  However, in most cases, the code in main.lua requires other scripts and runs them.  These scripts in turn may require even more scripts, …
 
All of these scripts do one of three things:

  • Something immediate, like creating a display group, drawing images, creating physics bodies, configuring physics, etc.
  • Set up an event listener(s).
  • Set up some time delayed action (which may or may not involve events):
    • A timer
    • A transition
    • A composer.* scene load

After main.lua gets done executing, no more code is executed until:

  • a timer completes and executes its payload.
  • an event occurs and triggers a listener you set up.

This is a timer (one of the many types of time delayed actions):

timer.performWithDelay( 1000, function() print("It is 1 second later. I'm in the future!") end )

 
This is an event listener:

  • Create a display object (a rectangle) to attach a listener to.

  • Define a simple touch listener (touch rect and when finger is moved off rect it will be deleted)

  • Start listener

    –1 local obj = display.newRect( 100, 100, 100, 100 ) – 2 function obj.touch( self, event ) if( event.phase == “ended” ) then display.remove( self ) end return true end – 3 obj:addEventListener(“touch”)

 
That is essentially it.
 
Future Reading and Stuff
Once you get up to speed, you may also find the following useful:

I totally forget to mention this, but if you didn’t guess, enterFrame is the ‘every frame’ event.

It is used for situations where you need a piece of code to execute every frame.

Be warned, if you’re putting your entire game in a enterFrame loop, you’re using it wrong.

Well, in most cases that is wrong. There are always exception, but for typical designs you don’t have that many enterFrame listeners and they are not usually that long (code size).

This is a made up, but representative example of a enterFrame listener

local bob = display.newCircle( 50, 100, 20 ) function bob.enterFrame( self ) if( self.x \> = 200 ) then transition.cancel(self) self:removeEventListener("touch") Runtime:stopEventListener( "enterFrame", self ) self.x = 200 print("DONE!") end end function bob.touch( self, event ) if( event.phase == "began" ) then transition.cancel( self ) transition.to( self, { x = self.x + 25, time = 500 } ) end return true end bob.addEventListener( "touch" ) Runtime:addEventListener( "enterFrame", bob )

Assuming I made no typos, this code will

  • attach an enterFrame listener and a touch listener to ‘bob’ the circle.
  • ‘bob’ starts at <25, 100>
  • If you touch ‘bob’ it will cancel any prior transition and start a new one.  This new transition will try to move bob 25 pixels to the right in half a second.
  • The enterFrame listener will check bob’s position every frame and as soon as bob is at or above x == 200, it will
    • cancel any outstanding transitions on bob
    • stop listening for touches on bob
    • set bob to exactly 200
    • stop the enterframe listener on bob
    • print a message
  •  

Thanks Ed! This is good stuff. I found the section that starts “When Corona starts up, it does the following…” especially helpful. That text should be in the “official” Corona docs.

I haven’t read it all yet, but I’m working on it.  :slight_smile:

Thanks again

Dan

1.  Thanks for trying to format your code, but there is a tool on the editor bar for that.  It will make your life much easier. :slight_smile:

  1. NO.  Do not call transition.to in enterFrame.  At least don’t do it every frame.  That will just stack up a bunch of transition calls that will fight each other.

formatyourcode.jpg

  1. Ah ha! I’ll find that code formatting tool next time. :slight_smile:

  2. I found that I could get my object to move the way I wanted it to move (this time) by just setting object.x = and object.width = , but I was hoping to use the transition.to special effects sometime in the future.

I’m used to a display model where you move around objects and set their properties, THEN call a “repaint” or updateDisplay function to actually paint the display. Corona doesn’t seem to work that way, but 

I haven’t found a tutorial or guide about when the display gets updated in Corona. Do you know if there is any documentation on that? 

In any case, thanks for your answer! 

Dan

Dan,
 
 
Guides and Tuts
I can’t point you to a specific guide or tutorial, but I can get you started in a more general way:

How Corona Works
In Corona, you don’t set up a draw, then update to make the draw happen.  It is more immediate. For example if I type this:

local tmp = display.newRect( 100, 100, 10, 10 ) tmp:setFillColor(1,0,0)

The very next frame, a red square will be drawn at <100,100>.
 
Also, It will continue to be drawn every frame after that till it is destroyed by you, or as a side-effect of some game action.
 
( Tip: If you’re a previous LÖVE user, you will be used to setting up a draw, then forcing a draw each game loop.  That is NOT how Corona works.)
 
Speaking of game loops and frames, how does that work?  How do you control the game loop?
 
Game Loops
If you’re a prior LÖVE user, or some other engine that has a ‘manual’ game loop, you may be used to the idea of putting all your game code in a big loop.  i.e. The Game Loop.
 
The Game Loop code is run every frame or maybe even more often.  Again, this is not how Corona works.
 
Corona DOES have a game loop, but you don’t generally use it directly.  Instead all of the code you write in Corona is essentially ‘event’ based.
 
If you’re familiar with the concept, Corona is essentially an ‘event based simulator’ that executes game and app code as a result.
 
When Corona starts up, it does the following:

  • Magic device & OS dependent stuff we don’t care about and can’t control.
  • Reads config.lua and sets up the ‘content area’.  
  • Reads and executes the code in main.lua

For a really simple game/app, that may be it.  However, in most cases, the code in main.lua requires other scripts and runs them.  These scripts in turn may require even more scripts, …
 
All of these scripts do one of three things:

  • Something immediate, like creating a display group, drawing images, creating physics bodies, configuring physics, etc.
  • Set up an event listener(s).
  • Set up some time delayed action (which may or may not involve events):
    • A timer
    • A transition
    • A composer.* scene load

After main.lua gets done executing, no more code is executed until:

  • a timer completes and executes its payload.
  • an event occurs and triggers a listener you set up.

This is a timer (one of the many types of time delayed actions):

timer.performWithDelay( 1000, function() print("It is 1 second later. I'm in the future!") end )

 
This is an event listener:

  • Create a display object (a rectangle) to attach a listener to.

  • Define a simple touch listener (touch rect and when finger is moved off rect it will be deleted)

  • Start listener

    –1 local obj = display.newRect( 100, 100, 100, 100 ) – 2 function obj.touch( self, event ) if( event.phase == “ended” ) then display.remove( self ) end return true end – 3 obj:addEventListener(“touch”)

 
That is essentially it.
 
Future Reading and Stuff
Once you get up to speed, you may also find the following useful:

I totally forget to mention this, but if you didn’t guess, enterFrame is the ‘every frame’ event.

It is used for situations where you need a piece of code to execute every frame.

Be warned, if you’re putting your entire game in a enterFrame loop, you’re using it wrong.

Well, in most cases that is wrong. There are always exception, but for typical designs you don’t have that many enterFrame listeners and they are not usually that long (code size).

This is a made up, but representative example of a enterFrame listener

local bob = display.newCircle( 50, 100, 20 ) function bob.enterFrame( self ) if( self.x \> = 200 ) then transition.cancel(self) self:removeEventListener("touch") Runtime:stopEventListener( "enterFrame", self ) self.x = 200 print("DONE!") end end function bob.touch( self, event ) if( event.phase == "began" ) then transition.cancel( self ) transition.to( self, { x = self.x + 25, time = 500 } ) end return true end bob.addEventListener( "touch" ) Runtime:addEventListener( "enterFrame", bob )

Assuming I made no typos, this code will

  • attach an enterFrame listener and a touch listener to ‘bob’ the circle.
  • ‘bob’ starts at <25, 100>
  • If you touch ‘bob’ it will cancel any prior transition and start a new one.  This new transition will try to move bob 25 pixels to the right in half a second.
  • The enterFrame listener will check bob’s position every frame and as soon as bob is at or above x == 200, it will
    • cancel any outstanding transitions on bob
    • stop listening for touches on bob
    • set bob to exactly 200
    • stop the enterframe listener on bob
    • print a message
  •  

Thanks Ed! This is good stuff. I found the section that starts “When Corona starts up, it does the following…” especially helpful. That text should be in the “official” Corona docs.

I haven’t read it all yet, but I’m working on it.  :slight_smile:

Thanks again

Dan