For my final project, I wanted to create a simple virus simulation where one infected particle infects a population of healthy particles. The particles move across the canvas at random speeds and directions and bounce off the edges of the canvas. I wanted to show how quickly disease can spread within a population if you don’t take preventative measures such as wearing a mask and social distancing.
- Your mouse is a social distancing particle that repels all other particles that comes within its’ social distancing radius.
- Healthy particles that come within range of a sick particles’ “infection radius” will be infected.
- If you press any key on the keyboard, more healthy particles will be added to the screen (but will quickly be infected by the population of sick particles).
- If you click the “RETURN” key, the sick particles will all reset to healthy and the process of infection begins again.
- In the upper left corner, there is a counter for the number of sick particles.
//Maggie Ma
//Section D
//Final Project Virus Simulator
var dots = [];
var infectionRadius = 20; //light red infection radius
var rpc = 19000; //repelling constant
function setup() {
createCanvas(600, 600);
for (i = 0; i < 100; i++) { //create 100 healthy dots
var p = new dot();
dots.push(p);
}
frameRate(20);
}
function draw() {
background(255);
for (var i = 0; i< dots.length; i++) { //draw uninfected dots
dots[i].update();
dots[i].show();
}
if (frameCount ==100){
dots[9].infected = true; //after 100 frameCount, one dot becomes sick
}
//dots infect eachother if come in contact in the "infectionRadius"
for (var m = 0; m<dots.length; m++) {
for (var i = 0; i < dots.length; i++) {
if (dist(dots[m].x, dots[m].y,
dots[i].x, dots[i].y) <= infectionRadius) {
if (dots[m].infected == true) {
dots[i].infected = true;
}
}
}
}
//Social Distance dot that repels all infected dots
ellipseMode(CENTER);
noStroke();
fill(0,0,0,100);
ellipse(mouseX,mouseY,100,100);
fill(0);
ellipse(mouseX,mouseY,25,25);
var sickcounter = 0;
//var healthycounter = 100;
for (var i = 0; i < dots.length; i ++) {
if(dots[i].infected ==true) {
sickcounter++;
//healthycounter--;
}
}
noStroke();
fill(200);
textSize(12);
text("You are the social distancing particle.", 10, 25);
text("Press any key to add healthy particles.", 10, 50);
fill(200);
text("Press 'Return' key to reset.", 10, 75);
text("Sick Particles:", 10,100);
text(sickcounter, 130,100);
}
//add new uninfected dots by pressing key
function keyPressed() {
dots.push(new dot(mouseX, mouseY));
//healthycounter++;
//if click "Return key" simulation resets.
if (keyCode === RETURN) {
for (var m = 0; m<dots.length; m++) {
for (var i = 0; i < dots.length; i++) {
if(dots[i].infected == true) {
dots[i].infected = false;
dots[9].infected = true;
sickcounter = 0;
}
}
}
}
}
class dot {
constructor() {
this.x =random(3.5, width-3.5);
this.y =random(3.5,height-3.5);
this.dx =random(-10,7);
this.dy =random(-10,7);
this.infected = false
this.history = [];
}
update() {
//move black dots
this.x+= this.dx;
this.y+=this.dy;
//bounce off the edges of the canvas
if (this.x > width) { //bounce off right wall
this.x = width - (this.x - width);
this.dx = -this.dx
} else if (this.x < 0) { //bounce off left wall
this.x = -this.x;
this.dx = -this.dx
}
if (this.y > height) { // bounce off bottom
this.y = height - (this.y - height);
this.dy = -this.dy;
} else if (this.y < 0) { // bounce off top
this.y = -this.y;
this.dy = -this.dy;
}
//create the particle trail
var v = createVector(this.x, this.y);
this.history.push(v);
if (this.history.length>15) { //trail is 15 ellipses long
this.history.splice(0,1); //splice out the trail circle at index 0
}
//effect of the social distancing repeller
var dp = dist(this.x, this.y, mouseX, mouseY);
var f = rpc /(Math.pow(dp, 2)); //Math.pow is exponent w/ base dp
var dirx = (this.x - mouseX)/dp;
var diry = (this.y - mouseY)/dp;
this.x += f*dirx;
this.y += f*diry;
}
show() {
//if dot is infected, color red
if (this.infected ==true) {
noStroke();
//creating dot "tail"
for (var i = 0; i < this.history.length; i++) {
var pos = this.history[i];
fill('red');
ellipse(pos.x,pos.y, i*.15, i*.15)
}
//drawing red dot
fill(255,0,0,100);
ellipse(this.x, this.y, 30,30);
fill('red');
ellipse(this.x,this.y,10,10);
//else if dot is uninfected, color black dot
} else {
noStroke();
//creating dot "tail"
for (var i = 0; i < this.history.length; i++) {
var pos = this.history[i];
fill(0);
ellipse(pos.x,pos.y, i*.15, i*.15)
}
fill(0);
ellipse(this.x,this.y, 10,10);
}
}
}