My code for analog joystick

I developed analog joystick for one of my games. You can use and modify code below.

You can create more than one joystick (don’t forget to switch on multitouch then).

Joystick is analog - hero speed is related to stick position (slightly left - slowly left, max left - maximum speed left etc). If you free stick, il will (smoothly) return to neutral position.

The effect is below:

Below is the main.lua code (just put it on empty main.lua file).

Don’t forget to copy config.lua and build.settings and to put graphics in project folder.

I used sprite, but it can be whatever you will use (circle… I mean circle shape space ship).

display.setStatusBar(display.HiddenStatusBar) local joy local myHero local function setAnchor( obj, anchor ) obj.anchorX, obj.anchorY = anchor, anchor end -- setAnchor local function drawHero() local heroImageSheet = graphics.newImageSheet( "werewolf3.png", { width=70, height=75, numFrames=4 } ) local heroSprite = display.newSprite( heroImageSheet, { name="MyHero", start=1, count=4, time=1000 } ) heroSprite.x = 250 heroSprite.y = 70 heroSprite.fPlaying = false return heroSprite end -- end drawHero local function dragJoy( event ) local joy = event.target local phase = event.phase local stage = display.getCurrentStage() if ( phase == "began") then joy.fBusy = true stage:setFocus( joy, event.id ) joy.isFocus = true elseif ( phase == "moved" ) then local x = event.x local y = event.y local leftBorder = joy.centerX - joy.radius local rightBorder = joy.centerX + joy.radius local upperBorder = joy.centerY - joy.radius local lowerBorder = joy.centerY + joy.radius if ( x \< leftBorder ) then x = leftBorder end if ( x \> rightBorder ) then x = rightBorder end if ( y \< upperBorder ) then y = upperBorder end if ( y \> lowerBorder ) then y = lowerBorder end joy.x = x joy.y = y elseif( ( phase == "ended" ) or ( phase == "cancelled" ) ) then stage:setFocus(joy, nil) joy.isFocus = false joy.fBusy = false end -- if phase return true end -- end dragJoy local function drawJoystick( x, y ) local border = display.newRoundedRect( x, y, 100, 100, 15) border.alpha = 0.3 border:setFillColor(1,0,0) setAnchor( border, 0.5 ) local center = display.newCircle( x, y, 5 ) center:setFillColor(0.8,0,0) center.alpha = 0.5 setAnchor( center, 0.5 ) local joy = display.newCircle( x, y, 20 ) joy.alpha=0.5 joy:setFillColor(0.7,0,0) setAnchor( joy, 0.5 ) joy.centerX = x joy.centerY = y joy.radius = 30 joy:addEventListener( "touch", dragJoy ) return joy end -- drawJoystick local function drawWalls() local wall = display.newRect( 0, 0, 480, 10) setAnchor( wall,0 ) wall:setFillColor( 0.4, 0, 0 ) wall = display.newRect( 0,10, 10, 170 ) wall:setFillColor( 0.4, 0, 0 ) setAnchor( wall, 0 ) wall = display.newRect( 0, 180, 480, 10 ) wall:setFillColor( 0.4, 0, 0 ) setAnchor( wall, 0 ) wall = display.newRect( 470, 10, 10, 170 ) setAnchor( wall, 0 ) wall:setFillColor( 0.4, 0,0 ) end -- drawWalls local function updateHeroPosition() local dx = ( joy.x - joy.centerX ) \* 0.2 local x = myHero.x + dx if x \< 36 then x = 36 end -- wall coordinates if x \> 444 then x = 444 end -- wall coordinates myHero.x = x local dy = ( joy.y - joy.centerY ) \* 0.2 -- analog joy powers :-) local y = myHero.y + dy if y \< 40 then y = 40 end -- wall coordinates if y \> 154 then y = 154 end -- wall coordinates myHero.y = y if dx \< 0 then myHero.xScale = -1 end if dx \> 0 then myHero.xScale = 1 end if ( ( dx == 0 ) and ( dy == 0 ) ) then if ( myHero.fPlaying ) then myHero:pause() myHero.fPlaying = false end -- if\_playing else if ( not myHero.fPlaying) then myHero:play() myHero.fPlaying = true end -- if\_not\_fPlaying end -- because I am not sure if\_play() on playing sprite decreases efficiency end -- updateHeroPosition local function updateJoystickPosition() -- joystick auto return, if not used if ( not joy.fBusy ) then local dx = math.round( ( joy.x - joy.centerX ) / 3 ) -- smooth return local x = joy.centerX + dx joy.x = x local dy = math.round( ( joy.y - joy.centerY ) / 3 ) local y = joy.centerY + dy joy.y = y end -- if\_not\_fBusy end -- updateJoystickPosition local function updateFrame() updateHeroPosition() updateJoystickPosition() end drawWalls() myHero = drawHero() joy = drawJoystick( 350, 250 ) Runtime:addEventListener( "enterFrame", updateFrame ) 

Put graphic file werewolf3.png in project folder.

config.lua

application = { content = { width = 320, height = 480, scale = "letterBox", fps = 30 } }

and build.settings

settings = { orientation = { default = "landscapeRight", supported = { "landscapeRight" } } }

Enjoy the code and share your comments,

:slight_smile:

Gudicus

Hi Gudicus,

Thanks for sharing your controller code. I have actually started using it in one of my prototypes. Just had a quick question though.

What settings would I amend if I wanted the object to move faster in response to the joystick?

Also how would I “tighten it up”. For example what settings would I change so that the object moves faster with a smaller amount of joystick movement? Sorry if I am not explaining properly.

Thanks for your help.

I can answer your first question, about moving the object faster.

In updateHeroPosition() change the multiplier at the end of the dx/dy calculations:

local dx = ( joy.x - joy.centerX ) \* 0.2 --change 0.2 to something higher if you want to move faster local dy = ( joy.y - joy.centerY ) \* 0.2 --change 0.2 to something higher if you want to move faster

Personally, I would create a new single variable called “playerSpeed” or something, and use that:

local playerSpeed = 0.4 local function updateHeroPosition() local dx = ( joy.x - joy.centerX ) \* playerSpeed local dy = ( joy.y - joy.centerY ) \* playerSpeed --etc end

Hi, 

I’m glad that my code was useful.

Player speed is determined by dx and dy, which are result of multiplication of joy distance from joy center and factor equal to 0.2.

As Alan wrote, you can change this factor (for example, to 0.4) to change hero maximum speed.

In this case hero will move faster with small joy movement, but still hero speed will be in linear relation with joy movement.

If you want to have faster speed growth with small move of joy and then slower on further move, you have to change formula of calculating dx and dy. Functions like atan (arcus tangent) seems to fit perfectly.

For example, changing

local dx = ( joy.x - joy.centerX ) \* 0.2&nbsp;

with

local dx = math.atan( (joy.x - joy.centerX) / 5 ) \* 4.3

will give you such effect - fast speed growth at the beginning of joystick movement, later speed will still grow, but slower. :slight_smile:

Enjoy,

Gudicus

Hi Gudicus,

Thanks for sharing your controller code. I have actually started using it in one of my prototypes. Just had a quick question though.

What settings would I amend if I wanted the object to move faster in response to the joystick?

Also how would I “tighten it up”. For example what settings would I change so that the object moves faster with a smaller amount of joystick movement? Sorry if I am not explaining properly.

Thanks for your help.

I can answer your first question, about moving the object faster.

In updateHeroPosition() change the multiplier at the end of the dx/dy calculations:

local dx = ( joy.x - joy.centerX ) \* 0.2 --change 0.2 to something higher if you want to move faster local dy = ( joy.y - joy.centerY ) \* 0.2 --change 0.2 to something higher if you want to move faster

Personally, I would create a new single variable called “playerSpeed” or something, and use that:

local playerSpeed = 0.4 local function updateHeroPosition() local dx = ( joy.x - joy.centerX ) \* playerSpeed local dy = ( joy.y - joy.centerY ) \* playerSpeed --etc end

Hi, 

I’m glad that my code was useful.

Player speed is determined by dx and dy, which are result of multiplication of joy distance from joy center and factor equal to 0.2.

As Alan wrote, you can change this factor (for example, to 0.4) to change hero maximum speed.

In this case hero will move faster with small joy movement, but still hero speed will be in linear relation with joy movement.

If you want to have faster speed growth with small move of joy and then slower on further move, you have to change formula of calculating dx and dy. Functions like atan (arcus tangent) seems to fit perfectly.

For example, changing

local dx = ( joy.x - joy.centerX ) \* 0.2&nbsp;

with

local dx = math.atan( (joy.x - joy.centerX) / 5 ) \* 4.3

will give you such effect - fast speed growth at the beginning of joystick movement, later speed will still grow, but slower. :slight_smile:

Enjoy,

Gudicus

hi Gudicus,

thanks for sharing. I imagine that it works also with the physics with

local dx = ( joy.x - joy.centerX ) \* 0.2 --0.2 must be adapted to the need with the physics&nbsp; local dy=...... character:applyLinearImpulse(dx,dy,character.x,character.y)

have you a advice to this ?

Hey guys! So i just went through the code and really cleaned it up and made it a simple as possible. Just the bare bones.

local actualHD2 = display.actualContentHeight/2 local actualWD2 = display.actualContentWidth/2 local centerX = display.contentCenterX local centerY = display.contentCenterY local checkJoyUse = false local Player = display.newCircle( centerX, centerY, 20 ) Player:setFillColor( 1, 0, 0 ) Player.stroke = { 0, 0, 0.5 } Player.strokeWidth = 4 local border = display.newRoundedRect( centerX - actualWD2 + 70, centerY + actualHD2 - 70, 100, 100, 15) border.alpha = 0.3 border:setFillColor (0.5, 0.5, 0.5 ) local center = display.newCircle( border.x, border.y, 5 ) center:setFillColor(0,0,0) center.alpha = 0.5 local joy = display.newCircle( border.x, border.y, 20 ) joy.alpha=0.5 joy:setFillColor( 0, 0, 0.5 ) local function dragJoystick(event) local joyStickMove = event.target local stage = display.getCurrentStage() if ( event.phase == "began") then checkJoyUse = true stage:setFocus( joyStickMove, event.id ) joyStickMove.isFocus = true elseif event.phase == "moved" then local xMove = event.x local yMove = event.y local leftBorder = border.x - 30 local rightBorder = border.x + 30 local upperBorder = border.y - 30 local lowerBorder = border.y + 30 if ( xMove \< leftBorder ) then xMove = leftBorder end if ( xMove \> rightBorder ) then xMove = rightBorder end if ( yMove \< upperBorder ) then yMove = upperBorder end if ( yMove \> lowerBorder ) then yMove = lowerBorder end joyStickMove.x = xMove joyStickMove.y = yMove elseif event.phase == "ended" or event.phase == "cancelled" then stage:setFocus(joyStickMove, nil) joyStickMove.isFocus = false checkJoyUse = false end return true end joy:addEventListener( "touch", dragJoystick ) local function updatePlayerPos() local speed = 0.3 local getX = ( joy.x - border.x ) \* speed local x = Player.x + getX local getY = ( joy.y - border.y ) \* speed local y = Player.y + getY Player.x = x Player.y = y end local function updateJoystickPos() if checkJoyUse == false then local getX = math.round( ( joy.x - border.x ) / 3 ) local x = border.x + getX local getY = math.round( ( joy.y - border.y ) / 3 ) local y = border.y + getY joy.x = x joy.y = y end end local function updateFrame() updatePlayerPos() updateJoystickPos() end Runtime:addEventListener( "enterFrame", updateFrame )

Thanks @Gudicus for this awesome code!

NOTE – I put this together in a landscape simulator. –

Nice work @SonicX278. I’m happy that my code was usefull and now, after your improvements, even more,

Enjoy,

Gudicus

Thank you for sharing the code Gudicus and also thank you SonicX278 for your work on the code. That really came in handy :slight_smile:

hi Gudicus,

thanks for sharing. I imagine that it works also with the physics with

local dx = ( joy.x - joy.centerX ) \* 0.2 --0.2 must be adapted to the need with the physics&nbsp; local dy=...... character:applyLinearImpulse(dx,dy,character.x,character.y)

have you a advice to this ?

Hey guys! So i just went through the code and really cleaned it up and made it a simple as possible. Just the bare bones.

local actualHD2 = display.actualContentHeight/2 local actualWD2 = display.actualContentWidth/2 local centerX = display.contentCenterX local centerY = display.contentCenterY local checkJoyUse = false local Player = display.newCircle( centerX, centerY, 20 ) Player:setFillColor( 1, 0, 0 ) Player.stroke = { 0, 0, 0.5 } Player.strokeWidth = 4 local border = display.newRoundedRect( centerX - actualWD2 + 70, centerY + actualHD2 - 70, 100, 100, 15) border.alpha = 0.3 border:setFillColor (0.5, 0.5, 0.5 ) local center = display.newCircle( border.x, border.y, 5 ) center:setFillColor(0,0,0) center.alpha = 0.5 local joy = display.newCircle( border.x, border.y, 20 ) joy.alpha=0.5 joy:setFillColor( 0, 0, 0.5 ) local function dragJoystick(event) local joyStickMove = event.target local stage = display.getCurrentStage() if ( event.phase == "began") then checkJoyUse = true stage:setFocus( joyStickMove, event.id ) joyStickMove.isFocus = true elseif event.phase == "moved" then local xMove = event.x local yMove = event.y local leftBorder = border.x - 30 local rightBorder = border.x + 30 local upperBorder = border.y - 30 local lowerBorder = border.y + 30 if ( xMove \< leftBorder ) then xMove = leftBorder end if ( xMove \> rightBorder ) then xMove = rightBorder end if ( yMove \< upperBorder ) then yMove = upperBorder end if ( yMove \> lowerBorder ) then yMove = lowerBorder end joyStickMove.x = xMove joyStickMove.y = yMove elseif event.phase == "ended" or event.phase == "cancelled" then stage:setFocus(joyStickMove, nil) joyStickMove.isFocus = false checkJoyUse = false end return true end joy:addEventListener( "touch", dragJoystick ) local function updatePlayerPos() local speed = 0.3 local getX = ( joy.x - border.x ) \* speed local x = Player.x + getX local getY = ( joy.y - border.y ) \* speed local y = Player.y + getY Player.x = x Player.y = y end local function updateJoystickPos() if checkJoyUse == false then local getX = math.round( ( joy.x - border.x ) / 3 ) local x = border.x + getX local getY = math.round( ( joy.y - border.y ) / 3 ) local y = border.y + getY joy.x = x joy.y = y end end local function updateFrame() updatePlayerPos() updateJoystickPos() end Runtime:addEventListener( "enterFrame", updateFrame )

Thanks @Gudicus for this awesome code!

NOTE – I put this together in a landscape simulator. –

Nice work @SonicX278. I’m happy that my code was usefull and now, after your improvements, even more,

Enjoy,

Gudicus

Thank you for sharing the code Gudicus and also thank you SonicX278 for your work on the code. That really came in handy :slight_smile: