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