Pixi.js

PixiJS是一個(gè)2D渲染引擎,能自動(dòng)偵測(cè)并使用WebGL或Canvas稽寒。

PixiJS使用JavaScript或HTML5基礎(chǔ)來(lái)顯示媒體扮碧,創(chuàng)建動(dòng)畫或管理交互式圖像,從而制作游戲或應(yīng)用。

PixiJS適合制作游戲但并非是游戲引擎慎王,其核心本質(zhì)是盡可能快速有效地在屏幕上移動(dòng)物體蚓土。

PixiJS作為JavaScript的2D渲染器,目標(biāo)是提供快速輕量且兼容所有設(shè)備的2D庫(kù)赖淤。提供無(wú)縫Canvas回退蜀漆、支持主流瀏覽器,包括桌面和移動(dòng)設(shè)備咱旱。

PIXI只做三件事

  • Loading and displaying of assets
  • interactivity
  • game loop

安裝測(cè)試

$ npm i pixi.js

引入

import * as PIXI from "pixi.js";
  • 開(kāi)發(fā)工具 Vistual Code
  • Web服務(wù)器插件 Live Server
  • Chrome調(diào)試工具 PixiJS devtools

測(cè)試

判斷當(dāng)前瀏覽器渲染引擎類型

$ vim index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.bootcss.com/pixi.js/5.2.1/pixi.min.js"></script>
</head>
<body>
    <script>
        //判斷瀏覽器渲染引擎
        const type = PIXI.utils.isWebGLSupported() ? "WebGL" : "canvas";
        //console.log(type);//WebGL
        PIXI.utils.sayHello(type);//PixiJS 5.2.1 - WebGL - http://www.pixijs.com/
    </script>
</body>
</html>

判斷代碼

//判斷瀏覽器渲染引擎
const type = PIXI.utils.isWebGLSupported() ? "WebGL" : "canvas";
//console.log(type);//WebGL
PIXI.utils.sayHello(type);//PixiJS 5.2.1 - WebGL - http://www.pixijs.com/

概念

使用PIXI的基本流程通常分為以下幾步

  1. 創(chuàng)建舞臺(tái)
  2. 創(chuàng)建畫布
  3. 將畫布添加到DOM
  4. 創(chuàng)建精靈
  5. 將精靈添加到畫布
  6. 將畫布添加舞臺(tái)
  7. 定時(shí)刷新舞臺(tái)

PIXI常用模塊包括

  • Application 應(yīng)用
  • Container 容器
  • Stage 舞臺(tái)
  • Renderer 渲染器
  • Ticker 計(jì)時(shí)器
  • Loader 加載器

舞臺(tái)stage

  • 所有需要渲染的對(duì)象都必須添加到舞臺(tái)中才能被顯示出來(lái)
  • 舞臺(tái)處于整個(gè)樹(shù)形展示結(jié)構(gòu)的對(duì)底層可理解為背景

畫布renderer

畫布是指使用WebGL或Canvas繪圖引擎進(jìn)行渲染的一塊區(qū)域

紋理texture

紋理可理解為承載圖片的結(jié)構(gòu)确丢,紋理本身不能直接用于顯示,需要通過(guò)精靈才能顯示莽龟,類似DOM中的臨時(shí)碎片蠕嫁。

精靈sprite

精靈是可以直接用于舞臺(tái)顯示的對(duì)象锨天,可理解為DOM中的元素毯盈。精靈可直接食用圖片創(chuàng)建,也可以先創(chuàng)建紋理在使用紋理創(chuàng)建精靈病袄。

事件event

事件用于交互

應(yīng)用PIXI.Application

PIXI擁有一個(gè)Pixi應(yīng)用對(duì)象PIXI.Application搂赋,可自動(dòng)創(chuàng)建一個(gè)canvas標(biāo)簽,用于計(jì)算圖片在其中的顯示益缠。PIXI.Application會(huì)自動(dòng)創(chuàng)建渲染器脑奠、計(jì)時(shí)器和根容器。

const app = new PIXI.Application(options);

PIXI.Application建立的同時(shí)會(huì)自動(dòng)建立render幅慌、ticker宋欺、root container。

const app = new PIXI.Application({width:400, height:300, view:document.querySelector("canvas")});
  • app.renderer 渲染器胰伍,優(yōu)先使用WebGL渲染若不支持則使用Canvas渲染齿诞。
  • app.ticker 渲染的更新頻率,計(jì)時(shí)器骂租。
  • app.stage 根容器

例如:創(chuàng)建可顯示圖片的矩形顯示區(qū)域

//創(chuàng)建一個(gè)Pixi應(yīng)用
const app = new PIXI.Application({width:400, height:300});
//pixi自動(dòng)創(chuàng)建canvas標(biāo)簽并添加到document文檔中
document.body.appendChild(app.view);

自動(dòng)創(chuàng)建canvas標(biāo)簽

<canvas width="400" height="300" style="touch-action: none; cursor: inherit;"></canvas>

使用PIXI.Application創(chuàng)建的pixi應(yīng)用計(jì)算并選擇渲染引擎祷杈,這取決于瀏覽器自身所支持的渲染引擎的類型。創(chuàng)建pixi應(yīng)用時(shí)需傳入options選項(xiàng)對(duì)象參數(shù)渗饮,options對(duì)象中可設(shè)置pixi應(yīng)用的寬高但汞、透明等屬性。若options對(duì)象中未設(shè)置view屬性互站,則會(huì)自動(dòng)創(chuàng)建一個(gè)canvas元素私蕾,創(chuàng)建出來(lái)的canvas元素就在pixi應(yīng)用的view屬性中。也可以使用view屬性手動(dòng)指定胡桃。

const app = new PIXI.Application({width:400, height:300, view:document.querySelector("canvas")});
document.body.appendChild(app.view);
選項(xiàng) 類型 默認(rèn)值 描述
width number 800 渲染器視寬度
height number 600 渲染視圖高度
view HTMLCanvasElement - 使用canvas作為視圖
transparent boolean false 視圖是否透明
resolution number 1 分辨率踩叭,渲染器設(shè)備像素比,R屏默認(rèn)為2.
antialias boolean false 是否平滑抗鋸齒标捺,取消字體平滑懊纳,抗混疊揉抵。
forceCanvas boolean false 是否強(qiáng)制使用canvas渲染模式,默認(rèn)使用WebGL嗤疯。
  • antialias可使字體的邊界和集合界面更為圓滑冤今,WebGL的anti-aliasing在所有平臺(tái)都不可用。
  • transparent會(huì)將整個(gè)canvas標(biāo)簽的透明度進(jìn)行設(shè)置
  • resolution會(huì)使pixi在不同分辨率和像素密度的設(shè)備上顯示正常
  • pixi的canvas畫布對(duì)象將會(huì)默認(rèn)選擇WebGL引擎渲染模式茂缚,若需使用canvas引擎繪制可設(shè)置 forceCanvas饮怯。

適配分辨率

pixi會(huì)自動(dòng)調(diào)整像素密度以匹配運(yùn)行內(nèi)容的設(shè)備的分辨率,開(kāi)發(fā)人員所要做的是為高分辨率和低分辨率提供不同的圖像靖诗。pixi將幫助你根據(jù)當(dāng)前的設(shè)備像素比devicePixelRatio選擇對(duì)應(yīng)的圖像芦拿。當(dāng)創(chuàng)建高分辨率圖像時(shí),可以將@2x添加到圖像文件名稱后悔耘,以說(shuō)明圖像是支持高分辨率的屏幕讲岁,例如Retina屏幕。

獲取當(dāng)前設(shè)備設(shè)備像素比衬以,dpr是一個(gè)描述設(shè)備像素比的數(shù)字缓艳,由運(yùn)行應(yīng)用程序的設(shè)備自動(dòng)提供,其中1表示為標(biāo)準(zhǔn)分辨率看峻,2表示高密度分辨率阶淘,3表示超高密度顯示器。

const dpr= window.devicePixelRatio;
const width = window.innerWidth;
const height = window.innerHeight;
const resolution = window.devicePixelRatio;
let app = new Application({width:width, height:height, resolution:resolution, transparent:true, antialias:true});
document.body.appendChild(app.view);

pixi應(yīng)用對(duì)象的成員

成員 類型 描述
app.loader PIXI.Loader 加載器實(shí)例用于資源加載互妓,用于加載靜態(tài)資源溪窒。
app.renderer PIXI.Renderer|PIXI.CanvasRenderer WebGL渲染器,可使用CanvasRenderer冯勉。
app.resizeTo Window|HTMLElement 元素或窗口尺寸更改
app.screen PIXI.Rentangle 渲染器的屏幕矩形對(duì)象
app.stage PIXI.Container 根顯示容器澈蚌,舞臺(tái),pixi創(chuàng)建的根容器珠闰。游戲中的精靈或容器都要添加到舞臺(tái)上才能顯示惜浅。
app.ticker PIXI.Ticker 計(jì)時(shí)器,可理解為每次渲染一幀前執(zhí)行伏嗜。
app.view HTMLCanvasElement 渲染器的canvas元素坛悉,pixi創(chuàng)建的DOM元素即用于渲染游戲的canvas。

修改canvas標(biāo)簽背景色

app.renderer.backgroundColor = 0xff0000;

獲取畫布的寬度和高度

console.log(app.renderer.view.width);//400
console.log(app.renderer.view.height);//300

重新設(shè)置畫布的canvas寬高尺寸

app.renderer.autoResize = true;
app.renderer.resize(512, 512);
console.log(app.renderer.view.width);//512
console.log(app.renderer.view.height);//512

設(shè)置canvas占滿整個(gè)窗口承绸,需配置CSS重置padding和margin為0裸影。

*{padding:0;margin:0;}
app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.autoResize = true;
app.renderer.resize(window.innerWidth, window.innerHeight);

渲染器app.renderer

獲取當(dāng)前應(yīng)用渲染器的類型

const rendererType = app.renderer.type;
const rendererType = PIXI.RENDERER_TYPE;
渲染模式 取值
UNKNOWN 0
WEBGL 1
CANVAS 2

渲染器選項(xiàng)參數(shù)

名稱 類型 默認(rèn)值 描述
width number 800 屏幕寬度
height number 600 屏幕長(zhǎng)度
view HTMLCanvasElement - canvas渲染模式需使用的視圖與選項(xiàng)
transparent boolean false 渲染器視圖是否透明

容器 PIXI.Container()

容器是用來(lái)轉(zhuǎn)載多個(gè)顯示對(duì)象的,創(chuàng)建的Pixi應(yīng)用的stage屬性本質(zhì)上就是一個(gè)容器對(duì)象军熏,stage對(duì)象被當(dāng)作根容器使用轩猩,它將包裹所有想用Pixi顯示的元素。

let container = new PIXI.Container();
container.addChild(sprite);

自定義的Container通常用來(lái)做分組使用,分組的好處在于修改Container的屬性均践,位于其中的子節(jié)點(diǎn)都會(huì)受到影響晤锹。

常見(jiàn)的作法是創(chuàng)建一個(gè)最頂層的rootContainer,之后所有的內(nèi)容都添加到rootContainer中彤委,rootContainer作為頂級(jí)元素可進(jìn)行縮放來(lái)適配不同的分辨率鞭铆。

Container與Sprite有何異同

  • Container表示顯示對(duì)象的集合,是作為其他對(duì)象的容器焦影,是所有顯示對(duì)象的基類车遂。
  • Container是用來(lái)轉(zhuǎn)載多個(gè)顯示對(duì)象,也包括自身Container斯辰。
  • Sprite表示基于紋理對(duì)象存在舶担,是能將紋理顯示到舞臺(tái)的顯示對(duì)象。
  • Container和Sprite的繼承關(guān)系是PIXI.Sprite繼承自PIXI.Container彬呻。

Sprite是繼承自Container的衣陶,Container又是繼承自什么對(duì)象呢?

Container繼承自DisplayObject废岂,DisplayObject是最基本的顯示對(duì)象祖搓。

PIXI.Sprite -> PIXI.Container -> PIXI.DisplayObject

Sprite和Container共享DisplayObject的函數(shù)和方法

顯示對(duì)象 PIXI.DisplayObject

  • DisplayObject是所有渲染到屏幕上的對(duì)象的基類
  • DisplayObject是一個(gè)抽象類
成員屬性 類型 描述
x number X軸坐標(biāo)值
y number Y軸坐標(biāo)值
position PIXI.Point / PIXI.ObservablePoint 位移坐標(biāo)
alpha number 透明度
visible boolean 顯示隱藏
rotation number 旋轉(zhuǎn)角度
angle number 旋轉(zhuǎn)角度
scale PIXI.Point / PIXI.ObservablePoint 縮放值
skew PIXI.ObsevablePoint 斜切值
transform PIXI.TransformBase 矩陣對(duì)象
cacheAsBitmap boolean 是否將顯示對(duì)象轉(zhuǎn)換為位圖
renderable boolean 是否能被渲染到舞臺(tái)

舞臺(tái)app.stage

創(chuàng)建pixi應(yīng)用對(duì)象并添加到document中后就有了一個(gè)畫布狱意,要在畫布上顯示東西就必須加入到一個(gè)稱為舞臺(tái)的pixi對(duì)象pixi.stage湖苞。

app.stage是一個(gè)Container的實(shí)例,作為最底層的舞臺(tái)详囤,所有需要渲染的圖形都應(yīng)放到stage的內(nèi)部财骨。

pixi.stage舞臺(tái)是一個(gè)pixi容器對(duì)象,可理解為將放入的東西分組并存儲(chǔ)的空箱子藏姐。stage舞臺(tái)對(duì)象是在場(chǎng)景總所有可見(jiàn)對(duì)象的根容器隆箩。所有放入到舞臺(tái)的東西都會(huì)被渲染到canvas中。

stage對(duì)象是Container容器羔杨,是所有Sprite精靈的根容器捌臊。

stage舞臺(tái)對(duì)象是pixi容器對(duì)象,所有的容器對(duì)象都具有相同的屬性和方法兜材。盡管stage舞臺(tái)擁有width和height屬性理澎,但不能查看畫圖窗口的大小。stage舞臺(tái)的width和height屬性僅僅告訴放入東西占用的大小曙寡。

舞臺(tái)內(nèi)科放入什么東西呢糠爬?是稱作精靈的特殊圖像對(duì)象。精靈是能夠使用代碼控制的圖像举庶,可以控制它的位置执隧、大小等屬性來(lái)產(chǎn)生交互和動(dòng)畫。

坐標(biāo)

  • 絕對(duì)坐標(biāo)global是以舞臺(tái)stage為基準(zhǔn)的坐標(biāo)系,精靈相對(duì)于舞臺(tái)的位置和方向镀琉。
  • 相對(duì)坐標(biāo)local是以舞臺(tái)stage中某個(gè)容器container為基準(zhǔn)的坐標(biāo)系峦嗤,一般是精靈的父容器。

Pixi提供了兩個(gè)函數(shù)用于坐標(biāo)變換

  • toGlobal 相對(duì)坐標(biāo)轉(zhuǎn)換為絕對(duì)坐標(biāo)
  • toLocal 絕對(duì)坐標(biāo)轉(zhuǎn)換為相對(duì)坐標(biāo)

無(wú)論是容器還是精靈的坐標(biāo)以及方向都是相對(duì)于父容器的坐標(biāo)系的屋摔,坐標(biāo)原點(diǎn)默認(rèn)是容器的左上角寻仗,可改變?nèi)萜鞯淖鴺?biāo)原點(diǎn)anchor

加載 PIXI.Loader

將圖片加載到紋理緩存凡壤,因?yàn)閜ixi使用WebGL和GPU渲染圖像署尤,所以圖像需轉(zhuǎn)化成GPU可以處理的格式⊙窍溃可以被GPU處理的圖像稱為紋理Texture曹体。使用精靈顯示圖片之前,需將圖片轉(zhuǎn)化成WebGL紋理硝烂,pixi使用紋理緩存存儲(chǔ)和應(yīng)用精靈所需的紋理箕别。紋理的名字是圖像的地址。

從紋理緩存中獲取圖片

PIXI.utils.TextureCache["images/cat.png"];

紋理被以WebGL兼容的格式存儲(chǔ)起來(lái)滞谢,可使Pixi渲染更加高效串稀。

例如:從紋理緩存中獲取圖片并轉(zhuǎn)化為紋理

//將圖像加載到紋理緩存
let texture = PIXI.utils.TextureCache["images/avatar.jpg"];
//使用紋理創(chuàng)建精靈
let sprite = new PIXI.Sprite(texture);

如何加載圖像并將其轉(zhuǎn)化為紋理呢?可使用pixi的Loader對(duì)象狮杨,pixi的Loader對(duì)象可加載任何種類的圖像資源母截,使用load方法加載圖像完成時(shí)可使用回調(diào)方法使用它。

const imgpath = "images/avatar.jpg";
PIXI.loader.add(imgpath).load(function(){
    let texture = PIXI.loader.resources[imgpath].texture;
    let sprite = new PIXI.Sprite(texture);
    app.stage.addChild(sprite);
});

紋理 PIXI.Texture

PixiJS使用WebGL或Canvas渲染圖像橄教,所以圖像需要轉(zhuǎn)化成GPU能夠處理的格式清寇,可以被GPU處理的圖像被稱為紋理Texture。比如护蝶,當(dāng)讓精靈顯示圖片之前华烟,需要將普通的圖片轉(zhuǎn)化成WebGL紋理。為了讓工作執(zhí)行的快速有效率持灰,PixiJS使用紋理緩存來(lái)存儲(chǔ)和應(yīng)用精靈所需的紋理盔夜。紋理的名稱也就是圖像的地址。

紋理存儲(chǔ)著圖像或圖像的部分信息堤魁,圖像是不能直接添加到顯示列表中喂链,必須將圖像轉(zhuǎn)化為精靈的紋理。

從圖片獲取紋理

const texture = PIXI.Texture.from(imgPath);

游戲是一種很耗資源的應(yīng)用姨涡,特別是在移動(dòng)設(shè)備中的游戲衩藤。紋理圖集(Texture Atlas)又稱為精靈表(Sprite Sheet)是將許多小的精靈圖片組合到一張大圖中。

精靈 PIXI.Sprite

PIXI的核心是Sprite涛漂,PIXI.Sprite繼承自PIXI.Container赏表,PIXI.Container繼承自PIXI.DisplayObject检诗。

Sprite對(duì)象是渲染到屏幕的所有紋理對(duì)象的基礎(chǔ),它能輕松的改變紋理瓢剿。

Sprite默認(rèn)是不會(huì)響應(yīng)點(diǎn)擊等事件的逢慌,必須需要Interactive。

pixi擁有一個(gè)sprite精靈類用來(lái)創(chuàng)建游戲精靈间狂,創(chuàng)建的方式有三種攻泼。

  • 使用單圖像文件創(chuàng)建
  • 使用雪碧圖來(lái)創(chuàng)建
  • 從紋理圖集中創(chuàng)建

創(chuàng)建Sprite的方式分為

  • 常用方式
const sprite  = new PIXI.Sprite(texture?);
  • 快捷方式
const sprite = PIXI.Sprite.from(source);

參數(shù)source可以是URL地址、Canvas鉴象、紋理忙菠。

  • 快捷方式
const sprite = PIXI.Sprite.fromFrame(key);

參數(shù)key是JSON格式中的key或加載時(shí)定義的key。

  • 快捷方式
const sprite = PIXI.Sprite.fromImage(url, crossorigin?;

例如:

const imgpath = "images/avatar.jpg";
//將圖片添加到紋理緩存
PIXI.loader.add(imgpath).load(function(){
    //從紋理緩存中獲取紋理
    let texture = PIXI.loader.resources[imgpath].texture;
    //使用紋理創(chuàng)建精靈
    let sprite = new PIXI.Sprite(texture);
    //隱藏精靈
    sprite.visible = false;
    //將精靈添加舞臺(tái)
    app.stage.addChild(sprite);
    //將精靈從舞臺(tái)中刪除
    app.stage.removeChild(sprite);
});

使用別名

//設(shè)置別名
let Application = PIXI.Application;
let loader = PIXI.loader;
let resources = PIXI.loader.resources;
let Sprite = PIXI.Sprite;
//創(chuàng)建應(yīng)用
let app = new Application({width:256, height:256, resolution:1, transparent:false, antialias:true});
//添加canvas到document
document.body.appendChild(app.view);
//添加圖片
const img = "images/avatar.jpg";
loader.add(img).load(function(){
    let texture = resources[img].texture;
    let sprite = new Sprite(texture);
    app.stage.addChild(sprite);
});

監(jiān)視加載進(jìn)程

const name = "avatar";
const url = "images/avatar.jpg";
loader.add(name, url).load(function(){
    let texture = resources[name].texture;
    let sprite = new Sprite(texture);
    app.stage.addChild(sprite);
}).on("progress", function(loader, resource){
    console.log("loading", loader.progress, resource.name, resource.url);
});

add方法參數(shù)

add(name, url, optionObject, callbackFunction)
參數(shù) 類型 描述
name string 加載源文件別名
url string 源文件地址
options object literal 加載設(shè)置
options.crossOrigin boolean 源文件請(qǐng)求跨域
options.loadType string 原文加加載類型纺弊,默認(rèn)為Resource.LOAD_TYPE.XHR
options.xhrType string XHR處理方式牛欢,默認(rèn)為Resource.XHR_RESPONSE_TYPE.DEFAULT
callbackFunction function 加載完后執(zhí)行的回調(diào)函數(shù)

add方法可傳入對(duì)象數(shù)組,也可使用鏈?zhǔn)郊虞d淆游。

const imgs = [
    {name:"avatar", url:"images/avatar.jpg"},  
    {name:"person", url:"images/person.png"},
    {name:"plane", url:"images/plane.bmp"},
];
loader.add(imgs).load(function(){
    let texture = resources["plane"].texture;
    let sprite = new Sprite(texture);
    app.stage.addChild(sprite);
}).on("progress", function(loader, resource){
    console.log("loading", loader.progress, resource.name, resource.url);
});

精靈位置

默認(rèn)精靈sprite對(duì)象保存x和y屬性用來(lái)定位

let sprite = new Sprite(texture);
sprite.x = 100;
sprite.y = 100;
sprite.position.set(10, 10);

設(shè)置精靈的寬高大小

sprite.width = 150;
sprite.height = 120;

設(shè)置精靈的縮放比例

sprite.scale.x = 0.5;
sprite.scale.y = 0.5;
sprite.scale.set(0.5, 0.5);

scale的值從0到1表示對(duì)原精靈大小的百分比傍睹,1表示100%原來(lái)大小,0.5表示50%一般大小犹菱。

設(shè)置精靈的旋轉(zhuǎn)角度

可設(shè)置精靈的rotation來(lái)設(shè)定角度來(lái)旋轉(zhuǎn)拾稳,旋轉(zhuǎn)是針對(duì)錨點(diǎn)anchor發(fā)生的,默認(rèn)在精靈的左上角腊脱,錨點(diǎn)是精靈旋轉(zhuǎn)的中心點(diǎn)访得。

sprite.rotation = 0.5;

設(shè)置紋理錨點(diǎn)anchor

sprite.anchor.x = 0.5;
sprite.anchor.y = 0.5;

錨點(diǎn)anchor取值范圍從0到1,是紋理長(zhǎng)度或?qū)挾鹊陌俜直取?/p>

設(shè)置精靈中心點(diǎn)pivot

精靈提供和anchor錨點(diǎn)類似的pivot屬性來(lái)設(shè)置精靈的原點(diǎn)虑椎,若改變pivot中心點(diǎn)的值后旋轉(zhuǎn)精靈震鹉,將會(huì)圍繞設(shè)置的原點(diǎn)來(lái)旋轉(zhuǎn)。

sprite.pivot.x = 100;
sprite.pivot.y = 100;
sprite.pivot.set(100, 100);

若精靈的尺寸為200x200捆姜,設(shè)置pivot(100, 100)后,精靈將圍繞其中心點(diǎn)旋轉(zhuǎn)迎膜。

錨點(diǎn)pivot和中心點(diǎn)pivot的區(qū)別在于

  • anchor錨點(diǎn)改變了紋理的原點(diǎn)泥技,使用0到1填充。
  • pivot中心點(diǎn)則精靈的原點(diǎn)磕仅,使用像素來(lái)填充珊豹。

雪碧圖SpriteSheet

雪碧圖是使用單個(gè)文件包含游戲所需的所有圖片文件,pixi中使用雪碧圖中的小圖片的方式是使用一個(gè)矩形去截取紋理緩存中的對(duì)應(yīng)位置來(lái)創(chuàng)建精靈榕订。

//設(shè)置別名
let Application = PIXI.Application;
let loader = PIXI.loader;
let resources = PIXI.loader.resources;
let Sprite = PIXI.Sprite;
let TextureCache = PIXI.utils.TextureCache;
let Rectangle = PIXI.Rectangle;
//創(chuàng)建應(yīng)用
let app = new Application({width:256, height:256, resolution:1, transparent:false, antialias:true});
//添加canvas到document
document.body.appendChild(app.view);
//設(shè)置滿屏
app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.autoResize = true;
app.renderer.resize(window.innerWidth, window.innerHeight);
//添加圖片
const imgs = [
    {name:"altas", url:"images/altas.png"},
];
loader.add(imgs).load(function(){

    let texture = TextureCache["altas"];
    let rectangle = new Rectangle(0, 0, 64, 64);
    texture.frame = rectangle;

    let sprite = new Sprite(texture);
    sprite.position.set(150, 150);

    app.stage.addChild(sprite);
}).on("progress", function(loader, resource){
    console.log("loading", loader.progress, resource.name, resource.url);
});

Pixi內(nèi)置通用Rectangle對(duì)象PIXI.Rectangle店茶,用來(lái)定義矩形對(duì)象,矩形對(duì)象僅僅是一個(gè)數(shù)據(jù)對(duì)象劫恒。

let rectangle = new PIXI.Rectangle(x, y, width, height);

Pixi的紋理中存在frame屬性可被設(shè)置為任何Rectangle矩形對(duì)象贩幻,frame將紋理映射到Rectangle的維度轿腺。

從雪碧圖創(chuàng)建精靈的紋理是一個(gè)使用頻繁的操作,Pixi提供更為合適的方式來(lái)處理丛楚。

紋理貼圖

紋理貼圖集是一個(gè)JSON數(shù)據(jù)文件族壳,包含了匹配的PNG雪碧圖的子圖像的大小和位置。使用紋理貼圖集時(shí)只需要知道對(duì)應(yīng)名稱即可趣些。修改或刪除圖片只需要修改JSON數(shù)據(jù)文件即可仿荆,游戲內(nèi)會(huì)自動(dòng)給程序內(nèi)所有數(shù)據(jù)應(yīng)用更新紋理貼圖集。

Pixi可使用Texture Packer軟件輸出標(biāo)準(zhǔn)紋理貼圖集格式

const imgs = [
    {name:"man", url:"texture/man.json"},
];
loader.add(imgs).load(function(){

    //let texture = TextureCache["man1.jpg"];
    let texture = resources["man"].textures["man1.jpg"];
    let sprite = new Sprite(texture);
    sprite.position.set(150, 150);

    app.stage.addChild(sprite);
}).on("progress", function(loader, resource){
    console.log("loading", loader.progress, resource.name, resource.url);
});

例如:加載并創(chuàng)建紋理貼圖集并獲取其一居中顯示

//設(shè)置別名
let Application = PIXI.Application;
let loader = PIXI.loader;
let resources = PIXI.loader.resources;
let Sprite = PIXI.Sprite;
let TextureCache = PIXI.utils.TextureCache;
let Rectangle = PIXI.Rectangle;
//創(chuàng)建應(yīng)用
const width = window.innerWidth;
const height = window.innerHeight;
let app = new Application({width:width, height:height, resolution:1, transparent:false, antialias:true});
//添加canvas到document
document.body.appendChild(app.view);
//設(shè)置滿屏
app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.autoResize = true;
app.renderer.resize(window.innerWidth, window.innerHeight);
//資源位置
const urls = [
    {name:"man", url:"texture/man.json"},
];
//加載紋理貼圖集
loader.add(urls).load(function(){
    //獲取紋理創(chuàng)建精靈
    let texture = resources["man"].textures["man1.jpg"];
    let sprite = new Sprite(texture);
    //水平垂直居中定位
    const x = (width - sprite.width)/2;
    const y = (height - sprite.height)/2;
    sprite.position.set(x, y);
    //精靈添加到舞臺(tái)
    app.stage.addChild(sprite);
}).on("progress", function(loader, resource){
    console.log("loading", loader.progress, resource.name, resource.url);
});

精靈移動(dòng)

使用pixi的ticker實(shí)現(xiàn)游戲循環(huán)坏平,任何在游戲循環(huán)中的代碼都會(huì)1秒更新60次拢操。

例如:讓hero精靈以每幀1像素的速率移動(dòng)

//加載紋理貼圖集
loader.add(urls).load(function(){
    //獲取紋理創(chuàng)建精靈
    let texture = resources["man"].textures["hero1.png"];
    let sprite = new Sprite(texture);
    //水平垂直居中定位
    const x = (width - sprite.width)/2;
    const y = (height - sprite.height)/2;
    sprite.position.set(x, y);
    sprite.scale.set(0.5, 0.5);
    sprite.vx = 1;
    sprite.vy = 1;
    //精靈添加到舞臺(tái)
    app.stage.addChild(sprite);
    //精靈移動(dòng)
    app.ticker.add(delay=>{
        console.log(sprite.y, sprite.vy);
        if(sprite.x < height/2){
            sprite.x += sprite.vx + delay;
            sprite.y += sprite.vy + delay;
        }
        
    });
}).on("progress", function(loader, resource){
    console.log("loading", loader.progress, resource.name, resource.url);
});

動(dòng)畫精靈 PIXI.AnimatedSprite

  • 動(dòng)畫精靈就是逐幀動(dòng)畫,是通過(guò) 一幀一幀的播放圖像來(lái)產(chǎn)生運(yùn)動(dòng)的錯(cuò)覺(jué)舶替。
  • 動(dòng)畫精靈使按一系列略不相同的圖像創(chuàng)建精靈庐冯,然后一幀一幀播放這些圖像產(chǎn)生運(yùn)動(dòng)的幻覺(jué)。
  • 制作動(dòng)畫精靈需使用PIXI的AnimatedSprite方法

例如:將序列幀圖片使用Texture Packer制作成紋理貼圖集并導(dǎo)出JSON文件后制作精靈動(dòng)畫

//設(shè)置別名
let Application = PIXI.Application;
let loader = PIXI.loader;
let resources = PIXI.loader.resources;
let Sprite = PIXI.Sprite;
let TextureCache = PIXI.utils.TextureCache;
let Rectangle = PIXI.Rectangle;
let AnimatedSprite = PIXI.AnimatedSprite;
//創(chuàng)建應(yīng)用
const width = window.innerWidth;
const height = window.innerHeight;
let app = new Application({width:width, height:height, resolution:1, transparent:false, antialias:true});
//添加canvas到document
document.body.appendChild(app.view);
//設(shè)置滿屏
app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.autoResize = true;
app.renderer.resize(window.innerWidth, window.innerHeight);
//資源位置
const urls = [
    {name:"effect", url:"texture/effect.json"},
];
//加載紋理貼圖集
loader.add(urls).load(setup).on("progress", function(loader, resource){
    console.log("loading", loader.progress, resource.name, resource.url);
});
let sprite;
//啟動(dòng)代碼
function setup(){
    //獲取紋理創(chuàng)建精靈
    let textures = resources["effect"].textures;
    //對(duì)象轉(zhuǎn)數(shù)組
    const arrTextures = Object.values(textures);
    //創(chuàng)建精靈動(dòng)畫
    sprite = new AnimatedSprite(arrTextures);
    sprite.animationSpeed = 1;
    //水平垂直居中定位
    const x = (width - sprite.width)/2;
    const y = (height - sprite.height)/2;
    sprite.position.set(x, y);
    //精靈添加到舞臺(tái)
    app.stage.addChild(sprite);
    //播放精靈動(dòng)畫
    sprite.play();
};

PIXI.AnimatedSpirte

使用紋理數(shù)組創(chuàng)建動(dòng)畫精靈

const sprite = new PIXI.AnimatedSprite(textures, autoUpdated);
參數(shù) 類型 默認(rèn)值 描述
textures array - 紋理貼圖數(shù)組
autoUpdated boolean true 是否使用PIXI.ticker.shared自動(dòng)更新動(dòng)畫時(shí)間

返回值:返回用于控制動(dòng)畫精靈的對(duì)象

返回值屬性 類型 描述
animationSpeed number 播放速度默認(rèn)為1坎穿,值越大速度越快展父。
currentFrame number 當(dāng)前幀編號(hào)
totalFrames number 幀總數(shù)
playing boolean 當(dāng)前動(dòng)畫是否在播放
loop boolean 是否循環(huán)播放
onLoop function loop為true時(shí)調(diào)用
onComplete function 當(dāng)loop為false時(shí)動(dòng)畫完成后調(diào)用
onFrameChange function 但動(dòng)畫更改要呈現(xiàn)的紋理時(shí)調(diào)用
textures array 紋理數(shù)組
返回值方法 參數(shù) 描述
play - 播放的動(dòng)畫精靈
stop - 停止播放動(dòng)畫精靈
gotoAndPlay frameNumber, numberType, frameIndex 轉(zhuǎn)到特定幀并開(kāi)始播放動(dòng)畫
gotoAndStop frameNumber, numberType, frameIndex 轉(zhuǎn)到特定幀并停止播放動(dòng)畫

平鋪精靈PIXI.TilingSprite

平鋪精靈是一種特殊的精靈,可在一定的范圍內(nèi)重復(fù)一個(gè)紋理玲昧∑苘裕可使用平鋪精靈創(chuàng)建無(wú)線滾動(dòng)的背景效果。

創(chuàng)建平鋪精靈

const TilingSprite = PIXI.TilingSprite;
const tiling = new TilingSprite(texture, width, height);
參數(shù) 類型 默認(rèn)值 描述
texture PIXI.Texture - 平鋪精靈紋理
width number 100 平鋪精靈的寬度
height number 100 平鋪精靈的高度

平鋪精靈具有和普通精靈相同的屬性孵延,與普通精靈工作方式相同吕漂。

例如:使用小圖創(chuàng)建平鋪精靈并移動(dòng)

brick.png
//設(shè)置別名
let Application = PIXI.Application;
let loader = PIXI.loader;
let resources = PIXI.loader.resources;
let TextureCache = PIXI.utils.TextureCache;
let Rectangle = PIXI.Rectangle;
let Container = PIXI.Container;
let Sprite = PIXI.Sprite;
let AnimatedSprite = PIXI.AnimatedSprite;
let TilingSprite = PIXI.TilingSprite;
//創(chuàng)建應(yīng)用
const width = window.innerWidth;
const height = window.innerHeight;
let app = new Application({width:width, height:height, resolution:1, transparent:false, antialias:true});
//添加canvas到document
document.body.appendChild(app.view);
//設(shè)置滿屏
app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.autoResize = true;
app.renderer.resize(window.innerWidth, window.innerHeight);
//資源位置
const urls = [
    {name:"brick", url:"images/brick.png"},
];
//加載紋理
loader.add(urls).load(setup).on("progress", function(loader, resource){
    console.log("loading", loader.progress, resource.name, resource.url);
});
//啟動(dòng)代碼
let tiling;
function setup(){
    //創(chuàng)建平鋪精靈
    const texture = resources["brick"].texture;
    tiling = new TilingSprite(texture, width, height);
    tiling.tileScale.set(0.5, 0.5);
    app.stage.addChild(tiling);

    app.ticker.add(delay=>loop(delay));
};

let state = play;
function loop(delay){
    state(delay);
}

function play(delay){
    tiling.tilePosition.x -= 1;
}

例如:視差滾動(dòng)的偽3D效果

wood.jpg
ground.png

在同一位置層疊多個(gè)平鋪精靈,遠(yuǎn)景圖片移動(dòng)要慢于近景圖像尘应。

//設(shè)置別名
let Application = PIXI.Application;
let loader = PIXI.loader;
let resources = PIXI.loader.resources;
let TextureCache = PIXI.utils.TextureCache;
let Rectangle = PIXI.Rectangle;
let Container = PIXI.Container;
let Sprite = PIXI.Sprite;
let AnimatedSprite = PIXI.AnimatedSprite;
let TilingSprite = PIXI.TilingSprite;
//創(chuàng)建應(yīng)用
const width = window.innerWidth;
const height = window.innerHeight;
let app = new Application({width:width, height:height, resolution:1, transparent:true, antialias:true});
//添加canvas到document
document.body.appendChild(app.view);
//設(shè)置滿屏
app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.autoResize = true;
app.renderer.resize(window.innerWidth, window.innerHeight);
//資源位置
const urls = [
    {name:"wood", url:"images/wood.jpg"},
    {name:"ground", url:"images/ground.png"},
];
//加載紋理
loader.add(urls).load(setup).on("progress", function(loader, resource){
    console.log("loading", loader.progress, resource.name, resource.url);
});
//啟動(dòng)代碼
let wood, ground;
function setup(){
    const woodTexture = resources["wood"].texture;
    wood = new TilingSprite(woodTexture, width, height);

    const groundTexture = resources["ground"].texture;
    ground = new TilingSprite(groundTexture, width, groundTexture.height);
    ground.y = height - groundTexture.height;

    app.stage.addChild(wood);
    app.stage.addChild(ground);

    app.ticker.add(delay=>loop(delay));
};

let state = play;
function loop(delay){
    state(delay);
}

function play(delay){
    wood.tilePosition.x -= 1;
    ground.tilePosition.x += 2;
}

精靈狀態(tài)SpriteUtilities

當(dāng)具有復(fù)雜的游戲角色或交互式對(duì)象時(shí)惶凝,可能希望角色根據(jù)游戲環(huán)境中發(fā)生的動(dòng)作,以不同的方式運(yùn)行犬钢。每個(gè)單獨(dú)的行為稱為狀態(tài)苍鲜,如果在精靈上定義狀態(tài),只要游戲中出現(xiàn)與該狀態(tài)相應(yīng)的事件時(shí)玷犹,就可以觸發(fā)這些狀態(tài)混滔。比如,通過(guò)鍵盤控制角色移動(dòng)歹颓。

使用精靈狀態(tài)坯屿,首先需要狀態(tài)播放器,狀態(tài)播放器用于控制精靈的狀態(tài)巍扛。pixi精靈沒(méi)有自己的狀態(tài)播放器领跛,可使用SpriteUtilities庫(kù)中的sprite方法,sprite方法將創(chuàng)建一個(gè)內(nèi)置狀態(tài)播放器的精靈撤奸。

游戲狀態(tài)

游戲狀態(tài)作為一種代碼風(fēng)格吠昭,幫助模塊組織代碼喊括,結(jié)構(gòu)化游戲循環(huán)代碼,使場(chǎng)景切換和關(guān)卡類操作變得更加簡(jiǎn)單怎诫。

//設(shè)置別名
let Application = PIXI.Application;
let loader = PIXI.loader;
let resources = PIXI.loader.resources;
let Sprite = PIXI.Sprite;
let TextureCache = PIXI.utils.TextureCache;
let Rectangle = PIXI.Rectangle;
//創(chuàng)建應(yīng)用
const width = window.innerWidth;
const height = window.innerHeight;
let app = new Application({width:width, height:height, resolution:1, transparent:false, antialias:true});
//添加canvas到document
document.body.appendChild(app.view);
//設(shè)置滿屏
app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.autoResize = true;
app.renderer.resize(window.innerWidth, window.innerHeight);
//資源位置
const urls = [
    {name:"man", url:"texture/man.json"},
];

let state;//游戲狀態(tài)

//加載紋理貼圖集
loader.add(urls).load(setup).on("progress", function(loader, resource){
    console.log("loading", loader.progress, resource.name, resource.url);
});
let sprite;
//啟動(dòng)代碼
function setup(){
    //獲取紋理創(chuàng)建精靈
    let texture = resources["man"].textures["hero1.png"];
    sprite = new Sprite(texture);
    //水平垂直居中定位
    const x = (width - sprite.width)/2;
    const y = (height - sprite.height)/2;
    sprite.position.set(x, y);
    sprite.scale.set(0.5, 0.5);
    sprite.vx = 1;
    sprite.vy = 1;
    //精靈添加到舞臺(tái)
    app.stage.addChild(sprite);

    //精靈移動(dòng)
    app.ticker.add(delay=>loop(delay));
};

//設(shè)置游戲狀態(tài)
state = play;

//游戲環(huán)迅
function loop(delay){
    state(delay);
};

//運(yùn)行狀態(tài)
function play(delay){
    console.log(sprite.y, sprite.vy);
    if(sprite.x < height/2){
        sprite.x += sprite.vx + delay;
        sprite.y += sprite.vy + delay;
    }
};

游戲狀態(tài)機(jī)

游戲狀態(tài)機(jī)是用于設(shè)計(jì)游戲的基本狀態(tài)邏輯

例如

const GAME_STATUS = {UNINIT:0, INIT:1, LOADED:2, PLAYING:3, GAMEOVER:4};

消息總線

監(jiān)聽(tīng)器模式是一個(gè)減少組件之間耦合的辦法瘾晃,不同組件之間通過(guò)消息總線收發(fā)消息,可以有效地避免組件之間的復(fù)雜調(diào)用幻妓。游戲是游戲互動(dòng)多狀態(tài)多的情況蹦误。比如游戲裝狀態(tài)機(jī)從LOADED轉(zhuǎn)變?yōu)镻LAYING時(shí)廣播這個(gè)消息給相關(guān)組件游戲開(kāi)始了。

鍵盤控制

自定義keyboard鍵盤函數(shù)用于監(jiān)聽(tīng)和捕獲鍵盤事件

編寫鍵盤方法

const keycode = {
    left:37,
    up:38,
    right:39,
    down:40    
};

function keyboard(code){
    let key = {};
    key.code = code;
    //key status
    key.isDown = false;
    key.isUp = true;
    //key action
    key.press = undefined;
    key.release = undefined;
    //key down handler
    key.down = evt=>{
        if(evt.keyCode === key.code){
            if(key.isUp && key.press){
                key.press();
            }
            key.isDown = true;
            key.isUp = false;
        }
        evt.preventDefault();
    };
    // key up handler
    key.up = evt=>{
        if(evt.keyCode===key.code){
            if(key.isDown && key.release){
                key.release();
            }
            key.isUp = true;
            key.isDown = false;
        }
        evt.preventDefault();
    };

    //attach event listeners
    window.addEventListener("keydown", key.down.bind(key), false);
    window.addEventListener("keyup", key.up.bind(key), false);

    return key;
}

使用鍵盤控制角色的移動(dòng)

//設(shè)置別名
let Application = PIXI.Application;
let loader = PIXI.loader;
let resources = PIXI.loader.resources;
let Sprite = PIXI.Sprite;
let TextureCache = PIXI.utils.TextureCache;
let Rectangle = PIXI.Rectangle;
let AnimatedSprite = PIXI.extras.AnimatedSprite;
//創(chuàng)建應(yīng)用
const width = window.innerWidth;
const height = window.innerHeight;
let app = new Application({width:width, height:height, resolution:1, transparent:false, antialias:true});
//添加canvas到document
document.body.appendChild(app.view);
//設(shè)置滿屏
app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.autoResize = true;
app.renderer.resize(window.innerWidth, window.innerHeight);
//資源位置
const urls = [
    {name:"effect", url:"texture/effect.json"},
];
//加載紋理貼圖集
loader.add(urls).load(setup).on("progress", function(loader, resource){
    console.log("loading", loader.progress, resource.name, resource.url);
});
let sprite;
//啟動(dòng)代碼
function setup(){
    //獲取紋理創(chuàng)建精靈
    let textures = resources["effect"].textures;
    //對(duì)象轉(zhuǎn)數(shù)組
    const arrTextures = Object.values(textures);
    //創(chuàng)建精靈動(dòng)畫
    sprite = new AnimatedSprite(arrTextures);
    sprite.animationSpeed = 1;
    //水平垂直居中定位
    const x = (width - sprite.width)/2;
    const y = (height - sprite.height)/2;
    sprite.position.set(x, y);
    //移動(dòng)速度
    sprite.vx = 0;
    sprite.vy = 0;

    //精靈添加到舞臺(tái)
    app.stage.addChild(sprite);
    //播放精靈動(dòng)畫
    sprite.play();
    //設(shè)置游戲狀態(tài)
    state = play;
    //循環(huán)播放
    app.ticker.add(delta=>loop(delta));
};

function loop(delta){
    state(delta);
}
function play(delta){
    sprite.x += sprite.vx;
    sprite.y += sprite.vy;
}
//鍵盤方向鍵
const keyUp = keyboard(keycode.up); 
const keyDown = keyboard(keycode.down); 
const keyLeft = keyboard(keycode.left); 
const keyRight = keyboard(keycode.right); 
//鍵盤控制
keyUp.press = function(){
    sprite.vx = 0;
    sprite.vy = -5;
};
keyUp.release = function(){
    if(sprite.vx===0 && !keyDown.isDown){
        sprite.vy = 0;
    }
};
keyDown.press = function(){
    sprite.vx = 0;
    sprite.vy = 5;
};
keyDown.release = function(){
    if(sprite.vx===0 && !keyUp.isDown){
        sprite.vy = 0;
    }
};
keyLeft.press = function(){
    sprite.vx = -5;
    sprite.vy = 0;
};
keyLeft.release = function(){
    if(sprite.vy===0 && !keyRight.isDown){
        sprite.vx = 0;
    }
};
keyRight.press = function(){
    sprite.vx = 5;
    sprite.vy = 0;
};
keyRight.release = function(){
    if(sprite.vy === 0 && !keyLeft.isDown){
        sprite.vx = 0;
    }
};

容器PIXI.Container

容器可以用來(lái)管理相似的多個(gè)精靈

例如:將不同精靈放入容器后添加到舞臺(tái)

//設(shè)置別名
let Application = PIXI.Application;
let loader = PIXI.loader;
let resources = PIXI.loader.resources;
let Sprite = PIXI.Sprite;
let TextureCache = PIXI.utils.TextureCache;
let Rectangle = PIXI.Rectangle;
let AnimatedSprite = PIXI.AnimatedSprite;
let Container = PIXI.Container;
//創(chuàng)建應(yīng)用
const width = window.innerWidth;
const height = window.innerHeight;
let app = new Application({width:width, height:height, resolution:1, transparent:false, antialias:true});
//添加canvas到document
document.body.appendChild(app.view);
//設(shè)置滿屏
app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.autoResize = true;
app.renderer.resize(window.innerWidth, window.innerHeight);
//資源位置
const urls = [
    {name:"hero1", url:"images/hero1.png"},
    {name:"hero2", url:"images/hero2.png"},
];
//加載紋理
loader.add(urls).load(setup).on("progress", function(loader, resource){
    console.log("loading", loader.progress, resource.name, resource.url);
});
//啟動(dòng)代碼
function setup(){
    //從紋理緩存中創(chuàng)建精靈
    let hero1 = new Sprite(resources["hero1"].texture);
    let hero2 = new Sprite(resources["hero2"].texture);
    //縮放精靈
    hero1.scale.set(0.5, 0.5);
    hero2.scale.set(0.5, 0.5);
    //創(chuàng)建容器并添加元素
    let container = new Container();
    container.addChild(hero1);
    container.addChild(hero2);
    //設(shè)置容器在場(chǎng)景中的位置
    const x = (width - container.width)/2;
    const y = (height - container.height)/2;
    container.position.set(x, y);
    //將容器添加到舞臺(tái)
    app.stage.addChild(container);
};

當(dāng)往一個(gè)Container容器中添加精靈時(shí)肉津,其x和y的位置是相對(duì)于分組左上角强胰,這是精靈的局部位置。精靈還具有一個(gè)全局位置妹沙,全局位置是舞臺(tái)左上角到精靈錨點(diǎn)(通常是精靈左上角)的距離偶洋,可通過(guò)toGlobal方法獲取精靈圖的全局位置。

粒子容器PIXI.ParticleContainer

Pixi有一個(gè)額外的距糖、高性能的容器稱為ParticleContainer玄窝,任何在ParticleContainer中的精靈都會(huì)比在普通Container的渲染速度快2到5倍,這是用于提升游戲性能的一個(gè)很不錯(cuò)的方式悍引。

為什么ParticleContainer中的精靈圖能處理的這么快呢恩脂?因?yàn)榫`的位置是直接在GPU上計(jì)算的。Pixi開(kāi)發(fā)團(tuán)隊(duì)正努力讓更多的雪碧圖在GPU上處理趣斤。

創(chuàng)建粒子容器

const ParticleContainer = PIXI.ParticleContainer;
const particleContainer = new ParticleContainer(options);

創(chuàng)建ParticleContainer時(shí)可以傳遞四個(gè)參數(shù)size俩块、properties、batchSize浓领、autoResize玉凯。

  • ParticleContainer中的精靈只有Container中少部分屬性x、y联贩、width漫仆、height、scale撑蒜、pivot歹啼、alpha、visible座菠。
  • ParticleContainer包含的精靈不能再繼續(xù)嵌套。
  • ParticleContainer不能使用Pixi中的視覺(jué)效果藤树,比如過(guò)濾器和混合模式浴滴。
  • 每個(gè)ParticleContainer只能使用一個(gè)紋理,如果想讓精靈有不同的表現(xiàn)形式岁钓,則必須更換雪碧圖升略。

幾何圖形PIXI.Graphics

使用圖片紋理制作精靈使最有效的方式之一微王,Pixi提供了自己的繪圖工具用來(lái)創(chuàng)造矩形、線段品嚣、多邊形以及文本炕倘。

Pixi的繪圖工具和Canvas Drawing API幾乎一致,不同之處在于Pixi的繪圖API是通過(guò)WebGL在GPU上渲染的翰撑。

所有圖形的初始化都需要先創(chuàng)建一個(gè)Pixi的Graphics類的實(shí)例

const Graphics = PIXI.Graphics;
const graphics = new Graphics();

矩形

繪制矩形

graphics.drawRect(x, y, width, height);

例如:繪制100x100罩旋,背景黑色,3像素紅色邊框的矩形眶诈。

//設(shè)置別名
let Application = PIXI.Application;
let Graphics = PIXI.Graphics;
//創(chuàng)建應(yīng)用
const width = window.innerWidth;
const height = window.innerHeight;
const resolution = window.devicePixelRatio;
let app = new Application({width:width, height:height, resolution:resolution, transparent:true, antialias:true});
//添加canvas到document
document.body.appendChild(app.view);
//設(shè)置滿屏
app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.autoResize = true;
app.renderer.resize(window.innerWidth, window.innerHeight);
//創(chuàng)建矩形
let graphics = new Graphics();
graphics.beginFill(0x000000);
graphics.lineStyle(3, 0xff0000, 1);
graphics.drawRect(0, 0, 100, 100);
graphics.endFill();
graphics.x = (width - graphics.width)/2;
graphics.y = (height - graphics.height)/2;
app.stage.addChild(graphics);

圓角矩形

graphics.drawRoundedRect(x, y, width, height, cornerRadius);

圓形

graphics.drawCircle(x, y, radius);

橢圓

graphics.drawEllipse(x, y, width, height);

顯示文本PIXI.Text

Pixi使用Text對(duì)象在舞臺(tái)上顯示文本涨醋,Text文本對(duì)象繼承自Sprite類,可以像處理精靈一樣在舞臺(tái)上定位和調(diào)整文本逝撬。

//設(shè)置別名
let Application = PIXI.Application;
let Text = PIXI.Text;
let TextStyle = PIXI.TextStyle;
//創(chuàng)建應(yīng)用
const width = window.innerWidth;
const height = window.innerHeight;
const resolution = 1;
let app = new Application({width:width, height:height, resolution:resolution, transparent:true, antialias:true});
//添加canvas到document
document.body.appendChild(app.view);
//設(shè)置滿屏
app.renderer.view.style.position = "absolute";
app.renderer.view.style.display = "block";
app.renderer.autoResize = true;
app.renderer.resize(window.innerWidth, window.innerHeight);
//創(chuàng)建文本并設(shè)置樣式
const style = new TextStyle({
    fontFamily:"Arial",
    fontSize:36,
    fill:"white",
    stroke:"#ff3300",
    strokeThickness:4,
    dropShadow:true,
    dropShadowColor:"#000000",
    dropShadowBlur:4,
    dropShadowAngle:Math.PI/6,
    dropShadowDistance:6
});
let str = "Hello World";
const text = new Text(str, style);
text.text = "HELLO WORLD";

let x = (width - text.width)/2;
let y = (height - text.height)/2;
text.position.set(x, y);
app.stage.addChild(text);

碰撞檢測(cè)hitTestRectangle

自定義hitTestRectangle函數(shù)用于檢測(cè)兩個(gè)矩形是否接觸

const boolean = hitTestRectangle(sprite1, sprite2);

若精靈1和精靈2發(fā)生重疊則返回true浴骂,反之為false。

//矩形碰撞檢查
function hitTestRectangle(r1, r2){
    let hit = false;//是否發(fā)生碰撞

    //獲取矩形中心點(diǎn)
    r1.centerX = r1.x + r1.width/2;
    r1.centerY = r1.y + r1.height/2;
    r2.centerX = r2.x + r2.width/2;
    r2.centerY = r2.y + r2.height/2;
    //計(jì)算矩形中心點(diǎn)距離
    const vx = Math.abs(r1.centerX - r2.centerX);
    const vy = Math.abs(r1.centerY - r2.centerY);
    //計(jì)算矩形合并時(shí)尺寸
    const combinedHalfWidth = (r1.width + r2.width)/2;
    const combinedHalfHeight = (r1.height + r2.height)/2;
    //檢測(cè)矩形是否發(fā)生碰撞
    if(combinedHalfWidth>vx && combinedHalfHeight>vy){
        hit = true;
    }
    
    return hit;
}

例如:繪制兩個(gè)矩形宪潮,測(cè)試是否發(fā)生碰撞溯警。

//設(shè)置別名
let Application = PIXI.Application;
let Rectangle = PIXI.Rectangle;
let Graphics = PIXI.Graphics;
//創(chuàng)建應(yīng)用
const width = window.innerWidth;
const height = window.innerHeight;
const resolution = 1;
let app = new Application({width:width, height:height, resolution:resolution, transparent:true, antialias:true});
//添加canvas到document
document.body.appendChild(app.view);
//設(shè)置別名
const renderer = app.renderer;
const stage = app.stage;
//設(shè)置滿屏
renderer.view.style.position = "absolute";
renderer.view.style.display = "block";
renderer.autoResize = true;
renderer.resize(window.innerWidth, window.innerHeight);
//創(chuàng)建矩形
const r1 = new Graphics();
r1.beginFill(0x00ffff);
r1.drawRect(0, 0, 100, 100);
r1.endFill();
r1.position.set((width-r1.width)/2, (height - r1.height)/2);
stage.addChild(r1);

const r2 = new Graphics();
r2.beginFill(0x0000ff);
r2.drawRect(0, 0, 100, 100);
r2.endFill();
r2.position.set((width-r2.width)/2, (height - r2.height)/2+10);
stage.addChild(r2);

//判斷舉行是否發(fā)生碰撞
const hit = hitTestRectangle(r1, r2);
console.log(hit);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市狡相,隨后出現(xiàn)的幾起案子梯轻,更是在濱河造成了極大的恐慌,老刑警劉巖谣光,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件檩淋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡萄金,警方通過(guò)查閱死者的電腦和手機(jī)蟀悦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)氧敢,“玉大人日戈,你說(shuō)我怎么就攤上這事∷锕裕” “怎么了浙炼?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)唯袄。 經(jīng)常有香客問(wèn)我弯屈,道長(zhǎng),這世上最難降的妖魔是什么恋拷? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任资厉,我火速辦了婚禮,結(jié)果婚禮上蔬顾,老公的妹妹穿的比我還像新娘宴偿。我一直安慰自己湘捎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布窄刘。 她就那樣靜靜地躺著窥妇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪娩践。 梳的紋絲不亂的頭發(fā)上活翩,一...
    開(kāi)封第一講書(shū)人閱讀 50,050評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音欺矫,去河邊找鬼纱新。 笑死,一個(gè)胖子當(dāng)著我的面吹牛穆趴,可吹牛的內(nèi)容都是我干的脸爱。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼未妹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼簿废!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起络它,我...
    開(kāi)封第一講書(shū)人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤族檬,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后化戳,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體单料,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年点楼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扫尖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掠廓,死狀恐怖换怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蟀瞧,我是刑警寧澤沉颂,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站悦污,受9級(jí)特大地震影響铸屉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜切端,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一抬探、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧帆赢,春花似錦小压、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至瘾婿,卻和暖如春蜻牢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背偏陪。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工抢呆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人笛谦。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓抱虐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親饥脑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子恳邀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容