//为实现各种现代浏览器的requestAnimationFrame()方法,创建一段简单的跨浏览器保障代码(polyfill),以实现流畅、高效的动画。由保罗•艾里什(Paul Irish)编写,网址为 http://bit.ly/req_anim_frame。
window.requestAnimationFrame = (function(){
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback){
window.setTimeout(callback, 1000 / 60);
};
})(); // Define the game logic module which keeps track of the game state, the players's score,
// the number of lives remaining, handles collisions between the player's character and
// other obstacles and ensures the game graphics are drawn onto the <canvas> at the
// right moment. This module contains the brains behind the game play and instructs other
// code modules to do the heavy lifting through the use of the observer design pattern.
//定义游戏的逻辑模块。此模块保持追踪以下内容,包括有游戏状态、玩家的分数、剩余的生命条数。此模块还处理玩家角色和其他物体碰撞。此模块还确保游戏图形可以在正确的时刻绘制到<canvas>上。
(function(Frogger) { // Define a variable to hold the current player's score
//定一个变量来记录玩家当前的分数。
var _score = 0, // Define and initialize a variable to hold the high score achieved in the game
//定义并初始化一个变量来记录游戏中所获得的最高分。
_highScore = 1000, // Define the number of lives the player has remaining before the game is over
//定义游戏结束前玩家还剩余的生命条数。
_lives = 5, // Define the number of milliseconds the player has to get their character to
// the goal (60 seconds). If they take too long, they will lose a life
//定义玩家要将他们的角色送达目标位置的毫秒数(60秒)。如果玩家耗用时间过长,则他们将失去一条生命。
_timeTotal = 60000, // Define a variable to store the current time remaining for the player to reach
// the goal
//定义一个变量来保存玩家要到达目标位置的当前剩余时间。
_timeRemaining = _timeTotal, // Define the refresh rate of the graphics on the <canvas> element (one draw every
// 33⅓ milliseconds = 30 frames per second). Attempting to redraw too frequently
// can cause the browser to slow down so choose this value carefully to maintain a
// good balance between fluid animation and smooth playability
//定义<canvas>元素上的图形的刷新时间(每33⅓毫秒绘制一次 = 每秒30帧)。频率太快的重新绘制会引起浏览器响应缓慢。因此,选择使用这个值可以在流畅的动画与利索的可玩性之间取得平衡。
_refreshRate = 33.333, // Define a variable to store the number of times the player's character has
// reached the goal
//定义一个变量来保存玩家的角色已经到达目标位置的次数。
_timesAtGoal = 0, // Define a variable to indicate the number of times the player's character needs
// to reach the goal for the game to be won
//定义一个变量来记录玩家的角色为取得胜利还须到达目标位置的次数。
_maxTimesAtGoal = 5, // Define a Boolean variable to indicate whether the player's movement is currently
// frozen in place
//定义一个布尔变量来记录玩家当前的移动状态是否被冻结在原地。
_isPlayerFrozen = false, // Define a variable to store the last time the game loop ran - this helps keep
// the animation running smoothly at the defined refresh rate
//定义一个变量来保存上一次游戏主循环运行的时间——这有助于使动画以所定义的刷新频率下流通运行。
_lastTimeGameLoopRan = (new Date()).getTime(); // Define a function to be called to count down the time remaining for the player to
// reach the goal without forfeiting a life
//定义一个函数进行调用,用来对玩家到达目标而不至于失去一条生命的剩余时间进行倒计时。
function countDown() {
if (_timeRemaining > 0) { // This function will be called as frequently as the _refreshRate variable
// dictates so we reduce the number of milliseconds remaining by the
// _refreshRate value for accurate timing
//此函数将会根据_refreshRate变量值的频率进行调用。这样,我们就可以用剩余的毫秒数减去_refreshRate变量的值来实现精确的倒计时。
_timeRemaining -= _refreshRate; // Publish the fact that the remaining time has changed, passing along the
// new time remaining as a percentage - which will help when we come to display
// the remaining time on the game board itself
//发出通知,剩余时间已经发生改变,把新的剩余时间以百分比形式传入——有助于我们在游戏面板上显式剩余时间。
Frogger.observer.publish("time-remaining-change", _timeRemaining / _timeTotal);
} else { // If the remaining time reaches zero, we take one of the player's remaining
// lives
//如果剩余时间到达零,则将玩家的剩余生命条数减一。
loseLife();
}
} // Define a function to be called when all the player's lives have gone and the game
// is declared over
//定义一个函数,当玩家所有的生命已经失去时调用此函数,并宣布游戏结束。
function gameOver() { // Pause the player's movements as they are no longer in the game
//暂停玩家的移动,因为他们已经不能再继续进行游戏了。
freezePlayer(); // Inform other code modules in this application that the game is over
//通知这个应用程序中的其他代码模块,游戏已经结束。
Frogger.observer.publish("game-over");
} // Define a function to be called when the player has reached the goal
//定义一个函数,当玩家到达最终目标时调用此函数。
function gameWon() { // Inform other code modules that the game has been won
//通知其他代码模块,游戏取得胜利。
Frogger.observer.publish("game-won");
} // Define a function to be called when the player loses a life
//定义一个函数,当玩家失去一条生命时调用此函数。
function loseLife() { // Decrease the number of lives the player has remaining
//玩家的剩余生命条数减一。
_lives--; // Pause the player's movements
//暂停玩家的移动。
freezePlayer(); // Inform other code modules that the player has lost a life
//通知其他代码模块,玩家已经失去一条生命。
Frogger.observer.publish("player-lost-life"); if (_lives === 0) { // Declare the game to be over if the player has no lives remaining
//如果玩家没有剩余生命,则宣布游戏结束。
gameOver();
} else { // If there are lives remaining, wait 2000 milliseconds (2 seconds) before
// resetting the player's character and other obstacles to their initial
// positions on the game board
//如果还有剩余生命,则等待2000毫秒(2秒),再把玩家角色和其他物体重新设置至他们各自在游戏面板中的初始位置。
setTimeout(reset, 2000);
}
} // Define a function to be called when the player's character is required to be frozen
// in place, such as when the game is over or when the player has lost a life
//定义一个函数,当玩家角色需要被冻结在原地时进行调用。如游戏结束时,或当玩家失去一条生命时。
function freezePlayer() { // Set the local variable to indicate the frozen state
//将局部变量_isPlayerFrozen设为true来表示冻结状态。
_isPlayerFrozen = true; // Inform other code modules - including that which controls the player's
// character - that the player is now be frozen
//通知其他代码模块——包括控制玩家角色的模块——玩家现在被冻结了。
Frogger.observer.publish("player-freeze");
} // Define a function to be called when the player's character is free to move after
// being previously frozen in place
//定义一个函数,当玩家的角色从先前的冻结在原地状态恢复至自由移动状态时,调用此函数。
function unfreezePlayer() { // Set the local variable to indicate the new state
//将局部变量_isPlayerFrozen设为false来表示新状态。
_isPlayerFrozen = false; // Inform other code modules that the player's character is now free to move around
// the game board
//通知其他代码模块,玩家的角色现在可以在游戏面板上自由移动。
Frogger.observer.publish("player-unfreeze");
} // Define a function to increase the player's score by a specific amount and update
// the high score accordingly
//定义一个函数来以特定的分值增加玩家的分数,并相应地更新最高分数记录。
function increaseScore(increaseBy) { // Increase the score by the supplied amount (or by 0 if no value is provided)
//用参数所提供的分值加增加分数(如果没有分值提供,则以0作为增加分值)。
_score += increaseBy || 0; // Inform other code modules that the player's score has changed, passing along
// the new score
//通知其他代码模块,玩家的分数已经发生改变,把新的分数传入。
Frogger.observer.publish("score-change", _score); // If the player's new score beats the current high score then update the high
// score to reflect the player's new score and inform other code modules of a
// change to the high score, passing along the new high score value
//如果玩家的新分数高于当前的最高分数记录,则更新最高分数记录的值来对应出玩家的新分数,并通知其他代码模块最高分记录发生了改变,把新的最高分值传入。
if (_score > _highScore) {
_highScore = _score;
Frogger.observer.publish("high-score-change", _highScore);
}
} // Define a function to execute once the player reaches the designated goal
//定义一个函数,一旦玩家到达指定的目标位置后,执行此函数。
function playerAtGoal() { // When the player reaches the goal, increase their score by 1000 points
//当玩家到达目标位置,将玩家的分数增加1000分。
increaseScore(1000); // Increment the value indicating the total number of times the player's character
// has reached the goal
//增加表示玩家的角色已经到达目标位置总次数的值。
_timesAtGoal++; // Freeze the player's character movement temporarily to acknowledge they have
// reached the goal
//临时冻结玩家角色的移动来表示确认玩家已经到达目标位置。
freezePlayer(); if (_timesAtGoal < _maxTimesAtGoal) { // The player must enter the goal a total of 5 times, as indicated by the
// _maxTimesAtGoal value. If the player has not reached the goal this many
// times yet, then reset the player's character position and obstacles on the
// game board after a delay of 2000 milliseconds (2 seconds)
//玩家必须进入目标位置5次,如_maxTimesAtGoal的值所示。如果玩家还没有完成这个数量,则等待2000毫秒(2秒),在游戏面板上重新设置玩家角色位置以及各个其他物体。
setTimeout(reset, 2000);
} else { // If the player has reached the goal 5 times, the game has been won!
//如果玩家已经到达目标位置5次,则游戏胜利。
gameWon();
}
} // Define a function to execute when the player moves their character on the game
// board, increasing their score by 20 points when they do
//定义一个函数,当玩家把角色在游戏面板上移动时,执行此函数。当玩家移动角色时,分数增加20分。
function playerMoved() {
increaseScore(20);
} // Define a function to be called when the game board needs to be reset, such as when
// the player loses a life
//定义一个函数,当游戏面板需要重新设置时进行调用。如当玩家失去一条生命时。
function reset() { // Reset the variable storing the current time remaining to its initial value
//把保存当前剩余时间的变量重设为它的初始值。
_timeRemaining = _timeTotal; // Release the player's character if it has been frozen in place
//如果玩家的角色已经被冻结在原地,则解除冻结。
unfreezePlayer(); // Inform other code modules to reset themselves to their initial conditions
//通知其他代码模块,使它们本身重设至各自的初始状态。
Frogger.observer.publish("reset");
} // The game loop executes on an interval at a rate dictated by value of the
// _refreshRate variable (once every 50 milliseconds), in which the game board is
// redrawn with the character and obstacles drawn at their relevant positions on
// the board and any collisions between the player's character and any obstacles
// are detected
//游戏主循环以特定的频率按某时间间隔执行,该频率由变量_refreshRate的值指定(每50毫秒一次【注:这里应是每33.333毫秒一次】),
function gameLoop() { // Calculate how many milliseconds have passed since the last time the game loop
// was called
//计算自从上一次游戏主循环调用以来,所过去的毫秒数。
var currentTime = (new Date()).getTime(),
timeDifference = currentTime - _lastTimeGameLoopRan; // Execute this function again when the next animation frame is ready for use by
// the browser - keeps the game loop looping
//当下一动画帧准备好可供浏览器使用时执行此函数——保持游戏主循环持续进行。
window.requestAnimationFrame(gameLoop); // If the number of milliseconds passed exceeds the defined refresh rate, draw
// the obstacles in the updated position on the game board and check for collisions
//如果已经过去的毫秒时间超过了所定义的刷新频率时间,则在游戏面板上将各物体绘制在更新后的位置,并检测是否存在碰撞。
if (timeDifference >= _refreshRate) { // Clear the <canvas> element's drawing surface - erases everything on the
// game board so we can redraw the player's character and obstacles in their
// new positions
//清空<canvas>元素的绘制表面——擦除在游戏上的所有内容以便我们能将玩家的角色和各物体绘制在各自的新位置上。
Frogger.drawingSurface.clearRect(0, 0, Frogger.drawingSurfaceWidth, Frogger.drawingSurfaceHeight); if (!_isPlayerFrozen) { // As long as the player's character is not frozen in place, ensure the
// timer is counting down, putting pressure on the player to reach the
// goal in time
//只要玩家的角色没有被冻结在原地,就要确保进行倒计时,给玩家施加压力使其能在限时内到达目标地点。
countDown(); // Inform other code modules to check the player has not collided with an
// obstacle on the game board
//通知其他代码模块来检查玩家是否撞上游戏面板上的某个物体。
Frogger.observer.publish("check-collisions");
} // Now on our empty canvas we draw our game board and the obstacles upon it in
// their respective positions
//现在,我们在空白的canvas上绘制游戏面板,以及把各个物体绘制到各自位置上。
Frogger.observer.publish("render-base-layer"); // After the game board and obstacles, we draw the player's character so that
// it is always on top of anything else on the <canvas> drawing surface
//绘制完游戏面板和各个物体后,我们才绘制玩家的角色。这样,在<canvas>的绘制平面中,玩家角色就实现了置顶的效果。
Frogger.observer.publish("render-character"); // Store the current time for later comparisons to keep the frame rate smooth
//保存当前时间用于稍后进行对比,以保持帧频流畅。
_lastTimeGameLoopRan = currentTime;
}
} // Define a function to kick-start the application and run the game loop, which renders
// each frame of the game graphics and checks for collisions between the player's
// character and any obstacles on the game board
//定义一个函数来启动应用程序并运行游戏主循环。游戏主循环会渲染每一帧的游戏图像,并检测玩家角色与游戏面板中的其他物体之间的碰撞。
function start() { // Inform other code modules of the initial state of the game's high score
//把游戏最高分数的初始值通知其他代码模块。
Frogger.observer.publish("high-score-change", _highScore); // Start the game loop running
//使游戏主循环开始运行。
gameLoop();
} // Execute the start() function to kick off the game loop once the "game-load" event
// is fired. We'll trigger this event after we've configured the rest of our code
// modules for the game
//一旦“game-load”事件发生,执行start()函数来启动游戏主循环。在我们为游戏完成其余的代码模块配置后,我们将触发该事件。
Frogger.observer.subscribe("game-load", start); // Execute the playerAtGoal() function when another code module informs us that the
// player has reached the goal
//当其他代码模块通知我们玩家已经到达目标位置后,执行playerAtGoal()函数。
Frogger.observer.subscribe("player-at-goal", playerAtGoal); // Execute the playerMoved() function when we have been informed that the player has
// moved their character
//当我们接到通知说玩家已经移动他们的角色时,执行playerMoved()函数。
Frogger.observer.subscribe("player-moved", playerMoved); // Execute the loseLife() function when we are informed by another code base that the
// player's character has collided with an obstacle on the game board
//当我们被其他代码通知说玩家的角色和游戏面板中的某个物体发生碰撞时,执行loseLife()函数。
Frogger.observer.subscribe("collision", loseLife); // Pass the global Frogger variable into the module so it can be accessed locally,
// improving performance and making its dependency clear
//把全局Frogger变量传入模块中,这样它就可以局部变量方式被访问,有助于提高性能。
}(Frogger));

最新文章

  1. linux 下 ls 文件夹和文件没有颜色的解决办法
  2. JS&amp;CSS文件请求合并及压缩处理研究(一)
  3. Java读取word文档,转换为网页
  4. 关于Delphi XE2的FMX的一点点研究之消息篇
  5. 【Python】考虑用生成器改写直接返回列表的函数
  6. JavaScript中var变量引用function与直接声明function
  7. 团队作业8——第二次项目冲刺(Beta阶段)博客汇总
  8. [HNOI 2016]树
  9. 用appuploader生成发布证书和描述性文件
  10. DAY16 模块和包的导入
  11. NodeJs Fs模块
  12. 第五周助教工作总结——NWNU李泓毅
  13. BZOJ1449[JSOI2009]球队收益&amp;BZOJ2895球队预算——最小费用最大流
  14. PHP06
  15. javascript获取style兼容性问题
  16. P4577 [FJOI2018]领导集团问题
  17. Lua和C++交互 学习记录之七:C++全局函数注册为Lua模块
  18. css实现三栏布局,两边定宽,中间自适应
  19. vi/vim编辑器必知必会
  20. 深入了解MyBatis二级缓存

热门文章

  1. OpenCV_contrib里的Text(自然场景图像中的文本检测与识别)
  2. CDH5.16.1的agent启动报错:ERROR Error, CM server guid updated, expected d9bcadb4-f983-41b8-a667-66760f47bc91, received a67f5efa-8473-4f6a-94d6-231d1f432ef0
  3. Centos安装MySQL5.6并重置密码
  4. Linux学习笔记(一)分区
  5. PAT乙级1042
  6. JavaScript(JS)入门篇
  7. CF827D Best Edge Weight[最小生成树+树剖/LCT/(可并堆/set启发式合并+倍增)]
  8. Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) B. Strings Equalization
  9. nginx+tomcat遇到的https重定向到http问题
  10. POI读取格式化后的单元格数据