checking touched area using physics.body

Hi,

im new to this forum, and have played with Codea for only a few days now. Im trying to make a simple touch-controller class to decide the direction of movement in a game.

My approach is to divied the whole screen into four triangles. when the touch position is within the upper triangle, i set a variable “up” to true, similar for left, right and down…

To determine which triangle has been touched i decided to go with the physics api because of the nice collision checks.

However, the check works only when the game is freshly started. After a few seconds the collision checks start failing. Im already printing the triangles to check if they somehow move automagically, but everything seems ok.

It would be nice if someone can give any hint, thanks in advance.

here’s the code of the controller class:

Controller = class()

function Controller:init()
    
    self.ptTopLeft = vec2(0, HEIGHT)
    self.ptTopRight = vec2(WIDTH, HEIGHT)
    self.ptBtLeft = vec2(0,0)
    self.ptBtRight = vec2(WIDTH, 0)
    self.ptCenter = vec2(WIDTH/2, HEIGHT/2)
    
    self.areaTop = physics.body(POLYGON, unpack({self.ptTopLeft, self.ptTopRight, self.ptCenter}))
    self.areaBottom = physics.body(POLYGON, unpack({self.ptBtLeft, self.ptBtRight, self.ptCenter}))
    self.areaLeft = physics.body(POLYGON, unpack({self.ptBtLeft, self.ptTopLeft, self.ptCenter}))
    self.areaRight = physics.body(POLYGON, unpack({self.ptBtRight, self.ptTopRight, self.ptCenter}))
    
    self.left = false
    self.right = false
    self.up = false
    self.down = false
    
    --local poly = physics.body(POLYGON, unpack(points))
    
end

function Controller:touched(touch)
    local touchVec
    touchVec = vec2(touch.x, touch.y)
    print(touch.state)
    if(touch.state == ENDED) then 
        self.up = false
        self.down = false
        self.left = false
        self.right = false
    elseif (self.areaTop:testPoint(touchVec) == true) then
        self.up = true
    elseif (self.areaBottom:testPoint(touchVec) == true) then
        self.down = true
    elseif (self.areaLeft:testPoint(touchVec) == true) then
        self.left = true
    elseif (self.areaRight:testPoint(touchVec) == true) then
        self.right = true
    end
end 

function Controller:draw()
    drawBody(self.areaRight)
    drawBody(self.areaLeft)
end

function drawBody(body)
    pushStyle()
    stroke(255, 0, 0, 255)
    strokeWidth(7)
    local points = body.points
        for j = 1,#points do
            a = points[j]
            b = points[(j % #points)+1]
            line(a.x, a.y, b.x, b.y)
        end
    popStyle()
end

after testing more and more, its getting obvious that my areas are moving down. Why is that, and why does’nt my drawBody function show that? i copied it from the debugDraw function in the physics example…

any help is still welcome

nevermind … setting zero gravity in my setup () fixed it.

physics.gravity(vec2(0,0))

But it would still be nice to know whats wrong with my drawBody function…

When you draw a body you need to transform your coordinates by the body’s position and rotation. There’s an example in the Physics Lab example (PhysicsDebugDraw class), which will draw a list of bodies.

pushMatrix()
translate(body.x, body.y)
rotate(body.angle)
--draw code
popMatrix()

Also if you want them not to move you can do this just after you create a body:

self.areaTop.type = STATIC

This will make the body unmovable and not influenced by gravity / forces.

Hope that helps.

thanks very much John. Using STATIC type is much better, so the areas aren’t affected by physics at all, and my Controller class does not depend on any surrounding configurations.

And… just for the case that anyone cares, here’s the final code:

Controller = class()

function Controller:init()
    local ptTopLeft = vec2(0, HEIGHT)
    local ptTopRight = vec2(WIDTH, HEIGHT)
    local ptBtLeft = vec2(0,0)
    local ptBtRight = vec2(WIDTH, 0)
    local ptCenter = vec2(WIDTH/2, HEIGHT/2)
    
    self.areaTop = physics.body(POLYGON, unpack({ptTopLeft, ptTopRight, ptCenter}))
    self.areaBottom = physics.body(POLYGON, unpack({ptBtLeft, ptBtRight, ptCenter}))
    self.areaLeft = physics.body(POLYGON, unpack({ptBtLeft, ptTopLeft, ptCenter}))
    self.areaRight = physics.body(POLYGON, unpack({ptBtRight, ptTopRight, ptCenter}))
    
    self.areaTop.type = STATIC
    self.areaBottom.type = STATIC
    self.areaLeft.type = STATIC
    self.areaRight.type = STATIC
    
    self.left = false
    self.right = false
    self.up = false
    self.down = false
    
    currentTouches = {}
end

function Controller:touched(touch)
    if touch.state == ENDED then
        currentTouches[touch.id] = nil
    else
        currentTouches[touch.id] = touch
    end
    
    self:clear()
    for id, currentTouch in pairs(currentTouches) do 
        local touchVec = vec2(currentTouch.x, currentTouch.y)
        if (self.areaTop:testPoint(touchVec) == true) then
            self.up = true
        end 
        if (self.areaBottom:testPoint(touchVec) == true) then
            self.down = true
        end 
        if (self.areaLeft:testPoint(touchVec) == true) then
            self.left = true
        end 
        if (self.areaRight:testPoint(touchVec) == true) then
            self.right = true
        end
    end
end 

function Controller:clear()
    self.up = false
    self.down = false
    self.left = false
    self.right = false
end