使用真实游戏引擎

它比从头开始做得更好。

追赶

在上一篇文章中,我指出我不知道我应该开发比Pong更困难的游戏,还是应该学习使用真实的游戏引擎。 好吧,事实证明,当您不知道应该做什么时,您可能应该只考虑上述所有内容。

这就是我所做的。 我在Phaser 2.6.2中实现了Breakout,并且进展顺利。 您可以在此处找到其代码。 首先,我跟随着这个播放列表与Phaser一起实现Pong,它为我提供了启动和运行所需的一切。

让我们开始吧

马上,您需要知道Phaser比从头开始编写引擎要容易处理一个数量级。 喜欢认真。 这就像从城市驶向山脉,然后吸入第一口深呼吸的新鲜空气。 但是,您知道,用于代码。

无论如何,我想指出的第一件大事是,虽然我不认为我对通用引擎的期望还差得很远,但我相信它们对命名状态,按钮,文本等的实现远不止这些比一般的同类产品有用。

此外,使用canvas元素比使用CSS制作形状并尝试使用JavaScript操纵形状要容易得多。 在我以前使用过骇客作业之后,拥有熟悉的笛卡尔坐标系非常受欢迎。

好多了 凉。 我该怎么办?

开始时您真正需要做的就是创建游戏对象:

参数如下:游戏的宽度(以像素为单位),高度,渲染模式和父元素(“空”表示附加到主体)。 可以使用大量的像素,这有很多优点,但是如果您想获得更快的响应速度,则引擎也可以在全屏模式下工作。 此外,Phaser可以使用canvas或WebGL进行渲染,在这种情况下,它将选择最适合我们的渲染模式。

获得游戏对象后,我们可以创建一些状态。 在这种情况下,我只是制作了一个对象状态,并创建了一些命名状态以在游戏中引用。

这是玩家击中所有障碍物时所显示状态的示例:

您创建的每个状态都需要实现preload()create()update()函数。

preload()函数用于加载状态所需的任何资产。 在这种情况下,我只需要加载图像文件,但是如果我需要任何音乐,tileset,JSON数据或其他任何内容,我也将调用game.load 。 我想指出的一件事是,如果您的资产存储在CDN上,或者存储在除提供JS之外的其他位置,则需要打开game.load.crossOrigin以便正确检索它们。 。

create()函数将用于初始化状态中的变量以及创建需要显示在屏幕上的每个实体。 我需要的状态是一些文本和一个按钮,但是在states.game状态的create()中,我定义了paddle,ball和block实体。

对于此状态,实际上没有任何事情可以执行update()函数,但这通常是该状态的所在。 在游戏状态下, update()函数处理来自玩家的输入,检查球,桨和块之间是否存在碰撞,并根据需要从状态转变为游戏状态。

说到状态之间的转换,您还会注意到我在初始化时直接将回调onClick()分配给了按钮。 在此函数中,我们只需调用this.state.start(’Game’) ,游戏便会切换到States.game状态。

定义所有状态后,将它们分配给游戏对象,如下所示:

并告诉游戏以哪种状态开头:

一切都很好,但是什么时候开始有趣呢?

现在,我们使用的是真实的引擎,我们终于可以利用实际的物理原理,而不是一堆手动的,容易出错的近似值。 让我们看一下我如何创建玩家的球拍:

所以我在这里要做的第一件事就是创建一个精灵添加到游戏中。 我将其xy位置设置为为此函数提供的任何值,并告诉它使用在此状态的preload()函数中加载的“桨状”图像。

将其添加到游戏中后,我将锚点设置为图像的中心。 该游戏并没有真正使用锚点,而不仅仅是将锚点居中,但您可以参考此视频以了解有关锚点以及如何使用锚点的更多信息。

接下来,我将图像缩放为比默认情况下宽的图像,以使桨叶更易于使用。

定位和缩放后,我仅启用了街机物理。 目前,Phaser中提供了三种物理系统,但是对于基本的2D游戏,您将需要使用街机游戏。 在精灵上启用物理功能后,您可以像我一样设置一些标志。 collideWorldBounds标志用于确保操纵杆不会移过游戏世界的左侧或右侧,而不动标志用于告知物理系统如果操纵杆与另一个物理接触,则不会移动。启用精灵(在这种情况下为小球)。

说到球,这是如何创建的:

除了设置跳动率外,物理设置几乎完全相同。 出于我们的目的,我们要说的是,当球与某物碰撞时,它应以与击中另一个物体时相同的速度沿相反的方向反弹。

states.game.create()函数中创建了这些之后,我们只需要在states.game.update()中调用一个方法来检查碰撞并做出响应:

而已?

是的 而已。

不再需要总的“ if(ball.left≤paddle.left || ball.left + ball.width≥paddle.left + paddle.width”的东西。现在,我们让引擎为我们处理它。

那块呢?

他们甚至更容易。 只需创建一个函数即可制作一个块(您可以从createPaddle函数复制其中的大部分内容):

一旦可以创建一个块,就可以在states.game.create()中创建一堆:

从那里检查在states.game.update()中是否存在冲突:

在这种情况下,我们希望在发生碰撞后删除块精灵,并且还希望从块列表中删除该块,以便我们知道玩家何时赢得比赛。

那里还有什么?

没有。

好的,我撒谎了。 这个游戏还有更多功能,而Phaser还有很多功能,但是创建状态,启用物理学以及检查碰撞是您必须了解的主要功能,才能启动Breakout并开始运行。

那么接下来是什么呢?

现在,我正在使用一个真正的引擎,我将开始探索如何使用它。 目前,这意味着将“突破”提升到一个新的水平。 我计划像原始样式一样修补速度和角度,但是还要添加一些缺少的功能,例如生命,水平和音频。 我们将看到发生了什么,但是我很高兴看到它的去向。