<!-- begin snippet: js hide: true -->

<!-- language: lang-js -->

         var envelopeHeight = 100;
            var fallRange = 8.5;
            var fallMidpoint = 75;
            var maxOnScreen = 6;
            var frequency = 4500; //time between falls
            var initialVelocity = 0.2;
            
            var gravity = 0.6;
            var friction = 0.97;
            var dampening = 2;
            
            var lastEnvelope = 0;
            var envelopes = [];
            
            function onFrame() {
            	var onScreen = 0;
            	for (var i = 0; i < envelopes.length; i++) {
            		if (!envelopes[i].dead) {
            			onScreen++;
            		}
            		envelopes[i].updateSelf();
            	}
            	if (Date.now() > lastEnvelope + frequency && onScreen <= maxOnScreen) {
            		var dropX = view.bounds.width * (((Math.random() * fallRange) + fallMidpoint) / 100);
            		var envelope = new Path.Rectangle(new Point(dropX, -envelopeHeight), 100, envelopeHeight);
            		envelope.position = new Point(dropX, -envelopeHeight);
            		envelope.fillColor = {
            			hue: Math.random() * 360,
            			saturation: 1,
            			brightness: 1
            		}
            		envelope.velocity = initialVelocity;
            		envelope.removed = false;
            		envelope.updateSelf = function() {
            			if (this.bounds.bottom > view.bounds.height + 1000) {
            				this.remove();
            				envelopes.splice(i,1);
            				return;
            			};
            			function bounce() {
            				if (this.velocity > dampening) {
            					this.velocity -= dampening;
            				} else {
            					this.velocity = 0;
            				}
            				this.velocity = -this.velocity;
            			};			
            
            			if (this.bounds.bottom >= view.bounds.height && !this.dead) {
            				bounce.apply(this);
            			}
            
            			for (var i = 0;i<envelopes.length;i++) {
            				var bottomLeft = new Point(this.bounds.left, this.bounds.bottom);
            				var bottomRight = new Point(this.bounds.left + this.bounds.width, this.bounds.bottom);
            				if (envelopes[i].hitTest(bottomLeft) && envelopes[i].id!=this.id) {
            					bounce.apply(this);
            				};
            				if (envelopes[i].hitTest(bottomRight) && envelopes[i].id!=this.id) {
            					bounce.apply(this);
            				};
            			}
            
            			this.position.y += this.velocity;
            			this.velocity += gravity;
            			this.velocity *= friction;			
            		}
            		envelopes.push(envelope);
            		lastEnvelope = Date.now();
            	};
            };
            
            function onMouseDown() {
            	for (var i = 0;i<envelopes.length;i++) {
            		envelopes[i].dead = true;
            	}
            }

<!-- language: lang-css -->

    #envelopes {
      height: 100%;
      width: 100%
    }

<!-- language: lang-html -->

    <script src="http://cdnjs.cloudflare.com/ajax/libs/paper.js/0.9.18/paper-full.min.js"></script>

    <script type="text/paperscript" canvas="envelopes" resize>
    	     var envelopeHeight = 100;
            var fallRange = 8.5;
            var fallMidpoint = 75;
            var maxOnScreen = 6;
            var frequency = 4500; //time between falls
            var initialVelocity = 0.2;
            
            var gravity = 0.6;
            var friction = 0.97;
            var dampening = 2;
            
            var lastEnvelope = 0;
            var envelopes = [];
            
            function onFrame() {
            	var onScreen = 0;
            	for (var i = 0; i < envelopes.length; i++) {
            		if (!envelopes[i].dead) {
            			onScreen++;
            		}
            		envelopes[i].updateSelf();
            	}
            	if (Date.now() > lastEnvelope + frequency && onScreen <= maxOnScreen) {
            		var dropX = view.bounds.width * (((Math.random() * fallRange) + fallMidpoint) / 100);
            		var envelope = new Path.Rectangle(new Point(dropX, -envelopeHeight), 100, envelopeHeight);
            		envelope.position = new Point(dropX, -envelopeHeight);
            		envelope.fillColor = {
            			hue: Math.random() * 360,
            			saturation: 1,
            			brightness: 1
            		}
            		envelope.velocity = initialVelocity;
            		envelope.removed = false;
            		envelope.updateSelf = function() {
            			if (this.bounds.bottom > view.bounds.height + 1000) {
            				this.remove();
            				envelopes.splice(i,1);
            				return;
            			};
            			function bounce() {
            				if (this.velocity > dampening) {
            					this.velocity -= dampening;
            				} else {
            					this.velocity = 0;
            				}
            				this.velocity = -this.velocity;
            			};			
            
            			if (this.bounds.bottom >= view.bounds.height && !this.dead) {
            				bounce.apply(this);
            			}
            
            			for (var i = 0;i<envelopes.length;i++) {
            				var bottomLeft = new Point(this.bounds.left, this.bounds.bottom);
            				var bottomRight = new Point(this.bounds.left + this.bounds.width, this.bounds.bottom);
            				if (envelopes[i].hitTest(bottomLeft) && envelopes[i].id!=this.id) {
            					bounce.apply(this);
            				};
            				if (envelopes[i].hitTest(bottomRight) && envelopes[i].id!=this.id) {
            					bounce.apply(this);
            				};
            			}
            
            			this.position.y += this.velocity;
            			this.velocity += gravity;
            			this.velocity *= friction;			
            		}
            		envelopes.push(envelope);
            		lastEnvelope = Date.now();
            	};
            };
            
            function onMouseDown() {
            	for (var i = 0;i<envelopes.length;i++) {
            		envelopes[i].dead = true;
            	}
            }
           </script>

    <canvas id="envelopes"></canvas>

<!-- end snippet -->

1. I'm not sure if it would be better to make the envelope into an extension of the Rectangle constructor.
2. The physics seem a bit dodgy, it works well most of the time, but sometimes the boxes overlap and sometimes the bouncing doesn't work properly.

<!--- --->

    var envelopeHeight = 100;
    var fallRange = 8.5;
    var fallMidpoint = 75;
    var maxOnScreen = 6;
    var frequency = 4500; //time between falls
    var initialVelocity = 0.2;
    
    var gravity = 0.6;
    var friction = 0.97;
    var dampening = 2;
    
    var lastEnvelope = 0;
    var envelopes = [];
    
    function onFrame() {
    	var onScreen = 0;
    	for (var i = 0; i < envelopes.length; i++) {
    		if (!envelopes[i].dead) {
    			onScreen++;
    		}
    		envelopes[i].updateSelf();
    	}
    	if (Date.now() > lastEnvelope + frequency && onScreen <= maxOnScreen) {
    		var dropX = view.bounds.width * (((Math.random() * fallRange) + fallMidpoint) / 100);
    		var envelope = new Path.Rectangle(new Point(dropX, -envelopeHeight), 100, envelopeHeight);
    		envelope.position = new Point(dropX, -envelopeHeight);
    		envelope.fillColor = {
    			hue: Math.random() * 360,
    			saturation: 1,
    			brightness: 1
    		}
    		envelope.velocity = initialVelocity;
    		envelope.removed = false;
    		envelope.updateSelf = function() {
    			if (this.bounds.bottom > view.bounds.height + 1000) {
    				this.remove();
    				envelopes.splice(i,1);
    				return;
    			};
    			function bounce() {
    				if (this.velocity > dampening) {
    					this.velocity -= dampening;
    				} else {
    					this.velocity = 0;
    				}
    				this.velocity = -this.velocity;
    			};			
    
    			if (this.bounds.bottom >= view.bounds.height && !this.dead) {
    				bounce.apply(this);
    			}
    
    			for (var i = 0;i<envelopes.length;i++) {
    				var bottomLeft = new Point(this.bounds.left, this.bounds.bottom);
    				var bottomRight = new Point(this.bounds.left + this.bounds.width, this.bounds.bottom);
    				if (envelopes[i].hitTest(bottomLeft) && envelopes[i].id!=this.id) {
    					bounce.apply(this);
    				};
    				if (envelopes[i].hitTest(bottomRight) && envelopes[i].id!=this.id) {
    					bounce.apply(this);
    				};
    			}
    
    			this.position.y += this.velocity;
    			this.velocity += gravity;
    			this.velocity *= friction;			
    		}
    		envelopes.push(envelope);
    		lastEnvelope = Date.now();
    	};
    };
    
    function onMouseDown() {
    	for (var i = 0;i<envelopes.length;i++) {
    		envelopes[i].dead = true;
    	}
    }
    
<!-- -->


[1]:http://sketch.paperjs.org/#S/tVZdT9swFP0rpg8oJSWUbcBWCC9j0x6GNsE0TaI8uMltY5HaWey0Q6j/fddOHDuhUO1hL205Pvf72JenAadLGEwGtw+gkmwwGiQi1X+vaEmAryAXBXwBtsgUicnxeHw+5fpoTvP8hvIFIPo+OvHQa5YWgnFNP7P4kv75xm+TEoAjfGrZJfyugCePiL07Qdfk6EixJZAZqLWmaney5jLOFKP5T8wnYUpbjKM36Kc+XZR0ZVHnnSWKCW7AD2cNmtJlAZzxBcLOPqdSfWqK1fyGbOuXiN3dG/a84rVXwT+X2LlgSJ4QV5ouXInaw1TNRUkCk72B8OvC+Yxy4AuVIRqGjZOpYnMS7LWUO3YfpUDT9niqbIwwPK+hTf3VsamKlCq4hXweDA3NkLTvK8QjLtaY9mW36tAbx/6+q+Ui9qfXZmJ6WYriF1a2YrCOZqLiqYzWLFUZOSBBEFxTlUUl5alYYrgDJ5mhDuYpZUiOtLKG5841uGFwWJPv2tUNJArNcwgMpC0Dk8KIHHaVOhxpf6Oefq1/i0aFkKxRyE6Pfds5y/OPIscBx244WQUT0i/77el4ZAmSqqqkOuaEHLforNQhOEiJ6NapRiun+95N6CdWwlKsIEUitlhC/9hJQzMaMQeewLRKVMakHehMKCWWqBZ/yln9IIS6zWPPeKqMaZ1DYJvW0Wcki5wlELDRsX9eAnaGt8Cm/dVeOB06gaATrU227c+lu+EdZpNZyzuMHdFLY0MAm/aaob3bDb9XuUc77AB+ZbUB39XxeFvL8WruGXLvXUAVmf5EtCjyR+PPtXfjgvWeJHbx7D3ynyN7HeuUvsJcde6Kn3WOhyPyvA5/yM7VTbNQXvaF4vIh867s8q872XkIM6Z+gFSBy3+oO9jhsHQvNm5Z2lPMKx31Fbozrin2PwT2xmr82PcseiRhTLbLr6tSpDWr8wXCQdzuUafbLVsnKiqZtT2w6fbWqls+9VLCz01/qV6LSsKVWLdv0r8J9tnqRCNVVmC34Ab/wZmVQB/M4pGDyd395i8=