Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat
Virtual onscreen controls/gamepad - does anybody want to share theirs? - Gideros Forum

Virtual onscreen controls/gamepad - does anybody want to share theirs?

snookssnooks Member
edited November 2017 in General questions
I am wondering before I start, whether anybody has a nice onscreen controls class in order to minimise wheel-reinvention? :)

Likes: Apollo14

+1 -1 (+1 / -0 ) Share on Facebook

Comments

  • totebototebo Member
    edited November 2017
    In my case I have made five games on mobile, and have five different implementations. I treat it as UI, and how it looks and works depends on the game. I suppose a gamepad could be more generic, I have one of those in Fast Food Rampage. But it's quite specific to that game in that you can fire burgers OR milkshakes on the right hand side. So not very generic either. :(

    Sorry, that's not very helpful! :D

    Likes: antix

    My Gideros games: www.totebo.com
    +1 -1 (+1 / -0 ) Share on Facebook
  • @snooks, what kind of control are you looking for? There are many kinds and not all could be rolled into one class without making that some ugly spaghetti code :bz
  • Virtual Joypad should be included in the Gideros Source code, we have permission to include it. Perhaps it can be one of the first Lua Plugins @hgy29 ?

    Likes: Apollo14

    +1 -1 (+1 / -0 ) Share on Facebook
  • @antix - that should be in the Gideros distribution now. Hopefully a Lua 'plugin' soon.

    Likes: Apollo14, antix

    +1 -1 (+2 / -0 ) Share on Facebook
  • Very good points re them all being different, I was just looking for a fast fix to test with. Good idea including one with Gideros.

    I like the joysticks that appear when you touch the screen, so I've just made one of those....

    https://gist.github.com/paul-reilly/8773861833b498a5cc6b3084f97d5e38

    Likes: Apollo14

    +1 -1 (+1 / -0 ) Share on Facebook
  • antixantix Member
    edited November 2017
    @snooks, that's pretty cool man. I messed about with it a bit...
    - You set the default options in init and just copy over any specified user options (if any).
    - Limits knob so it never goes past radius of main pad (looks nicer?).
    - Can pass in code that gets run on pressed, dragged, and released.
    - Doesn't add and remove listeners constantly, instead has an "enabled" bool.
    - Can now specify if the joypad should be on left or right side of screen.
    - Can supply colors for joypad.
    -- VirtualRelativeJoystick for Gideros
    --
    -- Onscreen joystick that only appears when lower left quadrant
    -- of screen is touched
    --
     
    VirtualRelativeJoystick = Core.class(Sprite)
     
    function VirtualRelativeJoystick:init(options)
      -- default options
      self.x = 100
      self.y = 100
      self.outerRadius = 100
      self.padColor = 0xaaaadd
      self.knobColor = 0xaaddaa
      self.onPressed = nil
      self.onDragged = nil
      self.onReleased = nil
     
      self.left = false
     
      self.xpos = 0
      self.ypos = 0
      self.strength = 0
      self.angle = 0
     
      self.enabled = false
     
      -- set user supplied options
      if options then
        for key, value in pairs(options) do
          self[key]= value
        end
      end
     
      self.outerCircle = self:getNewCircle(self.outerRadius, self.padColor, false)
      self:addChild(self.outerCircle)
     
      self.innerNubbin = self:getNewCircle(self.outerRadius * .5, self.knobColor, true)
      self:addChild(self.innerNubbin)
     
      self:setPosition(self.x, self.y)
      self:setVisible(false)
     
      self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
      self:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
      self:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
    end
     
    --
    function VirtualRelativeJoystick:onTouchesCancel(e)
      self:onTouchesEnd(e)
    end
     
    --
    function VirtualRelativeJoystick:onTouchesBegin(e)
      local tx, ty = e.touch.x, e.touch.y
      local mx, my = application:getContentWidth() * 0.5, application:getContentHeight() * 0.5
     
      if self.left then
        if tx > mx or ty < my then return end
      else
        if tx < mx or ty < my then return end
      end
     
      self.controlTouchId = e.touch.id
      self:setPosition(tx, ty)
      self:setVisible(true)
      self.enabled = true -- enable control
     
      if self.onPressed then
        self.onPressed()
      end -- run code
     
      e:stopPropagation()
    end
     
    --
    function VirtualRelativeJoystick:onTouchesMove(e)
      local cos, sin, sqrt, atan2 = math.cos, math.sin, math.sqrt, math.atan2
      if not self.enabled then return end
      if e.touch.id == self.controlTouchId then
        local x, y = self:globalToLocal(e.touch.x, e.touch.y)
        local radius = self.outerRadius
        local distance = sqrt(x * x + y * y) >< radius -- limit distance to outer radius
        -- normalized strength for use with angle
        local strength = (distance >< radius) / radius
        local angle = ^>atan2(y, x) + 90
     
        local ra = ^< self.angle
        y = -distance * cos(ra)
        x = distance * sin(ra)
        self.innerNubbin:setPosition(x, y)
     
        self.xpos, self.ypos = x / radius, -y / radius
     
        if self.onPressed then
          self.onDragged(angle, distance, strength) -- run code
        end
     
    	self.angle, self.distance, self.strength = angle, distance, strength
     
        e:stopPropagation()
      end
    end
     
    --
    function VirtualRelativeJoystick:onTouchesEnd(e)
      if not self.enabled then return end
      if e.touch.id == self.controlTouchId then
        self.innerNubbin:setPosition(0, 0)
        self.xpos, self.ypos = 0, 0
        self:setVisible(false)
     
        self.enabled = false
        if self.onReleased then
          self.onReleased() -- run code
        end
     
        e:stopPropagation()
      end
      self.controlTouchId = nil
    end
     
    --
    function VirtualRelativeJoystick:getNewCircle(r, color, fill)
      local p = Path2D.new()
      p:setSvgPath(("M %s 0 a %s %s 0 0 0 %s 0 a %s %s 0 0 0 %s 0 Z"):format(-r, r, r, 2 * r, r, r, -2 * r))
      p:setLineThickness(10) -- Outline width
      p:setFillColor(color, fill and .6 or .0) --Fill color
      p:setLineColor(color, .6) --Line color
      return p
    end

    Likes: snooks

    +1 -1 (+1 / -0 ) Share on Facebook
  • Nice, thanks for enhancing it! I did have it limited at the radius, but it only works when using angle/strength and I'm using xpos/ypos for my game. But limiting to radius for angle/strength is perfect.

    Likes: antix

    +1 -1 (+1 / -0 ) Share on Facebook
Sign In or Register to comment.