backingMode() missing in action?

I have recently gone from an iPad generation 3 to an iPad Air and of course I see plenty of changes in Codea functionality. Totally expected.

I have gotten most all my projects that ran on the old iPad running on my new Air with a few exceptions.

I notice backingMode() seems to be missing in action. Is there a workaround for this function? I used it to track the paths of “particles” under the influence of gravity. The result is cool to watch.

Thanks in advance for any advice offered. In the meantime I’ll keep searching.

1 Like

Hey, welcome back.

I have a vague recollection of it a few years ago. You may have some luck with the setContext(img) function, allowing for render-to-texture.

Call setContext(framebufferImage), do your rendering, setContext(nil) then sprite(framebufferImage, 0,0) to copy it to the display framebuffer.

If you avoid calling background() you should be able to achieve the same result.

Backing mode is always RETAINED now, so you shouldn’t need to specify it

Try the “Handling Touches” example to see it in action

Thanks @Steppers and @sim for your response. I believe I have it figured out. It seems to have everything to do with background() and when and when not to use it. Here is the project:


--# Main
--[[ ParticleAccelerator (Ver3)
Uses Newton's motion equations.
Some functionality along with the nested gravity application method is the work of others
This resembles an adam smasher where the particles fly off in unexpected directions. Particles travel towards the center of the screen and fly off on paths due to the influence of gravity. Project should restart after all four particles exit the screen, but not always.
--]]



viewer.mode=FULLSCREEN



function setup()
        
    
    X = WIDTH/2
    Y = HEIGHT/2
    
    offset = 20 -- For displaying text at an offset.
    
    -- standard colors
    red    = color(255,0,0,255)
    yellow = color(255,255,0,255)
    green  = color(0,225,0,255)
    blue   = color(0,0,255,255)
    white  = color(255, 255, 255, 255)

   
    -- define common vars for particle definition below
    G      =    1
    minG   =   10
    maxG   =  100
    ctP    =    1 -- to keep track of number of particles created
        

    bodies = {}
    -- Define four particles
    -- Located at random and aimed toward screen-center
    -- All var defs and table assignments happen in randomQuadParticle()
    -- ctP will be used in moveBodies()
    randomQuadParticle(ctP,red)
    ctP = ctP+1   
    randomQuadParticle(ctP,yellow)  
    ctP = ctP+1   
    randomQuadParticle(ctP,blue)
    ctP = ctP+1   
    randomQuadParticle(ctP,green)

   
    partCt = #bodies

    test = 0 -- where: 0=no; 1=yes  
    pov  = 1 -- where: 0=no; 1=yes  show path of particle  (persistance of vision)

end



function draw()

    -- I can't take credit for this bit of logic.
    if pov == 1 then
        --backingMode(RETAINED) -- no longer suported
        background(0)-- background() added -- now the project works.
        size = 5
        pov  = 2
    elseif pov == 0 then
        background(0)
        size = 15
    end



    if test == 1 then
        for k,v in pairs(bodies) do
            stroke(v.c)
            testRectangle(k) -- Draw "line" rectangles that are the sweetspots.
        end
        centerline(2)
    end
    
       
    applyGravity()  -- Apply Newton's gravity equations to update particle deltas.
    
    moveBodies(ctP) -- Display ctP particles according to new positions.
      
end






--# Functions




function applyGravity() -- by others
-- Apply gravity to all bodies and update the particle delta values
    
    for k1,v1 in pairs(bodies) do
        for k2,v2 in pairs(bodies) do
            if k2 > k1 then
                
                -- gravity factor - this is distance factoring for gravity
                d = v1.g / (( (v1.x - v2.x)^2 + (v1.y - v2.y)^2)^1.125) -- was 1.5
                
                -- adjust v1 velocity
                v1.dx = v1.dx - (v1.x - v2.x) * d * v2.m * G
                v1.dy = v1.dy - (v1.y - v2.y) * d * v2.m * G

                -- adjust v2 velocity
                v2.dx = v2.dx - (v2.x - v1.x) * d * v1.m * G
                v2.dy = v2.dy - (v2.y - v1.y) * d * v1.m * G
            end
        end
    end
end



function moveBodies(nth) -- by others
-- Move AND display bodies according to the new delta values calculated in applyGravity().
    
    local nth = nth
    local ct  = 0
    
    -- Update x,y locs.
    for k,v in pairs(bodies) do
        v.x = v.x + v.dx
        v.y = v.y + v.dy
    end
    
    -- Draw the particle...
    for k,v in pairs(bodies) do
        -- The planets:
        fill(v.c)
        ellipse(v.x, v.y, size) 
        if pov == 0 then
            fontSize(size)
            text(v.n, v.x+textSize(v.n)*2, v.y)
        end
    end
    

    -- Restart when the nth goes off screen (scotty)
    for k,v in pairs(bodies) do
        if v.x > WIDTH or v.x < 0 or v.y > HEIGHT or v.y < 0 then
            ct = ct+1
            if ct == nth then
                bodies = nil  -- "kill" body table before restart()
                restart()
            end
        end
    end  
    
    -- display particle count but only if backingMode() is OFF (scotty)
    if pov == 0 then
        pushStyle()
        fill(white)
        fontSize(20)
        text("Particle Count = "..partCt-ct, WIDTH/2, 50)
        popStyle()
    end

end





function randomQuadParticle(pNum,col)

    
    local pNum = pNum
    local col  = col
    
    
    sweetSpot  = {} -- A table to hold the sweetspot for each quadrant.
    low, high  = 300,350 -- Define the prefered range for the random particle location.
    
    -- Quad I
    xRangeL,xRangeH, yRangeL,yRangeH = low,high, low,high  
    sweetSpot[1] = { xRangeL,xRangeH, yRangeL,yRangeH }   

    -- Quad II
    xRangeL,xRangeH, yRangeL,yRangeH = -high,-low, low,high
    sweetSpot[2] = { xRangeL,xRangeH, yRangeL,yRangeH }
    
    -- Quad III
    xRangeL,xRangeH, yRangeL,yRangeH = -high,-low, -high,-low
    sweetSpot[3] = { xRangeL,xRangeH, yRangeL,yRangeH }
        
    -- Quad IV
    xRangeL,xRangeH, yRangeL,yRangeH =  low,high, -high,-low
    sweetSpot[4] = { xRangeL,xRangeH, yRangeL,yRangeH } 
    
    -- Define the raw slope (rise over run)
    slope = vec2(    -- Define the raw slope (rise over run)
        math.random(sweetSpot[pNum][1],sweetSpot[pNum][2]),
        math.random(sweetSpot[pNum][3],sweetSpot[pNum][4]) )

    
    loc  = vec2(X+slope.x,Y+slope.y) -- Add X and Y for full Cartesian display.
    grav = math.random(minG,maxG)    -- Define some gravity at random.
    ms   = 1
    
    -- Raw slope before X and Y was added in (for delta calculation)
    if     pNum == 1 then
        delta = vec2( -(slope.x/slope.y),-1)
    elseif pNum == 2 then
        delta = vec2( (-slope.x/slope.y),-1)
    elseif pNum == 3 then
        delta = vec2( ( slope.x/slope.y), 1)
    elseif pNum == 4 then
        delta = vec2( ( slope.x/slope.y), 1)
    end
        

    -- Stuff it all into the body table
    bodies[pNum] = {
        n  = ctP, -- from setup()
        g  = grav,
        m  = ms,
        x  = loc.x,
        y  = loc.y,
        dx = delta.x,
        dy = delta.y,
        c  = col -- imported
        }    
end




function centerline(typ)    
    -- Draw a pair of centerlines based on "centerlineType" parameter choice
    
    local clType = typ
    
    pushStyle()    
    strokeWidth(1)  
    stroke(white)
    if clType == 1 then 
        -- Screen center (X,Y placed here will ensure centerlines stay at screen center)
        X = WIDTH/2
        Y = HEIGHT/2 
        
        line(0,Y,WIDTH,Y)
        line(X,0,X,HEIGHT)
    elseif clType == 2 then
        -- Screen center (X,Y placed here will ensure centerlines stay at screen center)
        X = WIDTH/2
        Y = HEIGHT/2
        local gap   = 15  -- gap at center of crosshairs
        local multi = 10  -- a multiplier of "gap" 
        
        line(X+gap,Y,     X+gap*multi,Y)
        line(X-gap,Y,     X-gap*multi,Y)  
        line(X,    Y+gap, X,          Y+gap*multi)
        line(X,    Y-gap, X,          Y-gap*multi)  
    end
    popStyle()      
end



function testRectangle(ranQuad)
-- Draw a rectangle in the target quadrant
    
    local ranQuad = ranQuad
    
    -- draw a test rectangle using lines
    pushMatrix()
    translate(X,Y)
    pushStyle()
    strokeWidth(1)
    line(sweetSpot[ranQuad][1],sweetSpot[ranQuad][3],
    sweetSpot[ranQuad][2],sweetSpot[ranQuad][3])
    
    line(sweetSpot[ranQuad][2],sweetSpot[ranQuad][3],
    sweetSpot[ranQuad][2],sweetSpot[ranQuad][4])
    
    line(sweetSpot[ranQuad][2],sweetSpot[ranQuad][4],
    sweetSpot[ranQuad][1],sweetSpot[ranQuad][4])
    
    line(sweetSpot[ranQuad][1],sweetSpot[ranQuad][4],
    sweetSpot[ranQuad][1],sweetSpot[ranQuad][3])
    popStyle()
    popMatrix()
    
end

1 Like

Yes, background will clear the screen — so you’ll need to not use it if you want the previous screen’s contents in the next frame

Previously backingMode was an option because this had performance implications. Modern iOS devices are so fast that this is no longer relevant

@sim interesting. I’m enjoying my IPadAir as it a great deal faster than my old gen3.

Thanks again to you and @Steppers for your response.

1 Like