使用JavaScript和Canvas開發游戲之認識Canvas
1、認識一下Canvas
http://www.brighthub.com/internet/web-development/articles/38364.aspx
Canvas元素以及JavaScript引擎中新增的一些特性,讓Web開發人員不必借助第三方插件,即可設計開發出精細且具有交互性的2D網頁。這篇文章就向大家介紹一下Canvas元素,以及它的一些可能的用途。
JavaScript與Canvas元素
HTML是為創建靜態頁面而生的。HTML所能實現的動態效果,也僅限于顯示GIF動畫和閃爍的文本。JavaScript改變了這一切,通過它能夠動態修改網頁。今天,很多Web服務都利用AJAX來創建網頁,為用戶提供更加流暢的體驗,也超越了標準HTML頁面中常見的“點擊-重新加載-點擊”式的交互模式。
然而,JavaScript的某些功能會受到其宿主瀏覽器的制約。盡管可以在網頁中創建和修改任何元素,但JavaScript不能(輕易地)讓瀏覽器顯示一種新對象。通過JavaScript修改文本、插入圖像或者縮放表格都很容易,因為這些對象本來就是HTML所支持的。如果你想再玩得刺激一點,比如寫一個網頁游戲,怎么辦?那恐怕就得苦心積慮地改變標準HTML元素的用途,克服種種不測才能達到目的。要么,你就得求助于Flash或Silverlight這樣的插件。
Canvas元素登場了。這個新HTML元素為JavaScript開發者提供了一種無需插件即可在網頁中直接繪圖的機制。Canvas元素最早是由蘋果公司在其WebKit框架中引入的,Safari瀏覽器和Dashboard微件都在使用。Canvas元素現在也被建議加入了HTML5規范,得到了***的Chrome、Firefox、Opera以及Konqueror等瀏覽器的支持。Internet Explorer(至少在IE8之前)還不支持Canvas,但ExplorerCanvas項目倒是為IE提供了與Canvas元素類似的功能。
Canvas元素對做過2D圖形編程的人是小菜一碟。可以在這個元素上畫線、畫各種形狀、畫漸變,甚至可以利用與其他2D API中類似的函數來修改其中的每一個像素。得益于Chrome的V8、Firefox的SpiderMonkey以及Safari的Nitro等***JavaScript引擎的性能,創建精細且具有交互性的Web應用已經完全沒有問題。
我們這一系列文章將教會大家使用JavaScript和Canvas元素創建一個簡單的平臺游戲。將要涉及的內容包括動畫、加載資源、分層渲染、滾動和交互。通過一步一步地展示示例代碼和實際效果,你可以很快學會如何駕馭強大的Canvas元素。
2、在Canvas上繪圖
http://www.brighthub.com/internet/web-development/articles/38744.aspx
下面,我們就通過一個循序漸進的示例及實時演示,來介紹如何使用JavaScript在Canvas元素上繪圖及實現動畫。
準備工作
知道了什么是Canvas元素之后,該學習在屏幕上繪圖了。首先,需要一個HTML頁面來放置和顯示Canvas元素。
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
- <html lang="en">
- <head>
- <title>JavaScript Platformer 1</title>
- <script type="text/javascript" src="jsplatformer1.js"></script>
- <style type="text/css">
- body { font-family: Arial,Helvetica,sans-serif;}
- </style>
- </head>
- <body>
- <p>
- <a href="http://www.brighthub.com/internet/web-development/articles/38364.aspx">
- Game Development with Javascript and the canvas element
- </a>
- </p>
- <canvas id="canvas" width="600" height="400">
- <p>Your browser does not support the canvas element.</p>
- </canvas>
- </body>
- /html>
這些HTML代碼很直觀。其中有兩個重要的元素。
- <script type="text/javascript" src="jsplatformer1.js"></script>
這里包含的是將會修改Canvas元素的JavaScript代碼,對應的Canvas元素的標記如下:
- <canvas id="canvas" width="600" height="400">
- <p>Your browser does not support the canvas element.</p>
- </canvas>
以上代碼創建了一個Canvas元素。不支持Canvas的瀏覽器,比如Internet Explorer(IE8之前的版本),會忽略這個元素,而只顯示其子元素。在這個簡單的例子中,這個子元素就是一個段落,其中的文本告訴用戶他們的瀏覽器不支持Canvas元素。而對于那些支持Canvas元素的瀏覽器,如Chrome、Opera和Firefox,則會忽略Canvas元素的子元素。
這個Canvas元素的ID屬性很重要,因為后面的JavaScript將通過它來取得對該元素的引用。而width和height屬性指定了畫布的寬度和高度,這兩個屬性跟table或img等其他HTML元素中的同名屬性作用一樣。
以下是 jsplatformer1.js的代碼:
- //每秒鐘target幀
- const FPS = 30;
- var x = 0;
- var y = 0;
- var xDirection = 1;
- var yDirection = 1;
- var image = new Image();
- image.src = "jsplatformer1-smiley.jpg";
- var canvas = null;
- var context2D = null;
- window.onload = init;
- function init(){
- canvas = document.getElementById('canvas');
- context2D = canvas.getContext('2d');
- setInterval(draw, 1000/FPS);
- }
- function draw(){
- context2D.clearRect(0, 0, canvas.width, canvas.height);
- context2D.drawImage(image, x, y);
- x += 1* xDirection;
- y += 1* yDirection;
- if (x >= 450) {
- x = 450;
- xDirection = -1;
- }else if(x <= 0){
- x = 0;
- xDirection = 1;
- }
- if (y >= 250) {
- y = 250;
- yDirection = -1;
- }else if(y <= 0){
- y = 0;
- yDirection = 1;
- }
- }
如果只是一個Canvas元素,也沒有什么用。JavaScript必須要在這塊畫布上面畫點什么,相應的代碼保存在 jsplatformer1.js中。簡單來說,JavaScript在這里先加載了一幅圖像,然后將其畫在畫布上面,***讓它在畫布上移動。
首先,定義一些全局變量。
- const FPS = 30;
FPS定義的是畫布重繪的頻率。
- var x = 0;
- var y = 0;
- var xDirection = 1;
- var yDirection = 1;
變量x、y、xDirection和yDirection用于定義圖像(相對于畫布左上角)的位置,以及它在任意一時刻移動的方向。
- var image = new Image();
- image.src = "http://javascript-tutorials.googlecode.com/files/jsplatformer1-smiley.jpg";
要把圖像畫到畫布上,必須先加載一幅圖像。為此,我們創建一個Image對象,將其src屬性設置為一幅圖像文件的URL(建議把圖片下載到本地。——譯者注)。
- var canvas = null;
- var context2D = null;
我們還需要取得對Canvas元素以及繪圖上下文(稍后再詳細介紹繪圖上下文)的引用。稍后我們會把正確的值賦給這兩個變量,現在先把它們設置為null。
- window.onload = init;
***,當頁面加載完成后,我們必須知道立即運行繪制畫布的代碼;因此,在window對象的onload事件發生時,立即調用init函數。
init函數
- function init(){
- canvas = document.getElementById('canvas');
- context2D = canvas.getContext('2d');
- setInterval(draw, 1000/FPS);
- }
頁面加載完畢后就會調用上面這個init函數。在這個函數中,我們先通過在HTML文件中指定的ID屬性取得畫布元素(毫無疑問,除了把它叫做畫布,還能叫個啥?),然后再取得這個畫布的2D繪圖上下文對象。
上下文對象用于定義如何在畫布上繪圖。顧名思義,2D上下文嘛,支持在畫布上繪制2D圖形、圖像和文本。支持畫布元素的瀏覽器都支持2D上下文,除了2D上下文,還有其他試驗性的上下文對象。Opera有一個專門為游戲設計的2D上下文,而Mozilla則有一個能夠顯示3D場景的上下文??上а剑壳斑@些上下文對象只有特定的瀏覽器才支持。如果你想用畫布來創建Web應用,***還是只使用常見的2D上下文。
因為我們在這里是想繪制一幅能移動的圖像,所以必須建立渲染循環(render loop)。所謂渲染循環,實際上就是一個被重復調用的函數,渲染循環的每一次迭代,(在這個例子中)都可以讓圖像在屏幕上產生一點位移,如此循環往復就能給人圖像在移動的感覺。為此,我們調用了setInterval函數,它的***個參數是應該被重復調用的函數,這里的函數名是draw。setInterval函數的第二個參數指定調用函數的頻率。這個參數值的單位是毫秒,而用1000除以早先定義的FPS得到的就是每次調用之間相隔的毫秒數。
這里需要注意一下,雖然我們指定每秒鐘調用30次draw函數,但實際上不會調用30次。多長時間調用一次draw函數,取決于底層JavaScript引擎的速度和要執行的draw函數代碼的復雜程度。如果系統很慢的話,很可能每秒鐘只能調用一次draw函數。所以說,這里指定給setInterval的頻率只是一種最理想的情況。
draw函數
在畫布上繪圖的操作實際上都是由draw函數來完成的。下面我們就一步一步地說明其中的繪圖操作。
- context2D.clearRect(0, 0, canvas.width, canvas.height);
所有繪圖操作都是在上下文對象上發生的,并不是在畫布元素上發生的。這里首先清空上下文,以便為繪制每一幀畫面準備一個干凈的版面。
- context2D.drawImage(image, x, y);
緊接著,就把圖像繪制到上下文對象中,參數x和y指定了繪制圖像的左上角坐標。
- x += 1 * xDirection;
- y += 1 * yDirection;
為了讓圖像在畫布上移動,需要根據xDirection和yDirection是等于1(向右或向下)還是等于-1(向左或向上),來遞增或遞減x與y的值。
- if (x >= 450){
- x = 450;
- xDirection = -1;
- } else if (x <= 0) {
- x = 0;
- xDirection = 1;
- }
- if (y >= 250) {
- y = 250;
- yDirection = -1;
- } else if (y <= 0) {
- y = 0;
- yDirection = 1;
- }
如果圖像移動到了畫布外面,則反轉圖像的移動方向。我們知道圖像的大小是150×150像素,而畫布的大小的是600×400像素,因而就有了450(600 – 150)和250(400 – 150)這兩個值。
***的效果就是笑臉圖像會在畫布的范圍內反彈往復。此時此刻,有讀者可能會想:同樣的效果如果通過修改DIV元素的位置來實現可能更容易一些。這一點我不否認。但這個例子只演示了畫布元素所能實現的簡單效果。下一篇文章我們就會介紹使用畫布元素能夠實現的高級效果,同樣的效果若采用其他方式,恐怕就要困難多了。
原文作者:Matthew Casperson 原文鏈接: Game Development with JavaScript and the Canvas element
譯文作者:李松峰 譯文鏈接:http://www.cn-cuckoo.com/2011/08/10/game-development-with-javascript-and-the-canvas-element-2554.html
【編輯推薦】