本文章是由機器翻譯。

遊戲開發

2D 繪圖技術和網頁遊戲庫

MichaelOneppo

在很長時間,真的是只有一種方式使除­活動網頁遊戲:閃光。喜歡還是不喜歡 Flash 有一個快速的繪圖系統。每個人都用它來創建動畫、 指向和點擊冒險和各種各樣的其他經驗。

當瀏覽器符合 Web 標準 HTML5 時,傳來名副其實的爆炸聲的快速發展,高品質的圖形選項 — — 無需外掛程式。這篇文章將介紹一個小樣本的繪製方法,以及底層技術和一些用於使他們便於使用的庫。我將不會涵蓋圖書館專門為遊戲。有如此多的那些我要保存這種討論的另一篇文章。

製圖標準

隨著 HTML5 的爆發,出現了三種常用方法在 2D 繪圖:文件物件模型 (DOM)、 畫布和可縮放向量圖形 (SVG) 格式。在使用這些技術的圖書館調查之前,我將回顧每個人是如何更好地瞭解每種方法的好處和壞處。

毫不奇怪,在 HTML 中繪製圖形的最基本途徑實在與 HTML。通過創建圖像或背景的元素的數目和使用像 jQuery 庫,很快可以使您可以在移動,而不必重新繪製場景的精靈。瀏覽器將為你做它。這種結構通常被稱為場景圖。在 HTML 中,場景圖是 dom。因為您將使用 CSS 樣式你的精靈,你還可以使用 CSS 切換和動畫效果,為你的場景添加一些流暢的動作。

這種方法的關鍵問題是依賴于 DOM 渲染器。這可以放慢當你有一個複雜的場景。我不推薦使用多幾個幾百個元素。所以比匹配三個更複雜的東西或平臺遊戲可能有性能問題。突然的元素數目增加,喜歡在粒子系統,可以在動畫中導致打嗝。

這種方法的另一個問題是,您需要使用元素的樣式的 CSS。具體取決於您如何編寫 CSS,它可以是體面的快速或得很慢。最後,編寫針對 HTML 的代碼可能很難將移動到一個不同的系統,像本機 c + +。這是重要的如果你想要港口你到一個主控台之類的遊戲。下面是摘要的優點:

  • 基於 Web 頁面的基本結構
  • jQuery 和其他圖書館可以很容易地左右移動的東西
  • 精靈是相對容易設置
  • 內置動畫系統與 CSS 切換和動畫效果

和缺點的摘要:

  • 許多小元素可以慢下來了你
  • 需要使用 CSS 元素的樣式
  • 沒有向量圖像
  • 可以是困難地移植到其他平臺

HTML5 畫布

畫布元素涉及大量的缺點。 它提供了即時模式渲染環境 — — 平的小水線面雙體船的圖元為單位)。你告訴它在 JavaScript 中畫什麼,它立即繪製。因為它將您的繪圖命令轉換為圖元,您可以快速堆積一長串的浪尖,又關閉系統繪圖命令。您可以繪製幾何形狀、 文本、 圖像、 漸變和其他元素。閱讀更多關於使用畫布的遊戲,檢查出DavidCatuhe 在一條 bit.ly/1fquBuo

那麼壞處是什麼?因為畫布上忘記它畫做了的時刻,你必須重繪現場自己每的次你想要它改變。如果你想要修改的形狀以複雜的方式,如彎曲或動畫,你不得不做的計算和重繪該專案。這意味著你需要維護大量的關於你的場景在您自己的資料結構中的資料。這不是考慮有圖書館,使這更容易的一件大事。如果你真的想要做一些定制,請注意畫布上不保留為您的資訊。最後,畫布不包括動畫。你必須在連續的步驟,使一個平滑的動畫中繪製你的場景。下面是摘要的優點:

  • 直接繪製 — — 場景可以更複雜
  • 支援大量不同的視覺元素

和缺點的摘要:

  • 沒有固有的記憶的場景 ; 你需要自己構建
  • 複雜轉換和動畫必須手動完成
  • 沒有動畫系統

SVG:可縮放向量圖形

為基於 XML 的標記描述二維視覺效果,SVG 是類似于 HTML 的。關鍵的區別是 SVG 意味著對於繪圖,而 HTML 主要用於文本和佈局。因此,SVG 具有一些強大的繪圖功能,如光滑的形狀、 複雜的動畫、 變形和甚至像模糊的圖像篩選器。像 HTML,SVG 具有場景圖結構,所以你可以仔細閱讀 SVG 元素、 添加形狀、 更改它們的屬性和不擔心重繪的一切。瀏覽器將為你做它。視頻中,"工作與 SVG 在 HTML5,"從通道 9 (bit.ly/1DEAWmh) 作了詳細解釋。

像 HTML,複雜的場景可以拖後腿 SVG。SVG 可以處理一些複雜性,但它不能完全符合提供了通過使用畫布的複雜性。此外,操縱 SVG 的工具也可能很複雜,雖然有其他工具來簡化這個過程。下面是摘要的優點:

  • 很多像曲面和複雜形狀的繪圖選項
  • 結構,不需要重繪

和缺點的摘要:

  • 複雜性可以停滯不前
  • 難操作

2D 繪圖庫

現在,你知道關於標準可用於在 Web 上畫畫,我會看看可以使您的繪圖和動畫更容易一些圖書館。值得注意的你很少做畫不能去做點別的繪圖。例如,您經常需要圖形來對輸入做出反應。庫可以説明使繪圖更容易關聯的常見任務。

KineticJS 為帆布想場景圖嗎?KineticJS 是一個極其強大的畫布庫開頭場景圖並添加更多的功能。在基線水準,KineticJS 允許您定義圖層包含形狀繪製的畫布中。例如, 圖 1 演示如何繪製一個簡單的紅色圓圈,使用 KineticJS。

圖 1 繪製一個圓圈與 KineticJS

// Points to a canvas element in your HTML with id "myCanvas"
var myCanvas = $('#myCanvas'); 
var stage = new Kinetic.Stage({
  // get(0) returns the first element found by jQuery,
  // which should be the only canvas element
  container: myCanvas.get(0),
    width: 800,
    height: 500
  });
   
var myLayer = new Kinetic.Layer({id: “myLayer”});
stage.add(myLayer);
var circle = new Kinetic.Ellipse({
  // Set the position of the circle
  x: 100,                                            
  y: 100,
   
  // Set the size of the circle
  radius: {x: 200, y: 200},
   
  // Set the color to red
  fill: '#FF0000'  
});
 
myLayer.add(circle);
stage.draw();

您將需要調用的最後一行圖 1 每次你想要的場景重繪。KineticJS 將盡其餘通過記憶的現場佈局,確保一切都正確地繪製。

有一些有趣的東西,在 KineticJS,使其功能相當強大。例如,物件的填充屬性可以是很多東西,包括一個漸變:

fill: {
  start: {x: 0, y: 0},
  end: {x: 0, y: 200},
  colorStops: [0, '#FF0000', 1, '#00FF00']
},

或形象:

// The "Image" object is built into JavaScript and
// Kinetic knows how to use it
fillPatternImage: new Image('path/to/an/awesome/image.png'),

KineticJS 有一個動畫系統,以及使您可以通過創建動畫物件或通過使用過渡屬性的補間物件在你的場景中的形狀上,左右移動的東西。圖 2 顯示兩種類型的動畫。

圖 2 動畫使用 KineticJS

// Slowly move the circle to the right forever
var myAnimation = new Kinetic.Animation(
  function(frame) {
    circle.setX(myCircle.getX() + 1);
  },
  myLayer);
 
// The animation can be started and stopped whenever
myAnimation.start();
// Increase the size of the circle by 3x over 3 seconds
var myTween = new Kinetic.Tween({
  node: circle,
  duration: 3,
  scaleX: 3.0,
  scaleY: 3.0
});
 
// You also have to initiate tweens
myTween.play();

KineticJS 是強大且被廣泛使用,特別是對於遊戲。簽出代碼、 示例和文檔,網址為 kineticjs.com

Paper.js Paper.js 為簡化到畫布上的繪圖提供了更多隻是一個圖書館。它提供了 JavaScript 調用 PaperScript 來簡化常見的繪圖任務稍加修改的版本。當在您的專案中包括 PaperScript,將連結到它,就像你會週期性劇本,只是不同類型的代碼:

<script type=“text/paperscript" src=“mypaperscript.js”>

這讓 Paper.js 解釋代碼略有不同。真的有這僅有的兩件。首先,PaperScript 有兩個內置的物件稱為點和大小。PaperScript 在其職能包括共同使用這些物件,並提供直接添加、 相減和相乘這些類型的能力。例如,在 PaperScript 中移動的物件,你可以做這:

var offset = new Point(10, 10);
 
var myCircle = new Path.Circle({
  center: new Point(300, 300),
  radius: 60
});
 
// Direct addition of Point objects!
myCircle.position += offset;

Paper.js 以不同的方式解釋第二件事對事件的回應。請考慮您在 JavaScript 中編寫下面的代碼:

function onMouseDown(event) {
  alert("Hello!");
}

這不會因為該函數不綁定到任何元素的事件。然而,在 PaperScript 中編寫相同的代碼,Paper.js 會自動檢測該函數並將其綁定到滑鼠按下事件。瞭解更多關於這在 paperjs.org

Fabric.js Fabric.js 是一個功能豐富的畫布庫,與能夠混合使用了大量先進的效果和形狀放入 Web 頁中沒有大量的代碼。一些顯著的特點包括圖像篩檢程式等背景去除,製作你自己的綜合物件和"自由繪製"支援在那裡你可以只是在畫布上繪製大量的樣式的自訂類。Fabric.js 是類似于 KineticJS,它將場景圖,除了有一種更簡潔的結構,有些人喜歡。例如,你不需要永遠重繪場景:

var canvas = new fabric.Canvas('myCanvas');
var circle = new fabric.Circle({
  radius: 200,
    fill: '#FF0000',
    left: 100,
    top: 100
});
 
// The circle will become immediately visible
canvas.add(circle);

這不是很大的不同,但 Fabric.js 提供混合自動重繪和手動重繪的細細微性呈現控制項。舉個例子,加大在 Fabric.js 的圓看起來像這樣:

circle.animate(
  // Property to animate
  'scale',
  // Amount to change it to
  3,
  {
    // Time to animate in milliseconds
    duration: 3000,
    // What's this?
    onChange: canvas.renderAll.bind(canvas)
  });

當動畫中 Fabric.js 的東西,你必須告訴它該怎麼辦時,它將值更改為。大多數情況下,你想要它來重繪的場景。這是什麼 canvas.renderAll.bind(canvas) 引用。這段代碼返回一個函數,將使整個場面。如果你要利用動畫表示物件以這種方式很多,不過,現場將不必要地重繪一次為每個物件。相反,你可以抑制重繪整個場景,和重繪自己的動畫。圖 3 演示了此方法。

圖 3 緊縮在 Fabric.js 重新繪製控制項

var needRedraw = true;
 
// Do things like this a lot, say hundreds of times
circle.animate(
  'scale',
  3,
  {
    duration: 3000,
       
    // This function will be called when the animation is complete
    onComplete: function() {
      needRedraw = false;
    }
  });
 
// This function will redraw the whole scene, and schedule the
// next redraw only if there are animations going
function drawAnimations() {
  canvas.renderAll();
  if (needRedraw) {
    requestAnimationFrame(drawAnimations);
  }
}
 
// Now draw the scene to show the animations
requestAnimationFrame(drawAnimations);

Fabric.js 提供了大量的定制,所以您可以優化您的繪圖,只有當你需要的時候。對於一些人來說,可能很難處理。對於許多複雜的遊戲,不過,這可能是一項重要功能。查閱更多 fabricjs.com

Raphaël Raphaël 是一個有用的 SVG 庫,消除了大部分的 SVG 處理的複雜性。Raphaël 使用 SVG 時可用。當它不是時,Raphaël 實現 SVG 在 JavaScript 使用任何技術都在瀏覽器中可用。在 Raphaël 中創建的每個繪圖物件也是一個 DOM 物件,與所有功能的 DOM 物件享受,綁定事件處理常式和 jQuery 訪問等。Raphaël 還具有使您可以定義獨立的物件,繪製的動畫的動畫系統啟用重重用:

var raphael = Raphael(0, 0, 800, 600);
 
var circle = raphael.circle(100, 100, 200);
circle.attr("fill", "red");
circle.animate({r: 600}, 3000);
 
// Or make a custom animation
var myAnimation = Raphael.animation(
  {r: 600},
  3000);
circle.animate(myAnimation);

在此代碼中,而不是繪製一個圓圈,Raphaël 將與圓元素頁面上放置一個 SVG 文檔。奇怪的是,Raphaël 不以本機方式支援載入的 SVG 檔。Raphaël 沒有一個富裕的社區,所以那裡是一個外掛程式,可在 bit.ly/1AX9n7q

Snap.svg Snap.svg 看起來頗有點像 Raphaël:

var snap = Snap("#myCanvas"); // Add an SVG area to the myCanvas element
var circle = snap.circle(100, 100, 200);
circle.attr("fill", "#FF0000");
circle.animate({r: 600}, 1000);

主要的區別之一就是 Snap.svg 包括無縫 SVG 導入:

Snap.load("myAwesomeSVG.svg");

第二個關鍵的區別在於,Snap.svg 提供了功能強大的內置工具來搜索和編輯 SVG 結構就地,如果你知道你正在使用 SVG 的結構。例如,假設您想要使你 SVG 中的所有組 ("g"標記) 不可見。SVG 載入後,您必須在回檔中的此功能添加到 load 方法:

Snap.load("myAwesomeSVG.svg", function(mySVG) {
  mySVG.select("g").attr("opacity", 0);
});

Select 方法很像 jQuery"$"選擇器,且相當強大。查閱在 Snap.svg snapsvg.io

多一點: p5.js

很多這些庫提供少量的額外的常見任務。這將創建一系列的技術來解決廣泛的應用,從簡單的繪圖,互動媒體和複雜的遊戲體驗。什麼是外面在譜 — — 比簡單的繪圖解決方案,但並不完全是一個完整遊戲的引擎更多的東西?

值得注意的一個專案是 p5.js,由流行加工程式設計語言 (請參閱 processing.org)。此 JavaScript 庫通過在瀏覽器中實現加工提供互動式媒體環境。 p5.js 合併一組函數,您必須定義來回應事件,在系統中,像重繪場景或滑鼠輸入最常見的任務。它很像 Paper.js,但與多媒體圖書館,以及。下面是一個例子,演示了這種方法更簡潔的圖形代碼中的結果:

float size = 20;
function setup() {
  createCanvas(600, 600);
}
 
function draw() {
  ellipse(300, 300, size, size);
  size = size + .1;
}

這個程式使生長一圈大小,直到它填補了螢幕。查閱在 p5.js p5js.org

所以什麼用?

顯然是利弊來畫布和 SVG。也有明顯減少了很多不利因素對兩種方式的圖書館。所以你應該使用什麼?我一般不推薦使用傳統的 HTML。很有可能表現出現代遊戲將超過圖形的複雜性,它可以支援。所以,給我們帶來 SVG 與畫布上,是很難的抉擇。

極富特色的遊戲流派,回答起來有點容易。如果您正在構建一個遊戲與數以十萬計的粒子,你會想要使用畫布。如果您正在構建一款漫畫風格的指向和點擊冒險遊戲,你可能想要考慮 SVG。

對於大多數遊戲,它不會歸結為性能,如很多人會讓你相信。你可以花小時翻來覆去說明要使用哪個庫。最後,雖然,這是你可以編寫遊戲的時間。

我的建議是要基於你的藝術資產選擇。如果你正在你的人物動畫在 Adobe Illustrator 或 Inkscape,為什麼轉換到圖元動畫的每一幀?本機使用向量藝術。Don浪費所有的工作,通過你的藝術塞入畫布。

相反,如果你的作品大多是基於圖元的或者你打算會產生複雜的影響,在逐個圖元的基礎上,畫布是一個完美的選擇。

多一項選擇

如果你正在尋找最好的性能,你願意去處理一個小的更多複雜性,做到這一點,我強烈建議你考慮 Pixi.js。 像別的我展示你在這篇文章,Pixi.js 使用 WebGL 2D 渲染。這提供了一些主要的性能改進。

該 API 並不是像其他人形容這裡,但它不是一個巨大的區別的那樣簡單。此外,WebGL 不在盡可能多的瀏覽器上支援的其他技術。等較舊的系統 Pixi.js 有任何性能優勢。無論哪種方式,使您的選擇和享受的過程。


MichaelOneppo 是一個創造性的技師和 Direct3D 團隊在微軟前程式經理。他最近的努力包括在這項技術作為首席技術官工作非營利組織所有圖書館和探索在紐約大學電訊互動專案碩士學位。​

感謝以下的微軟技術專家對本文的審閱: Shai Hinitz