Play audio only while user rotates object

Hello,

I am trying to make an object I have created in my project play audio only when the user rotates it. I do not want the audio to continue playing if the user removes their finger from the object, or if they pause in the middle of rotating it.

I have put together something that almost works, except sometimes the audio continues to play after the user removes their finger from the object; sometimes too while the user pauses in the middle of rotating it.

Initially, I set the scene with the audio playing, and have the volume for this channel set to 0.

Here’s my code:

local circle1 = display.newCircle( 0, 0, 66 ) circle1:setFillColor( 0, 0, 255 ) circle1.x = display.contentCenterX - 166 circle1.y = display.contentCenterY - 82 circle1.alpha = 0.6 group:insert(circle1) physics.addBody( circle1, "static" ) local function rotateCircle1(event) --store initial position of finger local t = event.target local phase = event.phase if (phase == "began") then t.x1 = event.x t.y1 = event.y t:toFront(); display.getCurrentStage():setFocus( t, id ); t.isFocus = true elseif (phase == "moved") then t.x2 = event.x t.y2 = event.y angle1 = 180/math.pi \* math.atan2(t.y1 - t.y , t.x1 - t.x) angle2 = 180/math.pi \* math.atan2(t.y2 - t.y , t.x2 - t.x) print("angle1 = "..angle1) rotationAmt = angle1 - angle2 --rotate it t.rotation = t.rotation - rotationAmt print ("t.rotation = "..t.rotation) t.x1 = t.x2 t.y1 = t.y2 if rotationAmt == 0 then audio.fade( { channel=1, time=150, volume=0 } ) end if rotationAmt \> 2.5 or rotationAmt \< -2.5 then audio.fade( { channel=1, time=150, volume=1 } ) else audio.fade( { channel=1, time=150, volume=0 } ) end elseif (phase == "cancelled" or phase == "ended") then audio.fade( { channel=1, time=150, volume=0 } ) display.getCurrentStage():setFocus( t, nil ) t.isFocus = false end return true end circle1:addEventListener("touch", rotateCircle1)

That is the best I have come up with, and it just doesn’t quite work.

I have been banging my head against these forums and all the documentation trying to figure this out!

Can anyone help me!?

–I would also like to add that this is my first post, and I am so appreciative of all the tutorials, documentation, and help around the website and forums! Corona SDK is incredible! I’m kind of a newb, but I have learned so much in just a couple of months, and I’m almost ready to release my first app. I’m so excited, and I’m having tons of fun! Thanks for everything Corona team and community!

-Daniel

Hi Daniel

Have you tried adding a enterevent function and having a bollean true false to track local volume

This way the knob just moves the rotate amount and tells the other function to change the volume.

Hey Darryl, thanks for your reply!

I’m not sure if I know what you mean. I looked into the enterFrame event documentation, and I feel like that’s what would solve my problem, but I’m not sure if that’s what you’re talking about, or if I’ve implemented it as you suggested.

I’m producing about exactly the same results as before; still having the problem. My audio still gets stuck playing sometimes.

Here’s what my code looks like now:

local circle1 = display.newCircle( 0, 0, 66 ) circle1:setFillColor( 0, 0, 255 ) circle1.x = display.contentCenterX - 166 circle1.y = display.contentCenterY - 82 circle1.alpha = 0.6 group:insert(circle1) physics.addBody( circle1, "static" ) local circleVolume = false --Function to track circle movement, and add or remove volume local function trackCircleVolume( event ) if circleVolume == true then audio.fade( { channel=1, time=250, volume=1 } ) end if circleVolume == false then audio.fade( { channel=1, time=250, volume=0 } ) end end local function rotateCircle1(event) --store initial position of finger local t = event.target local phase = event.phase if (phase == "began") then t.x1 = event.x t.y1 = event.y t:toFront(); display.getCurrentStage():setFocus( t, id ); t.isFocus = true elseif (phase == "moved") then t.x2 = event.x t.y2 = event.y angle1 = 180/math.pi \* math.atan2(t.y1 - t.y , t.x1 - t.x) angle2 = 180/math.pi \* math.atan2(t.y2 - t.y , t.x2 - t.x) print("angle1 = "..angle1) rotationAmt = angle1 - angle2 --rotate it t.rotation = t.rotation - rotationAmt print ("t.rotation = "..t.rotation) t.x1 = t.x2 t.y1 = t.y2 --Detect that the user has ceased rotating the object if rotationAmt == 0 then circleVolume = false end --Detect that the user is rotating the object a little bit if rotationAmt \> 2.5 or rotationAmt \< -2.5 then circleVolume = true else circleVolume = false end elseif (phase == "cancelled" or phase == "ended") then circleVolume = false display.getCurrentStage():setFocus( t, nil ) t.isFocus = false end return true end Runtime:addEventListener( "enterFrame", trackCircleVolume ) circle1:addEventListener("touch", rotateCircle1)

Am I headed in the right direction? Is this what you’re talking about?

Thanks, again, for your help!

-Daniel

Hi Daniel

looked at your code and although i couldn’t solve your issue i though you may like to see my working out…

adding a line and a dot were 1st touch is pretty vital as visual items to solve your issue, i have got it to work as a knob with the 1st touch as the on’off position but maybe comparing 2 updated points of will achieve your goal.



– main.lua


local physics = require “physics”
physics.start()
physics.setGravity(0, 0)

 

local group = display.newGroup()

 

local circle1 = display.newCircle( 0, 0, 66 )
circle1:setFillColor( 0, 0, 255 )
circle1.x = display.contentCenterX - 166
circle1.y = display.contentCenterY - 82
circle1.alpha = 0.6
physics.addBody( circle1, “static” )

 

group:insert(circle1)

 

local l1x = circle1.x - 20
local line1 = display.newLine(circle1.x ,circle1.y ,l1x  ,circle1.y - 64)
local circle2 = display.newCircle( circle1.x, circle1.y -60, 5 )

 

local onoff = “off”

 

local myText = display.newText(onoff, 0, 0, display.contentWidth, display.contentHeight * 0.5, native.systemFont, 16)
myText:setTextColor(255, 255, 255)

 

local t

 

local function rotateCircle1(event)

 

  --store initial position of finger
  local t = event.target
 
  --l1x = t.x
 
  local phase = event.phase

 

    if (phase == “began”) then
        t.x1 = event.x
        t.y1 = event.y
  
  --put circle were 1st touch
  circle2.x = event.x
  circle2.y = event.y

 

        t:toFront();

 

        display.getCurrentStage():setFocus( t, id );
        t.isFocus = true

 

        elseif (phase == “moved”) then
            t.x2 = event.x
            t.y2 = event.y
   
   
   
            angle1 = 180/math.pi * math.atan2(t.y1 - t.y , t.x1 - t.x)
            angle2 = 180/math.pi * math.atan2(t.y2 - t.y , t.x2 - t.x)
            print("angle1 = "…angle1)
            rotationAmt = angle1 - angle2
   
   --use line to show how Knob is rotated
   line1.rotation = angle2 + event.x

 

            --rotate it
            t.rotation = t.rotation - rotationAmt
            print ("t.rotation = "…t.rotation)

 

   onoff = “off”
   
            --t.x1 = t.x2
            --t.y1 = t.y2

 

            if rotationAmt > 5 or rotationAmt < -5 then

 

   onoff = “on”
         
            end

 

            elseif (phase == “cancelled” or phase == “ended”) then

 

                onoff = “off”

 

                display.getCurrentStage():setFocus( t, nil )
                t.isFocus = false

 

            end

 

   myText.text = onoff
   
       return true

 

end

 

circle1:addEventListener(“touch”, rotateCircle1)

 

local function showoffon()
l1x = l1x - 20
l1x = l1x + 20
myText.text = onoff

 

end

 

Runtime:addEventListener( “enterFrame”, showoffon )

Hi Daniel

Have you tried adding a enterevent function and having a bollean true false to track local volume

This way the knob just moves the rotate amount and tells the other function to change the volume.

Hey Darryl, thanks for your reply!

I’m not sure if I know what you mean. I looked into the enterFrame event documentation, and I feel like that’s what would solve my problem, but I’m not sure if that’s what you’re talking about, or if I’ve implemented it as you suggested.

I’m producing about exactly the same results as before; still having the problem. My audio still gets stuck playing sometimes.

Here’s what my code looks like now:

local circle1 = display.newCircle( 0, 0, 66 ) circle1:setFillColor( 0, 0, 255 ) circle1.x = display.contentCenterX - 166 circle1.y = display.contentCenterY - 82 circle1.alpha = 0.6 group:insert(circle1) physics.addBody( circle1, "static" ) local circleVolume = false --Function to track circle movement, and add or remove volume local function trackCircleVolume( event ) if circleVolume == true then audio.fade( { channel=1, time=250, volume=1 } ) end if circleVolume == false then audio.fade( { channel=1, time=250, volume=0 } ) end end local function rotateCircle1(event) --store initial position of finger local t = event.target local phase = event.phase if (phase == "began") then t.x1 = event.x t.y1 = event.y t:toFront(); display.getCurrentStage():setFocus( t, id ); t.isFocus = true elseif (phase == "moved") then t.x2 = event.x t.y2 = event.y angle1 = 180/math.pi \* math.atan2(t.y1 - t.y , t.x1 - t.x) angle2 = 180/math.pi \* math.atan2(t.y2 - t.y , t.x2 - t.x) print("angle1 = "..angle1) rotationAmt = angle1 - angle2 --rotate it t.rotation = t.rotation - rotationAmt print ("t.rotation = "..t.rotation) t.x1 = t.x2 t.y1 = t.y2 --Detect that the user has ceased rotating the object if rotationAmt == 0 then circleVolume = false end --Detect that the user is rotating the object a little bit if rotationAmt \> 2.5 or rotationAmt \< -2.5 then circleVolume = true else circleVolume = false end elseif (phase == "cancelled" or phase == "ended") then circleVolume = false display.getCurrentStage():setFocus( t, nil ) t.isFocus = false end return true end Runtime:addEventListener( "enterFrame", trackCircleVolume ) circle1:addEventListener("touch", rotateCircle1)

Am I headed in the right direction? Is this what you’re talking about?

Thanks, again, for your help!

-Daniel

Hi Daniel

looked at your code and although i couldn’t solve your issue i though you may like to see my working out…

adding a line and a dot were 1st touch is pretty vital as visual items to solve your issue, i have got it to work as a knob with the 1st touch as the on’off position but maybe comparing 2 updated points of will achieve your goal.



– main.lua


local physics = require “physics”
physics.start()
physics.setGravity(0, 0)

 

local group = display.newGroup()

 

local circle1 = display.newCircle( 0, 0, 66 )
circle1:setFillColor( 0, 0, 255 )
circle1.x = display.contentCenterX - 166
circle1.y = display.contentCenterY - 82
circle1.alpha = 0.6
physics.addBody( circle1, “static” )

 

group:insert(circle1)

 

local l1x = circle1.x - 20
local line1 = display.newLine(circle1.x ,circle1.y ,l1x  ,circle1.y - 64)
local circle2 = display.newCircle( circle1.x, circle1.y -60, 5 )

 

local onoff = “off”

 

local myText = display.newText(onoff, 0, 0, display.contentWidth, display.contentHeight * 0.5, native.systemFont, 16)
myText:setTextColor(255, 255, 255)

 

local t

 

local function rotateCircle1(event)

 

  --store initial position of finger
  local t = event.target
 
  --l1x = t.x
 
  local phase = event.phase

 

    if (phase == “began”) then
        t.x1 = event.x
        t.y1 = event.y
  
  --put circle were 1st touch
  circle2.x = event.x
  circle2.y = event.y

 

        t:toFront();

 

        display.getCurrentStage():setFocus( t, id );
        t.isFocus = true

 

        elseif (phase == “moved”) then
            t.x2 = event.x
            t.y2 = event.y
   
   
   
            angle1 = 180/math.pi * math.atan2(t.y1 - t.y , t.x1 - t.x)
            angle2 = 180/math.pi * math.atan2(t.y2 - t.y , t.x2 - t.x)
            print("angle1 = "…angle1)
            rotationAmt = angle1 - angle2
   
   --use line to show how Knob is rotated
   line1.rotation = angle2 + event.x

 

            --rotate it
            t.rotation = t.rotation - rotationAmt
            print ("t.rotation = "…t.rotation)

 

   onoff = “off”
   
            --t.x1 = t.x2
            --t.y1 = t.y2

 

            if rotationAmt > 5 or rotationAmt < -5 then

 

   onoff = “on”
         
            end

 

            elseif (phase == “cancelled” or phase == “ended”) then

 

                onoff = “off”

 

                display.getCurrentStage():setFocus( t, nil )
                t.isFocus = false

 

            end

 

   myText.text = onoff
   
       return true

 

end

 

circle1:addEventListener(“touch”, rotateCircle1)

 

local function showoffon()
l1x = l1x - 20
l1x = l1x + 20
myText.text = onoff

 

end

 

Runtime:addEventListener( “enterFrame”, showoffon )