学习 PixiJS — 小精灵冒险

说明

小精灵冒险 是 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 方法使用全局坐标进行碰撞检测。

若是 pixieVsBlocktrue,而且当前小精灵可见,则运行小精灵爆炸成一堆小星星的代码。它使小精灵变的不可见,并产生粒子爆炸效果,并且在延迟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;
}

总结

以上就是如何实现 小精灵冒险 这个游戏的所有了,游戏中须要的各类东西,在前面几篇文章中都有提到。若是遇到什么不明白的东西,能够看看前面的几篇文章。
而这个小游戏还有许多小细节能够去实现,好比增长玩家的分数,增长开始游戏的按钮,增长一些场景过渡,增长音效 等等,这些你均可以尝试本身实现下。

上一篇 学习 PixiJS — 交互工具

相关文章
相关标签/搜索