/* Due Sept 18 2017 10PM on SLATE Intro to Media Computation Instructor: Nicolas Hesler "Rain Maker" Interactive Drawing By Catherine Doherty Move the mouse up and down to affect the cloud, orb, and hand. Move the mouse left and right to affect the cloud, orb, hills, and mountains. Click to view title and affect orb. Waves move on their own. */ void setup() { // Set display window size to 400 pixels by 400 pixels size(400, 400); // Set rectangle and ellipse modes (for ease of placement within scene). rectMode(CORNERS); ellipseMode(CENTER); } void draw() { // Frame rate reset to default 60: // Clicking drops framerate to 3 in order to be able to see the eye and read the text. frameRate(60); // Background = sky, stays blue. background(90, 190, 255); // Don't need stroke for anything in the image except for waves, and one line in the orb. noStroke(); //////////////////////////////////////////////////////////// ////////////////////MOUNTAINS //////////////////////////////////////////////////////////// // Furthest back mountains: lightest blue-grey, move a little left and right with mouse. // Like most things that had to be incremented in some way, I used the fibonacci sequence: // Here it's used to multiply against mouse coordinants (mouseX) to control the // speed of the mountains moving left and right. // It looks nice, and it eliminates the time I would have taken messing around with random digits. fill(220, 250, 255); quad(120+mouseX*.003, 160, 190+mouseX*.003, 150, 220+mouseX*.003, 220, 90+mouseX*.003, 220); // Middle back mountains, next lightest blue-grey, slightly more movement than furthest mountains. fill(200, 230, 255); triangle(20+mouseX*.005, 150, 100+mouseX*.005, 220, -30+mouseX*.005, 240); quad(60+mouseX*.005, 240, 90+mouseX*.005, 135, 130+mouseX*.005, 190, 130+mouseX*.005, 240); quad(250+mouseX*.005, 120, 290+mouseX*.005, 140, 330+mouseX*.005, 220, 210+mouseX*.005, 240); quad(340+mouseX*.005, 200, 440+mouseX*.005, 140, 500+mouseX*.005, 220, 340+mouseX*.005, 240); // Middle mountains, next lightest blue-grey, more blue, slightly more movement again. fill(180, 220, 255); quad(60+mouseX*.008, 160, 80+mouseX*.008, 140, 140+mouseX*.008, 240, 40+mouseX*.008, 240); quad(160+mouseX*.008, 190, 210+mouseX*.008, 150, 250+mouseX*.008, 240, 170+mouseX*.008, 240); // Front mountains, slightly more in front of other ones, bigger jump in movement. fill(160, 210, 255); triangle(40+mouseX*.013, 240, 150+mouseX*.013, 170, 220+mouseX*.013, 240); triangle(260+mouseX*.013, 240, 335+mouseX*.013, 160, 420+mouseX*.013, 240); //////////////////////////////////////////////////////////// ////////////////////RAIN //////////////////////////////////////////////////////////// // This is the wall of rain behind the cloud/in front of the mountains: the lowest part of // it drags a little behind (because of pmouse) as you move cloud left and right. fill(-mouseY/10+100, -mouseY/10+100, -mouseY/10+150, mouseY*255/800); quad(-mouseX*.2+112, 113, -mouseX*.2+400, 113, -pmouseX*.2+400, 240, -pmouseX*.2+112, 240); //////////////////////////////////////////////////////////// ////////////////////GREEN HILLS //////////////////////////////////////////////////////////// // The centre of an arc is x,y: arc(x,y,w,h,start,stop); translated to radian from degrees. // Hills are various greens to differentiate them (so they don't look like a weird blob). // OPEN cuts the arc in a straight line from degree to degree. // It doesn't matter because below the water layer anyway. // In fact, I could have saved myself a lot of trouble just using ellipses. Live and learn. fill(125, 190, 110); arc(200+mouseX*.021, 300, 200, 200, radians(210), radians(330)); ellipse(200+mouseX*.021, 300, 200, 200); // (see, the ellipse above is partially hidden under the water, so you'd never know it wasn't exactly the same as the arc above it.) arc(30+mouseX*.021, 300, 190, 170, radians(210), radians(330)); fill(134, 200, 34); arc(80+mouseX*.021, 300, 195, 195, radians(210), radians(330)); // Hill furthest left. arc(350+mouseX*.021, 300, 190, 200, radians(210), radians(330)); fill(100, 180, 110); // Hill second from left. arc(300+mouseX*.021, 300, 190, 170, radians(210), radians(330)); //////////////////////////////////////////////////////////// ////////////////////WATER - colour //////////////////////////////////////////////////////////// // The blues of the water and height of the rectangles are determined using the fibonacci sequence: // The height (y) of each rectangle is modified by adding numbers from the sequence. // Sequence numbers are also subtracted from Green and Blue values (Red value stays the same). // Red stays at 30 except the first fill is +60 red value to make transition into fog at hills less abrupt. // All rectangles go to the bottom of the sketch window for ease of typing. fill(90, 190, 255); rect(0, 240, 400, 400); fill(30, 187, 252); rect(0, 243, 400, 400); fill(30, 182, 247); rect(0, 248, 400, 400); fill(30, 174, 239); rect(0, 256, 400, 400); fill(30, 161, 226); rect(0, 269, 400, 400); fill(30, 127, 192); rect(0, 290, 400, 400); fill(30, 72, 137); rect(0, 324, 400, 400); //////////////////////////////////////////////////////////// ////////////////////FOG and/or HAZE //////////////////////////////////////////////////////////// // Haze is two different transparent rectangles to make look slightly like fading out at top. // One layer goes all the way down to the bottom over waves, // the other is specifically to make a fog at the base of the hills. fill(255, 70); rect(0, 230, 400, 400); rect(0, 235, 400, 240); //////////////////////////////////////////////////////////// ////////////////////MOVING WAVES //////////////////////////////////////////////////////////// // Waves have no fill, water is already blue behind waves, stroke weight set to two, stroke is white noFill(); strokeWeight(2); stroke(255); // This is probably the part I found the hardest to figure out (along with the Orb): // I largely figured out sin() by playing with values and looking at Brian Ho's project's code/waves. // Mine look pretty tacky in comparison, but they're doing what they're supposed to, so that's okay. // To space all arcs equally, all arc x-coordinants are changed by +94 pixels for each wave (adding as going rightward). // Lines are spaced similarly: each 2nd x-coordinant (each line's third parametre) is changed by +140 pixels. // sin() is changing its input to a value between -1 and 1. // frameCount (system variable) is a count of how many frames displayed since the program started running, // so it is constantly increasing, which makes it useful for controlling animation speed. // Multiplying frameCount by a tiny number slows the animation (leaving it at frameCount alone gives a jittery movement). // Multiplying sin() by 13 determines the distance of swaying left and right, // and is a higher number for closer waves which are moving faster (21 and 34, specifically). // Following the above calculations, x-coordinants are determined by adding or subtracting a number: // subtracting means the point is out of sketch window (meaning, it's not not visible), // i.e. the first arc below has a centre point out of view at -26, // (arc(x,y,w,h,start,stop) with (x,y) being the centre's coordinants) // but you can see that arc's stopping point at 93 degrees where it connects with the first line for the first breaking wave. // The arc is essentially a chunk of a centred ellipse, but you cut it off at two points (the two degrees). // Degrees make more sense to me than radians, so I'm using radians() to convert to degrees for all the arcs. arc((sin(frameCount*.05)*13)-26, 242, 98, 98, radians(21), radians(93)); line((sin(frameCount*.05)*13)+20, 260, (sin(frameCount*.05)*13)+110, 290); arc((sin(frameCount*.05)*13)+114, 242, 98, 98, radians(22), radians(93)); line((sin(frameCount*.05)*13)+160, 260, (sin(frameCount*.05)*13)+250, 290); arc((sin(frameCount*.05)*13)+254, 242, 98, 98, radians(22), radians(93)); line((sin(frameCount*.05)*13)+300, 260, (sin(frameCount*.05)*13)+390, 290); arc((sin(frameCount*.05)*13)+394, 242, 98, 98, radians(22), radians(93)); // MIDDLE WAVE LINES line((sin(frameCount*.05)*21)-460, 300, (sin(frameCount*.05)*21)-370, 330); arc((sin(frameCount*.05)*21)-366, 282, 98, 98, radians(22), radians(93)); line((sin(frameCount*.05)*21)-320, 300, (sin(frameCount*.05)*21)-230, 330); arc((sin(frameCount*.05)*21)-226, 282, 98, 98, radians(22), radians(93)); line((sin(frameCount*.05)*21)-180, 300, (sin(frameCount*.05)*21)-90, 330); arc((sin(frameCount*.05)*21)-86, 282, 98, 98, radians(22), radians(93)); line((sin(frameCount*.05)*21)-40, 300, (sin(frameCount*.05)*21)+50, 330); arc((sin(frameCount*.05)*21)+54, 282, 98, 98, radians(22), radians(93)); line((sin(frameCount*.05)*21)+100, 300, (sin(frameCount*.05)*21)+190, 330); arc((sin(frameCount*.05)*21)+194, 282, 97, 97, radians(22), radians(93)); line((sin(frameCount*.05)*21)+240, 300, (sin(frameCount*.05)*21)+330, 330); arc((sin(frameCount*.05)*21)+334, 282, 97, 97, radians(22), radians(93)); line((sin(frameCount*.05)*21)+380, 300, (sin(frameCount*.05)*21)+470, 330); // CLOSEST WAVE LINES (ones that are moving fastest from side to side). line((sin(frameCount*.05)*34)-100, 340, (sin(frameCount*.05)*34)-10, 370); arc((sin(frameCount*.05)*34)-6, 322, 97, 97, radians(22), radians(93)); line((sin(frameCount*.05)*34)+40, 340, (sin(frameCount*.05)*34)+130, 370); arc((sin(frameCount*.05)*34)+134, 322, 97, 97, radians(22), radians(93)); line((sin(frameCount*.05)*34)+180, 340, (sin(frameCount*.05)*34)+270, 370); arc((sin(frameCount*.05)*34)+274, 322, 97, 97, radians(22), radians(93)); line((sin(frameCount*.05)*34)+320, 340, (sin(frameCount*.05)*34)+410, 370); arc((sin(frameCount*.05)*34)+414, 322, 97, 97, radians(22), radians(93)); //////////////////////////////////////////////////////////// ////////////////////HAND //////////////////////////////////////////////////////////// // Back to no stroke: noStroke(); // Water right behind wrist: without this, future transparent layers in front of wrist become more grey/purple. fill(30, 30, 90, 170); rect(0, 379, 400, 400); // Hand is a bright greenish colour when your mouse is at top of sketch window, // and more blue when mouse at bottom of sketch window (when hand is going under or coming out of water). fill(100, -mouseY+220, 190); // HAND moves up until mouse gets to top of sketch window, and disappears under water when mouse about 2/3rd of way down cloud. // This is the thumb ellipse(157, pmouseY+325, 6.5, 6.5); quad(155, pmouseY+327, 160, pmouseY+322, 165, pmouseY+327, 160, pmouseY+332); quad(165, pmouseY+327, 170, pmouseY+332, 162, pmouseY+337, 160, pmouseY+332); quad(162, pmouseY+337, 170, pmouseY+332, 175, pmouseY+342, 165, pmouseY+352); quad(175, pmouseY+342, 177, pmouseY+342, 177, pmouseY+357, 165, pmouseY+352); triangle(165, pmouseY+352, 177, pmouseY+357, 175, pmouseY+370); // Palm and wrist quad(183, pmouseY+327, 202, pmouseY+327, 202, pmouseY+342, 177, pmouseY+342); quad(177, pmouseY+342, 220, pmouseY+342, 215, pmouseY+357, 177, pmouseY+357); quad(177, pmouseY+357, 215, pmouseY+357, 210, pmouseY+367, 175, pmouseY+370); quad(175, pmouseY+370, 210, pmouseY+367, 205, pmouseY+372, 175, pmouseY+372); quad(202, pmouseY+327, 215, pmouseY+335, 220, pmouseY+342, 202, pmouseY+342); quad(175, pmouseY+372, 205, pmouseY+372, 205, pmouseY+379, 175, pmouseY+379); quad(205, pmouseY+379, 175, pmouseY+379, 175, 400, 205, 400); // Index finger ellipse(187, pmouseY+300, 5, 5); quad(184, pmouseY+300, 190, pmouseY+300, 190, pmouseY+313, 183, pmouseY+313); quad(183, pmouseY+313, 190, pmouseY+313, 192, pmouseY+327, 183, pmouseY+327); // Middle finger ellipse(200, pmouseY+300, 5, 5); quad(197, pmouseY+300, 202, pmouseY+300, 202, pmouseY+313, 195, pmouseY+313); quad(195, pmouseY+313, 202, pmouseY+313, 202, pmouseY+327, 195, pmouseY+327); // Ring finger ellipse(210, pmouseY+302, 5, 5); quad(207, pmouseY+302, 212, pmouseY+302, 215, pmouseY+317, 207, pmouseY+317); quad(207, pmouseY+317, 215, pmouseY+317, 212, pmouseY+335, 205, pmouseY+330); // Pinky ellipse(222, pmouseY+315, 5, 5); quad(220, pmouseY+315, 225, pmouseY+315, 225, pmouseY+327, 220, pmouseY+327); quad(220, pmouseY+327, 225, pmouseY+327, 220, pmouseY+342, 215, pmouseY+335); //////////////////////////////////////////////////////////// ////////////////////ORB //////////////////////////////////////////////////////////// // Orb gets bigger as leaves cloud and lands in hand, or orb gets smaller as thrown to cloud. // Orb's transparency changes as mouse moves left (more transparent) or right (more opaque). // Ellipse(x,y,w,h) with (x,y) being location of ellipse centre. // Ellipse moves opposite of mouse because of -mouseY. // Orb stops at hand because of second parametre: 325 is the centre of orb on the y-axis at the stopping point. // Height and width of orb/ellipse are determined by the third and fourth parametres: // If don't divide by 6, it winds up shrinking and expanding on the way up instead of just shrinking. // First ellipse is stable: fill(30, 255, 255, mouseX*300/width); ellipse(195, -mouseY+325, (320-mouseY)/6, (320-mouseY)/6); // To make it more interesting to look at, used sin to mess with the width or height of following ellipses: // Sin makes the ellipse widths/heights fluctuate. Multiplying frameCount by small numbers changes speed of fluctuation. fill(30, 161, 226, mouseX*255/width); ellipse(195, -mouseY+325, ((320-mouseY)/6)*sin(frameCount*0.03), (320-mouseY)/6); fill(30, 255, 255, mouseX*255/width); ellipse(195, -mouseY+325, ((320-mouseY)/6)*sin(frameCount*0.05), (320-mouseY)/6); ellipse(195, -mouseY+325, (320-mouseY)/6, ((320-mouseY)/6)*sin(frameCount*0.13)); fill(30, 161, 226, mouseX*255/width); ellipse(195, -mouseY+325, ((320-mouseY)/6)*sin(frameCount*0.08), (320-mouseY)/6); ellipse(195, -mouseY+325, (320-mouseY)/6, ((320-mouseY)/6)*sin(frameCount*0.21)); // Looked a little too chaotic so put something less flashy over top. Gives your eyes a break. fill(30, 30, 90, (mouseX*255/width)-10); ellipse(195, -mouseY+325, (320-mouseY)/6, ((320-mouseY)/6)*sin(frameCount*0.042)); // Line representing closed eye inside orb. // Briefly set stroke to exist, and to change in opacity as you move mouse along the x-axis. // Because it's black, it seems to fade less quickly than the blue ellipses, // so made it fade quicker by multiplying by .3: stroke(1, (mouseX*255/width)*.3); line(187, -mouseY+325, 202, -mouseY+325); // Back to no stroke. noStroke(); //////////////////////////////////////////////////////////// ////////////////////sky to hide orb //////////////////////////////////////////////////////////// // To make it look like orb is disappearing into (or coming out from) the cloud, a chunk of sky: fill(90, 190, 255); rect(0, 0, 400, 100); //////////////////////////////////////////////////////////// ////////////////////SUN //////////////////////////////////////////////////////////// // Sun hidden behind cloud until mouse about halfway across sketch window from left. fill(250, 250, 0); ellipse(360, 75, 15, 15); //////////////////////////////////////////////////////////// ////////////////////CLOUD //////////////////////////////////////////////////////////// // To make cloud move across from right to left, move mouse in opposite direction (-mouseX). // Fill changes from white to grey as mouse moves toward bottom of sketch window. // Used ellipses and arcs and rectangles with rounded corners to make a cumulus cloud. // The fifth parametre for rectangles makes rounded corners. fill(255-(mouseY/10)); rect(-mouseX*.2+90, 90, -mouseX*.2+180, 110, 7); ellipse(-mouseX*.2+120, 90, 20, 20); ellipse(-mouseX*.2+150, 80, 60, 60); arc(-mouseX*.2+210, 100, 80, 80, radians(165), radians(375)); ellipse(-mouseX*.2+230, 60, 60, 60); ellipse(-mouseX*.2+260, 50, 20, 20); ellipse(-mouseX*.2+280, 40, 40, 40); ellipse(-mouseX*.2+320, 60, 60, 60); ellipse(-mouseX*.2+350, 70, 30, 30); ellipse(-mouseX*.2+380, 70, 40, 40); arc(-mouseX*.2+400, 100, 60, 60, radians(160), radians(380)); rect(-mouseX*.2+240, 50, -mouseX*.2+340, 110); rect(-mouseX*.2+330, 70, -mouseX*.2+380, 110); rect(-mouseX*.2+60, 100, -mouseX*.2+450, 113, 7); //////////////////////////////////////////////////////////// ////////////////////The Water in front of The Wrist //////////////////////////////////////////////////////////// // To make the wrist look like its coming up out of the water, what follows is // a series of rectangles of varying opacity (alphas). This way, the closer the // fingers are to the surface, the more visible they are. // full area of rectangle in front of (and also the matching one behind) wrist is rect(0, 379, 400, 400), // so all transparent rectangles have to cover this area. fill(30, 30, 90, 170); rect(0, 379, 400, 400); fill(30, 30, 90, 180); rect(0, 384, 400, 400); fill(30, 30, 90, 190); rect(0, 389, 400, 400); fill(30, 30, 90, 200); rect(0, 393, 400, 400); fill(30, 30, 90, 255); rect(0, 397, 400, 400); // Fog or haze in front of water in front of wrist to correct the colour to match the original water. fill(255, 255, 255, 70); rect(0, 379, 400, 400); //////////////////////////////////////////////////////////////////////////////////////////// ////////////////////William Lu's MOUSE POSITION AID //////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// // Modified from William Lu's San Francisco piece, to see pointer's (x,y) coordinants while working: // fill (0); // text(" x: "+mouseX+" y: "+mouseY+" ", 10, 15); // End of draw } //////////////////////////////////////////////////////////// ////////////////////TITLE and EYE //////////////////////////////////////////////////////////// // Using mousePressed means that when you click, the title and eye show up briefly. // Title shows up no matter where you click. Eye is hidden if Orb is hidden. void mousePressed () { // Frame rate lowered to 3 to make the title readable, and eye show up for more than a flash. // Also means you can mess around with the rain angle by clicking frantically. Accidental perk. frameRate(3); // Text is black. fill (0); // Text displays Rain Maker up in the cloud, x-coordinant 290 is start of text, one fourth down the sketch window. text ("Rain Maker", 290, height/4); // The Eye: I used two arcs for sclera, and an ellipse for iris/pupil // OPEN makes the fill stop at the degree points used in an arc (like the outside slice of an apple instead of a pie wedge) // The hills would have been fine as pies under the water, but using OPEN here means the eye's sclera is smooth. // If you start clicking anywhere when the orb is out of the cloud, the eye shows up: // Specifically, the eye starts being visible when the mouse's y-coordinant is at 208 pixels or fewer. // To make the eye show up as soon as the orb is out of the cloud, with as little fade-in as possible, I multiplied the alphas by 100. // sclera fill(255, (208-mouseY)*100); arc(195, 320-mouseY, 20, 20, radians(30), radians(140)); arc(195, 331-mouseY, 20, 20, radians(210), radians(330)); // iris and pupil fill(30, 30, 90, (208-mouseY)*200); ellipse(195, 325-mouseY, 8-mouseY/height, 8-mouseY/height); // End of mousePressed }