float socialDistance = 0;
boolean _collisions = true;
ArrayList<Person> _people = new ArrayList<Person>();
ArrayList<Button> _buttons = new ArrayList<Button>();
int _socialDistanceCount = 0;
size(_canvas, _canvas, P3D);
hint(DISABLE_DEPTH_TEST);
textFont(loadFont("Arial Bold", 24));
_normalColor = color(80, 200, 80);
_sickColor = color(210, 200, 0);
_recoveryColor = color(203, 138, 192);
_deadColor = color(255, 50, 50);
Button noDistButton = Button.create("No social distance", width - 160, 15, 150, 25);
noDistButton.registerClickEvent(noDistTriggered);
Button lowDistButton = Button.create("Low social distance", width - 160, 50, 150, 25);
lowDistButton.registerClickEvent(lowDistTriggered);
Button highDistButton = Button.create("High social distance", width - 160, 85, 150, 25);
highDistButton.registerClickEvent(highDistTriggered);
translate(_canvas / 2, _canvas / 2, _canvas / 2 - _zoomAmount);
rotateY(radians(map(mouseX, 0, width, -180, 180)));
rotateX(radians(map(mouseY, 0, height, 180, -180)));
pointLight(200, 200, 200, 35, 1000, 36);
ambientLight(102, 102, 102);
for (int i = 0; i < _people.size(); i++) {
_people.get(i).display();
_days = int(frameCount / 24);
for (int i = 0; i < _buttons.size(); i++) {
_buttons.get(i).display();
_normalCount = population;
_socialDistanceCount = 0;
for (int i = 0; i < population; i++) {
Person person = new Person(random(_bounds), random(_bounds), random(_bounds));
if (i / population * 100 < socialDistance) {
person.practiceSocialDistance();
for (int i = 0; i < _people.size(); i++) {
if (!_people.get(i).socialDistance) {
_people.get(i).setState(SICK);
void displayContainer() {
translate(-_bounds / 2, _bounds / 2, -_bounds / 2);
rect(0, 0, _bounds, _bounds);
translate(-_bounds / 2, -_bounds / 2, -_bounds / 2);
rect(0, 0, _bounds, _bounds);
translate(-_bounds / 2, -_bounds / 2, -_bounds / 2);
rect(0, 0, _bounds, _bounds);
translate(-_bounds / 2, -_bounds / 2, _bounds / 2);
rect(0, 0, _bounds, _bounds);
text("Total: " + _people.size(), 10, 20);
text("Social dist: " + _socialDistanceCount + " (" + percentage(_socialDistanceCount, _people.size()) + "%)", 10, 40);
text("Healthy: " + _normalCount + " (" + percentage(_normalCount, _people.size()) + "%)", 10, 60);
text("Sick: " + _sickCount + " (" + percentage(_sickCount, _people.size()) + "%)", 10, 80);
text("Recovered: " + _recoveryCount + " (" + percentage(_recoveryCount, _people.size()) + "%)", 10, 100);
text("Passed: " + _deathCount + " (" + percentage(_deathCount, _people.size()) + "%)", 10, 120);
text("Days: " + _days, 10, 140);
void drawBar(int x, int y, int count, color barColor) {
rect(x, y, map(count, 0, _people.size(), 0, 200), 15);
drawBar(x, 17, population, color(0));
drawBar(x, 36, _socialDistanceCount, color(0));
drawBar(x, 55, _normalCount, _normalColor);
drawBar(x, 72, _sickCount, _sickColor);
drawBar(x, 93, _recoveryCount, _recoveryColor);
drawBar(x, 112, _deathCount, _deadColor);
text("OUTBREAK DONE", width / 2, height / 2);
void percentage(value, maxValue) {
return (value / maxValue * 100.0).toFixed(1);
void lowDistTriggered() {
void highDistTriggered() {