Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Joysticks! My first project ever.

edited February 2014 in Code Sharing Posts: 342

This here is a joystick class which, while horribly inefficient (cut me some slack, it's my first project ever!), is rather easy to use and implement into other projects. I am aware it is sloppy but with some tinkering most parts of it can be easily changed:

Joystiqs = class()

touch = nil
originx = nil
originy = nil
originid = nil
touch2 = nil
originx2 = nil
originy2 = nil
originid2 = nil

function Joystiqs:init()
end

function Joystiqs:draw()
    background(0, 0, 0, 255)
    stroke(127, 127, 127, 25)
    strokeWidth(0)
    lineCapMode(SQUARE)
    self:j1Calc()
    self:j2Calc()
    self:cleanJoystickData()
end

function Joystiqs:touched(touched)
    if touched.x < WIDTH/2 and touch == nil and touched.state == BEGAN then
        touch = touched
        originid = touched.id
        originx = touched.x
        originy = touched.y  
    elseif touch ~= nil and  touched.id == originid then
        touch = touched 
    end

    if (touched.state == ENDED) and (touched.id == originid) then
        touch = nil
        originx = nil
        originy = nil
        originid= nil
    end

    if touched.x > WIDTH/2 and touch2 == nil and touched.state == BEGAN then
        touch2 = touched
        originid2 = touched.id
        originx2 = touched.x
        originy2 = touched.y  
    elseif touch2 ~= nil and  touched.id == originid2 then
        touch2 = touched 
    end

    if (touched.state == ENDED) and (touched.id == originid2) then
        touch2 = nil
        originx2 = nil
        originy2 = nil
        originid2 = nil
    end

end

function Joystiqs:j1Calc()

    if (touch ~= nil) then
        offsetx = touch.x - originx
        offsety = touch.y - originy
        preangle = (math.atan((offsety)/(offsetx)))
            if offsetx == 0 and offsety > 0 then
                angle = math.pi/2
            else
                if offsetx <= 0 and offsety > 0 then
                    angle = math.pi + preangle
                elseif offsetx < 0 and offsety <= 0 then
                    angle = math.pi + preangle
                elseif offsetx >=0 and offsety < 0 then
                    angle = (2*math.pi) + preangle
                else
                    angle = preangle
                end
            end
            if math.sqrt((offsetx*offsetx)+(offsety*offsety)) > 75 then
                linelimiterx = (75*math.cos(angle)) + originx
                linelimitery = (75*math.sin(angle)) + originy
            else
                linelimiterx = touch.x 
                linelimitery = touch.y
            end
        magnitude = math.sqrt(((linelimiterx-originx)^2)+((linelimitery-originy)^2))
        fill(255, 255, 255, 100)
        ellipse(originx, originy, 150)
        line(originx, originy, linelimiterx, linelimitery)
        fill(0, 0, 0, 100)
        ellipse(linelimiterx, linelimitery, 150)
        if magnitude < 25 and magnitude >10 then
            magnitude = 0
        elseif magnitude <= 10 then
            magnitude = 0
            angle = nil
        else
            magnitude = magnitude - 25
        end
    end

end

function Joystiqs:j2Calc()

    if (touch2 ~= nil) then
        offsetx2 = touch2.x - originx2
        offsety2 = touch2.y - originy2
        preangle2 = (math.atan((offsety2)/(offsetx2)))
            if offsetx2 == 0 and offsety2 > 0 then
                angle2 = math.pi/2
            else
                if offsetx2 <= 0 and offsety2 > 0 then
                    angle2 = math.pi + preangle2
                elseif offsetx2 < 0 and offsety2 <= 0 then
                    angle2 = math.pi + preangle2
                elseif offsetx2 >=0 and offsety2 < 0 then
                    angle2 = (2*math.pi) + preangle2
                else
                    angle2 = preangle2
                end
            end
            if math.sqrt((offsetx2*offsetx2)+(offsety2*offsety2)) > 75 then
                linelimiterx2 = (75*math.cos(angle2)) + originx2
                linelimitery2 = (75*math.sin(angle2)) + originy2
            else
                linelimiterx2 = touch2.x 
                linelimitery2 = touch2.y
            end
        magnitude2 = math.sqrt(((linelimiterx2-originx2)^2)+((linelimitery2-originy2)^2))
        fill(255, 255, 255, 100)
        ellipse(originx2, originy2, 150)
        line(originx2, originy2, linelimiterx2, linelimitery2)
        fill(0, 0, 0, 100)
        ellipse(linelimiterx2, linelimitery2, 150)
        if magnitude2 < 25 and magnitude2 > 10 then
            magnitude2 = 0
        elseif magnitude2 < 10
            magnitude2 = 0
            angle2 = nil
        else
            magnitude2 = magnitude2 - 25
        end
    end

end

function Joystiqs:cleanJoystickData()
    offsetx=nil
    offsety=nil
    offsetx2=nil
    offsety2=nil
    preangle=nil
    preangle2=nil
    angle=nil
    angle2=nil
    linelimiterx=nil
    linelimitery=nil
    linelimiterx2=nil
    linelimitery2=nil
    magnitude=nil
    magnitude2=nil  
end
Tagged:

Comments

  • IgnatzIgnatz Mod
    Posts: 5,396

    @Monkeyman32123 - nice work!

    You might want to make all the variables you declare at the beginning, local (especially "touch", which is commonly used in Codea). If you make them local, then they only exist in the current code tab, so if you put this class in its own tab, then they won't affect any code in other tabs. You should also make the other variables you use, like offsetx, local, as well, so they don't mess up a user's other code.

    It helps to give a little example, or maybe a video, if you want to show how it gets used. That may encourage more people to try it out.

    You will probably find several other examples in the forum if you search, which is useful.

    Below is one that Andrew_Stacey wrote recently. It returns an x and y value between -1 and +1. The interesting part is the update function, which smooths the movement of the joystick by interpolation. It needs to be run in the draw function to update it.

    JoyStick = class()
    
    function JoyStick:init(t)
        t = t or {}
        self.radius = t.radius or 100
        self.stick = t.stick or 30
        self.centre = t.centre or self.radius * vec2(1,1) + vec2(5,5)
        self.position = vec2(0,0)
        self.target = vec2(0,0)
        self.value = vec2(0,0)
        self.delta = vec2(0,0)
        self.mspeed = 60
        self.moving = 0
    end
    
    function JoyStick:draw()
        -- Codea does not automatically call this method
        pushStyle()
        fill(160, 182, 191, 50)
        stroke(118, 154, 195, 100)
        strokeWidth(1)
        ellipse(self.centre.x,self.centre.y,2*self.radius)
        fill(78, 131, 153, 50)
        ellipse(self.centre.x+self.position.x, self.centre.y+self.position.y, self.stick*2)
        popStyle()
    end
    
    function JoyStick:touched(t)
        if t.state == BEGAN then
            local v = vec2(t.x,t.y)
            if v:dist(self.centre)<self.radius-self.stick then
                self.mytouch = t.id
            end
        end
        if t.id == self.mytouch then
            if t.state~=ENDED then
                local v = vec2(t.x,t.y)
                if v:dist(self.centre)>self.radius-self.stick then
                    v = (v - self.centre):normalize()*(self.radius - self.stick) + self.centre
                end --set x,y values for joy based on touch
                self.target=v - self.centre
            else --reset joystick to centre when touch ends
                self.target=vec2(0,0)
                self.mytouch = false
            end
        end
    end
    
    function JoyStick:update()
        local p = self.target - self.position
        if p:len() < DeltaTime * self.mspeed then
            self.position = self.target
            if not self.mytouch then
                if self.moving ~= 0 then
                    self.moving = self.moving - 1
                end
            else
                self.moving = 2
            end
        else
            self.position = self.position + p:normalize() * DeltaTime * self.mspeed
            self.moving = 2
        end
        local v = self.position/(self.radius - self.stick)
        self.delta = v - self.value
        self.value = v
    end
    
    function JoyStick:isMoving()
        return self.moving
    end
    
  • Thanks for the tips! I'm pretty new to the whole coding scene, and since I'm teaching myself I didn't really know what local was used for (heck, I don't know what a lot of things are used for). But I will keep that in mind from now on ^-^

  • IgnatzIgnatz Mod
    Posts: 5,396

    @Monkeyman32123 - try some tutorials, see the wiki link above.

    I also have heaps of stuff here

    http://coolcodea.wordpress.com/2013/06/19/index-of-posts/

Sign In or Register to comment.