Verbose code (how to shorten)

I have this sketch (see below). Everything works, the green balls are healthy, the red balls are sick, if a green ball and a red ball collide the red ball infects the green ball and they both end up sick. After a while a sick ball can either recover (blue) or it can vanish.

There is a boolean variable (swap) so the game can be played one of two ways. If ‘swap’ is false, everyone moves freely around so everyone gets sick and some ‘vanish’. If ’swap’ is true, patient zero having been tested stays still (semi-isolation). In this case, there is a higher survival rate and some people don’t even get sick.

There is an integer variable (thresh) that determines how many frames the sickness persists, currently set at 750. There is also a float variable (risk) that determines how many sick balls recover and how many ‘vanish’. This is currently set at 499.6/500.

One could also vary the size to vary the density of the population.

Like I say, everything works except my code is very verbose. In draw(), I have a timer for each ball that only starts when the balls collide with a sick ball. This is repeated ten times. Then I have a script for each ball that times how long the ball is sick for, and whether it recovers or vanishes.

Is there a way to shorten the code? Should I be trying to put the temporal and existential elements in the class, or should I be trying to iterate through the ten balls in one ‘for’ loop? Thanking you in advance!

“All models are wrong, but some are useful.”

boolean swap = true; 

// rgb
color healthy = color(103, 188, 145); // #67BC91
color sickrgb = color(239, 145, 155); // #EF919B
color recovered = color(153, 168, 237); // #99A8ED

// hex
String sickhex = "EF919B";



//
float xspeedValue = 1;
float yspeedValue = 1;

Ball[] balls = new Ball[10];

int timer0 = 0;
int thresh = 750; // 600

int startTimer1 = 0;
int startTimer2 = 0;
int startTimer3 = 0;
int startTimer4 = 0;
int startTimer5 = 0;
int startTimer6 = 0;
int startTimer7 = 0;
int startTimer8 = 0;
int startTimer9 = 0;
int timer1 = 0;
int timer2 = 0;
int timer3 = 0;
int timer4 = 0;
int timer5 = 0;
int timer6 = 0;
int timer7 = 0;
int timer8 = 0;
int timer9 = 0;

float risk = 499.6;

void setup() {
  size(800, 800);
  frameRate(60); // probably don't need
  smooth(4); // probably don't need unless making a movie

  for (int i = 0; i < balls.length; i++) {
    balls[i] = new Ball(40, healthy); // diameter and colour
  }

  balls[0].col = sickrgb;

} // setup



void draw() {
  background(255);



  for (int i = 0; i < balls.length; i++) {
    balls[i].display();



    // flip

    if (!swap) {
      balls[i].move();
    } else {

      if (i !=0) {
        balls[i].move();
      }
    }

    // flip






    balls[i].edges();
    for (int o = 0; o < balls.length; o++) {




      float m = dist(balls[i].x, balls[i].y, balls[o].x, balls[o].y);
      if ((m < 40)&& (o!=i)) { 
        //if either (but not both) are sick then make both sick


        String zoo = hex(balls[o].col, 6);
        String goo = hex(balls[i].col, 6);


        if ((goo.equals(sickhex)) || (zoo.equals(sickhex))) {
          //println("poo poo");

          if (goo.equals(sickhex) == false) { // if i not infected 

            balls[i].col = sickrgb; // infect
            //turn on its timer

            if (i ==1) {
              startTimer1 = 1;
            } else if (i == 2) {
              startTimer2 = 1;
            } else if (i == 3) {
              startTimer3 = 1;
            } else if (i == 4) {
              startTimer4 = 1;
            } else if (i == 5) {
              startTimer5 = 1;
            } else if (i == 6) {
              startTimer6 = 1;
            } else if (i == 7) {
              startTimer7 = 1;
            } else if (i == 8) {
              startTimer8 = 1;
            } else if (i == 9) {
              startTimer9 = 1;
            } else {
              //nothing
            }
            //turn on its timer
          } else if (zoo.equals(sickhex) == false) { // if o not infected

            balls[o].col = sickrgb; // infect

            //turn on its timer

            if (o ==1) {
              startTimer1 = 1;
            } else if (o == 2) {
              startTimer2 = 1;
            } else if (o == 3) {
              startTimer3 = 1;
            } else if (o == 4) {
              startTimer4 = 1;
            } else if (o == 5) {
              startTimer5 = 1;
            } else if (o == 6) {
              startTimer6 = 1;
            } else if (o == 7) {
              startTimer7 = 1;
            } else if (o == 8) {
              startTimer8 = 1;
            } else if (o == 9) {
              startTimer9 = 1;
            } else {
              //nothing
            }
            //turn on its timer
          }
        } else {
          //
        }
      } else {
        //
      }


      if (o!=i) {

        balls[i].overlaps(balls[o]);
        balls[o].overlaps(balls[i]);
      }
    }
  }


  // life
  if (startTimer1 == 1) {
    // do something
    if (timer1 < thresh) {
      // risk
      if (random(500) > risk) { 
        balls[1].x = 100000000; 
        balls[1].y = 100000000;
        balls[1].col = color(255, 0, 0); // test by making red
      } else {
        timer1 = timer1 + 1;
      }
      // risk
    } else {
      balls[1].col = recovered;
    }
    // do something
  } else {
    // do nothing
  }

  // life

  // life
  if (startTimer2 == 1) {
    // do something
    if (timer2 < thresh) {
      // risk
      if (random(500) > risk) { 
        balls[2].x = 100000000; 
        balls[2].y = 100000000;
        balls[2].col = color(255, 0, 0); // test by making red
      } else {
        timer2 = timer2 + 1;
      }
      // risk
    } else {
      balls[2].col = recovered;
    }
    // do something
  } else {
    // do nothing
  }

  // life
  // life
  if (startTimer3 == 1) {
    // do something
    if (timer3 < thresh) {
      // risk
      // change 5 numbers
      if (random(500) > risk) { 
        balls[3].x = 100000000; 
        balls[3].y = 100000000;
        balls[3].col = color(255, 0, 0); // test by making red 
      } else {
        timer3 = timer3 + 1;
      }
      // risk
    } else {
      balls[3].col = recovered; 
    }
    // do something
  } else {
    // do nothing
  }




  // life
  // life
  if (startTimer4 == 1) {
    // do something
    if (timer4 < thresh) {
      // risk
      // change 5 numbers
      if (random(500) > risk) { 
        balls[4].x = 100000000; 
        balls[4].y = 100000000;
        balls[4].col = color(255, 0, 0); // test by making red 
      } else {
        timer4 = timer4 + 1;
      }
      // risk
    } else {
      balls[4].col = recovered; 
    }
    // do something
  } else {
    // do nothing
  }

  // life
  // life
  if (startTimer5 == 1) {
    // do something
    if (timer5 < thresh) {
      // risk
      // change 5 numbers
      if (random(500) > risk) { 
        balls[5].x = 100000000; 
        balls[5].y = 100000000;
        balls[5].col = color(255, 0, 0); // test by making red 
      } else {
        timer5 = timer5 + 1;
      }
      // risk
    } else {
      balls[5].col = recovered; 
    }
    // do something
  } else {
    // do nothing
  }

  // life
  // life
  if (startTimer6 == 1) {
    // do something
    if (timer6 < thresh) {
      // risk
      // change 5 numbers
      if (random(500) > risk) { 
        balls[6].x = 100000000; 
        balls[6].y = 100000000;
        balls[6].col = color(255, 0, 0); // test by making red 
      } else {
        timer6 = timer6 + 1;
      }
      // risk
    } else {
      balls[6].col = recovered; 
    }
    // do something
  } else {
    // do nothing
  }

  // life
  // life
  if (startTimer7 == 1) {
    // do something
    if (timer7 < thresh) {
      // risk
      // change 5 numbers
      if (random(500) > risk) { 
        balls[7].x = 100000000; 
        balls[7].y = 100000000;
        balls[7].col = color(255, 0, 0); // test by making red 
      } else {
        timer7 = timer7 + 1;
      }
      // risk
    } else {
      balls[7].col = recovered; 
    }
    // do something
  } else {
    // do nothing
  }

  // life
  // life
  if (startTimer8 == 1) {
    // do something
    if (timer8 < thresh) {



      // risk
      // change numbers
      if (random(500) > risk) { 
        balls[8].x = 100000000; 
        balls[8].y = 100000000;
        balls[8].col = color(255, 0, 0); // test by making red 
      } else {
        timer8 = timer8 + 1;
      }
      // risk
    } else {
      balls[8].col = recovered; 
    }
    // do something
  } else {
    // do nothing
  }

  // life
  // life
  if (startTimer9 == 1) {
    // do something
    if (timer9 < thresh) {
      // risk
      // change numbers
      if (random(500) > risk) { 
        balls[9].x = 100000000; 
        balls[9].y = 100000000;
        balls[9].col = color(255, 0, 0); // test by making red 
      } else {
        timer9 = timer9 + 1;
      }
      // risk
    } else {
      balls[9].col = recovered; 
    }
    // do something
  } else {
    // do nothing
  }

  // life




  if (timer0 < thresh) {



    if (random(500) > risk) { 



      balls[0].x = 100000000; 
      balls[0].y = 100000000;
      balls[0].col = color(255, 0, 0); // test by making red 
    } else {
      timer0 = timer0 + 1;
    }




  } else {
    balls[0].col = recovered; 


    //flip

    if (swap) {
      balls[0].move(); // now free to move 
    }

    //flip
  }


  //
} // end of draw


class Ball {
  float dia;
  float x;
  float y; 
  color col;
  float xspeed;
  float yspeed;
  float r;

  Ball (float tempD, color tempC) {
    x = random(50, width-50); // start location & not off stage 
    y = random(50, height-50); // start location & not off stage
    dia = tempD;
    col = tempC;
    r = dia/2;
    xspeed = xspeedValue;
    yspeed = yspeedValue;
  }

  void display() {
    noStroke();
    fill(col);
    ellipse(x, y, dia, dia);
  }

  void move() {

    x = x + xspeed;
    y = y + yspeed;
  }

  void edges() {
    if (x > width-r ) {
      xspeed = abs(xspeed) * -1;
    }
    if ( x < r) {
      xspeed = abs(xspeed);
    }
    if (y > height-r ) {
      yspeed = abs(yspeed) * -1;
    }
    if ( y < r) {
      yspeed = abs(yspeed);
    }
  }
  
  void overlaps(Ball o) { 

    float d = dist(x, y, o.x, o.y);
    if (d <= r + o.r) { //if collision

      if (x<o.x) {
        xspeed= -abs(xspeed);
      }
      if (x>o.x) {
        xspeed= abs(xspeed);
      }
      if (y<o.y) {
        yspeed= -abs(yspeed);
      }
      if (y>o.y) {
        yspeed= abs(yspeed);
      }
    }
  }
}
1 Like

If statements and else statements can be shortened when the code is simple, ie

if (x<o.x) {
        xspeed= -abs(xspeed);
      }

becomes

if (x<o.x)xspeed= -abs(xspeed);

note this can cause performance problems if you are changing more than one variable.

2 Likes

Thanks @GoToLoop I have now read these very good pages on arrays and on classes. I have used a class for all the things that are there from the beginning and that have a consistent behaviour, such as movement and collision detection. My problem is with the timers. Each ball has a timer (that measures the duration of its infection) but the timer does not start until a ball collides with a sick ball. This means that each ball’s timer starts at a different time. For that reason, I have code for each ball’s timer. Ten balls, ten repetitions of almost identical code. How do I avoid this repetition?

So it’s another attribute you need to create as an extra field inside your Ball class. :softball:

And if you prefer, you can use the Countdown class below in place of millis(): :timer_clock:

2 Likes