Final Project – Simple Virus Simulator

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.

  1. Your mouse is a social distancing particle that repels all other particles that comes within its’ social distancing radius.
  2. Healthy particles that come within range of a sick particles’ “infection radius” will be infected.
  3. 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).
  4. If you click the “RETURN” key, the sick particles will all reset to healthy and the process of infection begins again. 
  5. In the upper left corner, there is a counter for the number of sick particles.
Covid Simulation
//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); 
		}
	}
}

Leave a Reply