閒逛github發現一個javascript原生實現的小遊戲,源碼寫的很清晰,適合想提升水平的同窗觀摩學習。讀通源碼後,我決定寫一系列的博客來分析源碼,從總體架構到具體實現細節來幫助一些想提升水平的朋友。源碼地址爲:https://github.com/keenwon/flappy-pigjavascript
須要提醒你們的是,個人分析模式是,先給出源碼,加上註釋讓你們通讀一遍,而後分解源碼逐步分析。前端
下載了做者的源碼後先看一下目錄結構:java
其中做者使用了Grunt進行了打包,會使用的grunt的小夥伴一看這個目錄確定一目瞭然,若是你歷來沒有使用過任何前端構建工具,別擔憂,你只用關注src文件夾就能夠了,打開src文件夾,內容以下:git
這就是遊戲的所有組成部分了,咱們只關心具體的控制邏輯,因此直接進入js文件夾:github
var flappy = (function (self) { 'use strict';//開啓嚴格模式,新手能夠暫時忽視 var controller = self.controller,//獲取控制者對象,以後詳細介紹 option = self.option,//獲取配置值,以後詳細介紹 pig = self.pig,//獲取小豬模塊,以後詳細介紹 pillar = self.pillar,//獲取柱子模塊,以後詳細介紹 pos = self.position,//獲取位置模塊,以後詳細介紹 util = self.util,//獲取工具模塊,以後詳細介紹 $ = self.util.$;//從util.js中咱們能夠看出,$方法能夠經過id獲取DOM元素 //主程序 self.game = {//給self對象添加game屬性,該屬性指向一個對象 init: function () {//game對象的init方法 var t = this;//this指向函數調用者,非特殊狀況下(不使用call、apply或者直接調用),通常咱們就先認爲指向了game對象,由於從後面咱們也能夠看到,做者也是經過flappy.game.init()調用的。 t._isStart = false;//game有一個isStart屬性,用於標識遊戲是否開始,初始值爲false t._isEnd = false;//game有一個isEnd屬性,用於表示遊戲是否結束,初始值爲false t._timer = null;//game對象有一個定時器,初始化爲null pig.init(t.fall, t);//調用pig模塊的init方法,將game.fall方法和game對象傳遞過去 pillar.init();//調用pillar模塊的init方法 pos.init(t.hit, t);//調用pos模塊的init方法,將game.hit方法和game對象傳遞過去 t.addKeyListener();//將this指向game,給game對象添加鍵盤監聽 }, addKeyListener: function () {//監聽鍵盤事件 var t = this;//this指向函數調用者,從上面能夠看到調用者是game document.onkeydown = function (e) {//監聽鍵盤按下事件 e = e || window.event;//獲取事件對象,兼容IE var currKey = e.keyCode || e.which || e.charCode;//獲取按了哪個按鍵,兼容各家瀏覽器 if (currKey == 32) {//若是按下了空格 if (!t._isEnd) {//若是遊戲沒有結束 t.jump();//那麼調用game.jump()方法 } else { window.location.reload();//若是遊戲已經結束,按空格後刷新頁面,從新開始 } util.preventDefaultEvent(e);//阻止事件的默認行爲,具體細節在util.js中,我會在相應章節分析 } }; }, jump: function () {//這裏就是game.jump()方法 var t = this;//指向game對象 if (!t._isStart) {//若是遊戲沒有開始 $('start').style.display = 'none';//將遊戲開始界面隱藏 t._createTimer(function () {//調用game._createTimer方法,建立定時器,每二十毫秒執行一次 pig.start();//調用pig模塊的start方法,讓小豬開始移動,具體細節在pig.js中,我會在相應章節分析 pillar.move();//,調用pillar模塊的move方法,讓柱子移動,具體細節在pillar.js中,我會在相應章節分析 pos.judge();//調用pos模塊的judge方法,判斷位置,具體細節在position.js中,我會在相應章節分析 $('score').innerHTML = pillar.currentId + 1;//設置記分板分數 }); t._isStart = true;//設置遊戲狀態爲已開始 } else { pig.jump();//若是遊戲已經開始,那麼直接調用pig.jump方法 } }, hit: function () {//game對象的hit方法 var t = this; t.over();//調用game.over方法,遊戲結束 pig.hit();//調用pig模塊的hit方法,具體細節在pig.js中,我會在相應章節分析 }, fall: function () {//game對象的fall方法 var t = this; t.over();//調用game.over方法,遊戲結束 pig.fall();//調用pig模塊的fall方法,具體細節在pig.js中,我會在相應章節分析 }, over: function () {//game對象的over方法,負責結束遊戲 var t = this;//獲取game對象 clearInterval(t._timer);//取消計時器 t._isEnd = true;//將標識遊戲是否結束的變量設置爲true $('end').style.display = 'block';//遊戲結束的提示顯示出來 }, _createTimer: function (fn) {//game對象的_createTimer方法,建立定時器 var t = this;//獲取game對象 t._timer = setInterval(fn, option.frequency);//實現定時器,頻率爲配置項中的frequency屬性,具體細節在option.js中,我會在相應章節介紹 } }; flappy.init = function () {//暴露接口 self.game.init();//game.init()函數中this指向game }; return self;//返回self對象,實際上也就是給本來的flappy對象加了點東西 })(flappy || {});