1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 // maybe overridden in test file
7 var numBalls = parseInt(getArgValue('ball_count'));
8 if (numBalls == 0 || isNaN(numBalls)) {
11 var ballDiameter = 30;
12 var gravity = 0.5; //screen heights per second^2
13 var maxInitVelocity = 0.2;
14 var maxAngularVelocity = 5; // rad per second
16 var joltInterval = 1.5;
24 var timeOfLastJolt = 0;
26 function include(filename) {
27 var head = document.getElementsByTagName('head')[0];
28 var script = document.createElement('script');
29 script.src = filename;
30 script.type = 'text/javascript';
31 head.appendChild(script)
34 include("bouncing_balls_draw_ball_as_" + getArgValue('ball') + ".js");
35 include("bouncing_balls_draw_back_as_" + getArgValue('back') + ".js");
37 window.requestAnimFrame = (function(){
38 return window.requestAnimationFrame ||
39 window.webkitRequestAnimationFrame ||
40 window.mozRequestAnimationFrame ||
41 window.oRequestAnimationFrame ||
42 window.msRequestAnimationFrame ||
44 window.setTimeout(callback, 1000 / 60);
52 for (var i = 0; i < numBalls; i++) {
53 balls.push(new Ball());
55 window.addEventListener("resize", handleResize, false);
56 drawBallInit(ballDiameter); // externally defined
57 window.requestAnimFrame(updateFrame);
60 function handleResize() {
61 canvasWidth = window.innerWidth;
62 canvasHeight = window.innerHeight;
63 canvas.setAttribute('width', canvasWidth);
64 canvas.setAttribute('height', canvasHeight);
65 borderX = ballDiameter/canvasWidth;
66 borderY = ballDiameter/canvasHeight;
67 prepareBackground(); // externally defined
70 function updateFrame() {
71 var now = new Date().getTime() / 1000;
73 if (now - timeOfLastJolt > joltInterval) {
77 drawBackground(); // externally defined
78 for (var i = 0; i < numBalls; i++) {
81 window.requestAnimFrame(updateFrame);
85 var x = borderX + Math.random()*(1-2*borderX);
86 var y = borderY + Math.random()*(1-2*borderY);
87 var angle = Math.PI * 2 * Math.random();
88 var velocityY = Math.random()*maxInitVelocity*2 - maxInitVelocity;
89 var velocityX = Math.random()*maxInitVelocity*2 - maxInitVelocity;
90 var angularVelocity = Math.random()*maxAngularVelocity*2 -
92 var previousFrameTime = new Date().getTime();
93 var previousBounceTime = 0;
96 var curTime = new Date().getTime();
97 var timeStep = (curTime - previousFrameTime) / 1000;
98 previousFrameTime = curTime;
100 // handle balls that are no longer bouncing
103 // If a jolt is applied, bump the rollong balls enough for them to
104 // reach between 0.75x and 1x the height of the window
105 velocityY = -Math.sqrt(2 * gravity * (1-2 * borderY) * (0.75 + 0.25 *
107 velocityX = Math.random()*maxInitVelocity*2 - maxInitVelocity;
108 angularVelocity = Math.random()*maxAngularVelocity*2 -
112 // rolling on the ground
113 angularVelocity = 2*velocityX*canvasWidth/ballDiameter;
117 // Compute angular motion
118 angle += timeStep*angularVelocity;
119 // Compute horizontal motion
120 var remainingTime = timeStep;
121 var deltaX = velocityX*remainingTime;
122 while ((x+deltaX) < borderX || (x+deltaX) > (1-borderX)){
123 if ((x+deltaX) < borderX) {
125 remainingTime -= (borderX - x)/velocityX;
129 remainingTime -= ((1-borderX) - x)/velocityX;
132 velocityX = -elasticity*velocityX;
133 deltaX = velocityX*remainingTime;
137 // Compute vertical motion
138 remainingTime = timeStep;
139 var deltaY = alive ? velocityY*timeStep+gravity*timeStep*timeStep/2 : 0;
140 //Handle floor bounces
141 //To make sure the floor is air tight, we must be able to process multiple
142 //bounces per time step to avoid the "tunnel effect".
143 while ((y + deltaY) > (1 - borderY) && alive) {
145 var c = y-(1-borderY);
148 // The greater root is always the right one
149 var subStep = (-b + Math.sqrt(b*b-4*a*c))/(2*a);
150 //velocity after floor hit
151 velocityY = -elasticity*(velocityY + gravity*subStep);
152 remainingTime -= subStep;
153 var bounceTime = curTime - remainingTime;
154 if (bounceTime - previousBounceTime < 0.005){
155 // The number of iterations may not be finite within a timestep
156 // with elasticity < 1. This is due to power series convergence.
157 // To gard against hanging, we treat the ball as rolling on the ground
158 // once time between bounces is less than 5ms
162 deltaY = velocityY*remainingTime+gravity*remainingTime*remainingTime/2;
164 previousBounceTime = bounceTime;
168 velocityY += gravity*remainingTime;
170 drawBall(x * canvasWidth, y * canvasHeight, angle); // externally defined