• 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 <canvas> 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 //定义游戏的逻辑模块。此模块保持追踪以下内容,包括有游戏状态、玩家的分数、剩余的生命条数。此模块还处理玩家角色和其他物体碰撞。此模块还确保游戏图形可以在正确的时刻绘制到<canvas>上。
     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 <canvas> 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         //定义<canvas>元素上的图形的刷新时间(每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 <canvas> 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             //清空<canvas>元素的绘制表面——擦除在游戏上的所有内容以便我们能将玩家的角色和各物体绘制在各自的新位置上。
    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 <canvas> drawing surface
    309             //绘制完游戏面板和各个物体后,我们才绘制玩家的角色。这样,在<canvas>的绘制平面中,玩家角色就实现了置顶的效果。
    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));
    ---------------------------------------------------------------end
  • 相关阅读:
    IfcExternalReference
    IOException
    IfcExternalInformation
    IfcConnectionGeometry
    netty系列之:netty初探
    netty系列之:Event、Handler和Pipeline
    netty系列之:netty中的Channel详解
    防踩坑日记(一)(ES)elasticsearch中的对象QueryBuilder同时使用should和must查询不成功
    netty系列之:netty中的ByteBuf详解
    netty系列之:netty架构概述
  • 原文地址:https://www.cnblogs.com/da3j/p/4116600.html
Copyright © 2020-2023  润新知