// square is a state machine. class DigiSquare{ final int FALLING = 0; final int SPAWN_RUB = 0; int state; boolean onSurface, wasOnSurface, canTriggerAgain; float energy; float cx, cy; float happy; float lastAngle; float vA; float eyeAngle; Particle[] corner; Particle m; Spring[] mS; DigiSquare(){ state = FALLING; onSurface = false; wasOnSurface = false; canTriggerAgain = false; energy = 0; happy = 1; eyeAngle = 0; lastAngle = -1.5; vA = 0; m = physics.makeParticle( 1, 0, 0, 0 ); m.makeFixed(); mS = new Spring[4]; corner = new Particle[4]; int half = corner.length / 2; // create corners for( int i=0; i0.5?1:-1); float ry = random( energy*1.5 ); ry *= ry * (random(1)>0.5?1:-1); corner[i].addVelocity( rx, ry, 0 ); } physics.tick(); // out of bounds boolean outOfBounds = false; for( int i=0; i abs(vA) ) vA = fixAngle(angle - lastAngle)*5; vA *= vA>0.1?0.99:0.6; lastAngle = angle; // doesn't like to spin happy -= vA*0.25; // doesn't like being upside down happy -= abs( fixAngle(angle + 2.356) )*0.2; // wants attention! float mouseDist = dist(cx,cy,mouseX,mouseY); happy += max(0, (200 - mouseDist)/600); // likes energy! happy += energy*0.25; happy = constrain( happy, 0, 1); // draw eye float watch = atan2( mouseY-cy, mouseX-cx); float dA = fixAngle( watch - eyeAngle ); vA += constrain( dA*0.5, -0.1, 0.1 ); eyeAngle += constrain( vA, -1, 1); eyeAngle = fixAngle(eyeAngle); float watchDist = min( 12, mouseDist*0.2 ); fill(0.02); pushMatrix(); translate( cx, cy ); rotate( eyeAngle ); ellipse( watchDist, 0, 8, 8 ); popMatrix(); // draw mouth float mouthCorner = lerp( 0.20, 0.4, happy); float mouthSmile = lerp( -0.25, 0.55, happy ); float mouthCurve = lerp( 0.4, 0.55, happy ); float mouthLX = corner[3].position().x()*(1-mouthCorner) + cx*mouthCorner; float mouthLY = corner[3].position().y()*(1-mouthCorner) + cy*mouthCorner; float mouthRX = corner[2].position().x()*(1-mouthCorner) + cx*mouthCorner; float mouthRY = corner[2].position().y()*(1-mouthCorner) + cy*mouthCorner; float mouthCX = cx + (mouthLY - mouthRY)*mouthSmile; float mouthCY = cy + (mouthRX - mouthLX)*mouthSmile; strokeWeight( 1.5 ); stroke(0.02); if( mouthSmile > 0 ) fill(0.02); else noFill(); bezier( mouthLX, mouthLY, mouthLX + (mouthCX-cx)*mouthCurve, mouthLY + (mouthCY-cy)*mouthCurve, mouthRX + (mouthCX-cx)*mouthCurve, mouthRY + (mouthCY-cy)*mouthCurve, mouthRX, mouthRY ); } void bounceSurface( Particle p ){ if( surface - cy > 60 ) canTriggerAgain = true; if(p.position().y() > surface ){ p.moveTo( p.position().x(), surface, 0 ); p.setVelocity( 0, p.velocity().y()*0.5, 0); if( !onSurface && !wasOnSurface && canTriggerAgain ){ thump.trigger(); canTriggerAgain = false; } onSurface = true; } if(p.position().x() < 0){ p.moveTo( 0, p.position().y(), 0 ); p.addVelocity( p.velocity().x()*(-1.4), 0, 0 ); thump.trigger(); }else if(p.position().x() > width){ p.moveTo( width, p.position().y(), 0 ); p.addVelocity( p.velocity().x()*(-1.4), 0, 0 ); thump.trigger(); } } void drag( boolean on ){ for( int i=0; i PI ) in -= TWO_PI; while( in < -PI ) in += TWO_PI; return in; } }