OLD | NEW |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 (function() { | 4 (function() { |
5 'use strict'; | 5 'use strict'; |
6 /** | 6 /** |
7 * T-Rex runner. | 7 * T-Rex runner. |
8 * @param {string} outerContainerId Outer containing element id. | 8 * @param {string} outerContainerId Outer containing element id. |
9 * @param {Object} opt_config | 9 * @param {Object} opt_config |
10 * @constructor | 10 * @constructor |
11 * @export | 11 * @export |
12 */ | 12 */ |
13 function Runner(outerContainerId, opt_config) { | 13 function Runner(outerContainerId, opt_config) { |
14 // Singleton | 14 // Singleton |
15 if (Runner.instance_) { | 15 if (Runner.instance_) { |
16 return Runner.instance_; | 16 return Runner.instance_; |
17 } | 17 } |
18 Runner.instance_ = this; | 18 Runner.instance_ = this; |
19 | 19 |
20 this.outerContainerEl = document.querySelector(outerContainerId); | 20 this.outerContainerEl = document.querySelector(outerContainerId); |
21 this.containerEl = null; | 21 this.containerEl = null; |
22 this.snackbarEl = null; | 22 this.snackbarEl = null; |
23 | 23 |
24 this.config = opt_config || Runner.config; | 24 this.config = opt_config || Runner.config; |
25 | 25 // Logical dimensions of the container. |
26 this.dimensions = Runner.defaultDimensions; | 26 this.dimensions = Runner.defaultDimensions; |
27 | 27 |
28 this.canvas = null; | 28 this.canvas = null; |
29 this.canvasCtx = null; | 29 this.canvasCtx = null; |
30 | 30 |
31 this.tRex = null; | 31 this.tRex = null; |
32 | 32 |
33 this.distanceMeter = null; | 33 this.distanceMeter = null; |
34 this.distanceRan = 0; | 34 this.distanceRan = 0; |
35 | 35 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 | 89 |
90 /** @const */ | 90 /** @const */ |
91 var IS_IOS = /iPad|iPhone|iPod/.test(window.navigator.platform); | 91 var IS_IOS = /iPad|iPhone|iPod/.test(window.navigator.platform); |
92 | 92 |
93 /** @const */ | 93 /** @const */ |
94 var IS_MOBILE = /Android/.test(window.navigator.userAgent) || IS_IOS; | 94 var IS_MOBILE = /Android/.test(window.navigator.userAgent) || IS_IOS; |
95 | 95 |
96 /** @const */ | 96 /** @const */ |
97 var IS_TOUCH_ENABLED = 'ontouchstart' in window; | 97 var IS_TOUCH_ENABLED = 'ontouchstart' in window; |
98 | 98 |
| 99 /** @const */ |
| 100 var ARCADE_MODE_URL = 'chrome://dino/'; |
| 101 |
99 /** | 102 /** |
100 * Default game configuration. | 103 * Default game configuration. |
101 * @enum {number} | 104 * @enum {number} |
102 */ | 105 */ |
103 Runner.config = { | 106 Runner.config = { |
104 ACCELERATION: 0.001, | 107 ACCELERATION: 0.001, |
105 BG_CLOUD_SPEED: 0.2, | 108 BG_CLOUD_SPEED: 0.2, |
106 BOTTOM_PAD: 10, | 109 BOTTOM_PAD: 10, |
107 CLEAR_TIME: 3000, | 110 CLEAR_TIME: 3000, |
108 CLOUD_FREQUENCY: 0.5, | 111 CLOUD_FREQUENCY: 0.5, |
109 GAMEOVER_CLEAR_TIME: 750, | 112 GAMEOVER_CLEAR_TIME: 750, |
110 GAP_COEFFICIENT: 0.6, | 113 GAP_COEFFICIENT: 0.6, |
111 GRAVITY: 0.6, | 114 GRAVITY: 0.6, |
112 INITIAL_JUMP_VELOCITY: 12, | 115 INITIAL_JUMP_VELOCITY: 12, |
113 INVERT_FADE_DURATION: 12000, | 116 INVERT_FADE_DURATION: 12000, |
114 INVERT_DISTANCE: 700, | 117 INVERT_DISTANCE: 700, |
115 MAX_BLINK_COUNT: 3, | 118 MAX_BLINK_COUNT: 3, |
116 MAX_CLOUDS: 6, | 119 MAX_CLOUDS: 6, |
117 MAX_OBSTACLE_LENGTH: 3, | 120 MAX_OBSTACLE_LENGTH: 3, |
118 MAX_OBSTACLE_DUPLICATION: 2, | 121 MAX_OBSTACLE_DUPLICATION: 2, |
119 MAX_SPEED: 13, | 122 MAX_SPEED: 13, |
120 MIN_JUMP_HEIGHT: 35, | 123 MIN_JUMP_HEIGHT: 35, |
121 MOBILE_SPEED_COEFFICIENT: 1.2, | 124 MOBILE_SPEED_COEFFICIENT: 1.2, |
122 RESOURCE_TEMPLATE_ID: 'audio-resources', | 125 RESOURCE_TEMPLATE_ID: 'audio-resources', |
123 SPEED: 6, | 126 SPEED: 6, |
124 SPEED_DROP_COEFFICIENT: 3 | 127 SPEED_DROP_COEFFICIENT: 3, |
| 128 ARCADE_MODE_TOP_POSITION_PERCENT: 0.1 |
125 }; | 129 }; |
126 | 130 |
127 | 131 |
128 /** | 132 /** |
129 * Default dimensions. | 133 * Default dimensions. |
130 * @enum {string} | 134 * @enum {string} |
131 */ | 135 */ |
132 Runner.defaultDimensions = { | 136 Runner.defaultDimensions = { |
133 WIDTH: DEFAULT_WIDTH, | 137 WIDTH: DEFAULT_WIDTH, |
134 HEIGHT: 150 | 138 HEIGHT: 150 |
135 }; | 139 }; |
136 | 140 |
137 | 141 |
138 /** | 142 /** |
139 * CSS class names. | 143 * CSS class names. |
140 * @enum {string} | 144 * @enum {string} |
141 */ | 145 */ |
142 Runner.classes = { | 146 Runner.classes = { |
| 147 ARCADE_MODE: 'arcade-mode', |
143 CANVAS: 'runner-canvas', | 148 CANVAS: 'runner-canvas', |
144 CONTAINER: 'runner-container', | 149 CONTAINER: 'runner-container', |
145 CRASHED: 'crashed', | 150 CRASHED: 'crashed', |
146 ICON: 'icon-offline', | 151 ICON: 'icon-offline', |
147 INVERTED: 'inverted', | 152 INVERTED: 'inverted', |
148 SNACKBAR: 'snackbar', | 153 SNACKBAR: 'snackbar', |
149 SNACKBAR_SHOW: 'snackbar-show', | 154 SNACKBAR_SHOW: 'snackbar-show', |
150 TOUCH_CONTROLLER: 'controller' | 155 TOUCH_CONTROLLER: 'controller' |
151 }; | 156 }; |
152 | 157 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 MOUSEUP: 'mouseup', | 223 MOUSEUP: 'mouseup', |
219 RESIZE: 'resize', | 224 RESIZE: 'resize', |
220 TOUCHEND: 'touchend', | 225 TOUCHEND: 'touchend', |
221 TOUCHSTART: 'touchstart', | 226 TOUCHSTART: 'touchstart', |
222 VISIBILITY: 'visibilitychange', | 227 VISIBILITY: 'visibilitychange', |
223 BLUR: 'blur', | 228 BLUR: 'blur', |
224 FOCUS: 'focus', | 229 FOCUS: 'focus', |
225 LOAD: 'load' | 230 LOAD: 'load' |
226 }; | 231 }; |
227 | 232 |
228 | |
229 Runner.prototype = { | 233 Runner.prototype = { |
230 /** | 234 /** |
231 * Whether the easter egg has been disabled. CrOS enterprise enrolled devices. | 235 * Whether the easter egg has been disabled. CrOS enterprise enrolled devices. |
232 * @return {boolean} | 236 * @return {boolean} |
233 */ | 237 */ |
234 isDisabled: function() { | 238 isDisabled: function() { |
235 return loadTimeData && loadTimeData.valueExists('disabledEasterEgg'); | 239 return loadTimeData && loadTimeData.valueExists('disabledEasterEgg'); |
236 }, | 240 }, |
237 | 241 |
238 /** | 242 /** |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 */ | 415 */ |
412 adjustDimensions: function() { | 416 adjustDimensions: function() { |
413 clearInterval(this.resizeTimerId_); | 417 clearInterval(this.resizeTimerId_); |
414 this.resizeTimerId_ = null; | 418 this.resizeTimerId_ = null; |
415 | 419 |
416 var boxStyles = window.getComputedStyle(this.outerContainerEl); | 420 var boxStyles = window.getComputedStyle(this.outerContainerEl); |
417 var padding = Number(boxStyles.paddingLeft.substr(0, | 421 var padding = Number(boxStyles.paddingLeft.substr(0, |
418 boxStyles.paddingLeft.length - 2)); | 422 boxStyles.paddingLeft.length - 2)); |
419 | 423 |
420 this.dimensions.WIDTH = this.outerContainerEl.offsetWidth - padding * 2; | 424 this.dimensions.WIDTH = this.outerContainerEl.offsetWidth - padding * 2; |
| 425 if (this.isArcadeMode()) { |
| 426 this.dimensions.WIDTH = Math.min(DEFAULT_WIDTH, this.dimensions.WIDTH); |
| 427 if (this.activated) { |
| 428 this.setArcadeModeContainerScale(); |
| 429 } |
| 430 } |
421 | 431 |
422 // Redraw the elements back onto the canvas. | 432 // Redraw the elements back onto the canvas. |
423 if (this.canvas) { | 433 if (this.canvas) { |
424 this.canvas.width = this.dimensions.WIDTH; | 434 this.canvas.width = this.dimensions.WIDTH; |
425 this.canvas.height = this.dimensions.HEIGHT; | 435 this.canvas.height = this.dimensions.HEIGHT; |
426 | 436 |
427 Runner.updateCanvasScaling(this.canvas); | 437 Runner.updateCanvasScaling(this.canvas); |
428 | 438 |
429 this.distanceMeter.calcXPos(this.dimensions.WIDTH); | 439 this.distanceMeter.calcXPos(this.dimensions.WIDTH); |
430 this.clearCanvas(); | 440 this.clearCanvas(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 } else if (this.crashed) { | 489 } else if (this.crashed) { |
480 this.restart(); | 490 this.restart(); |
481 } | 491 } |
482 }, | 492 }, |
483 | 493 |
484 | 494 |
485 /** | 495 /** |
486 * Update the game status to started. | 496 * Update the game status to started. |
487 */ | 497 */ |
488 startGame: function() { | 498 startGame: function() { |
| 499 if (this.isArcadeMode()) { |
| 500 this.setArcadeMode(); |
| 501 } |
489 this.runningTime = 0; | 502 this.runningTime = 0; |
490 this.playingIntro = false; | 503 this.playingIntro = false; |
491 this.tRex.playingIntro = false; | 504 this.tRex.playingIntro = false; |
492 this.containerEl.style.webkitAnimation = ''; | 505 this.containerEl.style.webkitAnimation = ''; |
493 this.playCount++; | 506 this.playCount++; |
494 | 507 |
495 // Handle tabbing off the page. Pause the current game. | 508 // Handle tabbing off the page. Pause the current game. |
496 document.addEventListener(Runner.events.VISIBILITY, | 509 document.addEventListener(Runner.events.VISIBILITY, |
497 this.onVisibilityChange.bind(this)); | 510 this.onVisibilityChange.bind(this)); |
498 | 511 |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
819 this.distanceMeter.reset(this.highestScore); | 832 this.distanceMeter.reset(this.highestScore); |
820 this.horizon.reset(); | 833 this.horizon.reset(); |
821 this.tRex.reset(); | 834 this.tRex.reset(); |
822 this.playSound(this.soundFx.BUTTON_PRESS); | 835 this.playSound(this.soundFx.BUTTON_PRESS); |
823 this.invert(true); | 836 this.invert(true); |
824 this.update(); | 837 this.update(); |
825 } | 838 } |
826 }, | 839 }, |
827 | 840 |
828 /** | 841 /** |
| 842 * Whether the game should go into arcade mode. |
| 843 * @return {boolean} |
| 844 */ |
| 845 isArcadeMode: function() { |
| 846 return document.title == ARCADE_MODE_URL; |
| 847 }, |
| 848 |
| 849 /** |
| 850 * Hides offline messaging for a fullscreen game only experience. |
| 851 */ |
| 852 setArcadeMode: function() { |
| 853 document.body.classList.add(Runner.classes.ARCADE_MODE); |
| 854 this.setArcadeModeContainerScale(); |
| 855 }, |
| 856 |
| 857 /** |
| 858 * Sets the scaling for arcade mode. |
| 859 */ |
| 860 setArcadeModeContainerScale: function() { |
| 861 var windowHeight = window.innerHeight; |
| 862 var scaleHeight = windowHeight / this.dimensions.HEIGHT; |
| 863 var scaleWidth = window.innerWidth / this.dimensions.WIDTH; |
| 864 var scale = Math.max(1, Math.min(scaleHeight, scaleWidth)); |
| 865 var scaledCanvasHeight = this.dimensions.HEIGHT * scale; |
| 866 // Positions the game container at 10% of the available vertical window |
| 867 // height minus the game container height. |
| 868 var translateY = Math.max(0, (windowHeight - scaledCanvasHeight) * |
| 869 Runner.config.ARCADE_MODE_TOP_POSITION_PERCENT); |
| 870 this.containerEl.style.transform = 'scale(' + scale + ') translateY(' + |
| 871 translateY + 'px)'; |
| 872 }, |
| 873 |
| 874 /** |
829 * Pause the game if the tab is not in focus. | 875 * Pause the game if the tab is not in focus. |
830 */ | 876 */ |
831 onVisibilityChange: function(e) { | 877 onVisibilityChange: function(e) { |
832 if (document.hidden || document.webkitHidden || e.type == 'blur' || | 878 if (document.hidden || document.webkitHidden || e.type == 'blur' || |
833 document.visibilityState != 'visible') { | 879 document.visibilityState != 'visible') { |
834 this.stop(); | 880 this.stop(); |
835 } else if (!this.crashed) { | 881 } else if (!this.crashed) { |
836 this.tRex.reset(); | 882 this.tRex.reset(); |
837 this.play(); | 883 this.play(); |
838 } | 884 } |
(...skipping 1850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2689 | 2735 |
2690 /** | 2736 /** |
2691 * Add a new cloud to the horizon. | 2737 * Add a new cloud to the horizon. |
2692 */ | 2738 */ |
2693 addCloud: function() { | 2739 addCloud: function() { |
2694 this.clouds.push(new Cloud(this.canvas, this.spritePos.CLOUD, | 2740 this.clouds.push(new Cloud(this.canvas, this.spritePos.CLOUD, |
2695 this.dimensions.WIDTH)); | 2741 this.dimensions.WIDTH)); |
2696 } | 2742 } |
2697 }; | 2743 }; |
2698 })(); | 2744 })(); |
OLD | NEW |