# PixiJS基礎 ###### tags: `PixiJS` 2022.07.04(Mon.) ## ● 其他 參考資料:[PixiJS官方教學LearningPixi ](https://github.com/Zainking/learningPixi) 參考資料:[PixiJS v4 官方教學導讀 超入門](https://www.youtube.com/watch?v=CSxI5QGzxZM) 參考資料:[0x vs. hashtag](https://github.com/pixijs/pixijs/issues/458#issuecomment-45177704) 參考資料:[從 React 原始碼看 keyPress 與 keyDown 事件](https://blog.huli.tw/2019/03/24/react-keypress-keydown/) 參考資料:[[JavaScript] 函數原型最實用的 3 個方法 — call、apply、bind](https://realdennis.medium.com/javascript-%E8%81%8A%E8%81%8Acall-apply-bind%E7%9A%84%E5%B7%AE%E7%95%B0%E8%88%87%E7%9B%B8%E4%BC%BC%E4%B9%8B%E8%99%95-2f82a4b4dd66) 參考資料:[[筆記][JavaScript]使用call()、apply()、bind()設定函式中的「this」](https://ithelp.ithome.com.tw/articles/10198035) ## Step 1 將pixi載入 (1)這裡利用[cdn](https://cdnjs.com/libraries/pixi.js)的方式,將pixi載入到html裡面: ```htmlmixed= <script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/6.4.2/browser/pixi.min.js"></script> ``` 照著文件的說明,再來要看看pixi是否有成功載入(這裡利用vs code的live server測試),所以在`<body></body>`中放入以下內容: ```htmlmixed= <script type="text/javascript"> let type = "WebGL" if(!PIXI.utils.isWebGLSupported()){ type = "canvas" } PIXI.utils.sayHello(type) </script> ``` 之後到console查看,如果pixi載入成功,則會在console出現以下畫面: ![](https://i.imgur.com/O51T2W2.png) **** (2)回到上面那段程式碼,來看看他在幹麻 ```javascript= <script type="text/javascript"> let type = "WebGL" if(!PIXI.utils.isWebGLSupported()){ type = "canvas" } PIXI.utils.sayHello(type) </script> ``` 第2列代表我們一開始進來pixi,他是利用「WebGL」這套渲染引擎做渲染的,但不是所有瀏覽器都支援WebGL,所以就要先第3列`PIXI.utils.isWebGLSupported()`這個function來看這個瀏覽器是否支援WebGL,因此如果不支援的話,就會來到第4列,改成利用「canvas」的方式做渲染,最後再利用第6列`PIXI.utils.sayHello(type)`來看出到底用哪種渲染引擎去渲染的。 ## Step 2 開始使用pixi創建舞台(畫布) (1)利用以下程式碼,透過pixi將`<canvas>`在網頁上創建(這些程式碼要記得放在`<script></script>`標籤裡面): ```javascript= //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); ``` 在網頁中會像下面顯示,出現一個黑色的正方形: ![](https://i.imgur.com/YMfvguy.png) 這裡可以看到他在我們網頁中創建的黑色方框是一個`<canvas>`標籤: ![](https://i.imgur.com/1Ur13Na.png) (2)那這時會想是不是可以利用pixi的語法,做到像canvas一樣對圖形做變化呢?可以的!這裡將使用PIXI.Application的參數做到 PIXI.Application的參數使用方法如下: ```javascript= 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官方文件](http://pixijs.download/release/docs/PIXI.Application.html)。 例如說: 1. antialias:抗鋸齒 2. transparent:透明 3. resolution:解析度 (3)如果想改變畫布的大小可以利用resize,不過改變之前要記得將autoResize設置為true,才不會出錯。 ```javascript= app.renderer.autoResize = true; app.renderer.resize(512, 512); ``` 另外也可以利用pixi語法改變css,例如底下的程式碼可以將畫布填滿整個畫面: ```javascript= app.renderer.view.style.position = "absolute"; app.renderer.view.style.display = "block"; app.renderer.autoResize = true; app.renderer.resize(window.innerWidth, window.innerHeight); ``` 不過要記得再添加一行`<style>*{padding: 0,margin: 0}</style>`,將padding跟margin設置為0。 ## step 3 pixi sprite(精靈) (1)在step2中已經學會設置畫布了,再來就是要學怎麼把東西(圖片)丟到這個畫布上面。 在官方文件中有提到「將圖片加載到紋理緩存中」,意思是我們在pixi要渲染這個圖片的時候,必須先把圖片載入完成後,再透過pixi丟出去。 所以先來看看他程式長什麼樣: ```javascript= let texture = PIXI.utils.TextureCache["images/anySpriteImage.png"]; let sprite = new PIXI.Sprite(texture); ``` 第1列:要先用TextureCache(紋理緩存)將圖片給除存起來 第2列:儲存好後,再把他放到sprite這個物件之下,這個sprite物件提供了很多方法(例如說物件的xy、物件的大小等等),這些方法都儲存在sprite物件裡面。 (2)但是加載好之後,然後呢? 這裡將使用pixi中的loder! ```javascript= PIXI.loader .add("images/anyImage.png") .load(setup); function setup() { console.log("ok") } ``` loder前方記得要加上前綴詞"PIXI" 後方`.add`表示要儲存的圖片 `.load`表示加載完成後要執行的function 所以以上程式碼的大意就是,當圖片載入完成後,就會在console印出"ok"。 代表說當我們看到ok出現時,圖片也就成功載入到pixi裡面了。 :::danger 這裡在測試的時候,一直出現「Uncaught TypeError: Cannot read property 'add' of undefined」類似的訊息,不過後來看了[這個網站](https://github.com/pixijs/pixijs/issues/4870),看起來應該是pixi版本的問題,改成4.8.6版本的就沒問題了(原先使用最新版本6.4.2) ::: (3)圖片成功載入到pixi後,再來要看怎麼將圖片丟到畫布上面去 這裡要先創建一個sprite,用來連接loader的resources。 意思是要把loader.resources載入的圖片產生的紋理丟到sprite裡面去。 ```javascript= let sprite = new PIXI.Sprite( PIXI.loader.resources["images/anyImage.png"].texture ); ``` 接著要放到畫布上方來,我的畫布就是個舞台(app.stage) 利用.stage可以抓到整個畫布(或說舞台也可以),然後在這個舞台上addchild()。(加上`app.stage.addChild(bird);`後圖片就能顯示於畫面上了) 所以最後就長成這樣: ```javascript= let app = new PIXI.Application({ width: 256, height: 256 }); document.body.appendChild(app.view); PIXI.loader .add("bird.png") .load(setup); function setup() { let bird = new PIXI.Sprite( PIXI.loader.resources["bird.png"].texture ) app.stage.addChild(bird); } ``` (4)如果想移開圖片的話,有兩種方法把圖片從畫布中消失:(這兩種方法雖然都是將圖片弄不見,但是方法是有差異的) 第1種:完全從畫布中移除 ```javascript= app.stage.removeChild(anySprite) ``` 第2種:只是將圖片隱藏,但圖片還是在畫布上。 ```javascript= anySprite.visible = false ``` 所以可以依照不同情況使用不同方法將圖片消失。 ## Step 4 使用別名 因為前綴詞加起來實在太長,所以文件建議我們可以把一些常用的用變數的方法給存起來。 舉例來說: ```javascript= let Application = PIXI.Application, loader = PIXI.loader, resources = PIXI.loader.resources, Sprite = PIXI.Sprite; ``` ## Step 5 監視加載進程 有一個叫做progress的事件,progress事件可以透過.loader的.on來使用: ```javascript= PIXI.loader.on("progress", loadProgressHandler); ``` loadProgressHandler是我們可以隨意定義的函數名稱 (這裡就先用loadProgressHandler來命名) 每次加載時就會呼叫一次loadProgressHandler這個函數。 ```javascript= 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 + "%"); } ``` 我們可以在loadProgressHandler這個函數中增加兩個參數, 分別為loader跟resource。 可以用在圖片還沒載入時,秀出loading的畫面。 ## Step 6 Sprite的位置 用`.x`以及`.y`來表示位置,起始點在左上角。 以下圖為例,他的程式碼如下: ```javascript= cat.x = 96; cat.y = 96; ``` ![](https://i.imgur.com/106bzgi.png) 位置也有另外的表示方法:(sprite依照我們對他命名而有所不同) ```javascript= sprite.position.set(x, y) ``` ## Step 6 大小和比例 ```javascript= //大小 cat.width = 80; cat.height = 120; //比例 //放大2倍 cat.scale.x = 2; cat.scale.y = 2; //縮小2倍 cat.scale.x = 0.5; cat.scale.y = 0.5; //一行完成,一樣用到.set() cat.scale.set(0.5, 0.5); ``` ## Step 7 旋轉 會順時針做旋轉,整個轉一圈就會是1,所以轉一半就是0.5 現在的旋轉都是以左上角為中心做旋轉 ```javascript= cat.rotation = 0.5 ``` 再來的旋轉是會調整中心點做旋轉,將中心點的位置改變 ```javascript= cat.anchor.x = 0.5; cat.anchor.y = 0.5; ``` 如上,他的中心點就會移到圖片的正中心。 ## Step 8 移動Sprite(精靈) 從step 3得知怎麼將圖片丟到舞台上之後,這個步驟則是學習怎麼[移動那張圖片](https://github.com/Zainking/learningPixi#movingsprites)。 移動圖片的方式是使用了pixi中的ticker,ticker就是每秒多少次的去執行你的function。 ```javascript= app.ticker.add(delta =>{ cat.x += 1; }) ``` 以上方程式碼為例,就可以讓cat這張圖片以每幀1像素去移動。 另外一種移動方法是直接使用pixi的`.vx`以及`.vy`。 一樣要先將圖片放入sprite: ```javascript= let cat = new PIXI.Sprite(resources["cat.png"].texture); app.stage.addChild(cat) cat.vx = 1; cat.vy = 1; ``` 以上程式碼會使cat這張圖片每幀往右1px以及每幀往下1px。 ## Step 9 給Sprite分組 先創建好圖片,以及一個群組容器(這裡叫做animals): ```javascript= let cat = new PIXI.Sprite(resources["cat.png"].texture); let cow = new PIXI.Sprite(resources["cow.png"].texture); let bird = new PIXI.Sprite(resources["bird.png"].texture); let animals = new PIXI.Container(); ``` 創建好之後,把圖片先加到animals群組中: ```javascript= animals.addChild(cat); animals.addChild(cow); animals.addChild(bird); ``` 加到群組之後,再把群組加到畫布(舞台)上: ```javascript= app.stage.addChild(animals); ``` ## Step 10 局部位置/全局位置 分組之後就會需要區分局部位置以及全局位置 以step 9的程式碼為例,裡面的cat、cow、bird的位置會變成是相對於animals這個群組,這個位置稱作局部位置。 但如果想找到相對於整個畫布(舞台)的相對位置的話,就要找全局位置: ```javascript= parentSprite.toGlobal(childSprite.position); ``` ```javascript= cat.getGlobalPosition().x; cat.getGlobalPosition().y; ``` ## Step 11 碰撞偵測 在pixi裡面做碰撞偵測可以利用hitTestRectangle,可以在hitTestRectangle函數中丟進2個參數,去偵測這個參數是否產生碰撞(基本上參數就是丟到舞台上的圖片)。 如果他們兩重疊,hitTestRectangle就會回傳true;如果他們兩沒有重疊,hitTestRectangle就會回傳false ```javascript= if (hitTestRectangle(cat, box)) { console.log(重疊了); } else { console.log(沒有重疊); } ```