Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(432)

Side by Side Diff: experimental/flocking_geese/js/flocking_geese.js

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2011 (c) The Native Client 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 /**
6 * @file
7 * The FlockingGeese application object. Encapsulates three principle app
8 * elements: the NaCl module which runs the C++ implementation of the flocking
9 * algorithm, a canvas used by the JavaScript implementation, and a DOM
10 * element that contains the info display (which includes things like the
11 * speedometer, control buttons, etc.).
12 */
13
14 goog.provide('FlockingGeese');
15
16 goog.require('Flock');
17 goog.require('Goose');
18 goog.require('LoadProgress');
19 goog.require('Speedometer');
20 goog.require('Speedometer.Attributes');
21 goog.require('goog.Disposable');
22 goog.require('goog.array');
23 goog.require('goog.dom');
24 goog.require('goog.events.EventType');
25 goog.require('goog.math.Vec2');
26 goog.require('goog.style');
27
28 /**
29 * Constructor for the FlockingGeese class. Use the run() method to populate
30 * the object with controllers and wire up the events.
31 * @param {string} containerId The DOM id of the application's container.
32 * @constructor
33 * @extends {goog.Disposable}
34 */
35 FlockingGeese = function(containerId) {
36 goog.Disposable.call(this);
37
38 /**
39 * The DOM element that contains the application.
40 * @type {Element}
41 * @private
42 */
43 this.container_ = document.getElementById(containerId);
44
45 /**
46 * The flock of geese as implemented in JavaScript.
47 * @type {Flock}
48 * @private
49 */
50 this.flock_ = new Flock();
51
52 /**
53 * Bit that tells whether the JS simulation is running or not.
54 * @type {bool}
55 * @private
56 */
57 this.javascriptSimRunning_ = false;
58
59 /**
60 * The NaCl module. This is an <EMBED> element that contains the NaCl
61 * module. Set during moduleDidLoad().
62 * @type {Element}
63 * @private
64 */
65 this.naclModule_ = null;
66
67 /**
68 * The load progress bar.
69 * @type {LoadProgress}
70 * @private
71 */
72 this.progressBar_ = new LoadProgress();
73
74 /**
75 * The speedometer.
76 * @type {Speedometer}
77 * @private
78 */
79 this.speedometer_ = new Speedometer();
80
81 /**
82 * The simluation mode slider. This becomes a Slider object.
83 * @type {Slider}
84 * @private
85 */
86 this.simModeSlider_ = null;
87
88 /**
89 * The flock size slider. This becomes a Slider object.
90 * @type {Slider}
91 * @private
92 */
93 this.flockSizeSlider_ = null;
94
95 /**
96 * The current simulation mode. Starts in 'JavaScript'.
97 * @type {string}
98 * @private
99 */
100 this.simulationMode_ = FlockingGeese.SimulationMode.JAVASCRIPT;
101
102 /**
103 * Event handling.
104 */
105 this.mouseMoveListener_ = null;
106 this.mouseUpListener_ = null;
107 }
108 goog.inherits(FlockingGeese, goog.Disposable);
109
110 /**
111 * Method signatures that are sent from the NaCl module. A signature is really
112 * just a method id - later we can upgrade this to accept (say) full JSON
113 * strings and parse them, but for now a simple solution will work. The strings
114 * need to match the corresponding ones labeled "output method ids" in
115 * flocking_geese_app.cc.
116 * @enum {Object}
117 * @private
118 */
119 FlockingGeese.prototype.MethodSignatures_ = {
120 SET_SIMULATION_INFO: 'setSimulationInfo',
121 FRAME_RATE: 'frameRate'
122 };
123
124 /**
125 * The ids used for elements in the DOM. The FlockingGeese application
126 * expects these elements to exist.
127 * @enum {string}
128 */
129 FlockingGeese.DomIds = {
130 // The elements for the flock size slider. Contained in the info panel.
131 FLOCK_SIZE_SLIDER: 'flock_size_slider',
132 FLOCK_SIZE_SLIDER_RULER: 'flock_size_slider_ruler',
133 FLOCK_SIZE_SLIDER_THUMB: 'flock_size_slider_thumb',
134 // The <FORM> containing various controls.
135 CONTROLS_FORM: 'game_controls_form',
136 // The <CANVAS> where the JS implementation draws its geese.
137 GOOSE_CANVAS: 'flocking_geese_canvas',
138 // The <EMBED> element containing the NaCl module.
139 NACL_MODULE: 'flocking_geese_nacl_module',
140 // The <DIV> containing the simulation drawing area (either the NaCl module
141 // or the <CANVAS>.
142 NACL_VIEW: 'nacl_flocking_geese',
143 // The slider buttons used to select sim type (NaCL vs. JavaScript).
144 // Contained in the info panel.
145 SIM_MODE_SELECT: 'sim_mode_select',
146 SIM_SELECT_RULER: 'sim_select_ruler',
147 SIM_SELECT_THUMB: 'sim_select_thumb',
148 // The text that displays the speed difference.
149 SPEED_DIFFERENCE_LABEL: 'speed_difference',
150 // The speedometer <CANVAS> element. Contained in the info panel.
151 SPEEDOMETER: 'speedometer_canvas'
152 };
153
154 /**
155 * The list of simulation modes. These are the values assigned to the
156 * simulation mode radio buttons.
157 * @enum {string}
158 */
159 FlockingGeese.SimulationMode = {
160 NACL: 'NaCl',
161 JAVASCRIPT: 'JavaScript'
162 };
163
164 /**
165 * The list of meter names.
166 * @enum {string}
167 */
168 FlockingGeese.MeterNames = {
169 NACL: 'NaCl',
170 JAVASCRIPT: 'JavaScript'
171 };
172
173 /**
174 * Override of disposeInternal() to dispose of retained objects.
175 * @override
176 */
177 FlockingGeese.prototype.disposeInternal = function() {
178 this.terminate();
179 FlockingGeese.superClass_.disposeInternal.call(this);
180 }
181
182 /**
183 * Set up all the DOM elements and wire together the events.
184 */
185 FlockingGeese.prototype.initializeApplication = function() {
186 // Listen for 'unload' in order to terminate cleanly.
187 goog.events.listen(window, goog.events.EventType.UNLOAD, this.terminate);
188 var naclMeterAttribs = {};
189 naclMeterAttribs[Speedometer.Attributes.THEME] = Speedometer.Themes.GREEN;
190 naclMeterAttribs[Speedometer.Attributes.ODOMETER_LEFT] = 84;
191 naclMeterAttribs[Speedometer.Attributes.ODOMETER_TOP] = 156;
192 this.speedometer_.addMeterWithName(FlockingGeese.MeterNames.NACL,
193 naclMeterAttribs);
194 var jsMeterAttribs = {};
195 jsMeterAttribs[Speedometer.Attributes.THEME] = Speedometer.Themes.RED;
196 jsMeterAttribs[Speedometer.Attributes.ODOMETER_LEFT] = 84;
197 jsMeterAttribs[Speedometer.Attributes.ODOMETER_TOP] = 192;
198 this.speedometer_.addMeterWithName(FlockingGeese.MeterNames.JAVASCRIPT,
199 jsMeterAttribs);
200 this.speedometer_.setMaximumSpeed(10000.0); // Measured in frames per second.
201
202 var speedometerCanvas =
203 document.getElementById(FlockingGeese.DomIds.SPEEDOMETER);
204 this.speedometer_.setCanvas(speedometerCanvas);
205 this.speedometer_.reset();
206 this.speedometer_.render(this.speedometerCanvas_);
207
208 // Wire up the various controls.
209 goog.events.listen(this.container_, goog.events.EventType.MOUSEDOWN,
210 this.mouseDown_, true, this);
211
212 var simSelectSlider =
213 document.getElementById(FlockingGeese.DomIds.SIM_MODE_SELECT);
214 var simSelectRuler =
215 document.getElementById(FlockingGeese.DomIds.SIM_SELECT_RULER);
216 var simSelectThumb =
217 document.getElementById(FlockingGeese.DomIds.SIM_SELECT_THUMB);
218 this.simModeSlider_ = new Slider(
219 [{simMode: FlockingGeese.SimulationMode.NACL},
220 {simMode: FlockingGeese.SimulationMode.JAVASCRIPT}
221 ]);
222 this.simModeSlider_.decorate(simSelectSlider, simSelectRuler, simSelectThumb);
223 this.simModeSlider_.rulerLength = 80;
224 this.simModeSlider_.rulerOffset = 12;
225 this.simModeSlider_.slideToStep(1);
226 goog.events.listen(this.simModeSlider_, SliderEvent.EventType.CHANGE,
227 this.toggleSimMode, false, this);
228
229 var flockSizeSlider =
230 document.getElementById(FlockingGeese.DomIds.FLOCK_SIZE_SLIDER);
231 var sliderRuler = document.getElementById(
232 FlockingGeese.DomIds.FLOCK_SIZE_SLIDER_RULER);
233 var sliderThumb = document.getElementById(
234 FlockingGeese.DomIds.FLOCK_SIZE_SLIDER_THUMB);
235 this.flockSizeSlider_ = new Slider(
236 [{gooseCount: 50, meterLimit: 30000.0},
237 {gooseCount: 100, meterLimit: 8000.0},
238 {gooseCount: 500, meterLimit: 400.0},
239 {gooseCount: 1000, meterLimit: 100.0}
240 ]);
241 this.flockSizeSlider_.decorate(flockSizeSlider, sliderRuler, sliderThumb);
242 this.flockSizeSlider_.rulerLength = 110;
243 this.flockSizeSlider_.rulerOffset = 18;
244 this.flockSizeSlider_.slideToStep(0);
245 goog.events.listen(this.flockSizeSlider_, SliderEvent.EventType.CHANGE,
246 this.selectFlockSize, false, this);
247
248 // Populate the JavaScript verison of the simulation.
249 var flockSize = 0;
250 if (this.flockSizeSlider_) {
251 var stepObject = this.flockSizeSlider_.objectAtStepValue();
252 flockSize = stepObject.gooseCount;
253 this.speedometer_.setMaximumSpeed(stepObject.meterLimit);
254 }
255 var initialLocation = this.getCanvasCenter_();
256 this.flock_.resetFlock(flockSize, initialLocation);
257 }
258
259 /**
260 * Called by the module loading function once the module has been loaded.
261 * @param {?String} opt_naclModuleId The id of an <EMBED> element which
262 * contains the NaCl module. If unspecified, defaults to |NACL_MODULE|.
263 */
264 FlockingGeese.prototype.moduleDidLoad = function(opt_naclModuleId) {
265 // Set up the view controller, it contains the NaCl module.
266 var naclModuleId = opt_naclModuleId || FlockingGeese.DomIds.NACL_MODULE;
267 this.naclModule_ = document.getElementById(naclModuleId);
268 if (this.flockSizeSlider_) {
269 this.invokeNaClMethod('resetFlock',
270 {'size' : this.flockSizeSlider_.objectAtStepValue().gooseCount});
271 }
272 // Hide the load progress bar and make the module element visible.
273 this.progressBar_.setVisible(false);
274 this.naclModule_.style.visibility = 'inherit';
275 // If the NaCL module is being displayed, then start the simulation.
276 var naclView = document.getElementById(FlockingGeese.DomIds.NACL_VIEW);
277 if (naclView.style.visibility == 'visible') {
278 this.invokeNaClMethod('runSimulation');
279 }
280 }
281
282 /**
283 * Asserts that cond is true; issues an alert and throws an Error otherwise.
284 * @param {bool} cond The condition.
285 * @param {String} message The error message issued if cond is false.
286 */
287 FlockingGeese.prototype.assert = function(cond, message) {
288 if (!cond) {
289 message = "Assertion failed: " + message;
290 alert(message);
291 throw new Error(message);
292 }
293 }
294
295 /**
296 * Change the flock size.
297 * @param {!goog.events.Event} changeEvent The CHANGE event that triggered this
298 * handler.
299 */
300 FlockingGeese.prototype.selectFlockSize = function(changeEvent) {
301 changeEvent.stopPropagation();
302 var initialLocation = this.getCanvasCenter_();
303 var stepObject =
304 this.flockSizeSlider_.objectAtStepValue(changeEvent.stepValue);
305 var newFlockSize = stepObject.gooseCount;
306 this.speedometer_.setMaximumSpeed(stepObject.meterLimit);
307 // Reset the speedometers to 0.
308 this.speedometer_.updateMeterNamed(FlockingGeese.MeterNames.NACL, 0);
309 this.speedometer_.updateMeterNamed(FlockingGeese.MeterNames.JAVASCRIPT, 0);
310 this.speedometer_.reset();
311 this.flock_.resetFlock(newFlockSize, initialLocation);
312 this.invokeNaClMethod('resetFlock', {'size' : newFlockSize});
313 this.updateSpeedDifference_();
314 }
315
316 /**
317 * Toggle the simulation mode.
318 * @param {!goog.events.Event} changeEvent The CHANGE event that triggered this
319 * handler.
320 */
321 FlockingGeese.prototype.toggleSimMode = function(changeEvent) {
322 changeEvent.stopPropagation();
323 var simModeObject =
324 this.simModeSlider_.objectAtStepValue(changeEvent.stepValue);
325 var simMode = simModeObject.simMode;
326 if (simMode == this.simulationMode_)
327 return;
328 this.simulationMode_ = simMode;
329 if (simMode == FlockingGeese.SimulationMode.NACL) {
330 // When toggling to 'NaCl', turn off the JavaScript simulation timer and
331 // swap the DOM elements to display the NaCl implementation.
332 this.stopJavaScriptSimulation_();
333 var flockingCanvas =
334 document.getElementById(FlockingGeese.DomIds.GOOSE_CANVAS);
335 flockingCanvas.style.visibility = 'hidden';
336 var naclView =
337 document.getElementById(FlockingGeese.DomIds.NACL_VIEW);
338 naclView.style.visibility = 'visible';
339 // Start up the NaCl simulation.
340 this.invokeNaClMethod('runSimulation');
341 } else {
342 // In the 'on' state, the simulation runs the NaCl implementation.
343 this.invokeNaClMethod('pauseSimulation');
344 this.startJavaScriptSimulation_();
345 var flockingCanvas =
346 document.getElementById(FlockingGeese.DomIds.GOOSE_CANVAS);
347 flockingCanvas.style.visibility = 'visible';
348 var naclView =
349 document.getElementById(FlockingGeese.DomIds.NACL_VIEW);
350 naclView.style.visibility = 'hidden';
351 }
352 }
353
354 /**
355 * Format a method invocation and call postMessage with the formatted method
356 * string. This calls the NaCl module with the invocation string. Note that
357 * this is an asynchronous call into the NaCl module.
358 * @param {!string} methodName The name of the method. This must match a
359 * published method name in the NaCl module.
360 * @param {?Object} parameters A dictionary that maps parameter names to
361 * values. All parameter values are passed a strings.
362 */
363 FlockingGeese.prototype.invokeNaClMethod =
364 function(methodName, opt_parameters) {
365 if (!this.naclModule_) {
366 return;
367 }
368 var methodInvocation = methodName
369 if (opt_parameters) {
370 for (param in opt_parameters) {
371 methodInvocation += ' ' + param + ':' + opt_parameters[param]
372 }
373 }
374 this.naclModule_.postMessage(methodInvocation);
375 }
376
377 /**
378 * Handle a message posted by the NaCl module. An incomming NaCl message is
379 * formatted like the outgoing message in invokeNaClMethod() (see above).
380 * There is a method name, followed by a space-separated list of named
381 * parameters. The parameters are separated from their values by a ':'.
382 * @param {Event} messageEvent The Event wrapping the message.
383 */
384 FlockingGeese.prototype.handleNaClMessage = function(messageEvent) {
385 var methodInvocation = messageEvent.data.split(' ');
386 // The first element of |methodInvocation| is the method name. Use this as
387 // the key to look up the rest of the signature.
388 if (methodInvocation[0] == this.MethodSignatures_.SET_SIMULATION_INFO) {
389 for (var paramCount = 1;
390 paramCount < methodInvocation.length;
391 paramCount++) {
392 var parameter = methodInvocation[paramCount].split(':');
393 // The first element is the parameter name, the second element is its
394 // value.
395 if (parameter[0] == this.MethodSignatures_.FRAME_RATE) {
396 var frameRate = parseFloat(parameter[1]);
397 this.speedometer_.updateMeterNamed(FlockingGeese.MeterNames.NACL,
398 frameRate);
399 this.updateSpeedDifference_();
400 }
401 }
402 } else {
403 var error = 'Unrecognized NaCl message: ' + messageEvent.data;
404 console.log(error);
405 throw new Error(error);
406 }
407 }
408
409 /**
410 * The run() method starts and 'runs' the FlockingGeese app. An <EMBED> tag is
411 * injected into the <DIV> element |opt_viewDivName| which causes the NaCl
412 * module to be loaded. Once loaded, the moduleDidLoad() method is called via
413 * a 'load' event handler that is attached to the <DIV> element.
414 * @param {?String} opt_viewDivName The id of a DOM element in which to
415 * embed the NaCl module. If unspecified, defaults to DomIds.VIEW. The
416 * DOM element must exist.
417 */
418 FlockingGeese.prototype.run = function(opt_viewDivName) {
419 var viewDivName = opt_viewDivName || FlockingGeese.DomIds.NACL_VIEW;
420 var viewDiv = document.getElementById(viewDivName);
421 this.assert(viewDiv, "Missing DOM element '" + viewDivName + "'");
422
423 this.initializeApplication();
424
425 // A small handler for the 'load' event. It stops propagation of the 'load'
426 // event and then calls moduleDidLoad(). The handler is bound to |this| so
427 // that the calling context of the closure makes |this| point to this
428 // instance of the Applicaiton object.
429 var loadEventHandler = function(loadEvent) {
430 this.moduleDidLoad(FlockingGeese.DomIds.NACL_MODULE);
431 }
432
433 // Note that the <EMBED> element is wrapped inside a <DIV>, which has a 'load'
434 // event listener attached. This method is used instead of attaching the
435 // 'load' event listener directly to the <EMBED> element to ensure that the
436 // listener is active before the NaCl module 'load' event fires.
437 viewDiv.addEventListener('load', goog.bind(loadEventHandler, this), true);
438 // Attach a listener for messages coming from the NaCl module.
439 viewDiv.addEventListener('message',
440 goog.bind(this.handleNaClMessage, this),
441 true);
442 // Handle the load progress.
443 viewDiv.addEventListener(
444 'progress',
445 goog.bind(this.progressBar_.handleProgressEvent, this.progressBar_),
446 true);
447
448 var viewSize = goog.style.getSize(viewDiv);
449 viewDiv.appendChild(this.progressBar_.createDom());
450 var naclDom = goog.dom.createDom('embed', {
451 'id': FlockingGeese.DomIds.NACL_MODULE,
452 'class': 'autosize-view',
453 'width': viewSize.width,
454 'height': viewSize.height,
455 'src': 'flocking_geese.nmf',
456 'type': 'application/x-nacl',
457 'style': 'visibility: inherit'
458 });
459 viewDiv.appendChild(naclDom);
460 this.startJavaScriptSimulation_();
461 }
462
463 /**
464 * Run one tick of the simulation and then render the new flock. Update the
465 * speedometer with new timing values.
466 */
467 FlockingGeese.prototype.simulationTick = function() {
468 var flockingCanvas =
469 document.getElementById(FlockingGeese.DomIds.GOOSE_CANVAS);
470 // Clear the canvas
471 var context2d = flockingCanvas.getContext('2d');
472 var flockBox = new goog.math.Rect(0,
473 0,
474 flockingCanvas.width,
475 flockingCanvas.height);
476 context2d.fillStyle = 'white';
477 context2d.fillRect(flockBox.top,
478 flockBox.left,
479 flockBox.width,
480 flockBox.height);
481 var frameRate = this.flock_.flock(flockBox);
482 this.flock_.render(flockingCanvas);
483 this.speedometer_.updateMeterNamed(FlockingGeese.MeterNames.JAVASCRIPT,
484 frameRate);
485 this.updateSpeedDifference_();
486
487 if (this.javascriptSimRunning_) {
488 var self = this;
489 window.webkitRequestAnimationFrame(function() {
490 self.simulationTick();
491 });
492 }
493 }
494
495 /**
496 * Shut down the application instance. This unhooks all the event listeners
497 * and deletes the objects created in moduleDidLoad().
498 */
499 FlockingGeese.prototype.terminate = function() {
500 goog.events.removeAll();
501 this.stopJavaScriptSimulation_();
502 }
503
504 /**
505 * Handle a mousedown on the application view.
506 * @param {Event} mouseEvent The event that triggered this handler.
507 */
508 FlockingGeese.prototype.mouseDown_ = function(mouseEvent) {
509 mouseEvent.preventDefault();
510 mouseEvent.stopPropagation();
511 // Listen for mouse-move and mouse-up events. Dragging stops when the
512 // mouse-up event arrives.
513 if (this.mouseMoveListener_ == null) {
514 this.mouseMoveListener_ = goog.events.listen(
515 this.container_,
516 goog.events.EventType.MOUSEMOVE,
517 this.mouseMove_, true, this);
518 }
519 if (this.mouseUpListener_ == null) {
520 this.mouseUpListener_ = goog.events.listen(
521 window,
522 goog.events.EventType.MOUSEUP,
523 this.mouseUp_, true, this);
524 }
525 this.setAttractorFromEvent_(mouseEvent);
526 }
527
528 /**
529 * Handle a mousemove on the application view.
530 * @param {Event} mouseEvent The event that triggered this handler.
531 */
532 FlockingGeese.prototype.mouseMove_ = function(mouseEvent) {
533 this.setAttractorFromEvent_(mouseEvent);
534 }
535
536 /**
537 * Handle a mouseup on the application view.
538 * @param {Event} mouseEvent The event that triggered this handler.
539 */
540 FlockingGeese.prototype.mouseUp_ = function(mouseEvent) {
541 if (this.mouseMoveListener_ != null) {
542 goog.events.unlistenByKey(this.mouseMoveListener_);
543 this.mouseMoveListener_ = null;
544 }
545 if (this.mouseUpListener_ != null) {
546 goog.events.unlistenByKey(this.mouseUpListener_);
547 this.mouseUpListener_ = null;
548 }
549 }
550
551 /**
552 * Set the attractor position from the coordinates in a browser event.
553 * @param {Event} event The event.
554 */
555 FlockingGeese.prototype.setAttractorFromEvent_ = function(event) {
556 var origin = goog.style.getPageOffset(this.container_);
557 var attractor = new goog.math.Vec2(event.clientX - origin.x,
558 event.clientY - origin.y);
559 if (this.flock_.attractors.length == 0) {
560 this.flock_.attractors.push(attractor);
561 }
562 this.flock_.attractors[0] = attractor;
563 this.invokeNaClMethod('setAttractorLocation x:' + attractor.x +
564 ' y:' + attractor.y);
565 }
566
567 /**
568 * Start up the JavaScript implementation of the simulation by enabling the
569 * simulation timer.
570 * @private
571 */
572 FlockingGeese.prototype.startJavaScriptSimulation_ = function() {
573 // Start up the JavaScript implementation of the simulation.
574 if (this.javascriptSimRunning_)
575 return; // Don't run a tick if the sim is already running.
576 this.javascriptSimRunning_ = true;
577 this.simulationTick();
578 }
579
580 /**
581 * Stop the JavaScript implementation of the simulation by clearing the
582 * simulation timer.
583 * @private
584 */
585 FlockingGeese.prototype.stopJavaScriptSimulation_ = function() {
586 // Stop the JavaScript implementation of the simulation.
587 this.javascriptSimRunning_ = false;
588 }
589
590 /**
591 * Recompute the speed difference between JavaScript and Native Client.
592 * Color the result depending on which is faster.
593 * @private
594 */
595 FlockingGeese.prototype.updateSpeedDifference_ = function() {
596 var speedDifferenceLabel =
597 document.getElementById(FlockingGeese.DomIds.SPEED_DIFFERENCE_LABEL);
598 var naclSpeed = this.speedometer_.valueForMeterNamed(
599 FlockingGeese.MeterNames.NACL,
600 Speedometer.Attributes.ODOMETER_DISPLAY_VALUE);
601 var jsSpeed = this.speedometer_.valueForMeterNamed(
602 FlockingGeese.MeterNames.JAVASCRIPT,
603 Speedometer.Attributes.ODOMETER_DISPLAY_VALUE);
604 if (naclSpeed == 0 || jsSpeed == 0) {
605 speedDifferenceLabel.innerHTML = 'Not available&hellip;';
606 speedDifferenceLabel.style.fontStyle = 'italic';
607 speedDifferenceLabel.style.color = '#949596';
608 } else {
609 var diff = naclSpeed / jsSpeed;
610 speedDifferenceLabel.innerHTML = diff.toFixed(1) + 'X';
611 speedDifferenceLabel.style.fontStyle = 'normal';
612 speedDifferenceLabel.style.color = diff > 1.0 ? '#009933' : '#FF0033';
613 }
614 }
615
616 /**
617 * Find the center point of the simulation canvas. If the a canvas element
618 * with id |GOOSE_CANVAS| doesn't exist, return (0, 0).
619 * @return {goog.math.Vec2} The center of the simulation canvas, measured in
620 * pixels.
621 * @private
622 */
623 FlockingGeese.prototype.getCanvasCenter_ = function() {
624 var flockingCanvas =
625 document.getElementById(FlockingGeese.DomIds.GOOSE_CANVAS);
626 if (flockingCanvas)
627 return new goog.math.Vec2(flockingCanvas.width / 2,
628 flockingCanvas.height / 2);
629 else
630 return new goog.math.Vec2(0, 0);
631 }
OLDNEW
« no previous file with comments | « experimental/flocking_geese/js/flock.js ('k') | experimental/flocking_geese/js/frame_counter.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698