Is there any way to avoid having to exit the app all the time to avoid bugs?

Hi, I love Codea, I just started learning lua and its very cool.

But I can’t believe how often I have to leave the app to avoid bugs.

I have a project that works great, but only the first time it’s run. Usually the second or third time will throw errors. The reset button doesn’t help.

Sometimes leaving the project and starting it again from within Codea is enough, but sometimes I have to leave the app completely before it will run properly again. Sometimes I even have to terminate Codea from the app switcher.

Needless to say, this makes coding somewhat laborious, since I have to exit all the time. Is this SOP around here?

I run into that alot myself. I do something that puts the program in a loop and the only way out is to terminate Codea and start it again. Usually 2 starts before I get in. But I guess that makes me check the code more before I run it.

I’m a bit surprised of your remark: my experience of lua/codea is that debugging is very easy, compared to other langages, as long as you keep the program structure clear and check all your functions with unitary tests. When i get a bug i trace it back from the error message that indicates the line where the error occurs. Usually just ‘print()’ of the variables causing the bug, at various locations, helps to find quickly the root cause. Good luck!

Hi @UberGoober (love the name!) I’m finding the current versions very stable… Are you finding one particular project crashes a lot? Perhaps you have discovered a Codea bug? Any chance you could isolate it? We love to squash bugs, so if you posted a link to your code some folks might be able to help out.

Hi @Jmv38, can you please elaborate a bit on unit testing. Sure, it’s a best practice, but (lacking direct language support in Lua) how does one implement unit tests in Codea?
Thanks!

Hi @olaf. Well, my interpretation of unitary testing here is maybe not exactly what pro coders call unitary testing… :"> I don’t feel allowed to give lessons on the subject, but however i can tell you how i do:
.1 / i make many small functions rather than a big one, so i can check each element indivually (for me 1 function should not have more lines than the display, if possible)
.2. / i manage to do incremental code, so that i can run the program nearly after every couple line addition, and check the intermediate ouput is correct,
.3. /once i’ve implemented a new functionnality, i try to put it in a menu, so i can retry it any time later => when i add a function i can retry the old ones easily, and check 1/ they are still working, 2/ what is the impact of interractions. Hem, might be what everyone does, but i’ve not always done like that myself, and my code robustness has improved a lot since that time, thanks to those practices. Oh, and i just remember: i’ve implemented a kind of unitary testing in my controls_v3 post: this subproject is called as a dependency of another project, so i’ve put all the test in the main of the subproject, which is not loaded by the main project, and each time i make addition in the subproject, i add tests in its main. That can be called unitary testing, no?

@Fred:

Thanks a lot for the invitation. I need to clean up my code a bit before I post it. I’m working on that now. Then I’ll send it along. I will be glad to get any help.

Well, @Fred, I think you’ll be happy to learn that in cleaning up my code the bug went away. So cheers!

For giggles, here’s the cleaned up code. It’s intended to trace a line wherever you drag your finger, and make a little spider sprite follow that line.

You may be able to spot that I’m coming from Objective C and am not totally doing things the “lua way”. Any tips will be appreciated.

I have to say I’m a little blown away by how short lua programs can be.

--# Main
function setup()
    displayMode(FULLSCREEN)
    --object to hold drawn lines:
    webs = {}
    TouchHandler:recordTouchesIn(webs)
    --the spider!
    spider = MakeSprite ("Documents:Orb Spider Red PNG hopefully")
    spider:followPath(webs)
    --old, delete asap:
    draggedLines = {}
end

function draw()
    --standard, apparently necessary to prevent weirdness:
    background(0,0,0,0)    
    --sprite for background:
    sprite("Documents:Flower Twigs",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)    
    --this makes it easier to see thin lines:
    noSmooth()
    --drawing all recorded touches:
    TouchHandler:drawTouches(webs)
    --the spider! 
    spider:followPath()
    spider:draw()   
end  

function touched (touch)
    TouchHandler:touched(touch)
end

--# MakeSprite
MakeSprite = class()

function MakeSprite:init( name )
    self.name = name
    self.position = nil
    self.angle = 0
    self.movementVector = nil
    self.destination = nil
    self.path = nil
    self.resultReport = nil
end

function MakeSprite:draw()
    if self.position ~= nil then
        sprite( self.name , self.position.x, self.position.y ) 
    end 
end

function MakeSprite:moveSelf()
    if self.destination == nil then 
        self.resultReport = "no destination"          
    else
        if self:checkIfCloseEnough() == true then 
            self.position = self.destination 
            self.resultReport = "at destination" 
        else 
            self.position = self.position + self.movementVector
            self.resultReport =  "moved"
        end       
    end
end

function MakeSprite:setDestination(givenDestination)
    self.destination = givenDestination
    if givenDestination == nil then return end
    local angleToDestination = vec2(1,0):angleBetween(self.position  - self.destination)
    self.movementVector = vec2(-math.cos(angleToDestination),-math.sin(angleToDestination))
end

function MakeSprite:followPath(unlessNewPathPassedHere)
    --if no path is passed, try to move:
    if unlessNewPathPassedHere == nil then
        self:moveSelf()
        --if it was anything but a normal move, check where to go next:
        if self.resultReport == "moved" then return else self:checkPath() end
    --otherwise set path to value passed:
    else 
        self.path = unlessNewPathPassedHere 
    end
end
  
function MakeSprite:checkPath()
    --if at destination, iterate to find which one, then assign the next one
    if self.resultReport == "at destination" then
        --maxn(path) is -1 here so that loop stops before the end of the line
        for nextPoint = 1, table.maxn(self.path)-1 do
            if TouchHandler:arePositionsTheSameOfVectorAndTouch(self.position, 
            self.path[nextPoint]) == true then
                self:setDestination(TouchHandler:makeVectorFromTouch(self.path[nextPoint+1]))
                break
            end
        end
    --if not, if path table total == 2, set position and destination
    elseif self.resultReport == "no destination" and table.maxn(self.path) == 2 then
        self.position = TouchHandler:makeVectorFromTouch(self.path[1])
        self:setDestination(TouchHandler:makeVectorFromTouch(self.path[2]))
    --if there's no path, bail:
    elseif self.path == nil then 
        return
    end
end
           
function MakeSprite:checkIfCloseEnough()
    if (self.position.x < self.destination.x + 1 and self.position.x > self.destination.x - 1) 
        and (self.position.yself.destination.y-1) 
        then
            return true
    end
end
    
    
--# TouchHandler
TouchHandler = class()

function TouchHandler:recordTouchesIn(givenTable)
    -- takes passed-in table and fills it with recorded touches
    touchTable = givenTable
end

function TouchHandler:touched(touch)
    --to functionally function this function should be called by the Main:touched(touch) function
    --now: if a value has been set for touchTable, put each touch in it
    if touchTable ~= nil then
        table.insert(touchTable, touch)
    end
end

function TouchHandler:drawTouches(givenTouchTable)
    --for each point, draw a line between it and the next point, until one away from the end
    for currentTouch = 1, table.maxn(givenTouchTable)-1 do
        line(givenTouchTable[currentTouch].x,givenTouchTable[currentTouch].y,
        givenTouchTable[currentTouch+1].x,givenTouchTable[currentTouch+1].y)
    end
end

function TouchHandler:makeVectorFromTouch(givenTouch)
    --turning a touch into a vector
    return vec2(givenTouch.x, givenTouch.y)
end

function TouchHandler:arePositionsTheSameOfVectorAndTouch(givenVector,givenTouch)
    if givenVector == TouchHandler:makeVectorFromTouch(givenTouch) then
        return true else return false
    end
end

```

@UberGoober

I tried your program, but a bug is still there because the program cancels just after it starts in the MakeSprite:checkIfCloseEnough() function.

That’s actually a bug in the way the code pasted from the clipboard into the above post, somehow. Very weird. The part that reads

(self.position.yself.destination.y-1)

Should actually be

(self.position.y < self.destination.y + 1 and  self.position.y > self.destination.y-1)

Which is how it is in the actual code. It just pasted wrong. Very odd.

Hi @UberGoober! I changed your sprites because I didn’t have them, and it works fine with the adjusted code above.

I got interesting results using multiple fingers at once, as long as they all move, each one is allocated a point. Starts looking like a spiderweb.

I’m not really in a position to give pro tips, (!) but I did notice your variable names are very long… And Codea doesn’t use a virtual page - you get wrap around very quickly - so maybe that’s something to think about.

@Fred thanks for your comments!