您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關怎么用pixi.js開發微信小游戲的內容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。
微信小游戲是一個不同于瀏覽器的 JavaScript 運行環境,沒有 BOM 和 DOM API。然而pixi.js是用 JavaScript 結合其他 HTML5 技術來顯示媒體,創建動畫或管理交互式圖像。是依賴瀏覽器提供的 BOM 和 DOM API 的。所以如果要在微信小游戲中使用pixi.js,需要對引擎進行改造。
不過小游戲提供了對大部分 Canvas 2d 和 WebGL 1.0 特性的支持,支持情況參見 RenderingContext,pixi.js它能自動偵測使用WebGL還是Canvas來創建圖形。
無論是怎樣的引擎,最終在游戲運行時所做的大部分事情都是 隨著用戶的交互更新畫面和播放聲音。小游戲的開發語言是 JavaScript,那么在引擎的底層就需要通過 JavaScript 調用繪制 API 和音頻 API。
一段 JavaScript 代碼在運行時可以調用的 API 是依賴于 宿主環境
的。我們最常用的 console.log
甚至都不是 JavaScript 語言核心的一部分,而是瀏覽器這個宿主環境提供的。常見的宿主環境有瀏覽器、Node.js 等。瀏覽器有 BOM 和 DOM API,而 Node.js 則沒有;Node.js 有 fs、net 等 Node.js 核心模塊提供的文件、網絡 API,而瀏覽器則不具備這些模塊。例如,下面這段在瀏覽器中可以正常運行的代碼,在 Node.js 中運行就會報錯。
let canvas = document.createElement('canvas')復制代碼
因為 Node.js 這個宿主環境根本沒有提供 document 這個內置的全局變量。
ReferenceError: document is not defined復制代碼
小游戲的運行環境是一個不同于瀏覽器的宿主環境,沒有提供 BOM 和 DOM API,提供的是 wx API。通過 wx API,開發者可以調用 Native 提供的繪制、音視頻、網絡、文件等能力。
如果你想創建畫布,你需要調用 wx.createCanvas()
let canvas = wx.createCanvas()let context = canvas.getContext('2d')復制代碼
如果你想創建一個音頻對象,你需要調用 wx.createInnerAudioContext()
let audio = wx.createInnerAudioContext()// src 地址僅作演示,并不真實存在audio.src = 'bgm.mp3'audio.play()復制代碼
如果你想獲取屏幕的寬高,你需要調用 wx.getSystemInfoSync()
let { screenWidth, screenHeight } = wx.getSystemInfoSync()復制代碼
但是基于 pixi.js 渲染引擎會通過以下方式去創建stage 并掛載到頁面
document.body.appendChild(app.view);復制代碼
此時會產生錯誤,理由如前文所述,小游戲這個宿主環境根本沒有提供 document 和 window 這兩個在瀏覽器中內置的全局變量。因為小游戲環境是一個不同于瀏覽器的宿主環境。
ReferenceError: document is not definedReferenceError: window is not defined復制代碼
所以,基本上基于pixi.js開發的小游戲,都不能直接遷移到小游戲中使用,因為pixi.js的實現可能或多或少都用到了 BOM 和 DOM 這些瀏覽器環境特有的 API。只有對pixi.js進行改造,將對 BOM 和 DOM API 的調用改成 wx API 的調用,才能運行在小游戲環境中。
但是pixi.js的代碼我們不能改變,也沒辦法直接去修改API的實現,還有一種適配方式,即在渲染引擎和游戲邏輯代碼之間加一層模擬 BOM 和 DOM API 的適配層,我們稱之為 Adapter。這層適配層在全局通過 wx API 模擬了引擎會訪問到的那部分 window 和 document 對象的屬性和方法,使引擎感受不到環境的差異。
Adapter 是用戶代碼,不是基礎庫的一部分。關于 Adapter 的介紹,參見教程 Adapter。
小游戲的運行環境在 iOS 上是 JavaScriptCore,在 Android 上是 V8,都是沒有 BOM 和 DOM 的運行環境,沒有全局的 document 和 window 對象。因此當你希望使用 DOM API 來創建 Canvas 和 Image 等元素的時候,會引發錯誤。
const canvas = document.createElement('canvas')復制代碼
但是我們可以使用 wx.createCanvas 和 wx.createImage 來封裝一個 document。
const document = { createElement: function (tagName) { tagName = tagName.toLowerCase() if (tagName === 'canvas') { return wx.createCanvas() } else if (tagName === 'image') { return wx.createImage() } } }復制代碼
這時代碼就可以像在瀏覽器中創建元素一樣創建 Canvas 和 Image 了。
const canvas = document.createElement('canvas')const image = document.createImage('image')復制代碼
同樣,如果想實現 new Image() 的方式創建 Image 對象,只須添加如下代碼。
function Image () { return wx.createImage() }復制代碼
這些使用 wx API 模擬 BOM 和 DOM 的代碼組成的庫稱之為 Adapter。顧名思義,這是對基于瀏覽器環境的游戲引擎在小游戲運行環境下的一層適配層,使游戲引擎在調用 DOM API 和訪問 DOM 屬性時不會產生錯誤。
Adapter 是一個抽象的代碼層,并不特指某一個適配小游戲的第三方庫,每位開發者都可以根據自己的項目需要實現相應的 Adapter。官方實現了一個 Adapter 名為 weapp-adapter, 并提供了完整的源碼,供開發者使用和參考。
**
Adapter 下載地址 weapp-adapter.zip
weapp-adapter 會預先調用 wx.createCanvas() 創建一個上屏 Canvas,并暴露為一個全局變量 canvas。
require('./weapp-adapter')var context = canvas.getContext('2d') context.fillStyle = 'red'context.fillRect(0, 0, 100, 100)復制代碼
除此之外 weapp-adapter 還模擬了以下對象和方法:
需要強調的是,weapp-adapter 對瀏覽器環境的模擬是遠不完整的,僅僅只針對游戲引擎可能訪問的屬性和調用的方法進行了模擬,也不保證所有游戲引擎都能通過 weapp-adapter 順利無縫接入小游戲。直接將 weapp-adapter 提供給開發者,更多地是作為參考,開發者可以根據需要在 weapp-adapter 的基礎上進行擴展,以適配自己項目使用的游戲引擎。
小游戲基礎庫只提供 wx.createCanvas 和 wx.createImage 等 wx API 以及 setTimeout/setInterval/requestAnimationFrame 等常用的 JS 方法。
window對象是瀏覽器環境下的全局對象。小游戲運行環境中沒有BOM API,因此沒有window對象。但是小游戲提供了全局對象GameGlobal,所有全局定義的變量都是GameGlobal的屬性。
console.log(GameGlobal.setTimeout === setTimeout);console.log(GameGlobal.requestAnimationFrame === requestAnimationFrame);復制代碼
以上代碼執行結果均為true。 開發者可以根據需要把自己封裝的類和函數掛載到GameGlobal上。
GameGlobal.render = function(){ // 具體的方法實現} render();復制代碼
import { canvas } from './canvas'/** * Base Element */export class Element { style = { cursor: null } appendChild() {} removeChild() {} addEventListener() {} removeEventListener() {} }export const HTMLCanvasElement = canvas.constructorexport const HTMLImageElement = wx.createImage().constructorexport class HTMLVideoElement extends Element { }復制代碼
import { Canvas } from './canvas'import Image from './Image'import { Element } from './element'const stack = {}/** * document 適配 */export default { body: new Element('body'), addEventListener(type, handle) { stack[type] = stack[type] || [] stack[type].push(handle) }, removeEventListener(type, handle) { if (stack[type] && stack[type].length) { const i = stack[type].indexOf(handle) i !== -1 && stack[type].splice(i) } }, dispatch(ev) { const queue = stack[ev.type] queue && queue.forEach(handle => handle(ev)) }, createElement(tag) { switch (tag) { case 'canvas': { return new Canvas() } case 'img': { return new Image() } default: { return new Element() } } } }復制代碼
import { noop } from './util'import Image from './Image'import { canvas } from './canvas'import location from './location'import document from './document'import WebSocket from './WebSocket'import navigator from './navigator'import TouchEvent from './TouchEvent'import XMLDocument from './XMLDocument'import localStorage from './localStorage'import XMLHttpRequest from './XMLHttpRequest'import { Element, HTMLCanvasElement, HTMLImageElement, HTMLVideoElement } from './element'const { platform } = wx.getSystemInfoSync() GameGlobal.canvas = canvas // 全局canvascanvas.addEventListener = document.addEventListener canvas.removeEventListener = document.removeEventListener// 模擬器 掛載window上不能修改if (platform === 'devtools') { Object.defineProperties(window, { Image: {value: Image}, Element: {value: Element}, ontouchstart: {value: noop}, WebSocket: {value: WebSocket}, addEventListener: {value: noop}, TouchEvent: {value: TouchEvent}, XMLDocument: {value: XMLDocument}, localStorage: {value: localStorage}, XMLHttpRequest: {value: XMLHttpRequest}, HTMLVideoElement: {value: HTMLVideoElement}, HTMLImageElement: {value: HTMLImageElement}, HTMLCanvasElement: {value: HTMLCanvasElement}, }) // 掛載 document for (const key in document) { const desc = Object.getOwnPropertyDescriptor(window.document, key) if (!desc || desc.configurable) { Object.defineProperty(window.document, key, {value: document[key]}) } } } else { GameGlobal.Image = Image GameGlobal.window = GameGlobal GameGlobal.ontouchstart = noop GameGlobal.document = document GameGlobal.location = location GameGlobal.WebSocket = WebSocket GameGlobal.navigator = navigator GameGlobal.TouchEvent = TouchEvent GameGlobal.addEventListener = noop GameGlobal.XMLDocument = XMLDocument GameGlobal.removeEventListener = noop GameGlobal.localStorage = localStorage GameGlobal.XMLHttpRequest = XMLHttpRequest GameGlobal.HTMLImageElement = HTMLImageElement GameGlobal.HTMLVideoElement = HTMLVideoElement GameGlobal.HTMLCanvasElement = HTMLCanvasElement GameGlobal.WebGLRenderingContext = GameGlobal.WebGLRenderingContext || {} }復制代碼
思路建議為先引入通用的 Adapter 嘗試運行,然后遇到的問題再逐個解決掉。
感謝各位的閱讀!關于怎么用pixi.js開發微信小游戲就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。