基於官方教程翻譯;水平有限,若有錯誤歡迎提PR,轉載請註明出處。翻譯者爲htkz(完成了用 Pixi 繪製幾何圖形 和 顯示文本 章節)和zainking(完成了其餘全部章節) 另感謝htkz、NearZXH以及HHHHhgqcdxhg對錯誤及錯別字等作出的訂正。javascript
這個教程將要一步步介紹怎麼用Pixi作遊戲或者交互式媒體。這個教程已經升級到 Pixi v4.5.5。若是你喜歡這個教程,你必定也喜歡這本書,它比這個教程多了80%的內容。html
Pixi是一個超快的2D渲染引擎。這意味着什麼呢?這意味着它會幫助你用JavaScript或者其餘HTML5技術來顯示媒體,建立動畫或管理交互式圖像,從而製做一個遊戲或應用。它擁有語義化的,簡潔的API接口而且加入了一些很是有用的特性。好比支持紋理貼圖集和爲精靈(交互式圖像)提供了一個簡單的動畫系統。它也提供了一個完備的場景圖,你能夠在精靈圖層裏面建立另外一個精靈,固然也可讓精靈響應你的鼠標或觸摸事件。最重要的的是,Pixi沒有妨礙你的編程方式,你能夠本身選擇使用多少它的功能,你能夠遵循你本身的編碼風格,或讓Pixi與其餘有用的框架無縫集成。html5
Pixi的API事實上比起久經沙場又老舊的Macromedia/Adobe Flash API要精緻。若是你是一個Flash開發者,將會對這樣的API感受更好。其餘的同類渲染框架(好比CreateJS,Starling, Sparrow 和 Apple’s SpriteKit.)也在使用相似的API。Pixi API的優點在於它是通用的:它不是一個遊戲引擎。這是一個優點,由於它給了你全部的自由去作任何你想作的事,甚至用它能夠寫成你本身的遊戲引擎。(譯者:做者這點說的很對,譯者有一個朋友就使用它製做本身的Galgame引擎AVG.js)。java
在這個教程裏,你將會明白怎樣用Pixi的強大的圖片渲染能力和場景圖技術來和作一個遊戲聯繫起來。可是Pixi不只僅能作遊戲 —— 你能用這個技術去建立任何交互式媒體應用。這甚至意味着手機應用。node
你在開始這個教程以前須要知道什麼呢?git
你須要一個對於HTML和JavaScript大體的瞭解。你不必成爲這方面的專家才能開始,即便一個野心勃勃的初學者也能夠開始學習。這本書就是一個學習的好地方:github
Foundation Game Design with HTML5 and JavaScriptweb
我知道這本書是最好的,由於這本書是我寫的!算法
這裏有一些好的代碼來幫助你開始:spring
Khan Academy: Computer Programming
選擇一個屬於你的最好的學習方式吧!
因此,明白了麼?
你知道JavaScript的變量,函數,數組和對象怎麼使用麼?你知道JSON 數據文件是什麼麼? 你用過 Canvas 繪圖 API麼?
爲了使用Pixi,你也須要在你項目的根目錄運行一個web服務器,你知道什麼是web服務器,怎麼在你的項目文件夾裏面運行它麼?最好的方式是使用node.js 而且去用命令行安裝http-server. 不管如何,你須要習慣和Unix命令行一塊兒工做。你能夠在這個視頻中去學習怎樣使用 Unix當你完成時,繼續去學習 這個視頻.你應該學會怎樣用Unix,這是一個頗有趣和簡單的和電腦交互的方式,而且僅僅須要兩個小時。
若是你真的不想用命令行的方式,就嘗試下 Mongoose webserver:
或者來使用Brackets text editor這個使人驚豔的代碼編輯器。他會在你點擊那個「閃電按鈕」的時候自動啓動web服務器和瀏覽器。
如今,若是你以爲你準備好了了,開始吧!
(給讀者的小提示:這是一個 交互式的文檔.若是你有關於特殊細節的任何問題或須要任何澄清均可以建立一個GitHub工程 issue ,我會對這個文檔更新更多信息。)
在你開始寫任何代碼以前,給你的工程建立一個目錄,而且在根目錄下運行一個web服務器。若是你不這麼作,Pixi不會工做的。
如今,你須要去安裝Pixi。
這個教程使用的版本是 v4.5.5 你能夠選擇使用 Pixi v4.5.5的發佈頁面pixi
文件夾下的pixi.min.js
文件,或者從Pixi的主要發佈頁面中獲取最新版本。
這個文件就是你使用Pixi惟一須要的文件,你能夠忽視全部這個工程的其餘文件,你不須要他們。
如今,建立一個基礎的HTML頁面,用一個<script>
標籤去加載你剛剛下載的pixi.min.js
文件。<script>
標籤的src
屬性應該是你根目錄文件的相對路徑————固然請確保你的web服務器在運行。你的<script>
標籤應該看起來像是這樣:
<script src="pixi.min.js"></script>
這是你用來連接Pixi和測試它是否工做的基礎頁面。(這裏假設 pixi.min.js
在一個叫作pixi
的子文件夾中):
<!doctype html>
<html>
<head> <meta charset="utf-8"> <title>Hello World</title> </head> <script src="pixi/pixi.min.js"></script> <body> <script type="text/javascript"> let type = "WebGL" if(!PIXI.utils.isWebGLSupported()){ type = "canvas" } PIXI.utils.sayHello(type) </script> </body> </html>
若是Pixi鏈接成功,一些這樣的東西會在你的瀏覽器控制檯裏顯示:
PixiJS 4.4.5 - * canvas * http://www.pixijs.com/ ♥♥♥
舞臺
如今你能夠開始使用Pixi!
可是怎麼用?
第一步就是去建立一個能夠顯示圖片的矩形顯示區。Pixi擁有一個Pixi應用
對象來幫助你建立它。它會自動建立一個<canvas>
HTML標籤而且計算出怎麼去讓你的圖片在這個標籤中顯示。你如今須要建立一個特殊的Pixi容器
對象,他被稱做舞臺
。正如你所見,這個舞臺
對象將會被看成根容器而使用,它將包裹全部你想用Pixi顯示的東西。
這裏是你須要建立一個名叫app
的Pixi應用對象和一個舞臺
的必要的代碼。這些代碼須要在你的HTML文檔中以<script>
標籤包裹。
//Create a Pixi Application let app = new PIXI.Application({width: 256, height: 256}); //Add the canvas that Pixi automatically created for you to the HTML document document.body.appendChild(app.view);
這是你想要開始使用Pixi的最基本的代碼。它在你的文檔中建立了一個256像素寬高的黑色canvas標籤。當你運行這個代碼的時候瀏覽器應該顯示成這樣:
啊哈, 一個 black square!
PIXI.Application
算出了應該使用Canvas仍是WebGL去渲染圖象,它取決於你正在使用的瀏覽器支持哪個。它的參數是一個被稱做options
的對象。在這兒例子中,它的width
和 height
屬性已經被設置了,它們決定了canvas的寬和高(單位是像素)。你可以在options
對象中使用更多的屬性設置,這裏展現了你如何使用它來圓滑邊界,設置透明度和分辨率:
let app = new PIXI.Application({ width: 256, // default: 800 height: 256, // default: 600 antialias: true, // default: false transparent: false, // default: false resolution: 1 // default: 1 } );
若是你以爲Pixi的默認設置也不錯,你就不須要做任何的設置,可是若是你須要,就在這裏看一下Pixi的文檔吧:PIXI.Application.
這些設置作了些什麼呢? antialias
使得字體的邊界和幾何圖形更加圓滑(WebGL的anti-aliasing在全部平臺都不可用,因此你須要在你的遊戲的標籤平臺上測試他們)。transparent
將整個Canvas標籤的透明度進行了設置。resolution
讓Pixi在不一樣的分辨率和像素密度的平臺上運行變得簡單。設置分辨率對於這個教程而言有些超綱了,到那時你能夠看Mat Grove'sexplanation之中是如何使用resolution
的全部細節的。可是日常,只要保持resolution
是1,就能夠應付大多數工程了。
Pixi的畫布
對象將會默認選擇WebGL引擎渲染模式,它更快而且可讓你使用一些壯觀的視覺特效————若是你把他們都學了。可是若是你須要強制使用Canvas引擎繪製而拋棄WebGL,你能夠設置forceCanvas
選項爲true
,像這樣:
forceCanvas: true,
若是你須要在你建立canvas標籤以後改變它的背景色,設置 app.renderer
對象的backgroundColor
屬性爲一個任何的十六進制顏色:
app.renderer.backgroundColor = 0x061639;
若是你想要去找到畫布
的寬高,使用app.renderer.view.width
和app.renderer.view.height
。
使用畫布
的resize
方法能夠改變canvas的大小,提供任何新的width
和 height
變量給他都行。可是爲了確認寬高的格式正確,將autoResize
設置爲true
。
app.renderer.autoResize = true; app.renderer.resize(512, 512);
若是你想讓canvas佔據整個窗口,你能夠將這些CSS代碼放在文檔中,而且刷新你瀏覽器窗口的大小。
app.renderer.view.style.position = "absolute"; app.renderer.view.style.display = "block"; app.renderer.autoResize = true; app.renderer.resize(window.innerWidth, window.innerHeight);
可是,若是你這麼作了,要記得把padding和margin都設置成0:
<style>* {padding: 0; margin: 0}</style>
(*這個通配符, 是CSS選擇全部HTML元素的意思。)
若是你想要canvas在任何瀏覽器中統一尺寸,你可使用scaleToWindow
成員函數.
如今你就有了一個畫布,能夠開始往上面放圖像了。全部你想在畫布上顯示的東西必須被加進一個被稱做 舞臺
的Pixi對象中。你可以像這樣使用舞臺對象:
app.stage
這個舞臺
是一個Pixi 容器
對象。你能把它理解成一種將放進去的東西分組並存儲的空箱子。 舞臺
對象是在你的場景中全部可見對象的根容器。全部你放進去的東西都會被渲染到canvas中。如今舞臺
是空的,可是很快咱們就會放進去一點東西。 (你能夠從這瞭解關於Pixi容器
對象的更多信息here).
(重要信息:由於舞臺
是一個Pixi容器
對象,因此他有不少其餘容器
對象都有的屬性和方法。可是,儘管舞臺擁有width
和 height
屬性, 他們都不能查看畫布窗口的大小 。舞臺的width
和 height
屬性僅僅告訴了你你放進去的東西佔用的大小 - 更多的信息在前面!)
因此你能夠放些什麼到舞臺上呢?那就是被稱做 精靈 的特殊圖像對象。精靈是你能用代碼控制圖像的基礎。你可以控制他們的位置,大小,和許多其餘有用的屬性來產生交互和動畫。學習怎樣建立和控制精靈是學習Pixi最重要的部分。若是你知道怎麼建立精靈和把他們添加進舞臺,離作出一個遊戲就僅僅剩下一步之遙!
Pixi擁有一個精靈
類來建立遊戲精靈。有三種主要的方法來建立它:
你將要學習這三種方式,可是在開始以前,你得弄明白圖片怎麼用Pixi顯示。
由於Pixi用WebGL和GPU去渲染圖像,因此圖像須要轉化成GPU能夠處理的版本。能夠被GPU處理的圖像被稱做 紋理 。在你讓精靈顯示圖片以前,須要將普通的圖片轉化成WebGL紋理。爲了讓全部工做執行的快速有效率,Pixi使用 紋理緩存 來存儲和引用全部你的精靈須要的紋理。紋理的名稱字符串就是圖像的地址。這意味着若是你有從"images/cat.png"
加載的圖像,你能夠在紋理緩存中這樣找到他:
PIXI.utils.TextureCache["images/cat.png"];
紋理被以WEBGL兼容的格式存儲起來,它可使Pixi的渲染有效率的進行。你如今可使用Pixi的精靈
類來建立一個新的精靈,讓它使用紋理。
let texture = PIXI.utils.TextureCache["images/anySpriteImage.png"]; let sprite = new PIXI.Sprite(texture);
可是你該怎麼加載圖像並將它轉化成紋理?答案是用Pixi已經構建好的loader
對象。
Pixi強大的loader
對象能夠加載任何你須要種類的圖像資源。這裏展現了怎麼加載一個圖像並在加載完成時用一個叫作setup
的方法來使用它。
PIXI.loader .add("images/anyImage.png") .load(setup); function setup() { //This code will run when the loader has finished loading the image }
Pixi的最佳實踐 若是你使用了Loader,你就應該建立一個精靈來鏈接loader
的resources
對象,像下面這樣:
let sprite = new PIXI.Sprite( PIXI.loader.resources["images/anyImage.png"].texture );
這裏是一個完整的加載圖像的代碼。調用setup
方法,並未加載的圖像建立一個精靈。
PIXI.loader .add("images/anyImage.png") .load(setup); function setup() { let sprite = new PIXI.Sprite( PIXI.loader.resources["images/anyImage.png"].texture ); }
這是這個教程之中用來加載圖像和建立精靈的通用方法。
你能夠鏈式調用add
方法來加載一系列圖像,像下面這樣:
PIXI.loader .add("images/imageOne.png") .add("images/imageTwo.png") .add("images/imageThree.png") .load(setup);
更好的方式則是用數組給一個add
方法傳參,像這樣:
PIXI.loader .add([ "images/imageOne.png", "images/imageTwo.png", "images/imageThree.png" ]) .load(setup);
這個loader
也容許你使用JSON文件,關於JSON文件你應該已經在前面學過了。
在你加載一個圖像以後,能夠用它來建立一個精靈,你須要用stage.addChild
方法把它放到Pixi的舞臺
上面去,像這樣:
app.stage.addChild(cat);
記住,舞臺
是用來包裹你全部精靈的主要容器。
重點:你不該該看見任何沒被加入舞臺
的精靈
在咱們繼續以前,讓咱們看一個怎樣使用顯示一個單圖像的例子。在examples/images
文件夾中,你將找到一個64*64像素大小的貓的PNG圖像文件。
這裏是全部的顯示一個圖像,建立一個精靈,顯示在Pixi的舞臺上所須要的代碼。
//Create a Pixi Application let app = new PIXI.Application({ width: 256, height: 256, antialias: true, transparent: false, resolution: 1 } ); //Add the canvas that Pixi automatically created for you to the HTML document document.body.appendChild(app.view); //load an image and run the `setup` function when it's done PIXI.loader .add("images/cat.png") .load(setup); //This `setup` function will run when the image has loaded function setup() { //Create the cat sprite let cat = new PIXI.Sprite(PIXI.loader.resources["images/cat.png"].texture); //Add the cat to the stage app.stage.addChild(cat); }
程序跑起來,你會看到:
如今咱們已經取得了一些進展!
若是你想把一個精靈從舞臺上挪走,就可使用removeChild
方法:
app.stage.removeChild(anySprite)
可是一般,咱們都把精靈的visible
屬性設置成false
來讓精靈簡單的隱藏。
anySprite.visible = false;
你能夠對你使用頻繁的Pixi對象和方法設置一些簡略的可讀性更強的別名。舉個例子,你想給全部的Pixi對象增長PIXI
前綴麼?若是你這樣想,那就建立一個簡短的別名給他吧。下面是一個給TextureCache
對象建立別名的例子:
let TextureCache = PIXI.utils.TextureCache
如今就能夠像這樣使用別名了:
let texture = TextureCache["images/cat.png"];
使用別名給寫出簡潔的代碼提供了額外的好處:他幫助你緩存了Pixi的經常使用API。若是Pixi的API在未來的版本里改變了 - 沒準他真的會變! - 你將會須要在一個地方更新這些對象和方法,你只用在工程的開頭而不是全部的實例那裏!因此Pixi的開發團隊想要改變它的時候,你只用一步便可完成這個操做!
來看看怎麼將全部的Pixi對象和方法改爲別名以後,來重寫加載和顯示圖像的代碼。
//Aliases let Application = PIXI.Application, loader = PIXI.loader, resources = PIXI.loader.resources, Sprite = PIXI.Sprite; //Create a Pixi Application let app = new Application({ width: 256, height: 256, antialias: true, transparent: false, resolution: 1 } ); //Add the canvas that Pixi automatically created for you to the HTML document document.body.appendChild(app.view); //load an image and run the `setup` function when it's done loader .add("images/cat.png") .load(setup); //This `setup` function will run when the image has loaded function setup() { //Create the cat sprite let cat = new Sprite(resources["images/cat.png"].texture); //Add the cat to the stage app.stage.addChild(cat); }
大多數教程中的例子將會使用Pixi的別名來處理。除非另有說明,不然你能夠假定下面全部的代碼都使用了這些別名。
這就是你須要的全部的關於加載圖像和建立精靈的知識。
咱們的例子中的格式是加載圖像和顯示精靈的最佳實踐。因此你能夠安全的忽視這些章節直接看"定位精靈"。可是Pixi的加載器有一些你不經常使用的複雜功能。
爲了優化和效率咱們經常選擇從預加載的紋理緩存的紋理之中建立精靈。可是若是由於某些緣由你須要從JavaScript的Image
對象之中建立,你可使用Pixi的BaseTexture
和Texture
類:
let base = new PIXI.BaseTexture(anyImageObject), texture = new PIXI.Texture(base), sprite = new PIXI.Sprite(texture);
你可使用BaseTexture.fromCanvas
從任何已經存在canvas標籤中建立紋理:
let base = new PIXI.BaseTexture.fromCanvas(anyCanvasElement),
若是你想改變已經顯示的精靈的紋理,使用texture
屬性,能夠設置任何Texture
對象,像下面這樣:
anySprite.texture = PIXI.utils.TextureCache["anyTexture.png"];
你可使用這個技巧在遊戲發生一些重大變化時交互式的改變精靈的紋理。
你能夠給任何你加載的源文件分配一個獨一無二的別名。你只須要在add
方法中第一個參數位置傳進去這個別名就好了,舉例來講,下面實現了怎麼給這個貓的圖片重命名爲catImage
。
PIXI.loader .add("catImage", "images/cat.png") .load(setup);
這種操做在loader.resources
中建立了一個叫作catImage
的對象。 這意味着你能夠建立一個引用了catImage
對象的精靈,像這樣:
let cat = new PIXI.Sprite(PIXI.loader.resources.catImage.texture);
然而,我建議你永遠別用這個操做!由於你將不得不記住你全部加載文件的別名,並且必須確信你只用了它們一次,使用路徑命名,咱們將將這些事情處理的更簡單和更少錯誤。
Pixi的加載器有一個特殊的progress
事件,它將會調用一個能夠定製的函數,這個函數將在每次文件加載時調用。progress
事件將會被loader
的on
方法調用,像是這樣:
PIXI.loader.on("progress", loadProgressHandler);
這裏展現了怎麼將on
方法注入加載鏈中,而且每當文件加載時調用一個用戶定義的名叫loadProgressHandler
的函數。
PIXI.loader .add([ "images/one.png", "images/two.png", "images/three.png" ]) .on("progress", loadProgressHandler) .load(setup); function loadProgressHandler() { console.log("loading"); } function setup() { console.log("setup"); }
每個文件加載,progress事件調用loadProgressHandler
函數在控制檯輸出 "loading"。當三個文件都加載完畢,setup
方法將會運行,下面是控制檯的輸出:
loading
loading
loading
setup
這就不錯了,不過還能變的更好。你能夠知道哪一個文件被加載了以及有百分之多少的文件被加載了。你能夠在loadProgressHandler
增長loader
參數和resource
參數實現這個功能,像下面這樣:
function loadProgressHandler(loader, resource) { /*...*/ }
你如今可使用 resource.url
變量來找到如今已經被加載的文件。(若是你想找到你定義的別名,使用resource.name參數。)你可使用loader.progress
來找到如今有百分之多少的文件被加載了,這裏有一些關於上面描述的代碼:
PIXI.loader .add([ "images/one.png", "images/two.png", "images/three.png" ]) .on("progress", loadProgressHandler) .load(setup); function loadProgressHandler(loader, resource) { //Display the file `url` currently being loaded console.log("loading: " + resource.url); //Display the percentage of files currently loaded console.log("progress: " + loader.progress + "%"); //If you gave your files names as the first argument //of the `add` method, you can access them like this //console.log("loading: " + resource.name); } function setup() { console.log("All files loaded"); }
這裏是程序運行後的控制檯顯示:
loading: images/one.png progress: 33.333333333333336% loading: images/two.png progress: 66.66666666666667% loading: images/three.png progress: 100% All files loaded
這實在太酷了!由於你能用這個玩意作個進度條出來。 (注意:還有一些額外的resource
對象屬性, resource.error
會告訴你有哪些加載時候的錯誤,resource.data
將會給你文件的原始二進制數據。)
Pixi的加載器有不少能夠設置的功能,讓我速覽一下:
add
方法有四個基礎參數:
add(name, url, optionObject, callbackFunction)
這裏有文檔裏面對這些參數的描述:
name
(string): 加載源文件的別名,若是沒設置,url
就會被放在這.url
(string): 源文件的地址,是加載器 baseUrl
的相對地址.options
(object literal): 加載設置.options.crossOrigin
(Boolean): 源文件請求跨域不?默認是自動設定的。options.loadType
: 源文件是怎麼加載進來的?默認是Resource.LOAD_TYPE.XHR
。 options.xhrType
: 用XHR的時候該怎麼處理數據? 默認是Resource.XHR_RESPONSE_TYPE.DEFAULT
。callbackFunction
: 當這個特定的函數加載完,這個特定的函數將會被執行。
只有url
必填(你總得加載個文件吧。)
這裏有點用了add
方法加載文件的例子。第一個就是文檔裏所謂的「正常語法」:
.add('key', 'http://...', function () {}) .add('http://...', function () {}) .add('http://...')
這些就是所謂「對象語法」啦:
.add({
name: 'key2', url: 'http://...' }, function () {}) .add({ url: 'http://...' }, function () {}) .add({ name: 'key3', url: 'http://...' onComplete: function () {} }) .add({ url: 'https://...', onComplete: function () {}, crossOrigin: true })
你也能夠給add
方法傳一個對象的數組,或者既使用對象數組,又使用鏈式加載:
.add([
{name: 'key4', url: 'http://...', onComplete: function () {} }, {url: 'http://...', onComplete: function () {} }, 'http://...' ]);
(注意:若是你須要從新加載一批文件,調用加載器的reset
方法:PIXI.loader.reset();
)
Pixi的加載器還有許多其餘的高級特性,包括可讓你加載和解析全部類型二進制文件的選項。這些並不是你天天都要作的,也超出了這個教程的範圍,因此從GitHub項目中獲取更多信息吧!
如今你知道了怎麼建立和顯示一個精靈,讓咱們學習如何定位他們的位置和改變他們的大小 在最先的示例裏那個貓的精靈被放在了舞臺的左上角。它的x
和y
座標都是0。你能夠經過改變它的x
和y
座標的值來改變他們的位置。下面的例子就是你經過設置x
和y
爲96座標讓它在舞臺上居中。
cat.x = 96; cat.y = 96;
在你建立這個精靈以後,把這兩行代碼放進setup
方法。
function setup() { //Create the `cat` sprite let cat = new Sprite(resources["images/cat.png"].texture); //Change the sprite's position cat.x = 96; cat.y = 96; //Add the cat to the stage so you can see it app.stage.addChild(cat); }
(注意:在這個例子裏,Sprite
是 PIXI.Sprite
的別名,TextureCache
是PIXI.utils.TextureCache
的別名,resources
是PIXI.loader.resources
的別名,我從如今開始在代碼中使用這些別名。)
這兩行代碼將把貓往右移動96像素,往下移動96像素。
這隻貓的左上角(它的左耳朵)(譯者注:從貓的角度看實際上是它的右耳朵。。。)表示了它的x
和 y
座標點。爲了讓他向右移動,增長x
這個屬性的值,爲了讓他向下移動,就增長y
屬性的值。若是這隻貓的x
屬性爲0,他就呆在舞臺的最左邊,若是他的y
屬性爲0,他就呆在舞臺的最上邊。
你能夠一句話設置精靈的x
和y
:
sprite.position.set(x, y)
你可以經過精靈的width
和height
屬性來改變它的大小。這是怎麼把width
調整成80像素,height
調整成120像素的例子:
cat.width = 80; cat.height = 120;
在setup
函數裏面加上這兩行代碼,像這樣:
function setup() { //Create the `cat` sprite let cat = new Sprite(resources["images/cat.png"].texture); //Change the sprite's position cat.x = 96; cat.y = 96; //Change the sprite's size cat.width = 80; cat.height = 120; //Add the cat to the stage so you can see it app.stage.addChild(cat); }
結果看起來是這樣:
你能看見,這隻貓的位置(左上角的位置)沒有改變,只有寬度和高度改變了。
精靈都有scale.x
和 scale.y
屬性,他們能夠成比例的改變精靈的寬高。這裏的例子把貓的大小變成了一半:
cat.scale.x = 0.5; cat.scale.y = 0.5;
Scale的值是從0到1之間的數字的時候,表明了它對於原來精靈大小的百分比。1意味着100%(原來的大小),因此0.5意味着50%(一半大小)。你能夠把這個值改成2,這就意味着讓精靈的大小成倍增加。像這樣:
cat.scale.x = 2; cat.scale.y = 2;
Pixi能夠用一行代碼縮放你的精靈,那要用到scale.set
方法。
cat.scale.set(0.5, 0.5);
若是你喜歡這種,就用吧!
你能夠經過對一個精靈的rotation
設定一個角度來旋轉它。
cat.rotation = 0.5;
可是旋轉是針對於哪個點發生的呢? 你已經瞭解了,精靈的左上角表明它的位置,這個點被稱之爲 錨點 。若是你用像0.5
這種值設定rotation
,這個旋轉將會 圍繞着錨點發生 。下面這張圖就是結果:
你能看見錨點是貓的左邊耳朵(譯者:對貓來講其實是它的右耳朵!),那裏成了貓的圖片的旋轉中心。 你該怎麼改變錨點呢?經過改變精靈的anchor
屬性的xy值來實現。像下面這樣:
cat.anchor.x = 0.5; cat.anchor.y = 0.5;
anchor.x
和anchor.y
的值若是是從0到1,就會被認爲是整個紋理的長度或寬度百分比。設置他們都爲0.5,錨點就處在了圖像中心。精靈定位的依據點不會改變,錨點的改變是另一回事。
下面的圖顯示把錨點居中之後旋轉的精靈。
你能夠看到精靈的紋理向左移動了,這是個必須記住的重要反作用!
像是position
和scale
屬性同樣,你也能夠在一行內像這樣設置錨點的位置:
cat.anchor.set(x, y)
精靈也提供和anchor
差很少的pivot
屬性來設置精靈的原點。若是你改變了它的值以後旋轉精靈,它將會圍繞着你設置的原點來旋轉。舉個例子,下面的代碼將精靈的pivot.x
和pivot.y
設置爲了32。
cat.pivot.set(32, 32)
假設精靈圖是64x64像素,它將繞着它的中心點旋轉。可是記住:你若是改變了精靈的pivot
屬性,你也就改變了它的原點位置。
因此anchor
和 pivot
的不一樣之處在哪裏呢?他們真的很像!anchor
改變了精靈紋理的圖像原點,用0到1的數據來填充。pivot
則改變了精靈的原點,用像素的值來填充。你要用哪一個取決於你。兩個都試試就知道哪一個對你而言最適合。
你如今已經知道了怎麼從一個單文件內加載圖像。可是做爲一個遊戲設計師,你沒準更常用 雪碧圖(也被稱之爲 精靈圖)。Pixi封裝了一些方便的方式來處理這種狀況。所謂雪碧圖就是用一個單文件包含你遊戲中須要的全部文件,這裏就是一個包含了遊戲對象和遊戲角色的雪碧圖。
整個雪碧圖是192192像素寬高,但每個單圖像只佔有一個3232的網格。把你的全部遊戲圖像存儲在一個雪碧圖上是一個很是有效率和工程化的手段,Pixi爲此作出了優化。你能夠從一個雪碧圖中用一個矩形區域捕獲一個子圖像。這個矩形擁有和你想提取的子圖像同樣的大小和位置。這裏有一個怎麼從一個精靈圖中獲取「火箭」這個子圖像的例子。
讓咱們看看這部分的代碼,用Pixi的加載器
加載tileset.png
,就像你在以前的示例之中作到的那樣。
loader
.add("images/tileset.png") .load(setup);
如今,在圖像被加載以後,用一個矩形塊去截取雪碧圖來建立精靈的紋理。下面是提取火箭,建立精靈,在canvas上顯示它的代碼。
function setup() { //Create the `tileset` sprite from the texture let texture = TextureCache["images/tileset.png"]; //Create a rectangle object that defines the position and //size of the sub-image you want to extract from the texture //(`Rectangle` is an alias for `PIXI.Rectangle`) let rectangle = new Rectangle(192, 128, 64, 64); //Tell the texture to use that rectangular section texture.frame = rectangle; //Create the sprite from the texture let rocket = new Sprite(texture); //Position the rocket sprite on the canvas rocket.x = 32; rocket.y = 32; //Add the rocket to the stage app.stage.addChild(rocket); //Render the stage renderer.render(stage); }
它是如何工做的呢?
Pixi內置了一個通用的Rectangle
對象 (PIXI.Rectangle
),他是一個用於定義矩形形狀的通用對象。他須要一些參數,前兩個參數定義了x
和y
軸座標位置,後兩個參數定義了矩形的width
和 height
,下面是新建一個Rectangle
對象的格式。
let rectangle = new PIXI.Rectangle(x, y, width, height);
這個矩形對象僅僅是一個 數據對象,如何使用它徹底取決於你。在咱們的例子裏,咱們用它來定義子圖像在雪碧圖中的位置和大小。Pixi的紋理中有一個叫作frame
的頗有用的屬性,它能夠被設置成任何的Rectangle
對象。frame
將紋理映射到Rectangle
的維度。下面是怎麼用frame
來定義火箭的大小和位置。
let rectangle = new Rectangle(192, 128, 64, 64); texture.frame = rectangle;
你如今能夠用它裁切紋理來建立精靈了:
let rocket = new Sprite(texture);
如今成功了! 由於從一個雪碧圖建立精靈的紋理是一個用的很頻繁的操做,Pixi有一個更加合適的方式來幫助你處理這件事情。欲知後事如何,且聽下回分解。
若是你正在處理一個很大的,很複雜的遊戲,你想要找到一種快速有效的方式來從雪碧圖建立精靈。紋理貼圖集 就會顯得頗有用處,一個紋理貼圖集就是一個JSON數據文件,它包含了匹配的PNG雪碧圖的子圖像的大小和位置。若是你使用了紋理貼圖集,那麼想要顯示一個子圖像只須要知道它的名字就好了。你能夠任意的排序你的排版,JSON文件會保持他們的大小和位置不變。這很是方便,由於這意味着圖片的位置和大小沒必要寫在你的代碼裏。若是你想要改變紋理貼圖集的排版,相似增長圖片,修改圖片大小和刪除圖片這些操做,只須要修改那個JSON數據文件就好了,你的遊戲會自動給程序內的全部數據應用新的紋理貼圖集。你不必在全部用到它代碼的地方修改它。
Pixi兼容著名軟件Texture Packer輸出的標準紋理貼圖集格式。Texture Packer的基本功能是免費的。讓咱們來學習怎麼用它來製做一個紋理貼圖集,並把它加載進Pixi吧!(你也不是非得用它,還有一些相似的工具輸出的紋理貼圖集Pixi也是兼容的,例如:Shoebox和spritesheet.js。)
首先,從你要用在遊戲的圖片文件們開始。
在這個章節全部的圖片都是被Lanea Zimmerman創做的。你能在他的藝術工做室裏面找到更多相似的東西:這裏,謝謝你,Lanea!
下面,打開Texture Packer,選擇 JSON Hash 框架類型。把你的圖片放進Texture Packer的工做區。(你也能夠把Texture Packer放進包含你圖片的文件夾裏面去。)他將自動的把你的圖片們生成單個圖片文件,而且將他們的原始名稱命名爲紋理貼圖集中的圖片名稱。
若是你正在用免費版的Texture Packer,把 Algorithm 選項設爲Basic
,把 Trim mode 選項設爲None
,把 Extrude 選項設爲0
,把 Size constraints 選項設爲 Any size
,把 PNG Opt Level 中全部的東西都滑到左邊的 0
位置。這就可使得Texture Packer正常的輸出你的紋理貼圖集。
若是你作完了,點擊 Publish 按鈕。選擇輸出文件名和存儲地址,把生成文件保存起來。你將會得到兩個文件:一個叫作treasureHunter.json
,另一個就是treasureHunter.png
。爲了讓目錄乾淨些,咱們把他倆都放到一個叫作images
的文件夾裏面去。(你能夠認爲那個json文件是圖片文件的延伸,因此把他們放進一個文件夾是頗有意義的。)那個JSON文件裏面寫清楚了每個子圖像的名字,大小和位置。下面描述了「泡泡怪」這個怪物的子圖像的信息。
"blob.png": { "frame": {"x":55,"y":2,"w":32,"h":24}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":24}, "sourceSize": {"w":32,"h":24}, "pivot": {"x":0.5,"y":0.5} },
treasureHunter.json
裏面也包含了「dungeon.png」, 「door.png」, "exit.png", 和 "explorer.png"的數據信息,並以和上面相似的信息記錄。這些子圖像每個都被叫作 幀 ,有了這些數據你就不用去記每個圖片的大小和位置了,你惟一要作的就只是肯定精靈的 幀ID 便可。幀ID就是那些圖片的原始名稱,相似"blob.png"或者 "explorer.png"這樣。
使用紋理貼圖集的巨大優點之一就是你能夠很輕易的給每個圖像增長兩個像素的內邊距。Texture Packer默認這麼作。這對於保護圖像的 出血(譯者:出血是排版和圖片處理方面的專有名詞,指在主要內容周圍留空以便印刷或裁切)來講很重要。出血對於防止兩個圖片相鄰而相互影響來講很重要。這種狀況每每發生於你的GPU渲染某些圖片的時候。把邊上的一兩個像素加上去仍是不要?這對於每個GPU來講都有不一樣的作法。因此對每個圖像空出一兩個像素對於顯示來講是最好的兼容。
(注意:若是你真的在每一個圖像的周圍留了兩個像素的出血,你必須時時刻刻注意Pixi顯示時候「丟了一個像素」的狀況。嘗試着去改變紋理的規模模式來從新計算它。texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST;
,這每每發生於你的GPU浮點運算湊整失敗的時候。)
如今你明白了怎麼建立一個紋理貼圖集,來學習怎麼把他加載進你的遊戲之中吧。
可使用Pixi的loader
來加載紋理貼圖集。若是是用Texture Packer生成的JSON,loader
會自動讀取數據,並對每個幀建立紋理。下面就是怎麼用loader
來加載treasureHunter.json
。當它成功加載,setup
方法將會執行。
loader
.add("images/treasureHunter.json") .load(setup);
如今每個圖像的幀都被加載進Pixi的紋理緩存之中了。你可使用Texture Packer中定義的他們的名字來取用每個紋理。
一般Pixi給你三種方式從已經加載的紋理貼圖集中建立精靈:
TextureCache
:let texture = TextureCache["frameId.png"], sprite = new Sprite(texture);
loader
來加載紋理貼圖集, 使用loader的 resources
:let sprite = new Sprite( resources["images/treasureHunter.json"].textures["frameId.png"] );
textures
對象建立一個叫作id
的別名,象是這樣:let id = PIXI.loader.resources["images/treasureHunter.json"].textures;
如今你就能夠像這樣實例化一個精靈了:
let sprite = new Sprite(id["frameId.png"]);
真不錯啊~!
這裏在setup
函數中用三種不一樣的建立方法建立和顯示了dungeon
, explorer
, 和 treasure
精靈。
//Define variables that might be used in more //than one function let dungeon, explorer, treasure, id; function setup() { //There are 3 ways to make sprites from textures atlas frames //1. Access the `TextureCache` directly let dungeonTexture = TextureCache["dungeon.png"]; dungeon = new Sprite(dungeonTexture); app.stage.addChild(dungeon); //2. Access the texture using throuhg the loader's `resources`: explorer = new Sprite( resources["images/treasureHunter.json"].textures["explorer.png"] ); explorer.x = 68; //Center the explorer vertically explorer.y = app.stage.height / 2 - explorer.height / 2; app.stage.addChild(explorer); //3. Create an optional alias called `id` for all the texture atlas //frame id textures. id = PIXI.loader.resources["images/treasureHunter.json"].textures; //Make the treasure box using the alias treasure = new Sprite(id["treasure.png"]); app.stage.addChild(treasure); //Position the treasure next to the right edge of the canvas treasure.x = app.stage.width - treasure.width - 48; treasure.y = app.stage.height / 2 - treasure.height / 2; app.stage.addChild(treasure); }
這裏是代碼運行的結果:
舞臺定義爲512像素見方的大小,你能夠看到代碼中app.stage.height
和app.stage.width
屬性使得精靈們排成了一排。下面的代碼使得explorer
的y
屬性垂直居中了。
explorer.y = app.stage.height / 2 - explorer.height / 2;
學會使用紋理貼圖集來建立一個精靈是一個基本的操做。因此在咱們繼續以前,你來試着寫一些這樣的精靈吧:blob
們和exit
的門,讓他們看起來象是這樣:
下面就是全部的代碼啦。我也把HTML放了進來,如今你能夠看見全部的上下文。(你能夠在examples/spriteFromTextureAtlas.html
找到能夠用於演示的代碼。)注意,blob
精靈是用一個循環加進舞臺的,而且他有一個隨機的位置。
<!doctype html> <meta charset="utf-8"> <title>Make a sprite from a texture atlas</title> <body> <script src="../pixi/pixi.min.js"></script> <script> //Aliases let Application = PIXI.Application, Container = PIXI.Container, loader = PIXI.loader, resources = PIXI.loader.resources, TextureCache = PIXI.utils.TextureCache, Sprite = PIXI.Sprite, Rectangle = PIXI.Rectangle; //Create a Pixi Application let app = new Application({ width: 512, height: 512, antialias: true, transparent: false, resolution: 1 } ); //Add the canvas that Pixi automatically created for you to the HTML document document.body.appendChild(app.view); //load a JSON file and run the `setup` function when it's done loader .add("images/treasureHunter.json") .load(setup); //Define variables that might be used in more //than one function let dungeon, explorer, treasure, door, id; function setup() { //There are 3 ways to make sprites from textures atlas frames //1. Access the `TextureCache` directly let dungeonTexture = TextureCache["dungeon.png"]; dungeon = new Sprite(dungeonTexture); app.stage.addChild(dungeon); //2. Access the texture using throuhg the loader's `resources`: explorer = new Sprite( resources["images/treasureHunter.json"].textures["explorer.png"] ); explorer.x = 68; //Center the explorer vertically explorer.y = app.stage.height / 2 - explorer.height / 2; app.stage.addChild(explorer); //3. Create an optional alias called `id` for all the texture atlas //frame id textures. id = PIXI.loader.resources["images/treasureHunter.json"].textures; //Make the treasure box using the alias treasure = new Sprite(id["treasure.png"]); app.stage.addChild(treasure); //Position the treasure next to the right edge of the canvas treasure.x = app.stage.width - treasure.width - 48; treasure.y = app.stage.height / 2 - treasure.height / 2; app.stage.addChild(treasure); //Make the exit door door = new Sprite(id["door.png"]); door.position.set(32, 0); app.stage.addChild(door); //Make the blobs let numberOfBlobs = 6, spacing = 48, xOffset = 150; //Make as many blobs as there are `numberOfBlobs` for (let i = 0; i < numberOfBlobs; i++) { //Make a blob let blob = new Sprite(id["blob.png"]); //Space each blob horizontally according to the `spacing` value. //`xOffset` determines the point from the left of the screen //at which the first blob should be added. let x = spacing * i + xOffset; //Give the blob a random y position //(`randomInt` is a custom function - see below) let y =