相位游戏引擎
Play here: https://hungry-dog.herokuapp.com/
在这里播放: https : //hungry-dog.herokuapp.com/
During a four-day hackathon project, I created a simple food catching game written in JavaScript, using Phaser. Phaser is a 2D game framework that can be used to create HTML games. This article will cover some of the main aspects of creating such a game, namely moving the player, and managing collisions.
在为期四天的黑客马拉松项目中,我使用Phaser创建了一个简单的用JavaScript编写的美食游戏。 Phaser是一个2D游戏框架,可用于创建HTML游戏。 本文将介绍创建此类游戏的一些主要方面,即移动玩家和管理碰撞。
玩家动作 (Player Movements)
The main game assets are the sprites: the player sprite and the falling object sprites. To add animation to the main character, I used the following spritesheet and split it into frames:
游戏的主要资产是精灵:玩家精灵和掉落的对象精灵。 要将动画添加到主要角色,我使用了以下Spritesheet,并将其拆分为帧:
![Image for post](https://miro.medium.com/max/9999/1*CPdfk7RcNzysPEjA7M9wTg.png)
Each scene in Phaser can be broken down into three parts: load, create, and update. In the load function, we can load the spritesheet as follows:
Phaser中的每个场景可以分为三个部分: 加载,创建和更新 。 在加载函数中,我们可以按如下方式加载子画面:
We have to specify the height and width of the frame so that Phaser knows how to split the spritesheet when we create the animations. In the create function, we can then call the following helper function:
我们必须指定框架的高度和宽度,以便Phaser在创建动画时知道如何拆分子画面。 在create函数中,我们可以调用以下帮助器函数:
This selects the frames to be played for certain movements. For example, on line 4, the “left” movement was created using the first two frames on the spritesheet, and on line 17, the “right” movement was created using the last two frames of the spritesheet. Note: instead of having a right-facing sprite, we also could have taken the left-facing sprite and use Phaser’s flipX component to horizontally flip the image.
这为某些动作选择要播放的帧。 例如,在第4行,使用子画面的前两个帧创建“左”移动,在第17行,使用子画面的后两个帧创建“右”移动。 注意:除了拥有一个朝右的精灵外,我们还可以选择朝左的精灵,并使用Phaser的flipX组件水平翻转图像。
We can then use the helper function above to update the player’s movements. This function takes cursors as a parameter and moves the sprite based on the cursors pressed. The first argument of this.play is the key that was defined in the createAnimations helper function. Lines 6, 13, and 24 play the previously defined animations.
然后,我们可以使用上面的帮助器功能来更新玩家的动作。 该函数将光标作为参数,并根据按下的光标移动精灵。 this.play的第一个参数是在createAnimations帮助器函数中定义的键。 第6、13和24行播放以前定义的动画。
碰撞 (Collisions)
Collisions are key! In order for objects to interact with each other, we need to set collisions between them. There are two main steps to do this:
碰撞是关键! 为了使对象彼此交互,我们需要设置它们之间的碰撞。 为此,主要有两个步骤:
- Enable physics 启用物理学
- Add colliders 添加对撞机
For each sprite, I created a class that extends Phaser.Physics.Arcade.Sprite. In each class’s constructor, I added the following code:
对于每个精灵,我创建了一个扩展Phaser.Physics.Arcade.Sprite的类。 在每个类的构造函数中,我添加了以下代码:
this.scene.physics.world.enable(this);
This enables physics on that particular entity, allowing us to use gravity and collisions on it. This allows the objects to fall, bump into each other, disappear upon impact etc. If physics were disabled, objects would just remain statically in the air. For this game, I wanted the main player to land on the ground object, so I added the following collider.
这使该特定实体上的物理学成为可能,从而使我们能够在其上使用重力和碰撞。 这样可以使物体掉落,撞到彼此,撞击后消失等。如果禁用了物理,则物体将仅静态地保留在空中。 对于此游戏,我希望主玩家落在地面物体上,因此添加了以下对撞机。
this.physics.add.collider(this.player, this.groundGroup);
This code allows the player to walk and jump on the ground object. Without this collider, the player would fall through the ground.
该代码允许玩家在地面物体上行走和跳跃。 没有这种对撞机,玩家将掉落地面。
For this game, I wanted the fruits and vegetables to fall off the grid if the player doesn’t catch them. For this reason, no collider was added between the food objects and the ground.
对于这个游戏,我希望水果和蔬菜在玩家没有抓住的情况下掉落。 因此,在食物物体和地面之间未添加任何对撞机。
碰撞提示 (Tips for Collisions)
Tip#1: Set debug:true
提示1:设置debug:true
Collisions can be very tricky! A tip for detecting collision issues is to set debug:true in the Phaser configuration file. This creates a box around each object so we can see if the objects are actually colliding with each other.
碰撞可能非常棘手! 检测冲突问题的技巧是在Phaser配置文件中设置debug:true。 这将在每个对象周围创建一个框,以便我们可以查看这些对象是否实际上在相互碰撞。
Tip#2: Check image margins
提示2:检查图像边距
A problem that I faced during this project, was that even though a collider was added between two objects, the two objects were still falling through each other. After turning on debug mode, I realized that even though the objects appeared to be colliding, the actual image margin of one of the objects was very large but transparent. So the transparent part of one object was actually already overlapping with the second object. Since they were already overlapping, they couldn’t collide! Basically, double check the image margins since they could be transparent and overlapping!
我在该项目中遇到的一个问题是,即使在两个对象之间添加了对撞机,两个对象仍然彼此掉落。 开启调试模式后,我意识到即使对象看起来有冲突,其中一个对象的实际图像余量还是很大,但却是透明的。 因此,一个对象的透明部分实际上已经与第二个对象重叠。 由于它们已经重叠,因此它们无法碰撞! 基本上,请仔细检查图像边距,因为它们可能是透明和重叠的!
Tip#3: refreshBody( )
提示3:refreshBody()
When we scale an object, we need to make sure the changes are updated. refreshBody syncs the position and size of an object with its parent object. If debug mode is enabled, we can see that this syncs the collision boxes. For this project, the ground was made smaller, so refreshBody was called during its creation.
缩放对象时,需要确保更改已更新。 refreshBody将对象的位置和大小与其父对象同步。 如果启用了调试模式,我们可以看到它会同步冲突框。 对于此项目,地面被缩小了,因此在其创建期间调用了refreshBody。
this.groundGroup.create(x, y, "ground").setScale(0.6).refreshBody();
If refreshBody was not called, the image would shrink, but the size of the collision box would remain at the original size, so the objects would not collide properly. As shown below, Phaser thinks the player is colliding with the ground object, but the player is actually jumping in the air!
如果未调用refreshBody,则图像将缩小,但碰撞盒的大小将保持原始大小,因此对象将无法正确碰撞。 如下图所示,Phaser认为玩家正在与地面物体碰撞,但是玩家实际上是在空中跳跃!
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/d1d14d0aad2454860945e177761862d5.png)
坠落物体 (Falling Objects)
The first step in generating falling objects is to load and create the items. For this game I created a group of edible food for the player to catch, and a group of inedible food for the player to avoid. In order to make the game more dynamic, I made the object selection random, as shown below:
生成下落物体的第一步是加载和创建物品。 在此游戏中,我创建了一组可食用的食物供玩家捕捉,并创建了一组不可食用的食物供玩家避免。 为了使游戏更具动态性,我将对象选择随机化,如下所示:
The speed of the object fall can be controlled using gravity. For this project, I set the gravity in the config file as follows:
物体下落的速度可以通过重力来控制。 对于这个项目,我在配置文件中设置引力,如下所示:
gravity: {y:200}
This is the speed that game objects are pulled down along the y-axis. The higher the number, the faster the objects will fall.
这是游戏对象沿y轴下拉的速度。 数字越高,物体掉落的速度越快。
Finally, I also wrote the helper function to continuously drop items from random coordinates. The game window width is 1000, so line 2 causes the items to fall randomly from x-coordinates between 2 and 970. To make the game more challenging, rather than have the player collect all items, I set it so that edible food would be dropped ⅔ of the time and inedible food would be dropped ⅓ of the time.
最后,我还编写了辅助函数,以从随机坐标中连续删除项目。 游戏窗口的宽度为1000,因此第2行导致项目从2到970之间的x坐标随机下降。为了使游戏更具挑战性,而不是让玩家收集所有项目,我将其设置为可食用丢掉1/3的时间,不可食用的食物也会丢掉1/3的时间。
清除被抓物品 (Removing Caught Items)
What happens after an object is caught? The object is removed and the score and life counts are updated. In order to remove the object, we first need to add overlap to disable the object on collision.
捕获物体后会发生什么? 删除对象,并更新分数和寿命计数。 为了删除对象,我们首先需要添加重叠以在碰撞时禁用对象。
In this game, the item is disabled and removed inside the collectEdibles helper function shown below.
在这个游戏中,该物品被禁用,并在如下所示的collectEdibles帮助函数中删除。
最后的润色 (Final Touches)
Finally, in order to make the game more varied, I added multiple levels that the user can select from the home page. To make the game more difficult, I decreased the time delay between each item drop, so that even though the gravity is unchanged, in the harder levels more fruits and vegetables are falling at the same time.
最后,为了使游戏更加多样化,我添加了多个级别,用户可以从主页上进行选择。 为了使游戏更加困难,我减少了每次放下物品之间的时间延迟,以便即使重力不变,在更硬的水平上也同时落下了更多的水果和蔬菜。
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/f9b20889d2d5d5c076dacf7cf74bfd4e.png)
Thanks for reading!
谢谢阅读!
翻译自: https://medium.com/swlh/creating-a-catching-game-using-phaser-fa3a0b3fe5f
相位游戏引擎