# 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出現以下畫面:

****
(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);
```
在網頁中會像下面顯示,出現一個黑色的正方形:

這裡可以看到他在我們網頁中創建的黑色方框是一個`<canvas>`標籤:

(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;
```

位置也有另外的表示方法:(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(沒有重疊);
}
```