Drawing balls

Inspired on the work from Robert Hodgin: http://roberthodgin.com/stippling/ Picture from Sukanto Debnath http://www.flickr.com/photos/sukanto_debnath/3081836966/

by Javier Graciá Carpio

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>

JavaScript

var sketch = function(p) {
	// Global variables
	var img;
	var pos = p.createVector();
	var vel = p.createVector();
	var balls = [];

	// Load the image before the sketch is run
	p.preload = function() {
		img = p.loadImage("http://farm4.staticflickr.com/3137/3081836966_7945315150.jpg");
	};

	// Initial setup
	p.setup = function() {
		// Create the canvas
		var canvas = p.createCanvas(img.width, img.height);

		// Apply a force each time the mouse is pressed inside the canvas
		canvas.mousePressed(applyForce);

		// Draw setup
		p.ellipseMode(p.RADIUS);
		p.noStroke();

		// Load the image pixels, so we can access them later
		img.loadPixels();
	};

	// Execute the sketch
	p.draw = function() {
		// Clean the canvas
		p.background(0);

		// Add a new ball in each frame up to certain limit
		if (balls.length < 1500) {
			var r = 30 * p.random();
			var alpha = p.TWO_PI * p.random();
			pos.set(0.55 * p.width + r * p.cos(alpha), 0.4 * p.height + r * p.sin(alpha), 0);
			vel.set(0, 0, 0);
			balls[balls.length] = new Ball(pos, vel);
		}

		// Update the balls positions
		for (var i = 0; i < balls.length; i++) {
			balls[i].update();
		}

		// Check if the balls are in contact and move them in that case
		for (var i = 0; i < balls.length; i++) {
			for (var j = 0; j < balls.length; j++) {
				if (j != i) {
					balls[i].checkContact(balls[j]);
				}
			}
		}

		// Paint the balls in the canvas
		for (var i = 0; i < balls.length; i++) {
			balls[i].paint();
		}
	};

	/*
	 * This function applies a force to those balls that are near the cursor
	 */
	function applyForce() {
		for (var i = 0; i < balls.length; i++) {
			balls[i].force(p.mouseX, p.mouseY);
		}
	};

	/*
	 * The Ball class
	 */
	function Ball(initPos, initVel) {
		// Set the ball properties
		this.pos = initPos.copy();
		this.vel = initVel.copy();
		this.col = p.color(0);
		this.rad = 3;
	}

	//
	// The update method
	//
	Ball.prototype.update = function() {
		// Calculate the new ball position and...