Pro JavaScript List.11-11

  1 //为实现各种现代浏览器的requestAnimationFrame()方法,创建一段简单的跨浏览器保障代码(polyfill),以实现流畅、高效的动画。由保罗•艾里什(Paul Irish)编写,网址为 http://bit.ly/req_anim_frame。
  2 window.requestAnimationFrame = (function(){
  3     return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback){
  4         window.setTimeout(callback, 1000 / 60);
  5     };
  6 })();
  7 
  8 // Define the game logic module which keeps track of the game state, the players's score,
  9 // the number of lives remaining, handles collisions between the player's character and
 10 // other obstacles and ensures the game graphics are drawn onto the  at the
 11 // right moment. This module contains the brains behind the game play and instructs other
 12 // code modules to do the heavy lifting through the use of the observer design pattern.
 13 //定义游戏的逻辑模块。此模块保持追踪以下内容,包括有游戏状态、玩家的分数、剩余的生命条数。此模块还处理玩家角色和其他物体碰撞。此模块还确保游戏图形可以在正确的时刻绘制到上。
 14 (function(Frogger) {
 15 
 16     // Define a variable to hold the current player's score
 17     //定一个变量来记录玩家当前的分数。
 18     var _score = 0,
 19 
 20         // Define and initialize a variable to hold the high score achieved in the game
 21         //定义并初始化一个变量来记录游戏中所获得的最高分。
 22         _highScore = 1000,
 23 
 24         // Define the number of lives the player has remaining before the game is over
 25         //定义游戏结束前玩家还剩余的生命条数。
 26         _lives = 5,
 27 
 28         // Define the number of milliseconds the player has to get their character to
 29         // the goal (60 seconds). If they take too long, they will lose a life
 30         //定义玩家要将他们的角色送达目标位置的毫秒数(60秒)。如果玩家耗用时间过长,则他们将失去一条生命。
 31         _timeTotal = 60000,
 32 
 33         // Define a variable to store the current time remaining for the player to reach
 34         // the goal
 35         //定义一个变量来保存玩家要到达目标位置的当前剩余时间。
 36         _timeRemaining = _timeTotal,
 37 
 38         // Define the refresh rate of the graphics on the  element (one draw every
 39         // 33⅓ milliseconds = 30 frames per second). Attempting to redraw too frequently
 40         // can cause the browser to slow down so choose this value carefully to maintain a
 41         // good balance between fluid animation and smooth playability
 42         //定义元素上的图形的刷新时间(每33⅓毫秒绘制一次 = 每秒30帧)。频率太快的重新绘制会引起浏览器响应缓慢。因此,选择使用这个值可以在流畅的动画与利索的可玩性之间取得平衡。
 43         _refreshRate = 33.333,
 44 
 45         // Define a variable to store the number of times the player's character has
 46         // reached the goal
 47         //定义一个变量来保存玩家的角色已经到达目标位置的次数。
 48         _timesAtGoal = 0,
 49 
 50         // Define a variable to indicate the number of times the player's character needs
 51         // to reach the goal for the game to be won
 52         //定义一个变量来记录玩家的角色为取得胜利还须到达目标位置的次数。
 53         _maxTimesAtGoal = 5,
 54 
 55         // Define a Boolean variable to indicate whether the player's movement is currently
 56         // frozen in place
 57         //定义一个布尔变量来记录玩家当前的移动状态是否被冻结在原地。
 58         _isPlayerFrozen = false,
 59 
 60         // Define a variable to store the last time the game loop ran - this helps keep
 61         // the animation running smoothly at the defined refresh rate
 62         //定义一个变量来保存上一次游戏主循环运行的时间——这有助于使动画以所定义的刷新频率下流通运行。
 63         _lastTimeGameLoopRan = (new Date()).getTime();
 64 
 65     // Define a function to be called to count down the time remaining for the player to
 66     // reach the goal without forfeiting a life
 67     //定义一个函数进行调用,用来对玩家到达目标而不至于失去一条生命的剩余时间进行倒计时。
 68     function countDown() {
 69         if (_timeRemaining > 0) {
 70 
 71             // This function will be called as frequently as the _refreshRate variable
 72             // dictates so we reduce the number of milliseconds remaining by the
 73             // _refreshRate value for accurate timing
 74             //此函数将会根据_refreshRate变量值的频率进行调用。这样,我们就可以用剩余的毫秒数减去_refreshRate变量的值来实现精确的倒计时。
 75             _timeRemaining -= _refreshRate;
 76 
 77             // Publish the fact that the remaining time has changed, passing along the
 78             // new time remaining as a percentage - which will help when we come to display
 79             // the remaining time on the game board itself
 80             //发出通知,剩余时间已经发生改变,把新的剩余时间以百分比形式传入——有助于我们在游戏面板上显式剩余时间。
 81             Frogger.observer.publish("time-remaining-change", _timeRemaining / _timeTotal);
 82         } else {
 83 
 84             // If the remaining time reaches zero, we take one of the player's remaining
 85             // lives
 86             //如果剩余时间到达零,则将玩家的剩余生命条数减一。
 87             loseLife();
 88         }
 89     }
 90 
 91     // Define a function to be called when all the player's lives have gone and the game
 92     // is declared over
 93     //定义一个函数,当玩家所有的生命已经失去时调用此函数,并宣布游戏结束。
 94     function gameOver() {
 95 
 96         // Pause the player's movements as they are no longer in the game
 97         //暂停玩家的移动,因为他们已经不能再继续进行游戏了。
 98         freezePlayer();
 99 
100         // Inform other code modules in this application that the game is over
101         //通知这个应用程序中的其他代码模块,游戏已经结束。
102         Frogger.observer.publish("game-over");
103     }
104 
105     // Define a function to be called when the player has reached the goal
106     //定义一个函数,当玩家到达最终目标时调用此函数。
107     function gameWon() {
108 
109         // Inform other code modules that the game has been won
110         //通知其他代码模块,游戏取得胜利。
111         Frogger.observer.publish("game-won");
112     }
113 
114     // Define a function to be called when the player loses a life
115     //定义一个函数,当玩家失去一条生命时调用此函数。
116     function loseLife() {
117 
118         // Decrease the number of lives the player has remaining
119         //玩家的剩余生命条数减一。
120         _lives--;
121 
122         // Pause the player's movements
123         //暂停玩家的移动。
124         freezePlayer();
125 
126         // Inform other code modules that the player has lost a life
127         //通知其他代码模块,玩家已经失去一条生命。
128         Frogger.observer.publish("player-lost-life");
129 
130         if (_lives === 0) {
131 
132             // Declare the game to be over if the player has no lives remaining
133             //如果玩家没有剩余生命,则宣布游戏结束。
134             gameOver();
135         } else {
136 
137             // If there are lives remaining, wait 2000 milliseconds (2 seconds) before
138             // resetting the player's character and other obstacles to their initial
139             // positions on the game board
140             //如果还有剩余生命,则等待2000毫秒(2秒),再把玩家角色和其他物体重新设置至他们各自在游戏面板中的初始位置。
141             setTimeout(reset, 2000);
142         }
143     }
144 
145     // Define a function to be called when the player's character is required to be frozen
146     // in place, such as when the game is over or when the player has lost a life
147     //定义一个函数,当玩家角色需要被冻结在原地时进行调用。如游戏结束时,或当玩家失去一条生命时。
148     function freezePlayer() {
149 
150         // Set the local variable to indicate the frozen state
151         //将局部变量_isPlayerFrozen设为true来表示冻结状态。
152         _isPlayerFrozen = true;
153 
154         // Inform other code modules - including that which controls the player's
155         // character - that the player is now be frozen
156         //通知其他代码模块——包括控制玩家角色的模块——玩家现在被冻结了。
157         Frogger.observer.publish("player-freeze");
158     }
159 
160     // Define a function to be called when the player's character is free to move after
161     // being previously frozen in place
162     //定义一个函数,当玩家的角色从先前的冻结在原地状态恢复至自由移动状态时,调用此函数。
163     function unfreezePlayer() {
164 
165         // Set the local variable to indicate the new state
166         //将局部变量_isPlayerFrozen设为false来表示新状态。
167         _isPlayerFrozen = false;
168 
169         // Inform other code modules that the player's character is now free to move around
170         // the game board
171         //通知其他代码模块,玩家的角色现在可以在游戏面板上自由移动。
172         Frogger.observer.publish("player-unfreeze");
173     }
174 
175     // Define a function to increase the player's score by a specific amount and update
176     // the high score accordingly
177     //定义一个函数来以特定的分值增加玩家的分数,并相应地更新最高分数记录。
178     function increaseScore(increaseBy) {
179 
180         // Increase the score by the supplied amount (or by 0 if no value is provided)
181         //用参数所提供的分值加增加分数(如果没有分值提供,则以0作为增加分值)。
182         _score += increaseBy || 0;
183 
184         // Inform other code modules that the player's score has changed, passing along
185         // the new score
186         //通知其他代码模块,玩家的分数已经发生改变,把新的分数传入。
187         Frogger.observer.publish("score-change", _score);
188 
189         // If the player's new score beats the current high score then update the high
190         // score to reflect the player's new score and inform other code modules of a
191         // change to the high score, passing along the new high score value
192         //如果玩家的新分数高于当前的最高分数记录,则更新最高分数记录的值来对应出玩家的新分数,并通知其他代码模块最高分记录发生了改变,把新的最高分值传入。
193         if (_score > _highScore) {
194             _highScore = _score;
195             Frogger.observer.publish("high-score-change", _highScore);
196         }
197     }
198 
199     // Define a function to execute once the player reaches the designated goal
200     //定义一个函数,一旦玩家到达指定的目标位置后,执行此函数。
201     function playerAtGoal() {
202 
203         // When the player reaches the goal, increase their score by 1000 points
204         //当玩家到达目标位置,将玩家的分数增加1000分。
205         increaseScore(1000);
206 
207         // Increment the value indicating the total number of times the player's character
208         // has reached the goal
209         //增加表示玩家的角色已经到达目标位置总次数的值。
210         _timesAtGoal++;
211 
212         // Freeze the player's character movement temporarily to acknowledge they have
213         // reached the goal
214         //临时冻结玩家角色的移动来表示确认玩家已经到达目标位置。
215         freezePlayer();
216 
217         if (_timesAtGoal < _maxTimesAtGoal) {
218 
219             // The player must enter the goal a total of 5 times, as indicated by the
220             // _maxTimesAtGoal value. If the player has not reached the goal this many
221             // times yet, then reset the player's character position and obstacles on the
222             // game board after a delay of 2000 milliseconds (2 seconds)
223             //玩家必须进入目标位置5次,如_maxTimesAtGoal的值所示。如果玩家还没有完成这个数量,则等待2000毫秒(2秒),在游戏面板上重新设置玩家角色位置以及各个其他物体。
224             setTimeout(reset, 2000);
225         } else {
226 
227             // If the player has reached the goal 5 times, the game has been won!
228             //如果玩家已经到达目标位置5次,则游戏胜利。
229             gameWon();
230         }
231     }
232 
233     // Define a function to execute when the player moves their character on the game
234     // board, increasing their score by 20 points when they do
235     //定义一个函数,当玩家把角色在游戏面板上移动时,执行此函数。当玩家移动角色时,分数增加20分。
236     function playerMoved() {
237         increaseScore(20);
238     }
239 
240     // Define a function to be called when the game board needs to be reset, such as when
241     // the player loses a life
242     //定义一个函数,当游戏面板需要重新设置时进行调用。如当玩家失去一条生命时。
243     function reset() {
244 
245         // Reset the variable storing the current time remaining to its initial value
246         //把保存当前剩余时间的变量重设为它的初始值。
247         _timeRemaining = _timeTotal;
248 
249         // Release the player's character if it has been frozen in place
250         //如果玩家的角色已经被冻结在原地,则解除冻结。
251         unfreezePlayer();
252 
253         // Inform other code modules to reset themselves to their initial conditions
254         //通知其他代码模块,使它们本身重设至各自的初始状态。
255         Frogger.observer.publish("reset");
256     }
257 
258     // The game loop executes on an interval at a rate dictated by value of the
259     // _refreshRate variable (once every 50 milliseconds), in which the game board is
260     // redrawn with the character and obstacles drawn at their relevant positions on
261     // the board and any collisions between the player's character and any obstacles
262     // are detected
263     //游戏主循环以特定的频率按某时间间隔执行,该频率由变量_refreshRate的值指定(每50毫秒一次【注:这里应是每33.333毫秒一次】),
264     function gameLoop() {
265 
266         // Calculate how many milliseconds have passed since the last time the game loop
267         // was called
268         //计算自从上一次游戏主循环调用以来,所过去的毫秒数。
269         var currentTime = (new Date()).getTime(),
270             timeDifference = currentTime - _lastTimeGameLoopRan;
271 
272         // Execute this function again when the next animation frame is ready for use by
273         // the browser - keeps the game loop looping
274         //当下一动画帧准备好可供浏览器使用时执行此函数——保持游戏主循环持续进行。
275         window.requestAnimationFrame(gameLoop);
276 
277         // If the number of milliseconds passed exceeds the defined refresh rate, draw
278         // the obstacles in the updated position on the game board and check for collisions
279         //如果已经过去的毫秒时间超过了所定义的刷新频率时间,则在游戏面板上将各物体绘制在更新后的位置,并检测是否存在碰撞。
280         if (timeDifference >= _refreshRate) {
281 
282             // Clear the  element's drawing surface - erases everything on the
283             // game board so we can redraw the player's character and obstacles in their
284             // new positions
285             //清空元素的绘制表面——擦除在游戏上的所有内容以便我们能将玩家的角色和各物体绘制在各自的新位置上。
286             Frogger.drawingSurface.clearRect(0, 0, Frogger.drawingSurfaceWidth, Frogger.drawingSurfaceHeight);
287 
288             if (!_isPlayerFrozen) {
289 
290                 // As long as the player's character is not frozen in place, ensure the
291                 // timer is counting down, putting pressure on the player to reach the
292                 // goal in time
293                 //只要玩家的角色没有被冻结在原地,就要确保进行倒计时,给玩家施加压力使其能在限时内到达目标地点。
294                 countDown();
295 
296                 // Inform other code modules to check the player has not collided with an
297                 // obstacle on the game board
298                 //通知其他代码模块来检查玩家是否撞上游戏面板上的某个物体。
299                 Frogger.observer.publish("check-collisions");
300             }
301 
302             // Now on our empty canvas we draw our game board and the obstacles upon it in
303             // their respective positions
304             //现在,我们在空白的canvas上绘制游戏面板,以及把各个物体绘制到各自位置上。
305             Frogger.observer.publish("render-base-layer");
306 
307             // After the game board and obstacles, we draw the player's character so that
308             // it is always on top of anything else on the  drawing surface
309             //绘制完游戏面板和各个物体后,我们才绘制玩家的角色。这样,在的绘制平面中,玩家角色就实现了置顶的效果。
310             Frogger.observer.publish("render-character");
311 
312             // Store the current time for later comparisons to keep the frame rate smooth
313             //保存当前时间用于稍后进行对比,以保持帧频流畅。
314             _lastTimeGameLoopRan = currentTime;
315         }
316     }
317 
318     // Define a function to kick-start the application and run the game loop, which renders
319     // each frame of the game graphics and checks for collisions between the player's
320     // character and any obstacles on the game board
321     //定义一个函数来启动应用程序并运行游戏主循环。游戏主循环会渲染每一帧的游戏图像,并检测玩家角色与游戏面板中的其他物体之间的碰撞。
322     function start() {
323 
324         // Inform other code modules of the initial state of the game's high score
325         //把游戏最高分数的初始值通知其他代码模块。
326         Frogger.observer.publish("high-score-change", _highScore);
327 
328         // Start the game loop running
329         //使游戏主循环开始运行。
330         gameLoop();
331     }
332 
333     // Execute the start() function to kick off the game loop once the "game-load" event
334     // is fired. We'll trigger this event after we've configured the rest of our code
335     // modules for the game
336     //一旦“game-load”事件发生,执行start()函数来启动游戏主循环。在我们为游戏完成其余的代码模块配置后,我们将触发该事件。
337     Frogger.observer.subscribe("game-load", start);
338 
339     // Execute the playerAtGoal() function when another code module informs us that the
340     // player has reached the goal
341     //当其他代码模块通知我们玩家已经到达目标位置后,执行playerAtGoal()函数。
342     Frogger.observer.subscribe("player-at-goal", playerAtGoal);
343 
344     // Execute the playerMoved() function when we have been informed that the player has
345     // moved their character
346     //当我们接到通知说玩家已经移动他们的角色时,执行playerMoved()函数。
347     Frogger.observer.subscribe("player-moved", playerMoved);
348 
349     // Execute the loseLife() function when we are informed by another code base that the
350     // player's character has collided with an obstacle on the game board
351     //当我们被其他代码通知说玩家的角色和游戏面板中的某个物体发生碰撞时,执行loseLife()函数。
352     Frogger.observer.subscribe("collision", loseLife);
353 
354 // Pass the global Frogger variable into the module so it can be accessed locally,
355 // improving performance and making its dependency clear
356 //把全局Frogger变量传入模块中,这样它就可以局部变量方式被访问,有助于提高性能。
357 }(Frogger));

 

转载于:https://www.cnblogs.com/da3j/p/4116600.html

你可能感兴趣的:(Pro JavaScript List.11-11)