Introduction To Computational Media (ICM) : Week 4

Over and over again

Loops (once again)

Computers are very good at doing some things, particularly good at following exact instructions and very good at doing the same thing over and over again without complaint (unlike us). One example of of this repetition is Processing's built-in draw function or method. This is a loop; a block of code that gets repeatedly called until the program is terminated or some other condition is met. In the case of the draw() function, that stop condition is set by calling the noLoop() function.

This is an example of a Processing program that only goes through the draw function once.
            int x = 10; 
            
            void setup() 
            { 
              size(200, 200); 
              stroke(255);
              frameRate(30);
            } 
             
            void draw() 
            { 
              background(0);
              x++; 
               
              if (x >= width) 
              { 
                x = 0; 
              } 
              
              line(x, 0, x, height); 
              
              noLoop();
            }
        
The draw() function is called as it should be (automagically) but at the end of the first time through, noLoop() is called which sets a condition (somewhere that we can not see) that states that the draw() function should not be called repeatedly.

If we are to comment out the code that calls noLoop() or add a function that does the opposite, calls loop(), which sets the same condition to true when the mouse is pressed and again calls noLoop() when the mouse is released we can illustrate.
            int x = 10; 
            
            void setup() 
            { 
              size(200, 200); 
              stroke(255);
              frameRate(30);
              noLoop();
            } 
             
            void draw() 
            { 
              background(0);
              x++; 
               
              if (x >= width) 
              { 
                x = 0; 
              } 
              
              line(x, 0, x, height); 
              
            } 
             
            void mousePressed() 
            { 
              // Tell Processing to loop the draw function
              loop(); 
            } 
             
            void mouseReleased() 
            { 
              // Tell Processing not to loop the draw function
              noLoop(); 
            } 
        
This does not mean that execution of the program has suspended. Other functions may be running and the program is still listening for mouse input.

While Loops

Of course, we can create our own loops and have our own conditions on whether or not they should run.
            void setup()
            {
              size(100,100);
              noLoop();  // Tells the draw function not to loop, it still runs once.
            }
            
            void draw()
            {
              whileExample();  // Call our function with the while loop
            }
            
            void whileExample()
            {
              int x = 10;
              while (x < 100)  // Just like an if statement only keep doing it until the condition is no longer true
              {
                line(x,0,x,height);
                x = x + 10;
              }
              redraw();  // Call the draw function once we are done to display the lines.
            }
        
This is an example of the while loop which is very much like an if statement in that an expression is evaluated and the code block is executed if that expression turns out to be true.

A couple of interesting things other than the while loop:

noLoop() Tells Processing not to run draw as a loop. It will still run it once.

redraw() Tells Processing to run the draw function (once).

Of course, you can nest loops (loop within a loop):
            void setup() 
            { 
              size(screen.width,screen.height);
            } 
            
            void draw()
            {
              drawCrazyBackground(20);
            }
            
            void drawCrazyBackground(int bsize)
            {  
              int x = 0;
              int y = 0;
              
              while (x < width)
              {
                while(y < height)
                {
                  ellipse(x,y,bsize,bsize);
                  y = y + bsize;
                }
                y = 0;
                x = x + bsize;
              }
            }
        
Some fun that I had with while loops

For Loops

For loops are very much like while loops with the exception that they specify an initialization, a condition and what to update. Generally, these three are all related.

In our while loop example above, we also had the same thing but in multiple steps.
            int x = 10;  // Initialization
            while (x < 100)  // Condition
            {
                line(x,0,x,height);
                x = x + 10; // Update or increment
            }
        
The corresponding for loop:
            for (int x = 0; x < 100; x = x + 10)
            {
                line(x,0,x,height);
            }
        
Much easier and less to remember because it all done in one step..

Lots and lots of things

Arrays

Arrays are a convient way to handle multiple items of the same data type (integers, objects or anything else).

This is a representation of an int array containing 9 elements:
            ------------------------------------------
            | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 |
            ------------------------------------------
        
The code to create this array might be something like the following:
            int[] myArray = {1,2,4,8,16,32,64,128,256};
        
or it could be done using a for loop
            int[] myArray = new int[9];
            for (int i = 0; i < myArray.length; i++)
            {
                myArray[i] = pow(2,i);
            }
        
nameOfArray.length gives you the number of elements in the array.

nameOfArray[indexNumber] gives you the individual element of the array at a given index number. Remember, index numbers start at 0 so the first index of the array is 0 and the last one in our array is 8.

pow(base, exponent) is a built-in processing function for the math expression of power. 2 to the power of 2 is 4 (in other words squared). 2 power of 3 is 8 (in other words, 2 cubed). Anyh base to the power of exponent is the base multiplied by itself the exponent number of times. 2 to the power of 4 is 2 x 2 x 2 x 2 or 16.

For Loops, as you can see above, are great for dealing with arrays. Start at 0 and go to the length of the array to perform the same operation on each element in the array.

Arrays and Objects

If we develop a Ball Class such as follows:
// The name of our class
class Ball
{

  // our Class variables.  
  int wWidth;
  int wHeight;
  int bSize;
  
  int x, y;
  int xDirection, yDirection;
  
  // Constructor.  This gets called when we create a "new Ball"
  Ball(int windowWidth, int windowHeight, int ballSize)
  {
    wWidth = windowWidth;
    wHeight = windowHeight;
    bSize = ballSize;
    x = 1;
    y = 1;
    xDirection = 1;
    yDirection = 1;
  }

  Ball(int windowWidth, int windowHeight, int ballSize, int xPosition, int yPosition, int xDir, int yDir) 
  {
    this(windowWidth, windowHeight, ballSize);
    x = xPosition;
    y = yPosition;
    xDirection = xDir;
    yDirection = yDir;
  }
  
  // Our method to determine current position of the ball.
  void compute()
  {
    if (x < wWidth && x > 0)
    {
      // Move along x axis
      x += xDirection;
    }
    else
    {
      // Change direction, from positive to negative and vice versa
      xDirection = xDirection * -1;
      x += xDirection;
    }
    
    if (y < wHeight && y > 0)
    {
      y += yDirection;    
    }
    else
    {
      yDirection = yDirection * -1;
      y += yDirection;
    }
  }
  
  // This actually displays our ball, it gets called in the main draw function
  void display()
  {
    compute();  // first we run the computation
    ellipseMode(CENTER);
    ellipse(x,y,bSize,bSize);   
  }

}
	
And decide that we want multiple Ball's, we can use an "array" of Ball objects like so:
            Ball[] ourBalls;  // Declare array of Ball objects called ourBalls
            int numBalls = 50;  // An integer to hold the number of Ball objects we are going to create
            
            void setup()
            {
              size(500,500);
              ourBalls = new Ball[numBalls];  // Initalize the array, passing in the brackets the number of Ball objects
              for (int i = 0; i < ourBalls.length; i++)  // Use our nifty for loop, starting at 0 and going to the number of objects in the array.  Incrementing i by 1 each time.
              {
                // Using the overloaded constructor
                // Ball(int windowWidth, int windowHeight, int ballSize, int xPosition, int yPosition, int xDirection, int yDirection)
                // Picking some values just to see what happens    
                // Create a Ball object for each element in the array.
                ourBalls[i] = new Ball(width, height, i+10, i+1, i-1, i, 1 - i);
              }
            }
            
            void draw()
            {
              background(0);
              // Use another for loop to tell each of the Ball objects to display
              for (int i = 0; i < ourBalls.length; i++)
              {
                ourBalls[i].display();
              }
            }        
        
See it

More of Last Week

One type to another

Casting is the process of turning data from a variable or constant from one type another. Of course, you can only cast to and from compatible types such as from int to float and vice versa.

            int x = 0;
            float y = (float) x;
        
The above example casts the integer x as a float so as to assign it to the y variable.

A common use of casting is when a function or method gives you one type of value, perhaps a float and you need to use it as an integer.

For instance:
The random() function is very useful when you want to mix things up, such as x and y position. Unfortunately, random generates floats and therefore in order to be use for integer based x and y positions it needs to be cast (effectively disregarding the floating point or decimal value).
        int x, y;
        int w, h;
        size(400,400);
        x = (int) random(width);
        y = (int) random(height);
        h = (int) random(height);
        w = (int) random(width);
        ellipse(x,y,w,h);
        
This would draw an ellipse with a random height and width at a random x and y point.