手记

学习 PixiJS — 粒子效果

你如何创造火,烟,魔法和爆炸等效果?你制作了许多小精灵,几十,几百,甚至上千个精灵。然后对这些精灵应用一些物理效果,使它们的行为类似于你尝试模拟的元素。你还必须给他们一些关于它们应该如何出现和消失以及应该形成什么样的模式的规则。这些微小的精灵被称为粒子。你可以使用它们为游戏制作各种特效。

使用 Dust 库

Pixi 没有内置的制作粒子效果的功能,但你可以使用一个名为 Dust 的轻量级的库来制作它们。

注意:Dust 是一种快速简便的方法,可以制作游戏所需的大部分粒子效果,但如果你需要功能更全面,更复杂的库,请查看 Proton

使用 Dust 库和使用 SpriteUtilities 库是一样的。

首先直接用 script 标签,引入 js 文件

<script src="https://www.kkkk1000.com/js/dust.js"></script>

然后创建它的实例

d = new Dust(PIXI);

变量 d 现在就代表 Dust 实例。

接下来,在游戏循环中调用 Dust 的 update 方法,这个方法用于更新粒子。我们在上篇文章中制作的示例中有 gameLoop 和 play 两个函数 ,你可以在这两个函数中执行此操作。建议在 gameLoop 中执行此操作,就在调用 state 函数之后但在渲染阶段之前,如下所示:

function gameLoop(){
 requestAnimationFrame(gameLoop);
 state();
 d.update();
 renderer.render(stage);
}

制作粒子

制作粒子需要用到 Dust 库的 create 方法

参数:

名称 类型 默认值 描述
x number 0 粒子出现的 x 坐标
y number 0 粒子出现的 y 坐标
spriteFunction function 一个函数,它返回要用于每个粒子的精灵,如果提供具有多个帧的精灵,Dust 将随机显示不同帧
container object 一个 PIXI 容器 要添加粒子的容器
numberOfParticles number 20 要创建的粒子数
gravity number 0 重力
randomSpacing boolean true 随机间隔
minAngle number 0 最小角度
maxAngle number 6.28 最大角度
minSize number 4 最小尺寸
maxSize number 16 最大尺寸
minSpeed number 0.3 最小速度
maxSpeed number 3 最大速度
minScaleSpeed number 0.01 最小比例速度
maxScaleSpeed number 0.05 最大比例速度
minAlphaSpeed number 0.02 最小alpha速度
maxAlphaSpeed number 0.02 最大alpha速度
minRotationSpeed number 0.01 最小旋转速度
maxRotationSpeed number 0.03 最大旋转速度

返回值:

返回一个数组,其中包含对用作粒子的所有精灵的引用,如果需要进行碰撞检测等原因必须访问它们,这可能很有用。

现在我们来试试这个方法。

示例代码:

<!doctype html>
<html lang="zn">

<head>
    <meta charset="UTF-8">
</head>

<body>
    <div id="px-render"></div>

    <script src="https://www.kkkk1000.com/js/pixi4.8.2.js"></script>
    <script src="https://www.kkkk1000.com/js/spriteUtilities.js"></script>
    <script src="https://www.kkkk1000.com/js/dust.js"></script>
    <script>
        //创建一个 Pixi应用 需要的一些参数
        let option = {
            width: 400,
            height: 300,
            transparent: true,
        }
        //创建一个 Pixi应用
        let app = new PIXI.Application(option);
        //获取舞台
        let stage = app.stage;
        //获取渲染器
        let renderer = app.renderer;
        let playground = document.getElementById('px-render');
        //把 Pixi 创建的 canvas 添加到页面上
        playground.appendChild(renderer.view);

        let su = new SpriteUtilities(PIXI);
        let d = new Dust(PIXI);

        //需要加载的图片的地址
        let imgURL = "https://www.kkkk1000.com/images/learnPixiJS-ParticleEffects/star.png";
        //加载图像,加载完成后执行setup函数 
        PIXI.loader.add(imgURL).load(setup);

        function setup() {
            stars = d.create(
                128, //x 起始坐标
                128, //y 起始坐标
                () => su.sprite(imgURL), //返回要用于每个粒子的精灵
                stage, //粒子的容器
                50, //粒子数
                0,//重力
                false,//随机间隔
                0, 6.28,//最小/最大角度
                30, 90,//最小/最大尺寸
                1, 3//最小/最大速度
            );

            //开始游戏循环
            gameLoop();
        }

        function gameLoop() {
            requestAnimationFrame(gameLoop);
            d.update();
            renderer.render(stage);
        }
    </script>
</body>

</html>

使用 ParticleContainer

在前面的示例代码中,我们创建的粒子都被添加到根容器(第四个参数)。但是,你可以将粒子添加到任何你喜欢的容器或任何其他精灵。

Pixi 有一个叫 ParticleContainer 的方法,任何在 ParticleContainer 里的精灵都会比在一个普通的 Container 的渲染速度快2到5倍。

到这里可以了解 ParticleContainer

如果要对粒子使用 ParticleContainer,只需在 create 方法的第四个参数中添加要使用的 ParticleContainer 对象的名称。以下是修改前面的示例代码以将粒子添加到名为 starContainer 的 ParticleContainer 的方法。

//创建ParticleContainer并将其添加到stage
let starContainer = new PIXI.particle.ParticleContainer(
    1500,
    { alpha: true, scale: true, rotation: true, uvs: true }
);
stage.addChild(starContainer);

function setup() {
    //创建星形粒子并将它们添加到starContainer
    stars = d.create(
        128, //x 起始坐标
        128, //y 起始坐标
        () => su.sprite(imgURL),
        starContainer, //粒子的容器
        50, //粒子数
        0,//重力
        false,//随机间隔
        0, 6.28,//最小/最大角度
        30, 90,//最小/最大尺寸
        1, 3//最小/最大速度
    );

    //开始游戏循环
    gameLoop();
}

ParticleContainers 针对推送数千个精灵进行了优化,因此,除非你为很多粒子设置动画,否则你可能不会注意到对于使用普通 Container 对象的性能提升。

使用粒子发射器

create 方法会产生一次粒子爆发,但通常你必须产生连续的粒子流。你可以在粒子发射器的帮助下完成此操作。粒子发射器以固定的间隔产生粒子以产生流效果,你可以使用 Dustemitter 方法创建一个粒子发射器。发射器具有 play 和 stop 方法,可让打开和关闭粒子流,并可以定义粒子的创建间隔。

下面的代码是使用 Dustemitter 方法的一般格式。它需要两个参数。

第一个参数是创建粒子间隔(以毫秒为单位)。

第二个参数与我们在前面的示例中使用的 create 方法相同。

let particleStream = d.emitter(
 100,
 () => d.create();
);

任何100毫秒或更短的间隔值将使颗粒看起来以连续流的形式流动。这里有一些产生星形喷泉效果的代码。

let particleStream = d.emitter(
                100,
                () => d.create(
                    128, 128,
                    () => su.sprite(imgURL),
                    stage,
                    30,
                    0.1,
                    false,
                    3.14, 6.28,
                    30, 60,
                    1, 5
                )
            );

第六个参数,0.1,是重力。将重力设置为更高的数字,粒子将更快的下落。
角度介于3.14和6.28之间。这使得粒子出现在其原点之上的半月形大小的角度内。下图说明了如何定义该角度。

星星在中心原点处创建,然后在圆圈的上半部分向上飞出。然而,星星在重力的作用下,最终将落在画布的底部,这就是产生星形喷泉效果的原因。

你可以使用 emitter 的 play 和 stop 方法在代码中随时打开或关闭粒子流,如下所示:

particleStream.play();
particleStream.stop();

效果图:

完整代码:

<!doctype html>
<html lang="zn">

<head>
    <meta charset="UTF-8">
</head>

<body>
    <div id="px-render"></div>

    <script src="https://www.kkkk1000.com/js/pixi4.8.2.js"></script>
    <script src="https://www.kkkk1000.com/js/spriteUtilities.js"></script>
    <script src="https://www.kkkk1000.com/js/dust.js"></script>
    <script>
        //创建一个 Pixi应用 需要的一些参数
        let option = {
            width: 400,
            height: 300,
            transparent: true,
        }
        //创建一个 Pixi应用
        let app = new PIXI.Application(option);
        //获取舞台
        let stage = app.stage;
        //获取渲染器
        let renderer = app.renderer;
        let playground = document.getElementById('px-render');
        //把 Pixi 创建的 canvas 添加到页面上
        playground.appendChild(renderer.view);

        let su = new SpriteUtilities(PIXI);
        let d = new Dust(PIXI);
        let particleStream;

        //需要加载的图片的地址
        let imgURL = "https://www.kkkk1000.com/images/learnPixiJS-ParticleEffects/star.png";
        //加载图像,加载完成后执行setup函数 
        PIXI.loader.add(imgURL).load(setup);

        function setup() {
            let particleStream = d.emitter(
                100,
                () => d.create(
                    128, 128,
                    () => su.sprite(imgURL),
                    stage,
                    30,
                    0.1,
                    false,
                    3.14, 6.28,
                    30, 60,
                    1, 5
                )
            );

            particleStream.play();
            //开始游戏循环
            gameLoop();
        }

        function gameLoop() {
            requestAnimationFrame(gameLoop);
            d.update();
            renderer.render(stage);
        }
    </script>
</body>

</html>
2人推荐
随时随地看视频
慕课网APP