// TWANG // by Eric Vander Horst //Instructions: //Click the mouse to pull back the ball from it's origin point. //The further its being pulled, the faster it will be released, //the skinnier the hoop will be, and the faster the hoop will move. //Release click to let it go. //variable introductions //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ //BALL float ballX=200; float ballY=240;//ball position float xSpeed=0; float ySpeed=0;//ball speed float ballYMemory=240;//ball tracking. Stores the y position of the ball from the previous frame. //RING float ringX=200;//ring position float ringXChange=0;//ring speed //STRING float pullDist=0;//elastic string length, pulled from (200,240) //draw room //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ void setup() { size(400, 400); } void draw() { drawBackground(); //if the mouse is pressed, mouse pulls tethered ball //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ if (mousePressed) { updateBallDrag(); updateString(); //draw string from ball to origin. line(ballX, ballY, 200, 240); } //but if the mouse isn't pressed, ball is released. Ring moves whether the mouse is pressed or not. //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ else { updateBallRelease(); } updateRing(); //draw ball and ring //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ noStroke(); //if ball is beneath the ring, draw ball earlier a layer underneath the ring. if (ballY>=110) { drawBall(); } drawRing(); //if ball is above the ring, draw ball later on top of the ring. if (ballY<110) { drawBall(); } } //define functions //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ void drawBackground() { //Orange Walls background(255, 139, 28); //FLOOR, CEILING for (int i=0; i<8; i++) { //orange turning yellow as i increases fill(255, 159+(i+3)*5, 28+(i+3)*2); //floor pads printing up as i increases quad(0+(i*10), 400-(i*10), 20+(i*10), 380-(i*10), 380-(i*10), 380-(i*10), 400-(i*10), 400-(i*10)); //ceiling pads printing down as i increases quad(0+(i*10), -50+(i*10), 20+(i*10), -30+(i*10), 380-(i*10), -30+(i*10), 400-(i*10), -50+(i*10)); } } void updateBallDrag() { //BALL //set ball location to at mouse ballX=mouseX; ballY=mouseY; //return the ball to inside the window if the mouse is outside it. if (ballX>400) { ballX=400; } if (ballX<0) { ballX=0; } if (ballY>400) { ballY=400; } if (ballY<0) { ballY=0; } //depending on how far the ball is pulled, set x and y speed for when it is released. xSpeed=(200-ballX)/10; ySpeed=(240-ballY)/10; } void updateString() { //STRING //record distance from ball to ball origin pullDist=dist(ballX, ballY, 200, 240); //flicker and thin string more as it is pulled further stroke(265-random(pullDist/3)); strokeWeight(abs(350-pullDist)/80); } void updateBallRelease() { //remember last frame's ball y position. //** ballYMemory is used in hitBoxBounceY() to detect if the ball was previously above or below the hit box. ** ballYMemory=ballY; //move ball by its current speed ballX+=xSpeed; ballY+=ySpeed; //bounce on the ring //** "(abs(350-pullDist))" is the width of the outer circle, which makes the arguments look long and complicated. See "//draw ball and ring" to see how that value is used to draw the ring. ** hitBoxBounceY(ringX+(abs(350-pullDist))/2, ringX+(abs(300-pullDist)/1.3)/2, 14);//Right hitBoxBounceY(ringX-(abs(300-pullDist)/1.3)/2, ringX-(abs(350-pullDist))/2, 14);//Left //bounce on walls //400 & 0 are the max and min of both x and y. wallBounceBoth(400, 0); //gravity, horizontal air resistance. ySpeed+=0.2; xSpeed*=0.997; } void wallBounceBoth(float a, float i) { //when the ball goes beyond a wall, keep it inside and bounce it. if (ballX>a) { //keep it inside ballX=a-1; //bounce:reverse and diminish x speed xSpeed*=-0.8; } if (ballX<i) { //keep it inside ballX=i+1; //bounce:reverse and diminish x speed xSpeed*=-0.8; } if (ballY>a) { //keep it inside ballY=a-1; //bounce:reverse and diminish y speed ySpeed*=-0.8; } if (ballY<i) { //keep it inside ballY=i+1; //bounce:reverse and diminish y speed ySpeed*=-0.8; } } void hitBoxBounceY(float a, float b, float c) { //keep ball outside of hit box. a and b are x limits of the hit box, c is adjustable extra width to add to both a & b. //if ball x is between a & b if (ballX<a+c && ballX>b-c) { //if ball y is between top and bottom of hit box if (120>ballY && ballY>100 && (abs(ySpeed)>1.5 || abs(xSpeed)>20)) { //bounce:reverse and diminish y speed ySpeed*=-0.8; //if ball was previously below ring, if (ballYMemory>120) { //keep it below the ring and outside of the hit box. ballY=121; //if ball was previously above ring, } else { //keep it above the ring and outside the hit box. ballY=99; } } } } void drawBall() { fill(255, 78, 0); ellipse(ballX, ballY, 30, 30); } void updateRing() { //Ring speed changes depending on how far back string is pulled. ringXChange+=pullDist/5000; ringX=150*(sin(ringXChange))+200; } void drawRing() { //ring width is smaller when ball string length is longer //ring outside fill(223, 235, 235); ellipse(ringX, 110, abs(350-pullDist), 60); //ring inside fill(255, 139, 28); ellipse(ringX, 110, abs(300-pullDist)/1.3, 30); }