内容简介:小精灵冒险 是
说明
小精灵冒险 是 Learn Pixi.js 一书中最后一个案例。点击屏幕让小精灵飞起来,小精灵上升时,会拍打翅膀,并且会有小星星产生。如果她撞到柱子上,她会爆炸成一堆小星星。帮助她通过15个柱子的间隙到达终点,界面会显示一个巨大 Finish 标志。
下来让我们看看怎么制作这个游戏的吧!
创建滚动背景
还记得 学习 PixiJS — 视觉效果 一文中提到的视差效果吗?小精灵冒险的背景是使用视差效果做的,也就是背景比前景移动的速度慢一些,使得背景看上去好像距离更远。
为了制作天空背景,我们使用无缝的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像素,下图显示了它们彼此相邻时的样子。
每根柱子的顶部和底部之间的间隙逐渐变窄,你可以看到间隙从左侧的四块空间逐渐变窄到右侧的两块空间。
构成柱子的所有块都在一个名为 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;
}
总结
以上就是如何实现 小精灵冒险 这个游戏的全部了,游戏中需要的各种东西,在前面几篇文章中都有提到。如果遇到什么不明白的东西,可以看看前面的几篇文章。
而这个小游戏还有许多小细节可以去实现,比如增加玩家的分数,增加开始游戏的按钮,增加一些场景过渡,增加音效 等等,这些你都可以尝试自己实现下。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 内核地址空间大冒险(二):中断与异常
- 内核地址空间大冒险(二):中断与异常
- 设计模式大冒险第一关:观察者模式
- 用木兰语言编写文字冒险游戏(十三、四章),又一个特性发现
- 设计模式大冒险第二关:装饰者模式,煎饼果子的主场
- 设计模式大冒险第四关:单例模式,如何成为你的 “唯一”
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Game Engine Architecture, Second Edition
Jason Gregory / A K Peters/CRC Press / 2014-8-15 / USD 69.95
A 2010 CHOICE outstanding academic title, this updated book covers the theory and practice of game engine software development. It explains practical concepts and techniques used by real game studios,......一起来看看 《Game Engine Architecture, Second Edition》 这本书的介绍吧!