小精靈冒險 是 Learn Pixi.js 一書中最後一個案例。點擊屏幕讓小精靈飛起來,小精靈上升時,會拍打翅膀,而且會有小星星產生。若是她撞到柱子上,她會爆炸成一堆小星星。幫助她經過15個柱子的間隙到達終點,界面會顯示一個巨大 Finish
標誌。html
試玩一下 spring
下載源碼segmentfault
下來讓咱們看看怎麼製做這個遊戲的吧!數組
還記得 學習 PixiJS — 視覺效果 一文中提到的視差效果嗎?小精靈冒險的背景是使用視差效果作的,也就是背景比前景移動的速度慢一些,使得背景看上去好像距離更遠。 dom
爲了製做天空背景,咱們使用無縫的512 x 512的雲圖像。圖像是紋理貼圖集中的一幀,名爲 clouds.png,以下圖所示。
函數
在程序的 setup
函數中,使用 clouds.png 幀建立一個名爲 sky
的平鋪精靈 。工具
sky = new TilingSprite( id["clouds.png"], renderer.view.width, renderer.view.height ); stage.addChild(sky);
在遊戲循環中,經過減少平鋪精靈( sky
) 的 tilePosition.x
值,使其向左移動。學習
sky.tilePosition.x -= 1;
這樣就實現了背景的無限滾動了!動畫
遊戲中有15根柱子,想要通關,小精靈必須經過這些柱子。每5根柱子,頂部和底部之間的間隙會變得更窄。前5個柱子有四塊的間隙,接下來的5根柱子有三塊的間隙,後5根柱子有兩塊的間隙。隨着小精靈飛得更遠,遊戲也變得愈來愈困難。每根柱子的間隙的確切位置是隨機的,而且每次玩遊戲時都是不一樣的。而每一個柱子與柱子間隔384像素,下圖顯示了它們彼此相鄰時的樣子。spa
每根柱子的頂部和底部之間的間隙逐漸變窄,你能夠看到間隙從左側的四塊空間逐漸變窄到右側的兩塊空間。
構成柱子的全部塊都在一個名爲 blocks
的容器中。
blocks = new Container(); stage.addChild(blocks);
建立15根柱子須要兩層 for 循環,外層循環運行15次,一次建立一根柱子。內層循環運行8次,每次都會判斷是否要在柱子上加入1個綠色塊。不過只有在不是隨機間隙範圍內時,纔會添加綠色塊。外層循環每運行5次,柱子與柱子的間隙的大小就會縮小1。
//柱子之間的初始間隙 let gapSize = 4; //柱子的數量 let numberOfPillars = 15; //循環15次,造成15根柱子 for (let i = 0; i < numberOfPillars; i++) { //隨機肯定單個柱子的間隙 let startGapNumber = randomInt(0, 8 - gapSize); //每隔五根柱子就減小一個間隙 if (i > 0 && i % 5 === 0) gapSize -= 1; //若是不在柱子的間隙內,就建立一個塊放入柱子 for (let j = 0; j < 8; j++) { if (j < startGapNumber || j > startGapNumber + gapSize - 1) { let block = u.sprite(id["greenBlock.png"]); blocks.addChild(block); //每根柱子之間間隔384像素,第一根柱子的x位置爲512 block.x = (i * 384) + 512; block.y = j * 64; } } //建立柱子以後,在添加finish圖像 if (i === numberOfPillars - 1) { finish = u.sprite(id["finish.png"]); blocks.addChild(finish); finish.x = (i * 384) + 896; finish.y = 192; } }
代碼的最後一部分將 finish
精靈添加到 blocks
容器中,blocks
容器最後會添加到舞臺上,小精靈若是能堅持到最後,就能看見它。
若是 finish
精靈位於屏幕外時,每次遊戲循環在play
函數中都會將 blocks
容器向左移動2像素。
if (finish.getGlobalPosition().x > 256) { blocks.x -= 2; }
當 finish
精靈滾動到畫布的中心時, blocks
容器將中止移動。要注意,代碼使用 finish
精靈的全局座標的 x
位置來檢測它是否在畫布區域內。由於全局座標是相對於畫布而不是父容器,因此它們對於在畫布上找到嵌套精靈的位置很是有用。
在 學習 PixiJS — 動畫精靈 一文中提到了怎麼製做動畫精靈。
小精靈角色就是使用紋理貼圖集中的3個幀製做的動畫精靈。每一個幀都是小精靈拍打翅膀動畫中的一個圖像。
如下是 setup
函數中建立小精靈角色的代碼。
let pixieFrames = [ id["0.png"], id["1.png"], id["2.png"] ]; pixie = u.sprite(pixieFrames); stage.addChild(pixie); pixie.fps = 24; pixie.position.set(232, 32); pixie.vy = 0; pixie.oldVy = 0;
你能夠看到前面的代碼使用了 SpriteUtilities
庫中的 sprite
方法。這個方法能夠簡化建立精靈的步驟。
小精靈有了一個新的屬性,叫作 oldVy
, 它用來幫助咱們計算小精靈的垂直速度(vy)。
在 play
函數中,小精靈的垂直速度(vy)在每幀上都會減去0.05
,使小精靈下落。
pixie.vy -= 0.05; pixie.y -= pixie.vy;
玩家能夠經過點擊畫布上的任何位置來讓小精靈飛行。這是經過爲指針對象指定 tap
方法來完成的,指針對象在 學習 PixiJS — 交互工具 這篇文章中已經講的很清楚了。每次點擊都會使小精靈的垂直速度(vy)增長1.5
,將她向上推。如下是 setup
函數中的代碼,它生成指針對象並指定 tap
方法。
pointer = t.makePointer(); pointer.tap = () => { pixie.vy += 1.5; };
產生的小星星就是在 學習 PixiJS — 粒子效果 一文只提到的粒子。
當小精靈拍打翅膀時,會產生一些五彩的小星星。小星星的產生會約束在2.4到3.6之間的角度,所以它們會被髮射到小精靈左側的錐形內,以下圖所示。
產生的小星星多是紫色,粉紅色,綠色,或黃色,每一個小星星都是單獨的一個幀。
正如 學習 PixiJS — 粒子效果 一文中使用的 粒子效果庫(Dust
),有一個 create
方法,若是一個精靈包含多個幀,它將在精靈上隨機顯示一個幀。使用這個方法,首先要定義要用於製做粒子的紋理圖集幀數組。
dustFrames = [ id["pink.png"], id["yellow.png"], id["green.png"], id["violet.png"] ];
接下來,將這個數組做爲參數傳給 create
方法,而後再把 create
方法當作參數傳給粒子發射器方法(emitter
),如下是關鍵代碼:
//建立一個Dust實例 d = new Dust(PIXI); //建立粒子發射器 particleStream = d.emitter( 300, //時間間隔 () => d.create( pixie.x + 8, //x 座標 pixie.y + pixie.height / 2, //y 座標 () => u.sprite(dustFrames), //粒子精靈 stage, //父容器 3, //粒子數 0, //重力 true, //隨機間隔 2.4, 3.6, //最小,最大角度 18, 24, //最小,最大尺寸 2, 3, //最小,最大速度 0.005, 0.01, //最小,最大比例速度 0.005, 0.01, //最小,最大alpha速度 0.05, 0.1 //最小,最大旋轉速度 ) );
如今就有一個名爲 particleStream
的粒子發射器。只需調用其 play
方法就能夠開始發射粒子,產生小星星了。
particleStream.play();
當小精靈上升時,她會拍打翅膀,產生五彩的小星星。當她下落時,她中止拍打翅膀,而且中止產生小星星,但咱們怎麼知道她是向上仍是向下飛行呢?
咱們必須找到當前幀和前一幀之間的速度差別。若是她當前的速度大於她之前的速度,她就會上升。若是小於,而且當前速度小於零,那麼她就會下落。代碼將當前幀中的小精靈的 vy
值存儲在 oldVy
屬性中。在下一次遊戲循環時,經過比較這兩個屬性就能夠知道是上升仍是下落了。如下是關鍵代碼:
//若是她上升,則拍打翅膀併產生五彩的小星星 if (pixie.vy > pixie.oldVy) { if (!pixie.animating) { pixie.playAnimation(); if (pixie.visible && !particleStream.playing) { particleStream.play(); } } } //若是她往下落,中止拍打翅膀,展現第一幀,並中止產生五彩的小星星 if (pixie.vy < 0 && pixie.oldVy > 0) { if (pixie.animating) pixie.stopAnimation(); pixie.show(0); if (particleStream.playing) particleStream.stop(); } //存儲小精靈的當前vy值,以便咱們能夠在下一幀中使用它來肯定小精靈是否改變了方向 pixie.oldVy = pixie.vy;
當小精靈撞到柱子時,她會爆炸成一堆小星星,以下圖所示。
實現這個效果須要使用 學習 PixiJS — 碰撞檢測 一文中提到的 Bump
庫中的 hitTestRectangle
方法。在代碼中遍歷 blocks.children
數組,檢測每一個塊和小精靈之間的碰撞。若是 hitTestRectangle
方法返回 true
,則退出循環,表示小精靈碰撞到柱子了。
//小精靈碰撞到柱子時,pixieVsBlock 爲 true let pixieVsBlock = blocks.children.some(block => { return b.hitTestRectangle(pixie, block, true); });
使用 some
循環,一旦找到一個等於 true
的值,循環就會退出,這樣能夠避免多餘的檢測。
小精靈是 舞臺(stage
) 的子級,但每一個 block
都是 blocks
容器的子級,這意味着它們不使用相同的局部座標。因此 hitTestRectangle
方法的第三個參數必須爲 true
,以便強制 hitTestRectangle
方法使用全局座標進行碰撞檢測。
若是 pixieVsBlock
爲 true
,而且當前小精靈可見,則運行小精靈爆炸成一堆小星星的代碼。它使小精靈變的不可見,併產生粒子爆炸效果,並且在延遲3秒後調用遊戲的 reset
函數,重置遊戲。如下是在 play
函數中的代碼:
if (pixieVsBlock && pixie.visible) { //讓小精靈變得不可見 pixie.visible = false; //製做爆炸小星星效果 d.create( pixie.centerX, pixie.centerY, //x 和 y 座標 () => u.sprite(dustFrames), //粒子精靈 stage, //父容器 20, //粒子數 0, //重力 false, //隨機間隔 0, 6.28, //最小角度,最大角度 16, 32, //最小尺寸,最大尺寸 1, 3 //最小速度,最大速度 ); //中止粒子發射器 particleStream.stop(); //等待3秒,而後重置遊戲 wait(3000).then(() => reset()); }
學習 PixiJS — 補間動畫 這篇文章中介紹了 wait
函數 。
若是小精靈碰撞到柱子,則在3秒鐘延遲後重置遊戲。遊戲的 reset
函數經過將小精靈和塊從新定位到其初始位置,並使小精靈再次可見來實現此功能。
function reset() { pixie.visible = true; pixie.y = 32; particleStream.play(); blocks.x = 0; }
以上就是如何實現 小精靈冒險 這個遊戲的所有了,遊戲中須要的各類東西,在前面幾篇文章中都有提到。若是遇到什麼不明白的東西,能夠看看前面的幾篇文章。
而這個小遊戲還有許多小細節能夠去實現,好比增長玩家的分數,增長開始遊戲的按鈕,增長一些場景過渡,增長音效 等等,這些你均可以嘗試本身實現下。