This page shows a number of programs that we discussed in class
Moving the mouse down the window displays all the colors in the color wheel:
void setup(){
size(500,500);
}
void draw(){
// Map mouse Y coordinate to color on color wheel
float hue = map(mouseY, 0, 499, 0, 360);
colorMode(HSB, 360, 100, 100); // HSB mode
// Set stroke color and weight
stroke(hue, 100, 100);
strokeWeight(10);
// Draw horizontal line across window
line(0, mouseY, 499, mouseY);
}
Shows the use of functions to repeatedly draw some shapes:
void setup(){
size(500,500);
noStroke();
}
void draw(){
eye(65, 44);
eye(20, 50);
eye2(325, 220, 180);
eye2(190, 202, 180);
threeXs();
}
// Draws an eyeball at x, y
void eye(int x, int y){
fill(255);
ellipse(x, y, 60, 60);
fill(0);
ellipse(x+10, y, 30, 30);
fill(255);
ellipse(x+16, y-5, 6, 6);
}
// Draws an eyeball of the given size at x, y
void eye2(int x, int y, float diam){
fill(255);
ellipse(x, y, diam, diam);
fill(0);
ellipse(x+diam/6, y, diam/2, diam/2);
fill(255);
ellipse(x+diam/3.75, y-diam/12, diam/10, diam/10);
}
// draws an X of the given size, weight and color
void drawX(int gray, int weight, int x, int y, int size){
stroke(gray);
strokeWeight(weight);
line(x, y, x+size, y+size);
line(x+size, y, x, y+size);
}
void threeXs(){
drawX(160, 20, 30, 355, 60);
drawX(0, 10, 60, 370, 60);
drawX(255, 2, 50, 388, 60);
}
Uses functions to return true if a point is in a circle or rectangle, also shows the use of the MousePressed function:
float circleX, circleY;
float circleDY, circleDX;
float rectX, rectY;
float rectWidth, rectHeight;
float diameter;
color circleColor;
color fuchsia = color(255, 0, 255);
color gold = color(255, 215, 0);
color white = color(255);
int transparency;
int dTrans;
void setup() {
size(500, 500);
// Starting point of shapes
circleX = 100;
circleY = 30;
diameter = 50;
rectX = 175;
rectY = 175;
rectWidth = 150;
rectHeight = 150;
// Initial speed of circle
circleDX = -2;
circleDY = 1;
// color
circleColor = fuchsia;
transparency = 128;
dTrans = 20;
noStroke();
}
void draw() {
background(white);
fill(circleColor);
ellipse(circleX, circleY, diameter, diameter);
circleX += circleDX;
circleY += circleDY;
// ball hits bottom edge
if (circleY > 499 - diameter/2) {
circleDY = -circleDY;
}
// ball hits top edge
if (circleY < 0 + diameter/2) {
circleDY = -circleDY;
}
// ball hits right edge
if (circleX > 499 - diameter/2) {
circleDX = -circleDX;
}
// ball hits left edge
if (circleX < 0 + diameter/2) {
circleDX = -circleDX;
}
// Draw Rectangle
fill(25, 25, 112, transparency);
rect(rectX, rectY, rectWidth, rectHeight);
}
// If the mouse is pressed in the circle change color
// If pressed in the rectangle make more or less
// transparent
void mousePressed() {
// If mouse in circle
if (pointInCircle(mouseX, mouseY,
circleX, circleY, diameter/2)) {
// Switch between fuchsia and gold
if (circleColor == fuchsia) {
circleColor = gold;
}
else {
circleColor = fuchsia;
}
}
// If mouse is in rectangle
if (pointInRect(mouseX, mouseY, rectX, rectY,
rectWidth, rectHeight)) {
// Make more opaque
if (transparency >= 255) {
dTrans = -dTrans;
}
// Or more transparent
else if (transparency <= 0) {
dTrans = -dTrans;
}
transparency += dTrans;
}
}
// Detects if the point (ptX, ptY) is in the circle
// with centre cX, cY and radius radius, returns true
// if it is, false otherwise
// Long winded version!
//boolean pointInCircle(float ptX, float ptY,
//float cX, float cY, float radius) {
//
// if (dist(ptX, ptY, cX, cY) < radius) {
// return true;
// }
// else {
// return false;
// }
//}
// Detects if the point (ptX, ptY) is in the circle
// with centre cX, cY and radius radius, returns true
// if it is, false otherwise
boolean pointInCircle(float ptX, float ptY,
float cX, float cY, float radius) {
return dist(ptX, ptY, cX, cY) < radius;
}
// Detects if the point (ptX, ptY) is in the rectangle
// with top left rX, rY and height h and width w,
// returns true if it is, false otherwise
// Long winded version!
//boolean pointInRect(float ptX, float ptY, float rX,
//float rY, float h, float w) {
//
// if ((ptX > rX && ptX < rX + w) &&
// (ptY > rY && ptY < rY + h) ) {
// return true;
// }
// else {
// return false;
// }
//}
// Detects if the point (ptX, ptY) is in the rectangle
// with top left rX, rY and height h and width w,
// returns true if it is, false otherwise
boolean pointInRect(float ptX, float ptY, float rX,
float rY, float h, float w) {
return (ptX > rX && ptX < rX + w) &&
(ptY > rY && ptY < rY + h);
}
Shows the use of easing, a technique to slow the speed of an object as it approaches its target:
// Demonstrates easing, where the speed of
// a ball decreases as it gets closer to the
// target -- the mouse
float x = 0;
float y = 0;
float easing = 0.05;
void setup() {
size(500, 500);
smooth();
}
void draw() {
background(0);
float targetX = mouseX;
float targetY = mouseY;
if (abs(targetX - x) > 1) {
x += (targetX - x) * easing;
}
if (abs(targetY - y) > 1) {
y += (targetY - y) * easing;
}
fill(153);
ellipse(mouseX, mouseY, 20, 20);
fill(255);
ellipse(x, y, 40, 40);
}
Shows how to display text (and how to load a font). Note that the loaded fonts have to have been created and saved in the project’s data folder:
PFont fontRavie;
PFont fontCooper;
String helloString;
String mouseString;
int mousePress;
float mTextY, mTextDY;
void setup(){
size(500, 500);
fontRavie = loadFont("Ravie-48.vlw");
fontCooper = loadFont("CooperBlack-24.vlw");
mousePress = 0;
mTextY = 180;
mTextDY = 1;
}
void draw(){
background(128);
fill(255);
textFont(fontRavie);
helloString = "Hello World!";
text(helloString, 50, 200);
noStroke();
float sw = textWidth(helloString);
rect(50, 205, sw, 5);
textFont(fontCooper);
fill(255,0,0, 128);
mouseString = mousePress +
" mouse clicks";
text(mouseString, 100, mTextY);
// Move the text
mTextY += mTextDY;
if(mTextY < 10){
mTextDY = -mTextDY;
}
if(mTextY >= 500){
mTextDY = -mTextDY;
}
}
void mousePressed(){
mousePress += 1;
}
Draws the closest four planets rotating around the sun, shows the use of transformations and pushMatrix and popMatrix:
// Planet Variables
float angleMercury;
float angleVenus;
float angleEarth;
float angleMoon;
float angleMars;
color colorSun = color(255, 255, 0);
color colorMercury = color(64, 64, 64);
color colorVenus = color(250, 225, 144);
color colorEarth = color(0, 0, 255);
color colorMoon = color(110, 110, 110);
color colorMars = color(250, 48, 8);
// Distances in AUs
float distanceMercury = 0.38;
float distanceVenus = 0.72;
float distanceEarth = 1.0; //149.6 m kms
float distanceMoon;
float distanceMars = 1.52;
float distanceConstant = 150;
// Diameters in kms
float diameterSun = 50; //pixels -- not to scale!
float diameterMercury = 4880;
float diameterVenus = 12104;
float diameterEarth = 12756;
float diameterMoon = 3476;
float diameterMars = 6794;
float diameterConstant = .0025;
// Sppeds comparative to earth rotation
float speedMercury = 4.1; //88 days
float speedVenus = 1.6; //224
float speedEarth = 1.0; //365
float speedMoon = 12.0;
float speedMars = 0.53; //687
float speedConstant = 0.01;
void setup() {
size(500, 500);
angleMercury = 0;
angleVenus = 0;
angleEarth = 0;
angleMoon = 0;
angleMars = 0;
distanceMercury *= distanceConstant;
distanceVenus *= distanceConstant;
distanceEarth *= distanceConstant;
distanceMoon = 20; //not to scale
distanceMars *= distanceConstant;
diameterMercury *= diameterConstant;
diameterVenus *= diameterConstant;
diameterEarth *= diameterConstant;
diameterMoon *= diameterConstant;
diameterMars *= diameterConstant;
speedMercury *= speedConstant;
speedVenus *= speedConstant;
speedEarth *= speedConstant;
speedMoon *= speedConstant;
speedMars *= speedConstant;
smooth();
}
void draw() {
background(0); // comment out this line to get a trail
// draw the sun
translate(width/2, height/2); // origin = center of the sun
fill(colorSun);
ellipse(0, 0, diameterSun, diameterSun);
// draw the earth rotating around the sun
pushMatrix();
angleEarth = planet(distanceEarth, diameterEarth,
speedEarth, angleEarth, colorEarth);
// Moon around earth, note it is inside
// the earth's transformations
pushMatrix();
angleMoon = planet(distanceMoon, diameterMoon,
speedMoon, angleMoon, colorMoon);
popMatrix();
popMatrix();
pushMatrix();
angleVenus = planet(distanceVenus, diameterVenus,
speedVenus, angleVenus, colorVenus);
popMatrix();
pushMatrix();
angleMars = planet(distanceMars, diameterMars,
speedMars, angleMars, colorMars);
popMatrix();
pushMatrix();
angleMercury = planet(distanceMercury, diameterMercury,
speedMercury, angleMercury, colorMercury);
popMatrix();
}
// The planet function makes it easy to add planets
float planet(float distance, float diameter,
float speed, float angle, color col){
rotate(angle);
translate(distance, 0);
fill(col);
ellipse(0, 0, diameter, diameter);
angle += speed;
return angle;
}
Example of a class with its own render method that uses transformations:
class Spiral {
float x;
float y;
color fill_color;
float angle; // angle of rotation
// Constructor
Spiral(float init_x, float init_y, color init_c) {
x = init_x;
y = init_y;
fill_color = init_c;
angle = 0;
}
// Draws a rotating spiral
void render() {
pushMatrix(); //start transformation
translate(x, y);
rotate(radians(angle));
noStroke();
float radius = 1;
fill(fill_color);
// Draw spiral of small circles (through 6 rotations)
for (int deg = 0; deg < 360*6; deg += 11) {
float angle_next = radians(deg);
float next_x = cos(angle_next) * radius;
float next_y = sin(angle_next) * radius;
ellipse(next_x, next_y, 6, 6);
radius = radius + 0.34;
}
popMatrix(); //end transformation
}
}
Spiral s1;
Spiral s2;
void setup() {
size(500, 500);
smooth();
s1 = new Spiral(100, 100, color(255));
s2 = new Spiral(400, 400, color(255, 126, 176));
}
void draw() {
background(196);
s1.render();
s1.angle += 1;
s2.render();
s2.angle -= 1;
}
Example of a particle system, note that the overall effect is much improved by adding fading to the path of the particles:
class Droplet {
float x, y;
float dx, dy;
float gravity;
float radius;
float originX, originY;
Droplet(float ix, float iy, float idx, float idy,
float ir, float iox, float ioy) {
x = ix;
y = iy;
dx = idx;
dy = idy;
radius = ir;
originX = iox;
originY = ioy;
gravity = 0.1;
}//constructor
// Re-use droplets once they have left the window
void regenerate() {
if (x - radius > width || x +- radius < 0 ||
y - radius > height || y +- radius < 0) {
x = originX;
y = originY;
dx = random(-1, 1);
dy = random(-8, -4);
}
}//regenerate
// Adjust position
void update() {
dy += gravity;
x += dx;
y += dy;
}//update
void render() {
//fill(0, 0, 255);
fill(0, 0, 255, 120);
noStroke();
ellipse(x, y, radius*2, radius*2);
}//render
}//Droplet
final int n = 1000;
ArrayList<Droplet> fountain;
void setup() {
size(500, 500);
smooth();
fountain = new ArrayList<Droplet>();
// Populate the arraylist
for (int i=0; i < n; i++) {
float dx = random(-1, 1);
float dy = -i;
fountain.add(new Droplet(width/2, height-20, dx, dy,
1.0, width/2, height-20));
}
}//setup
void draw() {
//background(255);
// fading trails behind droplets
fill(255, 36);
rect(0, 0, width, height);
for (Droplet drop : fountain) {
drop.update();
drop.regenerate();
drop.render();
}
}//draw
Multiple fountains, shows a fountain class that encapsulates a fountain:
class Droplet {
float x, y;
float dx, dy;
float gravity;
float radius;
Droplet(float idx, float idy, float ir) {
x = 0;
y = 0;
dx = idx;
dy = idy;
radius = ir;
gravity = 0.1;
}//constructor
// Re-use droplets once they have left the window
void regenerate() {
if (y - radius > 0) {
x = 0;
y = 0;
dx = random(-1, 1);
dy = random(-8, -4);
}
}//regenerate
// Adjust position
void update() {
dy += gravity;
x += dx;
y += dy;
}//update
void render() {
//fill(0, 0, 255);
fill(0, 0, 255, 120);
noStroke();
ellipse(x, y, radius*2, radius*2);
}//render
}//Droplet
class Fountain {
ArrayList<Droplet> water;
int n;
float x, y;
float size;
Fountain(float ix, float iy, int in, float isz) {
x = ix;
y = iy;
n = in;
size = isz;
water = new ArrayList<Droplet>();
// Populate the arraylist
for (int i=0; i < n; i++) {
float dx = random(-1, 1);
float dy = 0;
water.add(new Droplet(dx, dy, 1.0));
}
}
void render() {
pushMatrix();
translate(x,y);
scale(size);
for (Droplet drop : water) {
drop.update();
drop.regenerate();
drop.render();
}
popMatrix();
}
}
ArrayList <Fountain> park;
void setup() {
size(500, 500);
smooth();
park = new ArrayList<Fountain>();
}//setup
void draw() {
//background(255);
// fading trails behind droplets
fill(255, 36);
rect(0, 0, width, height);
for(Fountain fount : park){
fount.render();
}
}//draw
void mousePressed(){
int n = (int) random(150, 350);
float sc = random(.2, .6);
park.add(new Fountain(mouseX, mouseY, n, sc));
}
Another particle system, that demonstrates the use of transformations to simplify rendering complex objects, and to scale the objects:
class Arrow{
float x, y;
float dx, dy;
float gravity;
float angle;
float shaft;
Arrow(float ix, float iy, float idx,
float idy, float is){
x = ix;
y = iy;
dx = idx;
dy = idy;
shaft = is;
gravity = 0.1;
angle = 0;
}//constructor
void render(){
stroke(255);
pushMatrix();
translate(x, y); //origin becomes arrow base
rotate(angle); //rotate in direction of travel
scale(shaft); //scale based on shaft length
strokeWeight(1.0 / shaft); //set to 1.0
line(0, 0, 1, 0);
line(0.7, -0.3, 1, 0);
line(0.7, 0.3, 1, 0);
popMatrix();
}//render
void update(){
dy += gravity;
x += dx;
y += dy;
angle = atan2(dy, dx);
}//update
}
final int numArrows = 320;
ArrayList<Arrow> quiver;
void setup() {
frameRate(60);
size(600, 100);
smooth();
quiver = new ArrayList<Arrow>();
// Create new arrows
for(int i=0; i<numArrows; ++i){
float dx = random(1, 8);
float dy = random(-5, -1);
quiver.add(new Arrow(0, height/2, dx, dy, 20));
}
}//update
void draw() {
background(0);
for(Arrow a : quiver){
a.update();
a.render();
}
}//draw
Image processing application that demonstrates the use of get and set to create image variable that are sections of an image:
PImage temple;
PImage temp;
PImage temp2;
int tempX, tempY;
boolean moving;
void setup(){
temple = loadImage("temple.JPG");
size(temple.width, temple.height);
}
void draw(){
image(temple, 0, 0);
// Show moving image section
if(moving){
fill(128);
noStroke();
rect(tempX, tempY, 50 ,50); //grey rectangle
image(temp, mouseX, mouseY); //moving image
}
}
// Pick up 50 x 50 section of image
void mousePressed(){
moving = true;
temp = get(mouseX, mouseY, 50, 50);
tempX = mouseX;
tempY = mouseY;
}
// Swap sections of image
void mouseReleased(){
// Use underlying image to get the section of the
// image under the moving image
temp2 = temple.get(mouseX, mouseY, 50, 50);
temple.set(tempX, tempY, temp2);
temple.set(mouseX, mouseY, temp);
moving = false;
}
Image processing application that demonstrates the use of loadPixels and updatePixels to access the components of the pixels array. Also implements an image transformation that changes the red, green and blue components of each pixel in an image:
PImage temple;
void setup(){
temple = loadImage("temple.JPG");
size(temple.width, temple.height);
int count = temple.width * temple.height; // # of pixels
temple.loadPixels(); // image of temple
// Load pixels one by one
loadPixels();
// Change i+=1 to i+=2 and see the result
for(int i=0; i < count; i+=1){
// Change[i] to [i/2] and see the result
// Change[i] to [count - 1 - 1] and see the result
pixels[i] = temple.pixels[i];
}
updatePixels();
//invert(); //un-comment to invert
}
void draw(){
}
// Inverts the image
void invert(){
loadPixels();
int i = 0;
for(color c : pixels){
float r = 255 - red(c);
float g = 255 - green(c);
float b = 255 - blue(c);
pixels[i] = color(r, g, b);
i++;
}
updatePixels();
}
// Replaces pixel with a black pixel
void mousePressed(){
//set(mouseX, mouseY, color(0));
loadPixels();
println(width * mouseY + mouseX);
pixels[width * mouseY + mouseX] = color(0);
updatePixels();
}
Image processing application that acceses the red, green and blue components of each pixel to draw a graph showing how much colour is in each pixel. Also uses the constrain and map functions. To display the amount of red, green or blue in each pixel press the r, g, and b keys.:
PImage temple;
final int RED = 1;
final int GREEN = 2;
final int BLUE = 3;
int graphColor;
void setup() {
temple = loadImage("temple.JPG");
size(temple.width, temple.height+100);
graphColor = RED;
}
void draw() {
image(temple, 0, 0);
// Ensure that row is a legal row of the image
int row = constrain(mouseY, 0, height - 101);
// Set the line colour
if (graphColor == RED) {
stroke(255, 0, 0);
}
else if (graphColor == GREEN) {
stroke(0, 255, 0);
}
else if (graphColor == BLUE) {
stroke(0, 0, 255);
}
// Draw line on image to show row
fill(128);
rect(0, height-100, width-1, height-1);
line(0, row, width, row);
// Draw graph of the strength of the pixel colour
for (int i=0; i < width; ++i) {
stroke(255);
color c = temple.pixels[row * width + i];
float lineHeight = 0;
if (graphColor == RED) {
lineHeight = red(c);
}
else if (graphColor == GREEN) {
lineHeight = green(c);
}
else if (graphColor == BLUE) {
lineHeight = blue(c);
}
lineHeight = map(lineHeight, 0, 255, 0, 100);
line(i, height, i, height - lineHeight);
}
}
// Select colour
void keyPressed(){
if(key == 'r' || key == 'R'){
graphColor = RED;
}else if(key == 'g' || key == 'G'){
graphColor = GREEN;
}else if(key == 'b' || key == 'B'){
graphColor = BLUE;
}
}