前面的章節已經教會了如何用一個構造的Game對象來寫一個簡單的遊戲例子。你也發現JavaScript能夠獲取canvas和canvasContext的值,用來進行canvas的運算。你也知道了如何改變畫布背景色。也知道結合系統時間讓一個方塊在屏幕上進行移動。這章講解如何在屏幕上繪畫圖片,這是創造出好看遊戲的第一步。在計算機圖形學中,這些圖形被稱做精靈。精靈通常都從文件裏進行加載。這意味着任何繪畫精靈的程序再也不僅僅只是一個簡單的指令,而是須要知道這些遊戲資源放在何處。即將講的幾個事情你須要思考下:web
能夠從哪裏加載精靈?canvas
怎樣從一個圖像文件裏獲取信息瀏覽器
怎樣將精靈顯示在屏幕上markdown
這章將會回答這些問題。函數
音樂是另外一種類型的遊戲資源。它的處理與精靈十分相似。所以,在本章的最末,你會看到如何在你的遊戲中播放音樂和音效。oop
在一個程序可使用任何資源前,須要知道在哪裏找到這些資源。默認狀況下,瀏覽器會自動在當前文件夾下尋找精靈,和尋找JavaScript文件同樣。看這章的SpriteDrawing例子,你會發現一個spr_balloon.png文件和HTML文件和JavaScript文件在一個文件夾下。網站
如今看如何從一個文件裏面加載精靈。經過一個變量來加載精靈。你須要在遊戲循環裏不一樣的地方使用這個變量。在start方法裏,加載這個精靈而且存放在一個變量裏。所以,在Game對象中添加一個 balloonSprite變量。以下所示:rest
var Game = { canvas : undefined, canvasContext : undefined, balloonSprite : undefined };
能夠定義一個對象來包含關於這個精靈的全部信息。以下:code
Game.balloonSprite = { src : "spr_balloon.png", width : 35, height : 63, ... }
若是你想在你的遊戲里加載成百上千的精靈時,上述的就有問題了。每次你都必須定義一個相似上面的對象字變量。另外,你並不肯定是否會用到一個對象裏面的其餘變量。由於一個圖片有不一樣的表現。幸虧,你能夠經過類來避免這些問題。對象
類的基本定義就是一個對象的原型。它是一個對象的抽象。好比,JavaScript知道一個叫作Image的類,這個類定義一個關於圖片的對象,對象有寬和高,有源文件地址等等。經過image類能夠很是簡單的建立一個對象,只須要只要new關鍵字:
Game.balloonSprite = new Image();
這比在一個對象裏寫出全部變量的值輕鬆多了,表達式new Image()作到了這些。經過使用類,你能夠輕鬆的創造對象。並且能夠肯定這些對象都有相同的結構。
你還不知道這個變量裏面究竟含有什麼。你能夠給src變量賦值爲圖片源文件的地址。
Game.balloonSprite.src = "spr_balloon.png";
當src一設置,瀏覽器就開始加載文件。並且瀏覽器自動的獲取圖片的寬和高。
有時候,加載源文件須要一些時間。好比,這個文件存在於世界另外一邊的網站上。這意味着若是你想立刻就看到圖片是很困難的。所以,你須要確保在遊戲啓動以前全部圖片都加載完畢。這裏有一個很是簡潔的方式,使用一個事件處理函數。第七章你就會知道它是如何工做的。如今,想象半秒以內就能夠加載這個圖片。經過使用setTimeout方法,你能夠在500ms後加載mainLoop方法。
window.setTimeout(Game.mainLoop, 500);
完成後的start方法以下:
Game.start = function () { Game.canvas = document.getElementById("myCanvas"); Game.canvasContext = Game.canvas.getContext("2d"); Game.balloonSprite = new Image(); Game.balloonSprite.src = "spr_balloon.png"; window.setTimeout(Game.mainLoop, 500); };
精靈能夠從任何地方加載。若是你用JavaScript開發遊戲,思考如何組織你的精靈是個好習慣。好比,你能夠把你全部的精靈放在一個叫作sprites的文件夾裏。那樣你就能夠像下面這樣設置源文件。
Game.balloonSprite.src = "sprites/spr_balloon.png";
也許你不會使用本身的圖片,而是來自互聯網的圖片:
Game.balloonSprite.src = "http://www.somewebsite.com/images/spr_balloon.png";
JavaScript容許你從任何你想的地方加載圖片。只是但從互聯網上加載圖片時,須要確認圖片地址是固定不變的。不然,當網站主人在沒有告知你的狀況下移動掉這些文件,你的遊戲將沒法運行。
加載精靈並不意味着精靈就顯示到了屏幕上。想要讓精靈顯示出來,須要在draw方法裏面作些事情。爲了在畫布上畫出精靈,你可使用canvasContext對象的一個方法:drawImage。在JavaScript裏,當圖片須要顯示在固定的位置,這個位置的座標一般是圖片的左上角。下面是顯示精靈的指令:
Game.canvasContext.drawImage(sprite, 0, 0, sprite.width, sprite.height, 0, 0, sprite.width, sprite.height);
drawImage方法有不少不一樣的參數。好比,你能夠指定在何處繪畫精靈,或者是否只是精靈的一部分進行顯示。你能夠簡單的調用此方法達到目的。然而,若是你考慮到你之後建立的遊戲,你可使用繪畫狀態來繪畫精靈。
繪畫狀態從根本上來講就是一組參數,這些參數用於全部繪畫之間的轉換。使用繪畫狀態而不是用單一的drawImage方法的好處是你能夠對精靈作更復雜的轉換。好比,使用繪畫狀態,你能夠翻轉或者比例縮放精靈,這在之後的遊戲中很是有用。創造一個新的繪畫狀態是經過調用save方法。
Game.canvasContext.save();
如今你可使用這個繪畫狀態來進行各類轉換。好比,你能夠移動精靈到一個肯定位置:
Game.canvasContext.translate(100, 100);
若是你如今調用drawImage方法,精靈會被繪畫在(100,100)處。一旦你完成繪畫,你能夠像下面這樣移除繪畫狀態。
Game.canvasContext.restore();
爲了方便,定義一個能夠作上述一切的方法:
Game.drawImage = function (sprite, position) { Game.canvasContext.save(); Game.canvasContext.translate(position.x, position.y); Game.canvasContext.drawImage(sprite, 0, 0, sprite.width, sprite.height, 0, 0, sprite.width, sprite.height); Game.canvasContext.restore(); };
經過上述參數看出,這個方法須要兩個信息,要被繪畫的精靈和繪畫精靈所在的位置。精靈應該是image類,這個地址是一個含有x和y部分的對象。當你調用這個方法,你須要提供上述這些信息。好比,像下面這樣在(100,100)出畫一個氣球精靈:
Game.drawImage(Game.balloonSprite, { x : 100, y : 100 });
你使用花括號定義了一個含有x和y的對象。正如你看到的那樣,容許在調用方法的指令中定義一個對象。固然,你能夠開始就定義一個對象,儲存在變量裏,好比下面這樣:
var balloonPos = { x : 100, y : 100 }; Game.drawImage(Game.balloonSprite, balloonPos);
這段代碼和以前的代碼是同樣的,只是多寫了些。你能夠把drawImage方法放在draw方法裏面,這樣氣球就會顯示在你想要的位置:
Game.draw = function () { Game.drawImage(Game.balloonSprite, { x : 100, y : 100 }); };
在瀏覽器上看到的結果如圖4-1
(省略圖4-1)
如今你能夠在屏幕上顯示一個精靈了,你可使用遊戲循環來讓它移動,就像上章裏面讓方塊移動那樣。在這裏咱們讓氣球的位置基於通過的時間來進行移動。爲了完成這個,你須要儲存氣球的位置。須要在update方法計算位置和在draw方法裏繪畫氣球。所以,在Game對象裏面添加一個位置變量:
var Game = { canvas : undefined, canvasContext : undefined, balloonSprite : undefined, balloonPosition : { x : 0, y : 50 } };
如上所示,在game對象裏面定義了一個含有兩個變量的對象。如今你能夠在update方法裏面添加一條經過通過的時間來改變位置的指令,就像在移動方塊例子裏面同樣。以下:
Game.update = function () { var d = new Date(); Game.balloonPosition.x = d.getTime() % Game.canvas.width; };
剩下的就是畫出氣球:
Game.drawImage(Game.balloonSprite, Game.balloonPosition);
加載和繪畫多重精靈
建立一個只有白色背景的遊戲怎麼看都是乏味的。你可讓你的遊戲經過繪畫一個背景精靈來使其更具備可看性。這意味着你須要在start方法裏面加載另外一個精靈而且在draw裏面進行顯示。這個程序的最終版本叫作FlyingSprite。若是你在瀏覽器裏面打開的話,你會看見兩個精靈,一個背景圖和一個氣球。爲了實現這個,增長一個含有背景精靈的變量,以下所示:
var Game = { canvas : undefined, canvasContext : undefined, backgroundSprite : undefined, balloonSprite : undefined, balloonPosition : { x : 0, y : 50 } };
固然,在draw裏面,如今有兩個要繪畫方法調用:
Game.draw = function () {
Game.drawImage(Game.backgroundSprite, { x : 0, y : 0 });
Game.drawImage(Game.balloonSprite, Game.balloonPosition);
};
這些方法調用的順序是很是重要的。由於你想氣球顯示在背景上面。首先就得畫出背景,而後畫氣球。若是你反過來作,背景會覆蓋掉氣球,你將什麼也看不到。圖4-2展現了程序的輸出結果:
(省略圖4-2)
每次你想在屏幕上繪畫一個精靈,你就在draw方法裏多調用一次drawImage,你能夠一個精靈繪畫屢次,顯示在不一樣的位置。好比,你想在背景上畫出一些不一樣位置的氣球,你只須要調用屢次調用drawImage和睦球的位置參數:
Game.draw = function () { Game.drawImage(Game.backgroundSprite, { x : 0, y : 0 }); Game.drawImage(Game.balloonSprite, { x : 0, y : 0 }); Game.drawImage(Game.balloonSprite, { x : 100, y : 0 }); Game.drawImage(Game.balloonSprite, { x : 200, y : 0 }); Game.drawImage(Game.balloonSprite, { x : 0, y : 300 }); Game.drawImage(Game.balloonSprite, { x : 200, y : 300 }); };
固然,再次注意繪畫的順序。
你能夠同時畫出多個移動的精靈。對於每個氣球,你能夠定義一個專屬於它的位置變量,以下所示:
Game.update = function () { var d = new Date(); Game.balloonPosition1.x = d.getTime() % Game.canvas.width; Game.balloonPosition2.x = (d.getTime() + 100) % Game.canvas.width; Game.balloonPosition3.x = (d.getTime() + 200) % Game.canvas.width; };
在draw方法裏,能夠用這些變量畫出靜止的和移動的氣球:
Game.draw = function () { Game.drawImage(Game.backgroundSprite, Game.balloonPosition1); Game.drawImage(Game.balloonSprite, Game.balloonPosition2); Game.drawImage(Game.balloonSprite, Game.balloonPosition3); Game.drawImage(Game.balloonSprite, { x : 200, y : 0 }); Game.drawImage(Game.balloonSprite, { x : 0, y : 300 }); Game.drawImage(Game.balloonSprite, { x : 200, y : 300 }); };
另外一個常見的遊戲資源是音效。不少遊戲都有音效和背景音樂。這有不少重要的緣由。音效能夠告訴用戶某些重要的線索。好比,當用戶按下一個鍵時有一個肯定的點擊音效。聽見腳步聲表示敵人接近了,即便玩家沒有看見他們。老遊戲迷霧之島就是一個典型的這類型的遊戲,由於裏面的不少線索都是經過音效來找到的。
好的音效能給遊戲世界帶來更好的感覺。它們讓環境更真實,即便屏幕上什麼都沒有發生。
在JavaScript中播放背景音樂或音效是很是簡單的。使用音效以前首先須要音效文件。在FlyingSpriteWithSound這個例子裏,文件是snd_music.mp3,被當作背景音樂。跟儲存精靈同樣,須要一個變量來儲存音樂數據。以下:
var Game = { canvas : undefined, canvasContext : undefined, backgroundSprite : undefined, balloonSprite : undefined, balloonPosition : { x : 0, y : 50 }, backgroundMusic : undefined };
在start方法裏須要加載音效。JavaScript提供了一個能夠操做音效的類。類型叫作Audio,建立方法以下:
Game.backgroundMusic = new Audio(); Game.backgroundMusic.src = "snd_music.mp3";
上面看起來就跟加載精靈同樣。如今你能夠這個對象的方法了,好比下面這樣播放音效:
Game.backgroundMusic.play();
也能夠像下面這樣減小背景音樂的聲音:
Game.backgroundMusic.volume = 0.4;
volume變量的值的大小範圍是0到1,0表示沒有聲音,1表示聲音最大。
從技術上來講,背景音樂和音效之間沒有什麼不一樣。通常,背景音樂聲音要小點。不少背景音樂在遊戲循環裏面播放,完了後又從新開始。後面你將看到怎麼實現。這本書的全部遊戲都用到了聲音來讓遊戲更有趣。
這章裏,你學到了: