Friday, 8 January 2010

Chunk 41 - 2nd program

The second program is an attempt to create a Star Wars type lightspeed effect whilst using the program from the chunk. The end result looks like this:





// the number of stars
int numberOfStars;
// coordinates of the vertices
float[][] vertexCoords;
// speed (number of pixels) that the vertices move in the x direction
int xSpeed;
// speed (number of pixels) that the vertices move in the x direction
int ySpeed;

void setup() {

// setup display variables
size(600, 400);
background(0);
smooth();
strokeWeight(2);
stroke(255);
frameRate(30);

ySpeed = 4;
xSpeed = 10;
numberOfStars = 500;
// initialise each vertex to be the middle of the display
vertexCoords = new float[numberOfStars][4];
for (int i = 0; i < numberOfStars; i++) {
createCoords(i);
}

}

void draw() {
// clear the screen by resetting the background
background(0);
// for every vertex
for (int i = 0; i < numberOfStars; i++) {
if (hasLeftScreen(i)) {
// reset
createCoords(i);
}
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(vertexCoords[i][0], vertexCoords[i][1]);
// to coordinates nearer the centre to give the illusion of movement
vertex(vertexCoords[i][0] + (vertexCoords[i][2] * 5), vertexCoords[i][1] + (vertexCoords[i][3] * 5));
endShape();
// draw the point at the coordinates - this will give a 'classic' starfield simulation
//point(vertexCoords[i][0], vertexCoords[i][1]);
vertexCoords[i][0] = vertexCoords[i][0] + vertexCoords[i][2];
vertexCoords[i][1] = vertexCoords[i][1] + vertexCoords[i][3];

}
}

/**
* Work out of the vertex has left the screen
*
* @param vertexIndex the index of the vertex
* @return true if the vertex has left the screen
*/
boolean hasLeftScreen(int vertexIndex) {
// return true if the vertex has reached the top, the bottom or either side of the screen
return vertexCoords[vertexIndex][0] >= width
|| vertexCoords[vertexIndex][0] <= -width
|| vertexCoords[vertexIndex][1] >= height
|| vertexCoords[vertexIndex][1] <= -height;

}

/**
* Create the coordinates for the given vertex index number
*
* @param vertexIndex the index number of the vertex
*/
void createCoords(int vertexIndex) {
// create a random direction for the star
float xDirection = random(-xSpeed, xSpeed);
float yDirection = random(-ySpeed, ySpeed);

//create the coordinates as an array consisting of:
//0 - current x coordinate
//1 - current y coordinate
//2 - direction of the x coordinate
//3 - direction of the y coordinate
vertexCoords[vertexIndex] = new float[] {
(width / 2) + xDirection,
(height / 2) + yDirection,
xDirection,
yDirection};
}

Chunk 41 - FINAL

This is the first chunk in which we show you what can be achieved in Processing using the vertex function introduced in the previous chunk. We will create a small program that uses vertices (that is, many vertexes) to create an animation. The display we are aiming to achieve is shown in figure 41.1



Figure 41.1 The final animation

The code for this is shown below:


// the number of vertices
int numberOfVertices;
// coordinates of the vertices
float[][] vertexCoords;
// speed (number of pixels) that the vertices move
int speed;

void setup() {

// setup display variables
size(600, 400);
background(0);
smooth();
strokeWeight(10);
stroke(255);
frameRate(100);

speed = 4;
numberOfVertices = width;
// initialise each vertex to be the middle of the display
vertexCoords = new float[numberOfVertices][2];
for (int i = 0; i < numberOfVertices; i++) {
vertexCoords[i] = new float[] {width / 2, height / 2};
}

}

void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// for every vertex
for (int i = 0; i < numberOfVertices; i++) {
// draw the vertex at the coordinates
vertex(vertexCoords[i][0], vertexCoords[i][1]);
// draw the point at the coordinates
//point(xCoords[i], yCoords[i]);
// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
vertexCoords[i][0] = vertexCoords[i][0] + randomXDirection;
vertexCoords[i][1] = vertexCoords[i][1] + randomYDirection;
}
endShape();
}


Don't worry about understanding this code yet as we will walk through it. What we are attempting to produce is the image in figure 41.1 – a 'sparkler' type effect that will animate and grow in a random pattern. Each point in the animation will be separate from the others so that the sparkling will grow as each point moves away from the others.

We will start with using the vertex function similarly to page xx by simply creating a 'dot' on the screen, as shown in figure 41.2



Figure 41.2 A single vertex

The code for this is fairly simple:



void setup() {

// setup display variables
size(600, 400);
background(0);
smooth();
strokeWeight(10);
stroke(255);

}

void draw() {
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(width / 2, height / 2);
endShape();
}


Here we are simply creating a window of size 600 x 400 with a black background and drawing a single white vertex in the middle of the screen (where width / 2 is the width of the window divided by 2, and height /2 is the height of the window divided by 2, so the middle). As seen on page xx, the smooth() function is the anti-aliasing function that gives a smoother appearance to lines and shapes. Adding this function displays the image with smoother lines and is more appealing to look at. Try removing it and you will see that the dot has jaggedy lines, whereas adding smooth() results in a circular looking dot

As we are using the Processing continuous mode (in the above example the dot appears static because it is being drawn over the top of the previous one each time the draw() method is run), we can introduce some animation by moving the vertex each time. We can add some variables to store the current coordinates of the vertex, and a speed variable to control how much it moves each time


float xCoords;
float yCoords;
int speed;


In the setup() method we can initalise these so that the starting coordinates are the middle of the screen.


speed = 2;
xCoords = width / 2;
yCoords = height / 2;


The coordinate variables can then be accessed and updated in the draw() method by drawing the vertex at the value of the coordinates, then updating them by adding the value of the speed variable, so that next time the draw() method is run, the coordinates will have changed and the dot will appear to move


beginShape();
// draw the vertex at the coordinates
vertex(xCoords, yCoords);
endShape();
// add the speed direction to the existing coordinates
xCoords = xCoords + speed;
yCoords = yCoords + speed;


The updated program is shown below


// coordinates of the vertices
float xCoords;
float yCoords;
// speed (number of pixels) that the vertices move
int speed;

void setup() {

// setup display variables
size(600, 400);
background(0);
smooth();
strokeWeight(10);
stroke(255);

speed = 2;
xCoords = width / 2;
yCoords = height / 2;

}

void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(xCoords, yCoords);
endShape();
// add the speed direction to the existing coordinates
xCoords = xCoords + speed;
yCoords = yCoords + speed;
}


If you run this you will see that the dot now moves off the screen, from the middle towards the bottom-right, because we are adding the value of the speed variable to the coordinates each time. The illusion of movement is enhanced by clearing the screen each time by setting the background each time

We can now introduce some random movement to the vertex by randomising the direction it will move by using the random() function seen on page xx to randomise the speed variable each time. To do this, all we need to do is replace the following lines in the draw() method


// add the speed direction to the existing coordinates
xCoords = xCoords + speed;
yCoords = yCoords + speed;


with the lines


// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords = xCoords + randomXDirection;
yCoords = yCoords + randomYDirection;


This piece of code creates a random number between the values -speed and speed (currently set to 2) and uses the random value to set the coordinate values for the next time the vertex is drawn. This makes the draw method look like the below


void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(xCoords, yCoords);
endShape();
// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords = xCoords + randomXDirection;
yCoords = yCoords + randomYDirection;

}


If you run this, you will see that the the dot now moves around its starting point in a random fashion. This is due to the random value added to the coordinates that means the dot moves slightly each time it is drawn.

The next stage of our animation is to create more vertices. This is where our program begins to become a bit more complex. In order to create many vertices we need to issue the vertex() function as many times as we want them created. For a few vertices it would be acceptable to just write the command that many times such as


vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));
vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));
vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));


where the coordinates are altered for successive vertices so that they are displayed in different places on the screen by adding or removing a number, in this case a random amount between -speed and speed. However, if we want a large number of vertices, this would become rather cumbersome and tedious to write. A loop statement would make this easier by simply looping for the number of vertices we want to create, such as


for (int i = 0; i < 100; i++) {
vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));
}


This would create 100 vertices at random coordinates around the xCoords and yCoords values. The draw() method now looks like the following



void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
for (int i = 0; i < 100; i++) {
vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));
}
endShape();
// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords = xCoords + randomXDirection;
yCoords = yCoords + randomYDirection;
}


If you run this, you will see a 'sparkler' type effect shown in figure 41.3, similar to the effect we wanted, except that the whole animation moves, rather than individual points, and so it stays the same size.



Figure 41.3 Sparkler effect

As you can see, rather than the dots we started with, creating more than one vertex has created a solid, but complex, shape with little coding. This is because we have placed the vertex() function call between the beginShape() and endShape() functions. Doing this means that each vertex is taken as a point in a shape, and each vertex is joined up to create a single shape, rather than a set of dots. The shape is filled-in white because of the stroke(255) in the setup() method which tells Processing to create the shape white.

If each vertex were taken as a single shape, by putting beginShape() and endShape() inside the loop statement, each vertex would be drawn as a dot and a shape would not be created from all of the vertices together. This is the same effect that would be achieved by using point() rather than vertex(), which highlights the difference between the two functions.

To enable each vertex to act independently we need to be able to specify the coordinates of each vertex independently, rather than linking them all to being a random number from the one set of coordinates, which means that every vertex will move more-or-less together.

To do this we can create an array containing the coordinates of each vertex. As we need each vertex to have two values, one for the x (horizontal) coordinates and one for the y (vertical) coordinates, either we would need two arrays to hold the values, or we could use a 2-dimensional array as introduced on page xx. Another, and possibly preferable, option would be to define the concept of a vertex's coordinates using a class – this is discussed later on page xx.

Our array will need to be the same size as the number of vertices we are going to create. The 2nd dimension will then need to contain the coordinates of the vertex – so its size will be 2 – and we will store them in the order x, y. The declaration for the array looks like


float[][] vertexCoords;



We also need a variable to contain the number of vertices we will be creating


int numberOfVertices;



We can then specify the size of the arrays using the numberOfVertices


numberOfVertices = width;
vertexCoords = new float[numberOfVertices][2];


This initialises the number of vertices to be the size of the screen's width, which we have found yields good results. The array is then declared as being of that size in its first dimension, and size two in its second dimension, which will hold the coordinates.

Previously we set the coordinates to start with a value that places them in the middle of the screen. We will still need to do that but now we have a large number of coordinates to set, so we can use a loop to set the initial values


for (int i = 0; i < numberOfVertices; i++) {
vertexCoords[i] = new float[] {width / 2, height / 2};
}


This sets the 2nd dimension in the array as being the centre of the window as before, so that each vertex is created at the same point. This makes the setup() method look like the following


void setup() {

// setup display variables
size(600, 400);
background(0);
smooth();
strokeWeight(10);
stroke(255);
frameRate(100);

speed = 4;
numberOfVertices = width;
// initialise each vertex to be the middle of the display
vertexCoords = new float[numberOfVertices][2];
for (int i = 0; i < numberOfVertices; i++) {
vertexCoords[i] = new float[] {width / 2, height / 2};
}

}


Now we need to access the coordinates of each vertex and draw it inside our loop by looping through the arrays and using the coordinates found there to create a vertex. As we now have the number of vertices stored in the numberOfVertices variable, we can use that in the loop to define the number of times it should loop



beginShape();
// for every vertex
for (int i = 0; i < numberOfVertices; i++) {
// draw the vertex at the coordinates
vertex(vertexCoords[i][0], vertexCoords[i][1]);
}



The line


vertex(vertexCoords[i][0], vertexCoords[i][1]);


is the one that draws the vertex, using the 2nd dimension array found in at position i. To begin with, every coordinate is set as the same value – the ones we set in the setup() method, so each vertex will be drawn on top of each other.

We also now need to alter our code for updating the coordinates each time the draw() method is run. As the coordinates are now held in an array, rather than single float variables, we will need to update every value. This is where we have scope for altering each vertex independently, which we can do in a random fashion by randomly assigning a value to alter the coordinates by.

Each time the a vertex is drawn inside the loop, we can also update the value of each coordinate so that the value is changed for the next time the vertex is drawn. If we use our previously created random coordinate calculation, we can update the value in the arrays by adding that random value to the coordinates currently held at that position in the array


float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
vertexCoords[i][0] = vertexCoords[i][0] + randomXDirection;
vertexCoords[i][1] = vertexCoords[i][1] + randomYDirection;


The lines at the bottom set the coordinate value to the old value and add the random value to it. As this is now set as the value in the array, the coordinates for that vertex will have changed next time it is drawn. As the random value will be different each time it is generated, the coordinates of each vertex will gradually become more different, and so move further away from the starting point. This means that the sparkler animation will appear to grow as the coordinates are updated.

Running the program, which should now be the same as the very first listing, will show a small sparkler that gradually seems to grow and 'flicker'. If you want to speed up the animation you can add a call inside the setup() method to the frameRate() function that sets how many frames are displayed and therefore the speed at which the animation runs. The default is 60, so frameRate(100); will make it run faster

As a final point, the difference between using vertex() and point() is highlighted even more now that we have introduced this final piece of functionality using the arrays. Changing the vertex() function call to a point() function call


point(vertexCoords[i][0], vertexCoords[i][1]);


will display each point as a dot, except now each one is controlled independently using the arrays. If you make this change, something quite interesting happens – as each point is moving randomly, but starts at the same point, they appear to multiply from the centre a little like bacteria growth.




Figure 41.4 Bacteria growth animation

Thursday, 7 January 2010

First 1500 words or so (draft)

This is the first chunk in which we show you what can be achieved in Processing using the vertex function introduced in the previous chunk. We will create a small program that uses vertices (that is, many vertexes).

The display we are aiming to achieve is shown in figure 41.1



Figure 41.1 The final animation

The code for this is shown below:


// coordinates of the vertices
float[] xCoords;
float[] yCoords;
// the number of vertices
int numberOfVertices;
// the screen size
int screenXSize;
int screenYSize;
// speed (number of pixels) that the vertices move
int speed;

void setup() {

// initialise
screenXSize = 600;
screenYSize = 400;

speed = 2;
numberOfVertices = screenXSize;
xCoords = new float[numberOfVertices];
yCoords = new float[numberOfVertices];

// setup display variables
size(screenXSize, screenYSize);
background(0);
smooth();
strokeWeight(10);
stroke(255);
// initialise each vertex to be the middle of the display
for (int i = 0; i < numberOfVertices; i++) {
xCoords[i] = screenXSize / 2;
yCoords[i] = screenYSize / 2;
}

}

void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// for every vertex
for (int i = 0; i < numberOfVertices; i++) {
// draw the vertex at the coordinates
vertex(xCoords[i], yCoords[i]);
// draw the point at the coordinates
// point(xCoords[i], yCoords[i]);
// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords[i] = xCoords[i] + randomXDirection;
yCoords[i] = yCoords[i] + randomYDirection;
}
endShape();
}


Don't worry about understanding this code yet as we will walk through it. What we are attempting to produce is the image in figure 41.1 – a 'sparkler' type effect that will animate and grow in a random pattern. Each point in the animation will be separate from the others so that the sparkling will grow as each point moves away from the others.

We will start with using the vertex function similarly to page xx by simply creating a 'dot' on the screen, as shown in figure 41.2



Figure 41.2 A single vertex

The code for this is fairly simple:


// the screen size
int screenXSize;
int screenYSize;

void setup() {

// initialise
screenXSize = 600;
screenYSize = 400;

// setup display variables
size(screenXSize, screenYSize);
background(0);
smooth();
strokeWeight(10);
stroke(255);

}

void draw() {
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(screenXSize / 2, screenYSize / 2);
endShape();
}


Here we are simply creating a window of size 600 x 400 with a black background and drawing a single white vertex in the middle of the screen (where screenXSize / 2 is the size of the x-axis divided by 2, so the middle). As seen on page xx, the smooth() function is the anti-aliasing function that gives a smoother appearance to lines and shapes. Adding this function displayes the image with smoother lines and is more appealing to look at. Try removing it and you will see that the dot has jaggedy lines, whereas adding smooth() results in a circular looking dot

As we are using the Processing continuous mode (in the above example the dot appears static because it is being drawn over the top of the previous one each time the draw() method is run), we can introduce some animation by moving the vertex each time. We can add some variables to store the current coordinates of the vertex, and a speed variable to control how much it moves each time


float xCoords;
float yCoords;
int speed;


In the setup() method we can initalise these so that the starting coordinates are the middle of the screen.


speed = 2;
xCoords = screenXSize / 2;
yCoords = screenYSize / 2;


The coordinate variables can then be accessed and updated in the draw() method by drawing the vertex at the value of the coordinates, then updating them by adding the value of the speed variable, so that next time the draw() method is run, the coordinates will have changed and the dot will appear to move


beginShape();
// draw the vertex at the coordinates
vertex(xCoords, yCoords);
endShape();
// add the speed direction to the existing coordinates
xCoords = xCoords + speed;
yCoords = yCoords + speed;


The updated program is shown below


// coordinates of the vertices
float xCoords;
float yCoords;
// the screen size
int screenXSize;
int screenYSize;
// speed (number of pixels) that the vertices move
int speed;

void setup() {

// initialise
screenXSize = 600;
screenYSize = 400;

speed = 2;
xCoords = screenXSize / 2;
yCoords = screenYSize / 2;

// setup display variables
size(screenXSize, screenYSize);
background(0);
smooth();
strokeWeight(10);
stroke(255);

}

void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(xCoords, yCoords);
endShape();
// add the speed direction to the existing coordinates
xCoords = xCoords + speed;
yCoords = yCoords + speed;
}


If you run this you will see that the dot now moves off the screen, from the middle towards the bottom-right, because we are adding the value of the speed variable to the coordinates each time. The illusion of movement is enhanced by clearing the screen each time by setting the background each time

We can now introduce some random movement to the vertex by randomising the direction it will move by using the random() function seen on page xx to randomise the speed variable each time. To do this, all we need to do is replace the following lines in the draw() method


// add the speed direction to the existing coordinates
xCoords = xCoords + speed;
yCoords = yCoords + speed;


with the lines


// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords = xCoords + randomXDirection;
yCoords = yCoords + randomYDirection;


This piece of code creates a random number between the values -speed and speed (currently set to 2) and uses the random value to set the coordinate values for the next time the vertex is drawn. This makes the draw method look like the below


void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(xCoords, yCoords);
endShape();
// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords = xCoords + randomXDirection;
yCoords = yCoords + randomYDirection;

}


If you run this, you will see that the the dot now moves around its starting point in a random fashion. This is due to the random value added to the coordinates that means the dot moves slightly each time it is drawn.

The next stage of our animation is to create more vertices. This is where our program begins to become a bit more complex. In order to create many vertices we need to issue the vertex() function as many times as we want them created. For a few vertices it would be acceptable to just write the command that many times such as


vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));
vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));
vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));


where the coordinates are altered for successive vertices so that they are displayed in different places on the screen by adding or removing a number, in this case a random amount between -speed and speed. However, if we want a large number of vertices, this would become rather cumbersome and tedious to write. A loop statement would make this easier by simply looping for the number of vertices we want to create, such as


for (int i = 0; i < 100; i++) {
vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));
}


This would create 100 vertices at random coordinates around the xCoords and yCoords values. The draw() method now looks like the following



void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
for (int i = 0; i < 100; i++) {
vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));
}
endShape();
// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords = xCoords + randomXDirection;
yCoords = yCoords + randomYDirection;
}


If you run this, you will see a 'sparkler' type effect shown in figure 41.3, similar to the effect we wanted, except that the whole animation moves, rather than individual points, and so it stays the same size.


Figure 41.3

As you can see, rather than the dots we started with, creating more than one vertex has created a solid, but complex, shape with little coding. This is because we have placed the vertex() function call between the beginShape() and endShape() functions. Doing this means that each vertex is taken as a point in a shape, and each vertex is joined up to create a single shape, rather than a set of dots. The shape is filled-in white because of the stroke(255) in the setup() method which tells Processing to create the shape white.

If each vertex were taken as a single shape, by putting beginShape() and endShape() inside the loop statement, each vertex would be drawn as a dot and a shape would not be created from all of the vertices together. This is the same effect that would be achieved by using point() rather than vertex(), which highlights the difference between the two functions.

To enable each vertex to act independently we need to be able to specify the coordinates of each vertex independently, rather than linking them all to being a random number from the one set of coordinates, which means that every vertex will move more-or-less together.

To do this we can create arrays containing the coordinates of each vertex. We will need two arrays, one to hold the x (horizontal) coordinates and one to hold the y (vertical) coordinates. Another, and possibly preferable, option would be to define the concept of a vertex's coordinates using a class – this is discussed later on page xx.

Our two arrays will need to be of equal size as each will be holding half the coordinates for a vertex. We can adapt our xCoords and yCoords variables to be arrays by adding the brackets


float[] xCoords;
float[] yCoords;


and adding a variable to contain the number of vertices we will be creating


int numberOfVertices;



We then need to specify the size of the arrays using the numberOfVertices


numberOfVertices = screenXSize;
xCoords = new float[numberOfVertices];
yCoords = new float[numberOfVertices];


This initialises the number of vertices to be the size of the screen's width, which we have found yields good results. The arrays are then declared as being of that size. Previously we set the coordinates to start with a value that places them in the middle of the screen. We will still need to do that but now we have a large number of coordinates to set, so we can use a loop to set the initial values


for (int i = 0; i < numberOfVertices; i++) {
xCoords[i] = screenXSize / 2;
yCoords[i] = screenYSize / 2;
}


This sets every float in the xCoords array to be the centre of the screen width, and every float in the yCoords array to be the centre of the screen height. This makes the setup() method look like the following


void setup() {

// initialise
screenXSize = 600;
screenYSize = 400;

speed = 2;
numberOfVertices = screenXSize;
xCoords = new float[numberOfVertices];
yCoords = new float[numberOfVertices];

// setup display variables
size(screenXSize, screenYSize);
background(0);
smooth();
strokeWeight(10);
stroke(255);
// initialise each vertex to be the middle of the display
for (int i = 0; i < numberOfVertices; i++) {
xCoords[i] = screenXSize / 2;
yCoords[i] = screenYSize / 2;
}

}


Now we need to access the coordinates of each vertex and draw it inside our loop by looping through the arrays and using the coordinates found there to create a vertex. As we now have the number of vertices stored in the numberOfVertices variable, we can use that in the loop to define the number of times it should loop



beginShape();
// for every vertex
for (int i = 0; i < numberOfVertices; i++) {
// draw the vertex at the coordinates
vertex(xCoords[i], yCoords[i]);
}
endShape();



The line


vertex(xCoords[i], yCoords[i]);


is the one that draws the vertex, using the value found in each array at position i. To begin with, every coordinate is set as the same value – the ones we set in the setup() method, so each vertex will be drawn on top of each other.

We also now need to alter our code for updating the coordinates each time the draw() method is run. As the coordinates are now held in arrays, rather than single float variables, we will need to update every value. This is where we have scope for altering each vertex independently in a random fashion.

Each time the a vertex is drawn inside the loop, we can also update the value of each coordinate so that the value is changed for the next time the vertex is drawn. If we use our previously created random coordinate calculation, we can update the value in the arrays by adding that random value to the coordinates currently held at that position in the array


float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords[i] = xCoords[i] + randomXDirection;
yCoords[i] = yCoords[i] + randomYDirection;


The lines at the bottom set the coordinate value to the old value and add the random value to it. As this is now set as the value in the array, the coordinates for that vertex will have changed next time it is drawn. As the random value will be different each time it is generated, the coordinates of each vertex will gradually become more different, and so move further away from the starting point. This means that the sparkler animation will appear to grow as the coordinates are updated.

Running the program, which should be the same as the very first listing, will show a small sparkler that gradually seems to grow and 'flicker'. If you want to speed up the animation you can add a call inside the setup() method to the frameRate() function that sets how many frames are displayed and therefore the speed at which the animation runs. The default is 60, so frameRate(100); will make it run faster

As a final point, the difference between using vertex() and point() is highlighted even more now that we have introduced this final piece of functionality using the arrays. Changing the vertex() function call to a point() function call


point(xCoords[i], yCoords[i]);


will display each point as a dot, except now each one is controlled independently using the arrays. If you make this change, something quite interesting happens – as each point is moving randomly, but starts at the same point, they appear to multiply from the centre a little like bacteria growth.



Figure 41.4 Bacteria growth animation

First 1000 words (draft)

This is the first chunk in which we show you what can be achieved in Processing using the vertex function introduced in the previous chunk. We will create a small program that uses vertices.

The display we are aiming to achieve is shown in figure 41.1



Figure 41.1 The final animation

The code for this is shown below:


// coordinates of the vertices
float[] xCoords;
float[] yCoords;
// the number of vertices
int numberOfVertices;
// the screen size
int screenXSize;
int screenYSize;
// speed (number of pixels) that the vertices move
int speed;

void setup() {

// initialise
screenXSize = 600;
screenYSize = 400;

speed = 2;
numberOfVertices = screenXSize;
xCoords = new float[numberOfVertices];
yCoords = new float[numberOfVertices];

// setup display variables
size(screenXSize, screenYSize);
background(0);
smooth();
strokeWeight(10);
stroke(255);
frameRate(60);
// initialise each vertex to be the middle of the display
for (int i = 0; i < numberOfVertices; i++) {
xCoords[i] = screenXSize / 2;
yCoords[i] = screenYSize / 2;
}

}

void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// for every vertex
for (int i = 0; i < numberOfVertices; i++) {
// draw the vertex at the coordinates
vertex(xCoords[i], yCoords[i]);
// draw the point at the coordinates
// point(xCoords[i], yCoords[i]);
// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords[i] = xCoords[i] + randomXDirection;
yCoords[i] = yCoords[i] + randomYDirection;
}
endShape();
}


Don't worry about understanding this code yet as we will walk through it. What we are attempting to produce is the image in figure 41.1 which will animate and grow in a random pattern.

We will start with using the vertex function similarly to page xx by simply creating 'dots' on the screen, as shown in figure 41.2



Figure 41.2 A single vertex

The code for this is fairly simple:


// the screen size
int screenXSize;
int screenYSize;

void setup() {

// initialise
screenXSize = 600;
screenYSize = 400;

// setup display variables
size(screenXSize, screenYSize);
background(0);
smooth();
strokeWeight(10);
stroke(255);

}

void draw() {
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(screenXSize / 2, screenYSize / 2);
endShape();
}


Here we are simply creating a window of size 600 x 400 with a black background and drawing a single white vertex in the middle of the screen (where screenXSize / 2 is the size of the x-axis divided by 2, so the middle). As seen on page xx, the smooth() function is the anti-aliasing function that gives a smoother appearance to lines and shapes. Adding this function displayes the image with smoother lines and is more appealing to look at. Try removing it and you will see that the dot has jaggedy lines, whereas adding smooth() results in a circular looking dot

As we are using the Processing continuous mode (in the above example the dot appears static because it is being drawn over the top of the previous one each time the draw() method is run), we can introduce some animation by moving the vertex each time. We can add some variables to store the current coordinates of the vertex, and a speed variable to control how much it moves each time, as shown below


// coordinates of the vertices
float xCoords;
float yCoords;
// the screen size
int screenXSize;
int screenYSize;
// speed (number of pixels) that the vertices move
int speed;

void setup() {

// initialise
screenXSize = 600;
screenYSize = 400;

speed = 2;
xCoords = screenXSize / 2;
yCoords = screenYSize / 2;

// setup display variables
size(screenXSize, screenYSize);
background(0);
smooth();
strokeWeight(10);
stroke(255);

}

void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(xCoords, yCoords);
endShape();
// add the speed direction to the existing coordinates
xCoords = xCoords + speed;
yCoords = yCoords + speed;
}


If you run this you will see that the dot now moves off the screen, from the middle towards the bottom-right, because we are adding the value of the speed variable to the coordinates each time. The illusion of movement is enhanced by clearing the screen each time by setting the background each time

We can now introduce some random movement to the vertex by randomising the direction it will move by using the random() function seen on page xx to randomise the speed variable each time. To do this, all we need to do is replace the following lines in the draw() method


// add the speed direction to the existing coordinates
xCoords = xCoords + speed;
yCoords = yCoords + speed;


with the lines


// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords = xCoords + randomXDirection;
yCoords = yCoords + randomYDirection;


This piece of code creates a random number between the values -speed and speed (currently set to 2) and uses the random value to set the coordinate values for the next time the vertex is drawn. This makes the draw method look like the below


void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(xCoords, yCoords);
endShape();
// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords = xCoords + randomXDirection;
yCoords = yCoords + randomYDirection;

}


If you run this, you will see that the the dot now moves around its starting point in a random fashion. This is due to the random value added to the coordinates that means the dot moves slightly each time it is drawn.

The next stage of our animation is to create more vertices. This is where our program begins to become a bit more complex. In order to create many vertices we need to issue the vertex() function as many times as we want them created. For a few vertices it would be acceptable to just write the command that many times such as


vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));
vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));
vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));


where the coordinates are altered for successive vertices so that they are displayed in different places on the screen by adding or removing a number, in this case a random amount between -speed and speed. However, if we want a large number of vertices, this would become rather cumbersome and tedious to write. A loop statement would make this easier by simply looping for the number of vertices we want to create, such as


for (int i = 0; i < 100; i++) {
vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));
}


This would create 100 vertices at random coordinates around the xCoords and yCoords values. The draw() method now looks like the following



public void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
for (int i = 0; i < 100; i++) {
vertex(xCoords + random(-speed, speed), yCoords + random(-speed, speed));
}
endShape();
// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords = xCoords + randomXDirection;
yCoords = yCoords + randomYDirection;
}


If you run this, you will see a 'sparkler' type effect shown in figure 41.3, similar to the effect we wanted, except that the whole animation moves, rather than individual points, and so it stays the same size.


Figure 41.3

As you can see, rather than the dots we started with, creating more than one vertex has created a solid, but complex, shape with little coding. This is because we have placed the vertex() function call between the beginShape() and endShape() functions. Doing this means that each vertex is taken as a point in a single shape, and each vertex is joined up to create a single shape, rather than a set of dots. The shape is filled-in white because of the stroke(255) in the setup() method which tells Processing to create the shape white.

If each vertex were taken as a single shape, by putting beginShape() and endShape() inside the loop statement, each vertex would be drawn as a dot and a shape would not be created from all of the vertices together. This is the same effect that would be achieved by using point() rather than vertex(), which highlights the difference between the two functions.

To enable each vertex to act independently we need to be able to specify the coordinates of each vertex independently, rather than linking them all to being a random number from the one set of coordinates, which means that every vertex will move more-or-less together.

To do this we can create arrays containing the coordinates of each vertex. We will need two arrays, one to hold the x (horizontal) coordinates and one to hold the y (vertical) coordinates. Another, and possibly preferable, option would be to define the concept of a vertex's coordinates using a class – this is discussed later on page xx.

Our two arrays will need to be of equal size as each will be holding half the coordinates for a vertex. We can adapt our xCoords and yCoords variables to be arrays by adding the brackets


float[] xCoords;
float[] yCoords;


and adding a variable to contain the number of vertices we will be creating


int numberOfVertices;



We then need to specify the size of the arrays using the numberOfVertices


numberOfVertices = screenXSize;
xCoords = new float[numberOfVertices];
yCoords = new float[numberOfVertices];


This initialises the number of vertices to be the size of the screen's width, which we have found yields good results. The arrays are then declared as being of that size. Previously we set the coordinates to start with a value that places them in the middle of the screen. We will still need to do that but now we have a large number of coordinates to set, so we can use a loop to set the initial values


for (int i = 0; i < numberOfVertices; i++) {
xCoords[i] = screenXSize / 2;
yCoords[i] = screenYSize / 2;
}


This sets every float in the xCoords array to be the centre of the screen width, and every float in the yCoords array to be the centre of the screen height.

Wednesday, 6 January 2010

First 500 words (draft)

This is the first chunk in which we show you what can be achieved in Processing using the vertex function introduced in the previous chunk. We will create a small program that uses vertices.

The display we are aiming to achieve is shown in figure 41.1



Figure 41.1 The final animation

The code for this is shown below:


// coordinates of the vertices
float[] xCoords;
float[] yCoords;
// the number of vertices
int numberOfVertices;
// the screen size
int screenXSize;
int screenYSize;
// speed (number of pixels) that the vertices move
int speed;

void setup() {

// initialise
screenXSize = 600;
screenYSize = 400;

speed = 2;
numberOfVertices = screenXSize;
xCoords = new float[numberOfVertices];
yCoords = new float[numberOfVertices];

// setup display variables
size(screenXSize, screenYSize);
background(0);
smooth();
strokeWeight(10);
stroke(255);
frameRate(60);
// initialise each vertex to be the middle of the display
for (int i = 0; i < numberOfVertices; i++) {
xCoords[i] = screenXSize / 2;
yCoords[i] = screenYSize / 2;
}

}

void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// for every vertex
for (int i = 0; i < numberOfVertices; i++) {
// draw the vertex at the coordinates
vertex(xCoords[i], yCoords[i]);
// draw the point at the coordinates
// point(xCoords[i], yCoords[i]);
// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords[i] = xCoords[i] + randomXDirection;
yCoords[i] = yCoords[i] + randomYDirection;
}
endShape();
}


Don't worry about understanding this code yet as we will walk through it. What we are attempting to produce is the image in figure 41.1 which will animate and grow in a random pattern.

We will start with using the vertex function similarly to page xx by simply creating 'dots' on the screen, as shown in figure 41.2



Figure 41.2 A single vertex

The code for this is fairly simple:


// the screen size
int screenXSize;
int screenYSize;

void setup() {

// initialise
screenXSize = 600;
screenYSize = 400;

// setup display variables
size(screenXSize, screenYSize);
background(0);
smooth();
strokeWeight(10);
stroke(255);

}

void draw() {
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(screenXSize / 2, screenYSize / 2);
endShape();
}


Here we are simply creating a window of size 600 x 400 with a black background and drawing a single white vertex in the middle of the screen (where screenXSize / 2 is the size of the x-axis divided by 2, so the middle). As seen on page xx, the smooth() function is the anti-aliasing function that gives a smoother appearance to lines and shapes. Adding this function displayes the image with smoother lines and is more appealing to look at. Try removing it and you will see that the dot has jaggedy lines, whereas adding smooth() results in a circular looking dot

As we are using the Processing continuous mode (in the above example the dot appears static because it is being drawn over the top of the previous one each time the draw() method is run), we can introduce some animation by moving the vertex each time. We can add some variables to store the current coordinates of the vertex, and a speed variable to control how much it moves each time, as shown below


// coordinates of the vertices
float xCoords;
float yCoords;
// the screen size
int screenXSize;
int screenYSize;
// speed (number of pixels) that the vertices move
int speed;

void setup() {

// initialise
screenXSize = 600;
screenYSize = 400;

speed = 2;
xCoords = screenXSize / 2;
yCoords = screenYSize / 2;

// setup display variables
size(screenXSize, screenYSize);
background(0);
smooth();
strokeWeight(10);
stroke(255);

}

void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(xCoords, yCoords);
endShape();
// add the speed direction to the existing coordinates
xCoords = xCoords + speed;
yCoords = yCoords + speed;
}


If you run this you will see that the dot now moves off the screen, from the middle towards the bottom-right, because we are adding the value of the speed variable to the coordinates each time. The illusion of movement is enhanced by clearing the screen each time by setting the background each time

We can now introduce some random movement to the vertex by randomising the direction it will move by using the random() function seen on page xx to randomise the speed variable each time. To do this, all we need to do is replace the following lines in the draw() method


// add the speed direction to the existing coordinates
xCoords = xCoords + speed;
yCoords = yCoords + speed;


with the lines


// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords = xCoords + randomXDirection;
yCoords = yCoords + randomYDirection;


This piece of code creates a random number between the values -speed and speed (currently set to 2) and uses the random value to set the coordinate values for the next time the vertex is drawn. This makes the draw method look like the below


void draw() {
// clear the screen by resetting the background
background(0);
// begin drawing the shape
beginShape();
// draw the vertex at the coordinates
vertex(xCoords, yCoords);
endShape();
// create a random direction for next time
float randomXDirection = random(-speed, speed);
float randomYDirection = random(-speed, speed);
// add the random direction to the existing coordinates
xCoords = xCoords + randomXDirection;
yCoords = yCoords + randomYDirection;

}


If you run this, you will see that the the dot now moves around its starting point in a random fashion. This is due to the random value added to the coordinates that means the dot moves slightly each time it is drawn.

Tuesday, 8 December 2009

Chunk 41

CHUNK 41
TITLE Vertex functions 1
DESCRIPTION This is one of five sections of the book that provides examples in the use of vertex functions. Describe a program that is about 50 lines of code which uses vertex functions.
OUTCOME

* Be able to understand a program that uses vertex functions.

REFERENCE Greenberg 209--225
HINT Use anti-aliasing
PROGRAM Modify the program that you present in the text so that its functionality changes