Virtual Joystick and Double Tap at the same time

Thanks for the reply.  Multitouch is already activated.  Like I mentioned before, "touch"ing the button and using the joystick at the same time works as it should.  I just can’t get double “tap” to work.  Do you know if there is a way to set focus for a tap event like you can for a touch event?

I’m still confused. To get a double tap you would need to create a counter to check how many taps happened. Then do something like 

if counter == 2 then Do something end

This what you need?

Sorry for the delay… haven’t been able to get back on here to post my code.  Below is the extracted code I’m running.  The analog stick changes the rotation and the gas button propels the car.  The “tap” listener works fine if you’re not touching the analog stick, but I need it to work even if your thumb is on the analog stick like the gas button does.  Any help would be appreciated.

This is the code in scene running the game itself:

[lua]local physics = require “physics”

physics.start() 

physics.setVelocityIterations( 6 )  --try and fix instability with pivot joints

physics.setGravity(0, 0)

system.activate(“multitouch”)

system.setTapDelay(.5)

local StickLib   = require(“lib_analog_stick”)

–=========================================================================

–Zero Gravity Nitro boost function

–=========================================================================                             

local function nitroBoost5 ( event )

    if gameIsActive == 1 then          

        if numNitro > 0 then

            if ( event.numTaps == 2 ) then                                                    

                if boosted == 1 then

                    nitroBoostChannel = audio.play(nitroBoostSound, {channel=17})

                    boosted = 0

                    numNitro = numNitro - 1                                                       

                    nitroStatus.text = "Nitro:  "…numNitro 

   

                    backWheel:applyLinearImpulse( xDirection*3, yDirection*3, backWheel.x, backWheel.y ) 

                    frontWheel:applyLinearImpulse( xDirection*3, yDirection*3, frontWheel.x, frontWheel.y )

  

                    local function limitTap1()

                        boosted = 1

                    end

                    timer.performWithDelay(1000, limitTap1)

                end

            else

                return true    

            end

        end 

    end

end                                 

gas:addEventListener( “tap”, nitroBoost5 )

– CREATE ANALOG STICK

brakeArrow.alpha = 0

gravityArrow.alpha = 0

gravityArrow2.alpha = 0

jumpArrow.alpha = 0

directionArrow.alpha = .5

gasArrow.xScale = .6 

gasArrow.yScale = .6 

MyStick = StickLib.NewStick( 

{

x             = brakeArrow.x+brakeArrow.x*.25,

y             = brakeArrow.y+brakeArrow.y*.25,

thumbSize     = 40,

borderSize    = 80, 

snapBackSpeed = .2, 

R             = 25,

G             = 255,

B             = 255

} )

local crossHair = display.newImageRect(hud, “images/crossHair.png”, 140, 140)

crossHair.x = MyStick.x

crossHair.y = MyStick.y 

crossHair.alpha = .6

 – MAIN LOOP


local function main( event )

    if gameIsActive == 1 then 

        – SHOW STICK INFO

        – Text.text = “ANGLE = “…MyStick:getAngle()…”   DIST = “…math.ceil(MyStick:getDistance())…”   PERCENT = “…math.ceil(MyStick:getPercent()*100)…”%”

        --print("MyStick:getAngle = "…MyStick:getAngle())

        --print("MyStick:getDistance = "…MyStick:getDistance())

        --print("MyStick:getPercent = "…MyStick:getPercent()*100)

        --print("POSICAO X / Y  " …hero.x,hero.y) 

        moving = MyStick:getMoving()

        local percent = MyStick:getPercent()*100 

        local boostPower = carTable.JUMP_POWER*.5 

        if bodyGroup.rotation <= 90 then 

            xDirection = (bodyGroup.rotation * .111111111111111) * boostPower * 2

            yDirection = ((90 - bodyGroup.rotation) * -.111111111111111) * boostPower * 2

        elseif bodyGroup.rotation > 90 and bodyGroup.rotation <= 180 then 

            xDirection = ((180 - bodyGroup.rotation) * .111111111111111) * boostPower * 2

            yDirection = ((bodyGroup.rotation - 90) * .111111111111111) * boostPower * 2

        elseif bodyGroup.rotation > 180 and bodyGroup.rotation <= 270 then 

            xDirection = ((180 - bodyGroup.rotation) * .111111111111111) * boostPower * 2

            yDirection = ((bodyGroup.rotation - 270) * -.111111111111111) * boostPower * 2

        elseif bodyGroup.rotation > 270 and bodyGroup.rotation <= 360 then 

            xDirection = ((360 - bodyGroup.rotation) * -.111111111111111) * boostPower * 2

            yDirection = ((270 - bodyGroup.rotation) * .111111111111111) * boostPower * 2

        end

        if globals.gasPressed == true then 

            bodyGroup.isFixedRotation = true

            if body3 then 

                body3:setSequence(“boosting”)

                body3:play()

            end      

            if percent > 0 then 

                 bodyGroup.rotation = globals.angle

                 gasArrow.rotation = globals.angle - 90

            end  

            MyStick:boost(bodyGroup, xDirection, yDirection, true, boostPower)

        else 

            if percent > 0 then 

                globals.angle = MyStick:getAngle() 

                bodyGroup.isFixedRotation = true

                if body3 then

                    body3:setSequence(“noBoost”)

                    body3:play()

                end  

                bodyGroup.rotation = globals.angle

                gasArrow.rotation = globals.angle - 90

                MyStick:boost(bodyGroup, 0, 0, false, boostPower)

            end 

        end 

    else 

        bodyGroup.isFixedRotation = false 

        if body3 then

            body3:setSequence(“noBoost”)

            body3:play()

        end  

        globals.angle = bodyGroup.rotation

        gasArrow.rotation = globals.angle - 90

        MyStick:boost(bodyGroup, 0, 0, false, boostPower)

    end 

end

Runtime:addEventListener( “enterFrame”, main )

–=========================================================================

–Gas Function - Zero Gravity

–=========================================================================

function gas:touch( event )

    if gameIsActive == 1 then

        if event.phase == “began” then

            event.target.alpha = .2 

            globals.gasPressed = true  

        elseif event.phase == “ended” or event.phase == “cancelled” then

            event.target.alpha = 0

            globals.gasPressed = false 

        end

    end 

    return true

end

gas:addEventListener( “touch”, gas )

[/lua]

This is the code that includes the functions needed for the analog stick:

[lua]

module (…, package.seeall)

–[[


ANALOG STICK MODULE FOR CORONA SDK


PRODUCT  :              ANALOG STICK MODULE FOR CORONA SDK

VERSION  :              1.0.1

AUTHOR   :              X-PRESSIVE.COM / MIKE DOGAN GAMES & ENTERTAINMENT

WEB SITE :              www.x-pressive.com

SUPPORT  :              support@x-pressive.com

PUBLISHER:              X-PRESSIVE.COM

COPYRIGHT:              ©2011 X-PRESSIVE.COM / MIKE DOGAN GAMES & ENTERTAINMENT


USAGE:


  1.  INCLUDE THE MODULE:

        StickLib = require(“lib_analog_stick”)

  1.  CREATE A STICK (RETURNS A DISPLAY GROUP HANDLE):

        MyStick = StickLib.NewStick( 

                {

                x             = [X-COORD],

                y             = [Y-COORD],

                thumbSize     = [THUMB  SIZE],

                borderSize    = [BORDER SIZE], 

                snapBackSpeed = [THUMB SNAP BACK SPEED 0.0 - 1.0], 

                R             = [COLOR RED   0 - 255],

                G             = [COLOR GREEN 0 - 255],

                B             = [COLOR BLUE  0 - 255],

                } )

  1.  TO MOVE AN OBJECT:  

        MyStick:move( ObjectHandle, maxSpeed, rotate = true | false)

        OR GET STICK INFO TO MOVE ANY OBJECT MANUALLY:

        MyStick:getAngle   () - RETURNS THE CURRENT ANGLE (DIRECTION) FROM 0 (TOP) TO 360 (CLOCKWISE)

        MyStick:getDistance() - RETURNS DISTANCE FROM THUMB TO CENTER IN PIXELS

        MyStick:getPercent () - RETURNS DISTANCE FROM THUMB TO CENTER (NORMALIZED, 0.0 - 1.0)

        

  1.  REMOVE STICK

        MyStick:delete()

        MyStick = nil


–]]

local Pi    = math.pi

local Sqr   = math.sqrt

local Rad   = math.rad

local Sin   = math.sin

local Cos   = math.cos

local Ceil  = math.ceil

local Atan2 = math.atan2


– FUNCTION: CREATE 


function NewStick( Props )

        local Group = display.newGroup()

        Group.x = Props.x

        Group.y = Props.y

        Group.Timer = nil

        Group.angle = 0

        Group.distance = 0

        Group.percent = 0

        Group.maxDist = Props.borderSize

        Group.snapBackSpeed = Props.snapBackSpeed ~= nil and Props.snapBackSpeed or .7

        Group.Border = display.newCircle(0,0,Props.borderSize)

        – for use images uncomment the line down and comment line up

        – Group.Border = display.newImage(“joystickmain1a.png”)

        Group.Border.strokeWidth = 2

        --Group.Border:setFillColor  (Props.R,Props.G,Props.B,46)

        --Group.Border:setStrokeColor(Props.R,Props.G,Props.B,255)

        Group.Border:setFillColor  (Props.R,Props.G,Props.B,0)

        Group.Border:setStrokeColor(Props.R,Props.G,Props.B,0)

        Group:insert(Group.Border)

        Group.Thumb = display.newCircle(0,0,Props.thumbSize)

        – for use images uncomment the line down and comment line up

        – Group.Thumb = display.newImage(“joystickmain1b.png”) 

        Group.Thumb.strokeWidth = 3

        Group.Thumb:setFillColor  (Props.R,Props.G,Props.B,96)

        Group.Thumb:setStrokeColor(Props.R,Props.G,Props.B,255)

        Group.Thumb.x0 = 0

        Group.Thumb.y0 = 0

        Group.Thumb.alpha = .2

        Group:insert(Group.Thumb)

        Group.collisionDetected = false 

        Group.lockedAngle =  false

        Group.beingMoved = false

        ---------------------------------------------

        – METHOD: DELETE STICK

        ---------------------------------------------

        function Group:delete()

                self.Border    = nil

                self.Thumb     = nil

                if self.Timer ~= nil then timer.cancel(self.Timer); self.Timer = nil end

                self:removeSelf()

        end

        

        ---------------------------------------------

        – METHOD: MOVE AN OBJECT

        ---------------------------------------------

        function Group:move(Obj, maxSpeed, rotate)

                if rotate == true then Obj.rotation = self.angle end

                Obj.x = Obj.x + Cos( Rad(self.angle-90) ) * (maxSpeed * self.percent) 

                Obj.y = Obj.y + Sin( Rad(self.angle-90) ) * (maxSpeed * self.percent)

        end

        ---------------------------------------------

        – METHOD: BOOST CAR

        ---------------------------------------------

        function Group:boost(Obj, xDirection, yDirection, rotate, boostPower)              

if rotate == true then 

if self.percent > 0 then 

Obj.rotation = self.angle 

–print("selfAngle = "…self.angle)

if self.angle <= 90 then 

xDirection = (self.angle * .111111111111111) * boostPower * 2

yDirection = ((90 - self.angle) * -.111111111111111) * boostPower * 2

elseif self.angle > 90 and self.angle <= 180 then 

xDirection = ((180 - self.angle) * .111111111111111) * boostPower * 2

yDirection = ((self.angle - 90) * .111111111111111) * boostPower * 2

elseif self.angle > 180 and self.angle <= 270 then 

xDirection = ((180 - self.angle) * .111111111111111) * boostPower * 2

yDirection = ((self.angle - 270) * -.111111111111111) * boostPower * 2

elseif self.angle > 270 and self.angle <= 360 then 

xDirection = ((360 - self.angle) * -.111111111111111) * boostPower * 2

yDirection = ((270 - self.angle) * .111111111111111) * boostPower * 2

end

else 

–Obj.rotation = self.angle 

if Obj.rotation <= 90 then 

xDirection = (Obj.rotation * .111111111111111) * boostPower * 2

yDirection = ((90 - Obj.rotation) * -.111111111111111) * boostPower * 2

elseif Obj.rotation > 90 and Obj.rotation <= 180 then 

xDirection = ((180 - Obj.rotation) * .111111111111111) * boostPower * 2

yDirection = ((Obj.rotation - 90) * .111111111111111) * boostPower * 2

elseif Obj.rotation > 180 and Obj.rotation <= 270 then 

xDirection = ((180 - Obj.rotation) * .111111111111111) * boostPower * 2

yDirection = ((Obj.rotation - 270) * -.111111111111111) * boostPower * 2

elseif Obj.rotation > 270 and Obj.rotation <= 360 then 

xDirection = ((360 - Obj.rotation) * -.111111111111111) * boostPower * 2

yDirection = ((270 - Obj.rotation) * .111111111111111) * boostPower * 2

end

end 

end

–print(xDirection, yDirection)

–print("percent = "…self.percent)

if self.percent > 0 then

Obj:applyForce( xDirection–[[* self.percent–]], yDirection–[[* self.percent–]], Obj.x, Obj.y )

else 

Obj:applyForce( xDirection, yDirection, Obj.x, Obj.y )

end 

        end


        – METHOD: SLIDE AN OBJECT

        ---------------------------------------------

        function Group:slide(Obj, maxSpeed)

if(self.getMoving()) then

Obj.model.x = ( Obj.model.x + Cos( Rad(self.angle-90) ) * (-maxSpeed * self.percent) )

Obj.model.y = ( Obj.model.y + Sin( Rad(self.angle-90) ) * (-maxSpeed * self.percent) )

end

if (math.abs(Obj.knockbackX) >= 5) then

Obj.model.x = Obj.model.x + Obj.knockbackX

Obj.knockbackX = Obj.knockbackX * .75

end

if (math.abs(Obj.knockbackY) >= 5) then

Obj.model.y = Obj.model.y + Obj.knockbackY

Obj.knockbackY = Obj.knockbackY * .75

end

        end


– METHOD: ROTATE AN OBJECT


function Group:rotate(Obj, rotate)

if rotate == true then Obj.rotation = self.angle end

end

        

        ---------------------------------------------

        – GETTER METHODS

        ---------------------------------------------

        function Group:getDistance() return self.distance    end

        function Group:getPercent () return self.percent     end

        function Group:getAngle   () return Ceil(self.angle) end

function Group:getMoving  () return Group.beingMoved end

        ---------------------------------------------

        – HANDLER: ON DRAG

        ---------------------------------------------

        Group.onDrag = function ( event )

                local T     = event.target – THUMB

                local S     = T.parent     – STICK

                local phase = event.phase

                local ex,ey = S:contentToLocal(event.x, event.y)

                      ex = ex - T.x0

                      ey = ey - T.y0

                if “began” == phase then

Group.beingMoved = true 

                        if S.Timer ~= nil then timer.cancel(S.Timer); S.Timer = nil end

                        --display.getCurrentStage():setFocus( T )

display.getCurrentStage():setFocus( T, event.id )

                        T.isFocus = true

                        – STORE INITIAL POSITION

                        T.x0 = ex - T.x

                        T.y0 = ey - T.y

                elseif T.isFocus then

                        if “moved” == phase then

                                -----------

                                S.distance    = Sqr (ex*ex + ey*ey)

                                if S.distance > S.maxDist then S.distance = S.maxDist end

                                S.angle       = ( (Atan2( ex-0,ey-0 )*180 / Pi) - 180 ) * -1

                                S.percent     = S.distance / S.maxDist

                                -----------

                                T.x       = Cos( Rad(S.angle-90) ) * (S.maxDist * S.percent) 

                                T.y       = Sin( Rad(S.angle-90) ) * (S.maxDist * S.percent) 

                        

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

Group.beingMoved = false 

                                T.x0      = 0

                                T.y0      = 0

                                T.isFocus = false

                                --display.getCurrentStage():setFocus( nil )

display.getCurrentStage():setFocus( nil, event.id )

                                S.Timer = timer.performWithDelay( 33, S.onRelease, 0 )

                                S.Timer.MyStick = S

                        end

                end

                – STOP FURTHER PROPAGATION OF TOUCH EVENT!

                return true

        end

        ---------------------------------------------

        – HANDLER: ON DRAG RELEASE

        ---------------------------------------------

        Group.onRelease = function( event )

                local S = event.source.MyStick

                local T = S.Thumb

                local dist = S.distance > S.maxDist and S.maxDist or S.distance

                          dist = dist * S.snapBackSpeed

                T.x = Cos( Rad(S.angle-90) ) * dist 

                T.y = Sin( Rad(S.angle-90) ) * dist 

                local ex = T.x

                local ey = T.y

                -----------

                S.distance = Sqr (ex*ex + ey*ey)

                if S.distance > S.maxDist then S.distance = S.maxDist end

                S.angle    = ( (Atan2( ex-0,ey-0 )*180 / Pi) - 180 ) * -1

                S.percent  = S.distance / S.maxDist

                -----------

                if S.distance < .5 then

                        S.distance = 0

                        S.percent  = 0

                        T.x            = 0

                        T.y            = 0

                        timer.cancel(S.Timer); S.Timer = nil

                end

        end

        Group.Thumb:addEventListener( “touch”, Group.onDrag )

        return Group

end

[/lua]

I do apologize if the code I posted looks terrible.  I’ve had a heck of a time getting the formatting to translate.  I appreciate any help.  Thanks.

I’ll be able to take a look in a couple hours.

Great… I appreciate it.

Anyone able to help me out?

I have the same problem when I updated to 2016.2830.

I used to be able to hold the left joystick for directional control and tap the right joystick to fire at the same time.  Now I can only tap to shoot when I stop moving!

Greg

If it’s the problem above can you try an older build? I did this in a couple games in an older build and it did work. Can’t say exactly which build though. I can say it was before the new console was introduced. 

Yes the problem started for me with version .2830.

Greg, are you using “tap” or “touch”?

I have touch working just fine whide holding the stick, but tap isn’t working while holding the stick. It sounds like, for your particular issue, you can remedy your problem by using touch and have it fire at event.phase = “began”.

I use touch for movement - left stick

I use touch to fire in a chosen direction - right stick

I was using tap to fire directly ahead - right stick  before it stopped working

Alright, I was able to figure out a work around for my situation. I read that tap events look for the release at the same approximate point as the tap.  So I’m guessing that holding down the analog stick is throwing that all out of wack.  So I decided to create my own version of a tap event using “touch” instead. To make it work, I had to create an invisible duplicate button over the top of the original button and never “return true” on it.  This allows a touch event to pass through and still activate my original gas button.  After building and testing on my phone, it works perfectly.  You can effectively adjust the tap delay by changing the delay time in “timer.performWithDelay(300, resetTap)”.  With the little testing I’ve done so far, 300 milliseconds seems to be a good number.  I hope this helps you in your situation.  Here is the code I came up with:

[lua]

local tapped = 0

function gas2:touch( event )

     if gameIsActive == 1 then

          if event.phase == “began” then

               if numNitro > 0 then

                    tapped = tapped + 1

                    if tapped == 2 then 

                         if globals.boosted == 1 then

                              nitroBoostChannel = audio.play(nitroBoostSound, {channel=17})

                              --print(“Nitro Boost Activated”)

                              globals.boosted = 0

                              numNitro = numNitro - 1                                                       

                              nitroStatus.text = "Nitro:  "…numNitro 

                              backWheel:applyLinearImpulse( xDirection*3, yDirection*3, backWheel.x, backWheel.y ) 

                              frontWheel:applyLinearImpulse( xDirection*3, yDirection*3, frontWheel.x, frontWheel.y )

                              local function limitTap1()

                                   globals.boosted = 1

                                   --print(“Boosted Reset”)

                              end

                              timer.performWithDelay(1000, limitTap1)

                         end

                    end

                    local function resetTap()

                         tapped = 0 

                    end 

                    timer.performWithDelay(300, resetTap)

               end                                     

          end

     end 

end

gas2:addEventListener( “touch”, gas2 )

[/lua]