• fullscreen
  • bouncingObjects.pde
  • 	static final int MAX_NUM_PARTICLES = 400;
    	Particle[] particles = new Particle[MAX_NUM_PARTICLES];
    
    	private float dt;
    	private int oldMillis;
    
    	static final double GRAVITY = 0.0015;
    	static final float BOUNCE_DAMPENING = (float) 0.025;
    
    	private int numberOfInstances = 200;
    	private float radius = 6;
    
    	private boolean grav = true;
    
    	void setup() {
    		oldMillis = millis();
    
    		size(640, 480);
    
    		for (int i = 0; i < MAX_NUM_PARTICLES; i++) {
    			float x = random(0, width);
    			float y = random(0, height);
    			particles[i] = new Particle(x, y, radius);
    		}
    
    		smooth();
    
    		PFont myFont = loadFont("Ziggurat-HTF-Black-32.vlw");
    		textFont(myFont, 12);
    		fill(255);
    		noStroke();
    	}
    
    	void draw() {
    		updateParticles();
    
    		background(51);
    
    		for (int i = 0; i < numberOfInstances; i++) {
    			int d = parseInt(particles[i].radius * 2);
    			ellipse((float) particles[i].posX, (float) particles[i].posY, d, d);
    		}
    
    		text("fps: " + parseInt(1000 / dt), 10, 20);
    		text("click left to push or right to pull", width/2, 20);
    		text("[+/-] objects: " + numberOfInstances, 10, 40);
    		text("[ g ] gravity: " + grav, 10, 60);
    	}
    
    	void keyPressed() {
    		if (keyPressed) {
    			if (key == 'g' || key == 'G') {
    				grav = !grav;
    			}
    
    			if (key == '+' && numberOfInstances < MAX_NUM_PARTICLES) {
    				numberOfInstances++;
    			}
    			if (key == '-' && numberOfInstances > 1) {
    				numberOfInstances--;
    			}
    		}
    	}
    
    	void updateParticles() {
    		for (int i = 0; i < numberOfInstances; i++) {
    			Particle particle = particles[i];
    
    			// bounce off bottom
    			if (particle.posY > height - particle.radius) {
    				particle.vY = -abs(particle.vY) * (1 - BOUNCE_DAMPENING);
    				particle.posY = height - particle.radius;
    			}
    
    			// bounce off ceiling
    			if (particle.posY < particle.radius) {
    				particle.vY = abs(particle.vY) * (1 - BOUNCE_DAMPENING);
    				particle.posY = particle.radius;
    			}
    
    			// bounce off left border
    			if (particle.posX < particle.radius) {
    				particle.vX = abs(particle.vX) * (1 - BOUNCE_DAMPENING);
    				particle.posX = particle.radius;
    			}
    
    			// bounce off right border
    			if (particle.posX > width - particle.radius) {
    				particle.vX = -abs(particle.vX) * (1 - BOUNCE_DAMPENING);
    				particle.posX = width - particle.radius;
    			}
    
    			// inter particle
    			for (int j = 0; j < numberOfInstances; j++) {
    
    				// bounce
    				bounce(particles[i], particles[j]);
    			}
    
    			// apply Gravity
    			if(grav){
    				particle.vY += GRAVITY*0.1*dt;
    			}
    
    			// apply interactive gravity
    			applyMouseGravity(particle);
    
    			// move it
    			particle.tick();
    		}
    		dt = millis() - oldMillis;
    		oldMillis = millis();
    
    	}
    
    	void applyMouseGravity(Particle particle) {
    		if (mousePressed) {
    			float d = sqrt(pow(particle.posX - mouseX, 2)
    					+ pow(particle.posY - mouseY, 2))
    					* (float) 2.0;
    			float ang = atan2(particle.posX - mouseX, particle.posY - mouseY);
    			float F = (float) 16 * dt;
    			F = min(1 / d, 3);
    			if (mouseButton == RIGHT) {
    				F = -F;
    			}
    
    			particle.vX += sin(ang) * F;
    			particle.vY += cos(ang) * F;
    		}
    	}
    
    	void bounce(Particle a, Particle b) {
    		if (sqrt(pow(a.posX - b.posX, 2) + pow(a.posY - b.posY, 2)) < (a.radius + b.radius)) {
    			if (sqrt(pow(a.posX - b.posX, 2) + pow(a.posY - b.posY, 2)) > sqrt(pow(
    					a.posX + a.vX - b.posX - b.vX, 2)
    					+ pow(a.posY + a.vY - b.posY - b.vY, 2))) {
    
    				float commonTangentAngle = atan2(b.posX - a.posX, b.posY
    						- a.posY)
    						+ asin(1);
    
    				float v1 = a.getVelocity();
    				float v2 = b.getVelocity();
    				float w1 = a.getMotionDirection();
    				float w2 = b.getMotionDirection();
    
    				a.vX = sin(commonTangentAngle) * v1 * cos(w1 - commonTangentAngle) + cos(commonTangentAngle) * v2 * sin(w2 - commonTangentAngle);
    				a.vY = cos(commonTangentAngle) * v1 * cos(w1 - commonTangentAngle) - sin(commonTangentAngle) * v2 * sin(w2 - commonTangentAngle);
    				b.vX = sin(commonTangentAngle) * v2 * cos(w2 - commonTangentAngle) + cos(commonTangentAngle) * v1 * sin(w1 - commonTangentAngle);
    				b.vY = cos(commonTangentAngle) * v2 * cos(w2 - commonTangentAngle) - sin(commonTangentAngle) * v1 * sin(w1 - commonTangentAngle);
    
    				a.vX *= (1 - BOUNCE_DAMPENING);
    				a.vY *= (1 - BOUNCE_DAMPENING);
    				b.vX *= (1 - BOUNCE_DAMPENING);
    				b.vY *= (1 - BOUNCE_DAMPENING);
    
    			}
    		}
    	}
    
    	class Particle {
    
    		float posX;
    		float posY;
    
    		float vX = 0;
    		float vY = 0;
    
    		float radius;
    
    		Particle(float x, float y, float r) {
    			posX = x;
    			posY = y;
    			radius = r;
    		}
    
    		float getVelocity() {
    			return sqrt(vX * vX + vY * vY);
    		}
    
    		public float getMotionDirection() {
    			return atan2(vX, vY);
    		}
    
    		void tick() {
    			posX += vX * dt;
    			posY += vY * dt;
    		}
    
    	}
    
    

    code

    tweaks (0)

    about this sketch

    This sketch is running as Java applet, exported from Processing.

    license

    advertisement

    Felix Woitzel

    Bouncing Balls

    Add to Faves Me Likey@! 7
    You must login/register to add this sketch to your favorites.

    bouncing balls with some reactivity.

    Botho Willer
    21 May 2011
    This is fun!
    Nicely done!
    You need to login/register to comment.