#### Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

#### In this Discussion

Mod
in General Posts: 8,505

I took one of my older programs and modified it to show how a virus could spread. When the program starts, there are 350 white balls roaming around the screen. Once you tap the screen, you infect one of the balls (color yellow). That ball will interact with the other balls but nothing will happen. After it’s been infected for 6 days (1 day = 3 seconds), that ball becomes contagious (color red). Any white ball that comes in contact with the red ball becomes infected (yellow). That ball then goes thru the 6 day stretch before it becomes contagious (red). Each red ball will infect other balls for 15 days after which time it will be cured (color green). It takes about 50 some days for all balls to go from white to green. Of course, if we had millions of balls and a larger area, it would take a lot longer for this to run. I have counts in the middle of the screen to show the status of the balls.

Remember, tap the screen to start the infection.

``````displayMode(FULLSCREEN)

function setup()
colTab={color(255),color(255,255,0),color(255,0,0),color(0,255,0)}
dti=5
dtc=20
physics.continuous=true
speed=50
line1 = physics.body(EDGE,vec2(5,5),vec2(10,HEIGHT-5))
line2 = physics.body(EDGE,vec2(WIDTH-5,5),vec2(WIDTH-5,HEIGHT-5))
line3 = physics.body(EDGE,vec2(5,5),vec2(WIDTH-5,5))
line4 = physics.body(EDGE,vec2(5,HEIGHT-5),vec2(WIDTH-5,HEIGHT-5))
val=0
days=0
cnt=0
limit=180
nbr=350
tab={}                    -- table for balls
create()
end
end

function draw()
background(50, 50, 50)
normal,infected,contagious,cured=0,0,0,0
strokeWidth(0)
for a,b in pairs(tab) do
if b.inf>0 then
if days-b.inf>=dti and b.col==2 then
b.col=3
elseif days-b.inf>=dtc and b.col==3 then
b.col=4
end
end
fill(colTab[b.col])
ellipse(b.x,b.y,12)
if b.col==1 then
normal=normal+1
elseif b.col==2 then
infected=infected+1
elseif b.col==3 then
contagious=contagious+1
elseif b.col==4 then
cured=cured+1
end
end
stroke(255)
strokeWidth(5)
line(5,5,5,HEIGHT-5)
line(WIDTH-5,5,WIDTH-5,HEIGHT-5)
line(5,5,WIDTH-5,5)
line(5,HEIGHT-5,WIDTH-5,HEIGHT-5)
cnt=cnt+val
if cnt>limit then
cnt=0
days=days+1
end
fill(255, 0, 217)
text("day "..days,WIDTH/2,HEIGHT/2+200)
fill(255)
text("normal "..normal,WIDTH/2,HEIGHT/2+150)
fill(255,255,0)
text("infected "..infected,WIDTH/2,HEIGHT/2+100)
fill(255,0,0)
text("contagious "..contagious,WIDTH/2,HEIGHT/2+50)
fill(0,255,0)
text("cured "..cured,WIDTH/2,HEIGHT/2)
end

function touched(t)
if t.state==BEGAN and infected==0 then
tab[1].col=2
tab[1].inf=1
val=1
end
end

function collide(contact)
if contact.state==BEGAN then
if contact.bodyA.col==3 then
if contact.bodyB.col==1 then
contact.bodyB.inf=days
contact.bodyB.col=2
infected=infected+1
normal=normal-1
end
elseif contact.bodyB.col==3 then
if contact.bodyA.col==1 then
contact.bodyA.inf=days
contact.bodyA.col=2
infected=infected+1
normal=normal-1
end
end
end
end

function create()
local a=#tab+1
tab[a]=physics.body(CIRCLE,6)
tab[a].mass=2
tab[a].friction=0
tab[a].x=math.random(30,WIDTH-30)
tab[a].y=math.random(30,HEIGHT-30)
tab[a].gravityScale=0
tab[a].restitution=1
tab[a].sleepingAllowed=false
a1=math.random(-1,1)*speed
a2=math.random(-1,1)*speed
tab[a].linearVelocity=vec2(a1,a2)
tab[a].inf=0
tab[a].col=1
end
``````

• edited March 17 Posts: 1,768

@dave1707 - interesting, funnily enough I’ve been looking for game of Life to do something similar. Overlaying a graph of the numbers of the 4 inhabitants of the game would show progress. Saved the project as Corona.

• Posts: 545

@dave1707 cool! Would be nice to add a plot of the time dependence for the various categories. Then send it to Boris Johnson, so he finally takes it seriously!

• Posts: 684

Neat ... why does it slow to a stop? Looks like there's no friction and perfect collisions ...

• Mod
Posts: 8,505

@RonJeffries I don’t know the exact answer why it’s slows, but it might be based on the angle it hits the side walls. If it’s straight on, it bounces back ok. If it’s a glazing hit, it doesn’t bounce back enough. I’ll have to make a copy and strip out a lot of stuff and display velocities of the ball when it hits at different angles.

• Posts: 684

physics, can't live with it, can't live without it.

• Mod
Posts: 8,505

@RonJeffries I tried different angles and speeds with one ball bouncing off the wall. The smaller the angle, the higher the velocity had to be to get a good bounce. There might be a speed that can be calculated based on the angles where you get the bounce limit. I haven’t found a setting that fixes everything. I tried linearDamping to get the bounce to work, but that just caused the balls to speed up out of control.

• Posts: 72

I think the balls slow down because they are "sheltering in place". What an interesting program.

• Mod
Posts: 8,505

@Scotty I like your answer, “sheltering in place”. But one thing it shows is that even though they shelter in place, if one of them is infected, eventually they all get infected. I ran this one time where one of the balls didn’t get infected for a very long time. Eventually it ran into an infected ball because just about every ball around it was infected. But it shows that as long as you can avoid the ones infected, then your OK.

• Mod
edited March 19 Posts: 8,505

Added code to graph the different categories as the program runs.

``````displayMode(FULLSCREEN)

function setup()
nbr=350
nTab,iTab,coTab,cuTab={nbr},{0},{0},{0}
colTab={color(255),color(255,255,0),color(255,0,0),color(0,255,0)}
dti=5
dtc=20
physics.continuous=true
speed=50
line1 = physics.body(EDGE,vec2(5,5),vec2(10,HEIGHT-5))
line2 = physics.body(EDGE,vec2(WIDTH-5,5),vec2(WIDTH-5,HEIGHT-5))
line3 = physics.body(EDGE,vec2(5,5),vec2(WIDTH-5,5))
line4 = physics.body(EDGE,vec2(5,HEIGHT-5),vec2(WIDTH-5,HEIGHT-5))
val=0
days=0
cnt=0
limit=180
tab={}                    -- table for balls
for x=1,nbr do
create()
end
end

function draw()
background(50, 50, 50)
stroke(255)
strokeWidth(5)
line(5,5,5,HEIGHT-5)
line(WIDTH-5,5,WIDTH-5,HEIGHT-5)
line(5,5,WIDTH-5,5)
line(5,HEIGHT-5,WIDTH-5,HEIGHT-5)

normal,infected,contagious,cured=0,0,0,0
strokeWidth(0)
for a,b in pairs(tab) do
if b.inf>0 then
if days-b.inf>=dti and b.col==2 then
b.col=3
elseif days-b.inf>=dtc and b.col==3 then
b.col=4
end
end
fill(colTab[b.col])
ellipse(b.x,b.y,12)
if b.col==1 then
normal=normal+1
elseif b.col==2 then
infected=infected+1
elseif b.col==3 then
contagious=contagious+1
elseif b.col==4 then
cured=cured+1
end
end

fill(255, 0, 217)
text("day "..days,WIDTH/2,HEIGHT/2+200)
fill(255)
text("normal "..normal,WIDTH/2,HEIGHT/2+150)
fill(255,255,0)
text("infected "..infected,WIDTH/2,HEIGHT/2+100)
fill(255,0,0)
text("contagious "..contagious,WIDTH/2,HEIGHT/2+50)
fill(0,255,0)
text("cured "..cured,WIDTH/2,HEIGHT/2)

if days<75 then
cnt=cnt+val
if cnt>limit then
cnt=0
days=days+1
end
end

w=WIDTH/60
nTab[days]=normal
iTab[days]=infected
coTab[days]=contagious
cuTab[days]=cured

strokeWidth(3)
stroke(colTab[1])
for z=1,#nTab-1 do
line((z-1)*w,nTab[z-1]*2+100,z*w,nTab[z]*2+100)
end
stroke(colTab[2])
for z=1,#iTab-1 do
line((z-1)*w,iTab[z-1]*2+100,z*w,iTab[z]*2+100)
end
stroke(colTab[3])
for z=1,#coTab-1 do
line((z-1)*w,coTab[z-1]*2+100,z*w,coTab[z]*2+100)
end
stroke(colTab[4])
for z=1,#cuTab-1 do
line((z-1)*w,cuTab[z-1]*2+100,z*w,cuTab[z]*2+100)
end
end

function touched(t)
if t.state==BEGAN then
if infected==0 then
tab[1].col=2
tab[1].inf=1
val=1
end
end
end

function collide(contact)
if contact.state==BEGAN then
if contact.bodyA.col==3 then
if contact.bodyB.col==1 then
contact.bodyB.inf=days
contact.bodyB.col=2
infected=infected+1
normal=normal-1
end
elseif contact.bodyB.col==3 then
if contact.bodyA.col==1 then
contact.bodyA.inf=days
contact.bodyA.col=2
infected=infected+1
normal=normal-1
end
end
end
end

function create()
local a=#tab+1
tab[a]=physics.body(CIRCLE,6)
tab[a].mass=20
tab[a].friction=0
tab[a].x=math.random(30,WIDTH-30)
tab[a].y=math.random(30,HEIGHT-30)
tab[a].gravityScale=0
tab[a].restitution=1
tab[a].sleepingAllowed=false
a1=math.random(-1,1)*speed
a2=math.random(-1,1)*speed
tab[a].linearVelocity=vec2(a1,a2)
tab[a].inf=0
tab[a].col=1
end
``````
• Posts: 1,768

@dave1707 - just started trying to do this today but didn’t get far. Ran the project and it’s great - just misses one component at a level of about 3%. One thing to note - ran this on three occasions and initially followed the progress and exited. On the other two occasions I was interrupted and had to leave it running - on both occasions it crashed Codea. Possibly need an end point on this to stop progress.

• edited March 19 Posts: 1,768

@dave1707 - just started trying to do this today but didn’t get far. Ran the project and it’s great - just misses one component at a level of about 3%. Just one thing - I have run the project 4 times now. The first ran to completion one closed the project. The second and third I ran and was interrupted - left the project running and in each case Codea crashed. Ran it on the fourth time and completed, plotted beyond the screen up to 108 days.

Ran it a fifth time - my iPad has a case with a magnet in the cover which when sensed freezes the iPad. Closed my cover this time - project incomplete and Codea crashed.

@Simeon - the shutdown is a design feature of the iPad as there are sensors present in the iPad. I have only noticed this with Codea - are there routines/protocols available from Apple to cope with this?

• Posts: 545

@dave1707 good, now i can send it to Boris! Interesting, the curves come out quite Gaussian.

• Mod
Posts: 8,505

@Bri_G I modified the above code to stop updating the counts and tables at 75 days. That should stop the crash. How long did you let it run. The program still updates the physics information. I never thought anyone would let this run for any length of time.

• edited March 19 Posts: 1,768

@dave1707 - first time when I took the dog for a walk, second time when I had my tea (each about 20 mins) but the third time as soon as the graph plotting had reached the right hand edge of the screen. But - I don’t think it is necessarily the code but due to the iPad freezing running apps. I think there must be routines or protocols to be run/complied with to re-open apps in a frozen state.

• Mod
Posts: 8,505

@piinthesky I’ve run this several times and noticed that when the infected graph peaks, it’s close to when the normal and contagious graphs cross. Also, when the contagious graph peaks, it’s close to when the infected and cured graphs cross.

Posts: 5,387

@dave1707 that's a very interesting simulation. I like the differentiation between "contagious" and "infected"

• Posts: 684

i sure wonder why they grind to a halt on the sides

• Mod
Posts: 8,505

@RonJeffries As far as I can determine, once the speed gets below a certain value, the physics engine doesn’t work like it does at faster speeds. I’m not sure if I’m not setting everything right, or that’s just the way it is.

• Posts: 684

Yes ... with restitution = 1, I'd expect perfect collisions. Maybe there's some friction thing somewhere that we're missing. I fiddled with settings on the EDGEs but no joy.

• Mod
Posts: 8,505

@RonJeffries I was trying things with just two balls and with the speed below a certain limit. Even setting the restitution to 2 or higher, when the 2 balls collided, they just stopped. When I would go just 1 above that speed limit, the balls went crazy on each collision with a high restitution. So I would say there’s a speed limit for physics to work right.

• Mod
Posts: 8,505

@RonJeffries Heres some code to show the speed limit for 2 balls to bounce off each other. A speed of 16 or less doesn’t cause a bounce while a speed greater than 16 does. I can set linearDamping to a negative number, but that just causes the balls to speed up with multiple collisions in the other program. Change the speed value to see the bounce, no bounce.

``````displayMode(STANDARD)

function setup()
physics.continuous=true
physics.gravity(0,0)

speed=16

create1()
create2()
end

function draw()
background(0)
fill(255)
ellipse(a1.x,a1.y,20)
ellipse(a2.x,a2.y,20)
v=a1.linearVelocity
text(v.y,a1.x+80,a1.y)
v1=a2.linearVelocity
text(v.y,a2.x+80,a2.y)
end

function create1()
a1=physics.body(CIRCLE,10)
a1.sleepingAllowed=false
a1.linearDamping=0
a1.restitution=1
a1.mass=1
a1.friction=0
a1.x=WIDTH/2
a1.y=HEIGHT/2-50
a1.linearVelocity=vec2(0,speed)
end

function create2()
a2=physics.body(CIRCLE,10)
a2.sleepingAllowed=false
a2.linearDamping=0
a2.restitution=1
a2.mass=1
a2.friction=0
a2.x=WIDTH/2
a2.y=HEIGHT/2+50
a2.linearVelocity=vec2(0,-speed)
end
``````
• Posts: 684

weird

• Posts: 545

@dave1707 i was intrigued by the bouncing problem and went to the Box2D documentation. It seems there is a default velocity threshold (1) below which the collisions become inelastic. This might be the origin. This threshold is not exposed in Codea so @John would have do some work to make it user settable or just set it to a lower value.
http://personal.boristhebrave.com/permanent/09/Box2DFlashAS3Docs/Box2D/Common/b2Settings.html#b2_velocityThreshold

• Mod
Posts: 8,505

@piinthesky Thanks for the link. Lots of interesting info there.

Posts: 5,387

@dave1707 just saw this video with a bunch of virus transmission simulations and it reminded me of your work

• Posts: 1,768

@Simeon - WOW (for the code) OMG - what have they let loose on us???

Thanks for posting, guess I won’t sleep for a while - lay back and ‘enjoy’ lockdown !!!

• Mod
Posts: 8,505

@Simeon That does look similar, but they put a lot more work into theirs.