Gaps Between Touch Events Are Causing Problems

I’m having a problem using touch events to collect squares in a grid. The idea is the player drags their finger over squares in a grid, each square has a touch listener attached to it (table listener). On every “moved” phase the code will check the square it is over and highlight it if it’s not.

This works fine for most of the time. Although we encountered some problems early on where the player would drag their finger fast in one direction and the code would miss a square or two. We found out that the touch event “moved” wasn’t updating fast enough to “land” on those squares.

So we came up with a function that would calculate the direction the drag is going, knowing the direction the code will back check the square in the opposite direction and make sure it’s highlighted, then repeat as necessary. This fixed our issue dramatically. Untill we started experiencing the problem when the player would drag around corners. But with simply tweaking the back checking code we managed to fix that aswell, at least we thought we did.

The problem now stems down to that the ‘back checking’ function is only operable if it knows which direction the player is dragging in. We attached an example image to illustrate this issue.

As the player starts his drag downwards each square is being highlighted via the touch “moved” phase (blue dots), also the angle between each phase is being calculated in reference to the x-axis to determine the direction( [lua] if angle > 45 and angle <= 135 then direction = “down” end[/lua] ). So the ‘back check’ function will trigger every time a square is highlighted, then using the direction will check the previous square (in this case the square above). Now if the players finger went along the path that covers ‘B’ along the dotted yellow line, and the drag was fast, the touch event may not register until they reach the ‘end’ square. So in this case the angle between the current “moved” phase and the last “moved” phase would create a roughly 130Deg angle, which the code will mark as “down”, causing the ‘back check’ code to check the square above, which would be ‘A’ not ‘B’, causing ‘B’ to remain unhighlighted.

I may add, we attempted to cancel touches when the angle was close to a 45 degree, although this caused issues elsewhere in the game where 50% of other legit drags create a 45 degree angle. Also, we don’t want diagonal drag collecting in the game, only the squares immediately next to each other.

So at this point we are wondering if there’s any other ways to go about collecting squares in a grid, other than using a touch listener. Or perhaps we are just implementing this all wrong.

Any help will be greatly appreciated!

P.S. Here’s some code

And we are running this game at 60 FPS.

[lua]

local function getDirection( angle )
    if angle > 45 and angle <= 135 then
        var.direction = “down”
    elseif angle > 135 and angle <= 225 then
        var.direction = “left”
    elseif angle > 225 and angle < 315 then
        var.direction = “up”
    elseif angle >= 315 and angle <= 360 or angle >= 0 and angle <= 45 then
        var.direction = “right”
    end
end

local function cornerFix(check, gridPlace, checkBorder, squareID)

    if squares[check].alpha >= 0.9 and checkBorder <= 8 and checkBorder >= 1 and squares[check].id == squareID then
        squares[check].alpha = 0.6
        
        if var.direction == “up” then
            cornerFix(check, gridPlace, var.checkP, squares[check+1].id)
        elseif var.direction == “down” then
            cornerFix(check, gridPlace, var.checkP, squares[check+1].id)
        elseif var.direction == “left” then
            cornerFix(check, gridPlace, var.checkP, squares[check-7].id)
        elseif var.direction == “right” then
            cornerFix(check, gridPlace, var.checkP, squares[check+7].id)
        end
        
    end
end

local function fixSelect(place, gridPlace)
    if var.direction == “up” then --up
        local check = place+7
            if check >= 1 and check <= 49 then
                if squares[check].gridPlace[1] <= gridPlace[1] and gridPlace[1] ~= 0 then
                    
                    var.checkI = squares[check].gridPlace[1]
                    var.checkI = var.checkI + 1
                    
                    if squares[check].alpha >= 0.9 and var.checkI <= 8 and squares[check].id == squares[check-7].id then
                        squares[check].alpha = 0.6

                        if squares[check].gridPlace[1] == gridPlace[1] then
                            if squares[check].gridPlace[2] < gridPlace[2] then
                                check = check + 1
                                cornerFix(check, gridPlace, var.checkP, squares[check+1].id)
                            elseif squares[check].gridPlace[2] > gridPlace[2] then
                                check = check - 1
                                cornerFix(check, gridPlace, var.checkP, squares[check+1].id)
                            end
                        end
                        
                        fixSelect( check, gridPlace) --check again
                        
                    end
                end
            end
    elseif var.direction == “down” then – down
        local check = place-7
            if check >= 1 and check <= 49 then
                if squares[check].gridPlace[1] >= gridPlace[1] and gridPlace[1] ~= 0 then
                
                    var.checkI = squares[check].gridPlace[1]
                    var.checkI = var.checkI - 1
                
                    if squares[check].alpha >= 0.9 and var.checkI >= 0 and squares[check].id == squares[check+7].id then
                        squares[check].alpha = 0.6
                       
                        if squares[check].gridPlace[1] == gridPlace[1] then
                            if squares[check].gridPlace[2] < gridPlace[2] then
                                check = check + 1
                                cornerFix(check, gridPlace, var.checkP, squares[check+1].id)
                            elseif squares[check].gridPlace[2] > gridPlace[2] then
                                check = check - 1
                                cornerFix(check, gridPlace, var.checkP, squares[check+1].id)
                            end
                        end
                        
                        fixSelect( check, gridPlace) --check again
                    end
                end
            end
    elseif var.direction == “left” then --left
        local check = place+1
            if check >= 1 and check <= 49 then
                if squares[check].gridPlace[2] <= gridPlace[2] and gridPlace[1] ~= 0 then
                
                    var.checkP = squares[check].gridPlace[2]
                    var.checkP = var.checkP + 1
                
                    if squares[check].alpha >= 0.9 and var.checkP <= 8 and squares[check].id == squares[check-1].id then
                        squares[check].alpha = 0.6

                        if squares[check].gridPlace[2] == gridPlace[2] then
                            if squares[check].gridPlace[1] < gridPlace[1] then
                                check = check + 7
                                cornerFix(check, gridPlace, var.checkP, squares[check-7].id)
                            elseif squares[check].gridPlace[1] > gridPlace[1] then
                                check = check - 7
                                cornerFix(check, gridPlace, var.checkP, squares[check+7].id)
                            end
                        end
                        
                        fixSelect( check, gridPlace) --check again
                    end
                end
            end
    elseif var.direction == “right” then – right
        local check = place-1
            if check >= 1 and check <= 49 then
                if squares[check].gridPlace[2] >= gridPlace[2] and gridPlace[1] ~= 0 then
                
                    var.checkP = squares[check].gridPlace[2]
                    var.checkP = var.checkP - 1
                
                    if squares[check].alpha >= 0.9 and var.checkP >= 0 and squares[check].id == squares[check+1].id then
                        squares[check].alpha = 0.6
                       
                        if squares[check].gridPlace[2] == gridPlace[2] then
                            if squares[check].gridPlace[1] < gridPlace[1] then
                                check = check + 7
                                cornerFix(check, gridPlace, var.checkP, squares[check-7].id)
                            elseif squares[check].gridPlace[1] > gridPlace[1] then
                                check = check - 7
                                cornerFix(check, gridPlace, var.checkP, squares[check+7].id)
                            end
                        end
                        
                        fixSelect( check, gridPlace) --check again
                    end
                end
            end
    end
end

local function slideCollect( self, e)
    if e.phase == “began” then
        var.firstSquare = self
        var.firstSquareid = self.id
        var.curSquare = self
        lastPlace[1] = self.gridPlace[1]; lastPlace[2] = self.gridPlace[2]
    end
    if e.phase == “moved” then
    
        --------------------------------------------------------------------------------------------------------------------------------------------
            --------------------------------------------------------------------------------------------------------------------------------------------
            if moveT.x[1] ~= nil then
                local disY = e.y - moveT.y[1]  --Calculate the distance between ‘moved’ phases
                local disX = e.x - moveT.x[1]
                
                    if disX >= 3 or disX <= -3 then
                        local angle = atan2(disY, disX) * 180/pi
                        if angle < 0 then
                            angle = angle + 360
                        end
                    getDirection( angle )
                    elseif disY >= 3 or disY <= -3 then
                        local angle = atan2(disY, disX) * 180/pi
                        if angle < 0 then
                            angle = angle + 360
                        end
                    getDirection( angle )
                    end
                    
                    
            end
            
            moveT.x[1] = e.x; moveT.y[1] = e.y – store the ‘moved’ phase x and y
        
        --------------------------------------------------------------------------------------------------------------------------------------------
            --------------------------------------------------------------------------------------------------------------------------------------------
            
                if var.firstSquareid == self.id and self.state == “unlocked” then
                
                    --Highlight if colours match
                    if self.alpha > 0.6 and self ~= var.firstSquare then
                        if var.firstSquare.alpha > 0.6 then
                            var.firstSquare.alpha = 0.6
                        end
                        
                        fixSelect(self.place, lastPlace)
                        lastPlace[1] = self.gridPlace[1]; lastPlace[2] = self.gridPlace[2]
                        
                        self.alpha = 0.6
                        

                        var.curSquare = self
                    end
                end
            --------------------------------------------------------------------------------------------------------------------------------------------
            --------------------------------------------------------------------------------------------------------------------------------------------
    end
    if e.phase == “ended” or e.phase == “stop” then
    
        moveT.x[1] = nil; moveT.y[1] = nil

        --Some code
    end
    return true
end

[/lua]

Thanks.

I’m so new to Corona, I probably shouldn’t even be suggesting any ideas. But I’ve been programming for over two decades, so maybe something here will spark an idea for you that will actually work.

One thing that comes to mind is what if you could throw a flag up on the touch listener and throw it back down when the touch ends. This flag could be checked in the enterFrame event (I’m assuming it fires more often than the touch event?), and if the flag is up, then check each square to find the current touch location. If the square being touched isn’t lit up already, then light it up.

You could just do the whole touch check in enterFrame, but I would imagine that having a continuous simple boolean check in your enterFrame event is probably much less intense than checking for touch each frame, right?

As far as the “Is it A or B” scenario. I can’t really think of any way to be 100% sure that you know which square the finger passed over. You might retain more accuracy by splitting the final square in half diagonally, and depending on which half the event registered inside, the neighboring square is assumed to be correct. However, I would still consider that hacky and not worthy to be considered a solution.

Kenny

I’m so new to Corona, I probably shouldn’t even be suggesting any ideas. But I’ve been programming for over two decades, so maybe something here will spark an idea for you that will actually work.

One thing that comes to mind is what if you could throw a flag up on the touch listener and throw it back down when the touch ends. This flag could be checked in the enterFrame event (I’m assuming it fires more often than the touch event?), and if the flag is up, then check each square to find the current touch location. If the square being touched isn’t lit up already, then light it up.

You could just do the whole touch check in enterFrame, but I would imagine that having a continuous simple boolean check in your enterFrame event is probably much less intense than checking for touch each frame, right?

As far as the “Is it A or B” scenario. I can’t really think of any way to be 100% sure that you know which square the finger passed over. You might retain more accuracy by splitting the final square in half diagonally, and depending on which half the event registered inside, the neighboring square is assumed to be correct. However, I would still consider that hacky and not worthy to be considered a solution.

Kenny