• Graphic of Code Basics Series on Buttons Part 2 848px

Code Basics – Create a UI Button in Corona SDK – Part 2

posted in: Tutorial | 0

In the previous Code Basics post on Creating a UI Button in Corona SDK, we worked our way from simply displaying a Red dot button on the screen, to creating a custom UI button that scaled (for user feedback) and fired off a bullet when pressed.

However, as we saw near the end of the tutorial there was some unexpected behaviour of the button. When I touched down on the button, but slide off the button and then raised my finger, two unexpected things happened –

  1. I did not get the “ended” phase on releasing the touch outside of the button bounds (60 pixel radius).
  2. The button remained scaled to 85% of its original (non-touched) size.. it did not scale back to 100% of its original size on releasing the touch.

To re-iterate visually, this is what happened,

 

Spring Return Style Button

With the design of the button, the intention was to have the button scale to 85% of its original size during the “began” and “moved” phase of the touch handler function, followed by a spring back to 100% of its original size when the “ended” phase occurs. The “ended” phase should be triggered when –

 

  1. The touch is lifted up (release) while my finger is within the bounds of the button, or
  2. The touch slides outside of the graphical bounds of the button.

 

In the physical world this would be analogous to any spring return style button (like the Staples “Easy Button”) –

 

Graphics of Staples Easy Button staples.com.au [Source: http://staples.com.au]

 

If you push it in, it remains in while triggering something to happen, but if you slide off the side of the button it springs back to the original state.

 

 

Vector Math 101: A Custom Solution

I apologise in advance for bringing up the words, math and vector together. Often either of these words alone can have the potential to induce that high school flashback of you peering up at the clock, sweating profusely with only 60 seconds left in the exam.. followed by “Okay class, put down your pencils!… I said put down your pencils!”.

 

Student exam graphic time up 350px

 

But don’t worry, I’ll do my best to describe what you need to know.. and there ain’t no grading in this lesson 😉

 

Referring to the figure below I have overlayed some key points, vectors and co-ordinate frames on a screen shot of our simple “Hello Button” demo app from Part 1 of the series. Before we get into the code I will describe each of these overlayed items here –

Co-ordinate Frames:

  • Global Content Frame: In the top left corner of the screen we have the Zero-Zero location, with the positive directions of the axes shown (as defined in Corona SDK).
  • Button Reference Frame: Assume the center of the button has its own local reference frame, with positive directions of the axes shown (as defined in Corona SDK).

Vectors:

  • XBG: The position vector (or called state vector, big X) of our Button relative to the Global Content Frame.
  • XTG: The position vector (big X) of our instantaneous Touch relative to the Global Content Frame.
  • XTB: The position vector (big X) of our instantaneous Touch relative to the local Button Reference Frame.

Relative frames in Corona for vector calc 720px

 

So as we touch down on the button, initiating the ‘began‘ phase.. and then move our finger around the content area, we can continually calculate how far away the touch is from the button and check if it moves outside the bounds of the button. All we need to calculate is the length of XTB, otherwise called the norm of XTB and symbolically described as | XTB | . Unfortunately, it has nothing to do with this Norm (or his beer…) –

 

Picture of Norm from sitcom Cheers for 1980s [Source: www.edadrian.com]

 

First, lets do the vector addition (referring to the 2nd figure above… not Norm drinking beer) –

XTG =  XBGXTB              [Eqn. 1]

So, XTB = XTG – XBG         [Eqn. 2]

 

Since we are only working in 2-D space we can expand [Eqn.2] out to be –

 

xTB = xTG – xBG              [Eqn.3]

yTB = yTG – yBG              [Eqn.4]

 

Then… good old Pythagoras… to get the length or norm

 

 Length of XTB = | XTB | = (xTB2+ yTB2)1/2       [Eqn.5]

 

Okay… that is the end of the equations! Now let’s implement it..

 

Within the function myButtonHandler(event) we are going to add the following lines of code –

As we can see both event.x and event.y give us the instantaneous location of the user touch once the “began” phase starts. This means –

 

From [Eqn.3] we use event.x to represent xTG

From [Eqn.4] we use event.y to represent yTG

 

Also, we can see in the code snippet above that event.target.x and event.target.y give us the location of the button that has been touched (specifically at its center). This means –

 

From [Eqn.3] we use event.target.x to represent xBG

From [Eqn.4] we use event.target.y to represent yBG

 

With the code snippet above, let’s also add in two other text objects –

  1. To remind us of the radial size of our round button;
  2. To see the length our touch vector, XTB , as we move our finger around the screen after the touch begins.

Your “main.lua” should now look like this –

 

So the changes were –

  • On Lines 19 and 20 we added local parameters rather than having hard-coded values
  • On Line 31 we added a text object to remind us of the bound size of our button
  • On Line 34 we added a text object to show us the instantaneous length of the touch vector (relative to the button)
  • On Lines 60-63 we added the vector difference equations to calculate the length (norm) of the touch vector
  • On Lines 72/73, 78/79, and 87/88 we manipulate the text objects depending on the active touch ‘phase’

 

And this is what happens –

 

Although we now have the additional display.newText objects to visualize what is happening while we calculate the length of the touch vector (relative to the button center), we still have the anomaly that we had previously.

Focus Your Efforts

A feature in Corona SDK that you should use in cases with buttons that change appearance when a user initially presses them is –

object:setFocus()

 

If we use this function in the ‘began‘ phase within our myButtonHandler function, we have the ability to tell Corona SDK to lock on to this target (our button) for all future hit events until we reset the focus property by setting it with nil. The two calls we need to place in our code are the following –

 

Let’s add these lines to our ‘main.lua‘ file, so that your code should now look like this –

The only changes were  –

  • On Line 66 – we set the focus on the current hit event (which is our button)
  • On Line 89 – we release the focus on the current hit event (which is our button)

We can now see that on release of the button anywhere outside of the button, we do get the ‘ended‘ phase and the button restores to its original size. See below –

 

The only issue we still have is that we want the button to spring back to its original scaled position when crossing the radial button boundary. To do this we simply add an if statement within the ‘moved‘ phase –

That’s it ! Now we have the spring back effect of the button to its original scaled position when crossing the radial boundary.

 

Depending on when your action happens (in our case the bullet was fired in the ‘began‘ phase) you may need to include a flag variable to indicate the first instance the button boundary was crossed.

As you are probably aware, by measuring the instantaneous touch vector relative to the button we could also identify its angle and direction relative to the local button co-ordinate frame… with this information you could do many things.

To see the instantaneous touch position relative to the button co-ordinate frame, add the following one-liner to Line 64 in the ‘main.lua‘ file –

Then open the Corona SDK console or ensure the Show Build Panel option is selected from with Sublime Text. Launch ‘main.lua‘ from the Simulator, touch the button, and while holding down move around the screen to see the local x and y positions in the button co-ordinate frame.

 

In the next session…. we’ll put on our Designer hat.

Who said Programmers can’t do app or game art?! (at least some basic stuff)

Vector or Raster graphics? What are the best tools?

Join me next time….. see you then !

 

 

Leave a Reply