- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / data / perf / rendering / throughput / canvas2d_balls_common / bouncing_balls.js
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.
4
5 // demo parameters
6 // maybe overridden in test file
7 var numBalls = parseInt(getArgValue('ball_count'));
8 if (numBalls == 0 || isNaN(numBalls)) {
9     numBalls = 500;
10 }
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
15 var elasticity = 0.7;
16 var joltInterval = 1.5;
17
18 // globals
19 var balls = [];
20 var canvasWidth;
21 var canvasHeight;
22 var borderX;
23 var borderY;
24 var timeOfLastJolt = 0;
25
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)
32 }
33
34 include("bouncing_balls_draw_ball_as_" + getArgValue('ball') + ".js");
35 include("bouncing_balls_draw_back_as_" + getArgValue('back') + ".js");
36
37 window.requestAnimFrame = (function(){
38   return window.requestAnimationFrame    ||
39       window.webkitRequestAnimationFrame ||
40       window.mozRequestAnimationFrame    ||
41       window.oRequestAnimationFrame      ||
42       window.msRequestAnimationFrame     ||
43       function( callback ){
44         window.setTimeout(callback, 1000 / 60);
45       };
46 })();
47
48 window.onload = init;
49
50 function init(){
51   handleResize();
52   for (var i = 0; i < numBalls; i++) {
53     balls.push(new Ball());
54   }
55   window.addEventListener("resize", handleResize, false);
56   drawBallInit(ballDiameter); // externally defined
57   window.requestAnimFrame(updateFrame);
58 }
59
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
68 }
69
70 function updateFrame() {
71   var now = new Date().getTime() / 1000;
72   var jolt = false;
73   if (now - timeOfLastJolt > joltInterval) {
74     jolt = true;
75     timeOfLastJolt = now;
76   }
77   drawBackground(); // externally defined
78   for (var i = 0; i < numBalls; i++) {
79     balls[i].step(jolt);
80   }
81   window.requestAnimFrame(updateFrame);
82 }
83
84 function Ball(){
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 -
91       maxAngularVelocity;
92   var previousFrameTime = new Date().getTime();
93   var previousBounceTime = 0;
94   var alive = true;
95   function step(jolt) {
96     var curTime = new Date().getTime();
97     var timeStep = (curTime - previousFrameTime) / 1000;
98     previousFrameTime = curTime;
99
100     // handle balls that are no longer bouncing
101     if (!alive) {
102       if (jolt) {
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 *
106             Math.random()))
107         velocityX = Math.random()*maxInitVelocity*2 - maxInitVelocity;
108         angularVelocity = Math.random()*maxAngularVelocity*2 -
109             maxAngularVelocity;
110         alive = true;
111       } else {
112         // rolling on the ground
113         angularVelocity = 2*velocityX*canvasWidth/ballDiameter;
114       }
115     }
116
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) {
124         // left side bounce
125         remainingTime -= (borderX - x)/velocityX;
126         x = borderX;
127       } else {
128         // right side bounce
129         remainingTime -= ((1-borderX) - x)/velocityX;
130         x = 1 - borderX;
131       }
132       velocityX = -elasticity*velocityX;
133       deltaX = velocityX*remainingTime;
134     }
135     x += deltaX;
136
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) {
144       // time to hit floor
145       var c = y-(1-borderY);
146       var b = velocityY;
147       var a = gravity/2;
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
159         alive = false;
160         deltaY = 0;
161       } else {
162         deltaY = velocityY*remainingTime+gravity*remainingTime*remainingTime/2;
163       }
164       previousBounceTime = bounceTime;
165       y = (1 - borderY);
166     }
167     y += deltaY;
168     velocityY += gravity*remainingTime;
169
170     drawBall(x * canvasWidth, y * canvasHeight, angle); // externally defined
171   }
172
173   return {
174     step: step
175   }
176 }