From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- .../animations_and_tweens/index.html | 117 +++++++++++++++ .../bounce_off_the_walls/index.html | 49 ++++++ .../build_the_brick_field/index.html | 164 +++++++++++++++++++++ .../2d_breakout_game_phaser/buttons/index.html | 104 +++++++++++++ .../collision_detection/index.html | 59 ++++++++ .../2d_breakout_game_phaser/extra_lives/index.html | 124 ++++++++++++++++ .../2d_breakout_game_phaser/game_over/index.html | 53 +++++++ .../tutorials/2d_breakout_game_phaser/index.html | 57 +++++++ .../initialize_the_framework/index.html | 90 +++++++++++ .../index.html | 71 +++++++++ .../move_the_ball/index.html | 49 ++++++ .../2d_breakout_game_phaser/physics/index.html | 99 +++++++++++++ .../player_paddle_and_controls/index.html | 122 +++++++++++++++ .../randomizing_gameplay/index.html | 61 ++++++++ .../2d_breakout_game_phaser/scaling/index.html | 64 ++++++++ .../2d_breakout_game_phaser/the_score/index.html | 76 ++++++++++ .../win_the_game/index.html | 59 ++++++++ 17 files changed, 1418 insertions(+) create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/animations_and_tweens/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/bounce_off_the_walls/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/build_the_brick_field/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/buttons/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/collision_detection/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/extra_lives/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/game_over/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/initialize_the_framework/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/load_the_assets_and_print_them_on_screen/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/move_the_ball/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/physics/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/player_paddle_and_controls/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/randomizing_gameplay/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/scaling/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/the_score/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_phaser/win_the_game/index.html (limited to 'files/zh-cn/games/tutorials/2d_breakout_game_phaser') diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/animations_and_tweens/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/animations_and_tweens/index.html new file mode 100644 index 0000000000..ff5aa23230 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/animations_and_tweens/index.html @@ -0,0 +1,117 @@ +--- +title: Animations and tweens +slug: Games/Tutorials/2D_breakout_game_Phaser/Animations_and_tweens +tags: + - 2D + - Animation + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial + - tween +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Animations_and_tweens +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Extra_lives", "Games/Workflows/2D_Breakout_game_Phaser/Buttons")}}

+ +
+

这是Gamedev Phaser教程 16 第14步您可以在Gamedev-Phaser-Content-Kit / demos / lesson14.html完成本课程后找到源代码

+
+ +

为了使游戏看起来更加多汁和活泼,我们可以使用动画和补间。这将导致更好,更有趣的体验。让我们来探讨如何在游戏中实现Phaser动画和补间。

+ +

动画

+ +

在Phaser,动画中,涉及从外部来源获取spritesheet并依次显示sprites。作为一个例子,当碰到一些东西时,我们会让球摇摆。

+ +

首先,从Github抓取spritesheet并将其保存在您的/img目录中。

+ +

接下来,我们将加载spritesheet - 将以下行放在preload()函数的底部

+ +
game.load.spritesheet('ball', 'img/wobble.png', 20, 20);
+
+ +

而不是加载单个图像的球,我们可以加载整个spritesheet - 不同图像的集合。我们将按顺序显示精灵,创造动画的幻觉。spritesheet()方法的两个额外的表格确定给定spritesheet文件中每个单个框架的宽度和高度,指示程序如何切割以获取单个框架。

+ +

加载动画

+ +

接下来,进入你的create()函数,找到加载球精灵的行,下面的调用animations.add()如下所示:

+ +
ball = game.add.sprite(50, 250, 'ball');
+ball.animations.add('wobble', [0,1,0,2,0,1,0,2,0], 24);
+
+ +

要向对象添加动画,我们使用该animations.add()方法,其中包含以下参数

+ + + +

当球击中桨时应用动画

+ +

arcade.collide()处理球和桨(第一行内部update(),见下文)之间的碰撞方法调用中,我们可以添加一个额外的参数,该参数指定每次发生碰撞时执行的功能,与该ballHitBrick()功能相同更新内部的第一行update(),如下所示:

+ +
function update() {
+    game.physics.arcade.collide(ball, paddle, ballHitPaddle);
+    game.physics.arcade.collide(ball, bricks, ballHitBrick);
+    paddle.x = game.input.x || game.world.width*0.5;
+}
+
+ +

然后我们可以创建ballHitPaddle()函数(具有ballpaddle作为默认参数),在调用时播放摆动动画。在结束</script>标签之前添加以下方法

+ +
function ballHitPaddle(ball, paddle) {
+    ball.animations.play('wobble');
+}
+
+ +

每次球击中桨时都会播放动画。你也可以animations.play()ballHitBrick()函数添加调用,如果你觉得它会使游戏看起来更好。

+ +

补间

+ +

而动画依次播放外部精灵,补间游戏中物体的属性平滑,如宽度或不透明度。

+ +

让我们在游戏中增加一个补间,使砖块在被球击中时顺利消失。转到您的ballhitBrick()功能,找到您的brick.kill();行,并将其替换为以下内容:

+ +
var killTween = game.add.tween(brick.scale);
+killTween.to({x:0,y:0}, 200, Phaser.Easing.Linear.None);
+killTween.onComplete.addOnce(function(){
+    brick.kill();
+}, this);
+killTween.start();
+
+ +

让我们来看看这里,看看这里发生了什么:

+ +
    +
  1. 当定义一个新的补间时,你必须指定哪些属性将被补间 - 在我们的例子中,而不是在被球击中时立即隐藏砖块,我们将把它们的宽度和高度缩放到零,所以它们将很好地消失。最后,我们使用该add.tween()方法,指定brick.scale为参数,因为这是我们想要补间。
  2. +
  3. to()方法定义补间结束时对象的状态。它需要一个包含所选参数的期望结束值的对象(比例取尺度值,1为大小的100%,0为大小的0%等),补间的时间(以毫秒为单位)以及使用的宽松类型补间。
  4. +
  5. 我们还将添加可选的onComplete事件处理程序,该处理程序定义了在补间程序完成时要执行的函数。
  6. +
  7. 最后一件事是立即开始补间start()
  8. +
+ +

这是补间定义的扩展版本,但是我们也可以使用速记语法:

+ +
game.add.tween(brick.scale).to({x:2,y:2}, 500, Phaser.Easing.Elastic.Out, true, 100);
+
+ +

这个补间将使用弹性宽松在半秒内将砖的比例翻倍,将自动启动,延迟100毫秒。

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/9o4pakrb/","","400")}}

+ +

下一步

+ +

动画和tweens看起来很不错,但我们可以添加更多的我们的游戏 - 在下一节我们将看看处理按钮输入。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Extra_lives", "Games/Workflows/2D_Breakout_game_Phaser/Buttons")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/bounce_off_the_walls/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/bounce_off_the_walls/index.html new file mode 100644 index 0000000000..2cc91361c6 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/bounce_off_the_walls/index.html @@ -0,0 +1,49 @@ +--- +title: Bounce off the walls +slug: Games/Tutorials/2D_breakout_game_Phaser/Bounce_off_the_walls +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial + - bouncing +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Bounce_off_the_walls +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Physics", "Games/Workflows/2D_Breakout_game_Phaser/Player_paddle_and_controls")}}

+ +
+

这是Gamedev Phaser教程 6 Gamedev-Phaser-Content-Kit / demos / lesson06.html完成本课后,您可以找到源代码

+
+ +

现在已经介绍了物理引擎,我们可以开始在游戏中实现碰撞检测 - 首先我们来看看墙壁。

+ +

反弹边界

+ +

让我们的球从墙壁上弹起的最简单的方法是告诉框架,我们想要将<canvas>元素的边界视为墙壁,而不是让球移过它们。在Phaser中,可以使用该collideWorldsBound属性轻松实现在现有game.physics.enable()方法调用之后添加此行

+ +
ball.body.collideWorldBounds = true;
+
+ +

现在球将停在屏幕的边缘,而不是消失,但它不会弹起。为了使这种情况发生,我们必须设置它的bounciness。在上一行下面添加以下行:

+ +
ball.body.bounce.set(1);
+
+ +

再次尝试重新加载index.html - 现在您应该看到球从墙壁上弹起并在画布区域内移动。

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/dcw36opz/","","400")}}

+ +

下一步

+ +

现在开始看起来更像是一个游戏,但是我们无法以任何方式控制它 - 现在是介绍玩家挡板和控制的时候了

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Physics", "Games/Workflows/2D_Breakout_game_Phaser/Player_paddle_and_controls")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/build_the_brick_field/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/build_the_brick_field/index.html new file mode 100644 index 0000000000..981b592469 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/build_the_brick_field/index.html @@ -0,0 +1,164 @@ +--- +title: Build the brick field +slug: Games/Tutorials/2D_breakout_game_Phaser/Build_the_brick_field +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Build_the_brick_field +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Game_over", "Games/Workflows/2D_Breakout_game_Phaser/Collision_detection")}}

+ +
+

这是Gamedev Phaser教程 16 第9步Gamedev-Phaser-Content-Kit / demos / lesson09.html完成本课后,您可以找到源代码

+
+ +

建立砖块比将单个对象添加到屏幕要复杂一点,尽管使用Phaser还是比纯JavaScript更容易。我们来探讨如何创建一组砖块,并使用循环在屏幕上打印。

+ +

定义新变量

+ +

首先,我们定义所需的变量 - 在以前的变量定义中添加以下内容:

+ +
var bricks;
+var newBrick;
+var brickInfo;
+
+ +

bricks变量将用于创建一个组,newBrick将在循环的每次迭代中添加到组中的新对象,brickInfo并将存储我们需要的所有数据。

+ +

渲染砖图像

+ +

接下来,我们加载砖的图像 - load.image()在其他地方添加以下调用:

+ +
function preload() {
+    // ...
+    game.load.image('brick', 'img/brick.png');
+}
+
+ +

您还需要从Github抓取砖图像并将其保存在您的/img目录中。

+ +

画砖

+ +

我们将将所有用于绘制砖块的代码放在一个initBricks函数中,以使其与其余代码分离。initBrickscreate()函数末尾添加一个调用

+ +
function create(){
+    // ...
+    initBricks();
+}
+
+ +

现在到函数本身。initBricks()在我们的游戏代码末尾添加功能,就在关闭</ script>标签之前,如下所示。首先我们已经包括了这个  brickInfo对象,因为这很快就会派上用场:

+ +
function initBricks() {
+    brickInfo = {
+        width: 50,
+        height: 20,
+        count: {
+            row: 7,
+            col: 3
+        },
+        offset: {
+            top: 50,
+            left: 60
+        },
+        padding: 10
+    };
+}
+
+ +

这个brickInfo对象将包含我们需要的所有信息:单个砖的宽度和高度,我们将在屏幕上看到的砖的行数和列数,顶部和左边的偏移量(画布上我们将开始绘制的位置)砖块)和每一列和砖块之间的填充。

+ +

现在,让我们开始创建砖块 - 首先添加一个空组来包含砖块,在initBricks()函数底部添加以下行

+ +
bricks = game.add.group();
+
+ +

我们可以循环遍历行和列,以便在每次迭代中创建新的砖块 - 在上一行代码下面添加以下嵌套循环:

+ +
for(c=0; c<brickInfo.count.col; c++) {
+    for(r=0; r<brickInfo.count.row; r++) {
+        // create new brick and add it to the group
+    }
+}
+
+ +

这样我们将创建我们需要的确切数量的砖,并将它们全部包含在一个组中。现在我们需要在嵌套循环结构中添加一些代码来绘制每个砖块。填写内容如下图所示:

+ +
for(c=0; c<brickInfo.count.col; c++) {
+    for(r=0; r<brickInfo.count.row; r++) {
+        var brickX = 0;
+        var brickY = 0;
+        newBrick = game.add.sprite(brickX, brickY, 'brick');
+        game.physics.enable(newBrick, Phaser.Physics.ARCADE);
+        newBrick.body.immovable = true;
+        newBrick.anchor.set(0.5);
+        bricks.add(newBrick);
+    }
+}
+
+ +

在这里,我们循环遍历行和列,创建新的砖块并将其放在屏幕上。新创建的砖块为Arcade物理引擎启用,它的身体被设置为不可移动(所以当球被击中时它不会移动),我们还将锚点放在中间并添加砖到集团。

+ +

目前的问题是,我们在一个地方绘制所有的砖,坐标(0,0)。我们需要做的是将每个砖块绘制在自己的x和y位置。更新brickXbrickY行如下:

+ +
var brickX = (r*(brickInfo.width+brickInfo.padding))+brickInfo.offset.left;
+var brickY = (c*(brickInfo.height+brickInfo.padding))+brickInfo.offset.top;
+
+ +

每个brickX位置都是brickInfo.widthbrickInfo.padding号乘以行号r,加上brickInfo.offset.left用于所述逻辑brickY是不同之处在于它使用的值列号相同cbrickInfo.heightbrickInfo.offset.top现在每个砖都可以放置在正确的位置,每个砖块之间填充,并从左侧和顶部画布边缘偏移绘制。

+ +

检查initBricks()代码

+ +

这是功能的完整代码initBricks()

+ +
function initBricks() {
+    brickInfo = {
+        width: 50,
+        height: 20,
+        count: {
+            row: 7,
+            col: 3
+        },
+        offset: {
+            top: 50,
+            left: 60
+        },
+        padding: 10
+    }
+    bricks = game.add.group();
+    for(c=0; c<brickInfo.count.col; c++) {
+        for(r=0; r<brickInfo.count.row; r++) {
+            var brickX = (r*(brickInfo.width+brickInfo.padding))+brickInfo.offset.left;
+            var brickY = (c*(brickInfo.height+brickInfo.padding))+brickInfo.offset.top;
+            newBrick = game.add.sprite(brickX, brickY, 'brick');
+            game.physics.enable(newBrick, Phaser.Physics.ARCADE);
+            newBrick.body.immovable = true;
+            newBrick.anchor.set(0.5);
+            bricks.add(newBrick);
+        }
+    }
+}
+
+ +

如果您现在重新加载index.html,您应该看到在屏幕上打印的砖块彼此相距甚远。

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

 

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/cck2b9e8/","","400")}}

+ +

下一步

+ +

有些东西丢失了 球不经停,经过砖块 - 我们需要适当的碰撞检测

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Game_over", "Games/Workflows/2D_Breakout_game_Phaser/Collision_detection")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/buttons/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/buttons/index.html new file mode 100644 index 0000000000..2b29b39714 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/buttons/index.html @@ -0,0 +1,104 @@ +--- +title: Buttons +slug: Games/Tutorials/2D_breakout_game_Phaser/Buttons +tags: + - 2D + - Beginner + - Buttons + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Buttons +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Animations_and_tweens", "Games/Workflows/2D_Breakout_game_Phaser/Randomizing_gameplay")}}

+ +
+

这是Gamedev Phaser教程 16 第15步您可以在Gamedev-Phaser-Content-Kit / demos / lesson15.html完成本课程后找到源代码

+
+ +

而不是立即开始游戏,我们可以通过添加他们可以按的开始按钮将该决定留给玩家。我们来调查如何做到这一点。

+ +

新变量

+ +

我们需要一个变量来存储表示游戏当前是否正在播放的布尔值,另一个代表我们的按钮。将以下行添加到其他变量定义之下:

+ +
var playing = false;
+var startButton;
+
+ +

加载按钮spritesheet

+ +

我们可以加载按钮spritesheet与我们加载球的摆动动画相同的方式。将以下内容添加到preload()函数底部

+ +
game.load.spritesheet('button', 'img/button.png', 120, 40);
+
+ +

单个按钮框架宽120像素,高40像素。

+ +

您还需要从Github抓取按钮spritesheet,并将其保存在您的/img目录中。

+ +

将按钮添加到游戏中

+ +

使用该add.button方法可以将新的按钮添加到游戏中将以下行添加到create()函数的底部

+ +
startButton = game.add.button(game.world.width*0.5, game.world.height*0.5, 'button', startGame, this, 1, 0, 2);
+startButton.anchor.set(0.5);
+
+ +

button()方法的参数如下:

+ + + +
+

注意:超越事件与悬停相同,当指针从按钮中移出时,当按下按钮时,向下移动。

+
+ +

现在我们需要定义startGame()上面代码中引用函数:

+ +
function startGame() {
+    startButton.destroy();
+    ball.body.velocity.set(150, -150);
+    playing = true;
+}
+
+ +

当按下按钮时,我们删除按钮,设置球的初始速度并将playing变量设置true

+ +

最后对于这一部分,回到你的create()函数,找到ball.body.velocity.set(150, -150);一行,并删除它。你只需要按下按钮时移动球,而不是之前!

+ +

在游戏开始之前仍然保持桨

+ +

它按预期工作,但是当游戏尚未开始时,我们仍然可以移动桨,这看起来有点愚蠢。为了阻止这一点,我们可以利用playing变量,使得桨只有在游戏开始时才能移动。要做到这一点,调整update()功能如下所示:

+ +
function update() {
+    game.physics.arcade.collide(ball, paddle, ballHitPaddle);
+    game.physics.arcade.collide(ball, bricks, ballHitBrick);
+    if(playing) {
+        paddle.x = game.input.x || game.world.width*0.5;
+    }
+}
+
+ +

这样一来,在所有的装载和准备之后,但在实际游戏开始之前,桨是不可移动的。

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/1rpj71k4/","","400")}}

+ +

下一步

+ +

在本系列文章中我们将做的最后一件事情是,通过添加一些随机化的方式,球从球上弹起来,使游戏更有趣

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Animations_and_tweens", "Games/Workflows/2D_Breakout_game_Phaser/Randomizing_gameplay")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/collision_detection/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/collision_detection/index.html new file mode 100644 index 0000000000..1977d93fb9 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/collision_detection/index.html @@ -0,0 +1,59 @@ +--- +title: Collision detection +slug: Games/Tutorials/2D_breakout_game_Phaser/Collision_detection +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial + - collision detection +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Collision_detection +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Build_the_brick_field", "Games/Workflows/2D_Breakout_game_Phaser/The_score")}}

+ +
+

这是Gamedev Phaser教程 16 第10步您可以在Gamedev-Phaser-Content-Kit / demos / lesson10.html完成本课程后找到源代码

+
+ +

现在接下来的挑战 - 球和砖块之间的碰撞检测。幸运的是,我们可以使用物理引擎来检查单个对象(如球和桨)之间的碰撞,也可以检测对象和组之间的碰撞。

+ +

砖/球碰撞检测

+ +

物理引擎使一切都变得更容易 - 我们只需要添加两个简单的代码。首先,在你的update()函数中添加一行,检查球和砖之间的碰撞检测,如下所示:

+ +
function update() {
+    game.physics.arcade.collide(ball, paddle);
+    game.physics.arcade.collide(ball, bricks, ballHitBrick);
+    paddle.x = game.input.x || game.world.width*0.5;
+}
+
+ +

球的位置是根据组中所有砖的位置计算的。第三个可选参数是发生冲突时执行的功能ballHitBrick()创建这个新功能作为代码的底部,就在结束</script>标签之前,如下所示:

+ +
function ballHitBrick(ball, brick) {
+    brick.kill();
+}
+
+ +

就是这样!重新加载你的代码,你应该看到新的碰撞检测工作正常。

+ +

感谢Phaser,有两个参数传递给函数 - 第一个是球,我们在碰撞方法中明确定义,第二个是球碰撞的砖组中的单个砖。在功能内部,我们从屏幕上删除所讨论的砖块,只需运行其kill()方法即可。

+ +

您将期望在使用纯JavaScript时编写更多自己的计算机来实现碰撞检测这是使用框架的好处 - 您可以为Phaser留下大量无聊的代码,并专注于制作游戏中最有趣和最有趣的部分。

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/wwneakwf/","","400")}}

+ +

下一步

+ +

我们可以打砖块并删除它们,这已经是游戏的一个很好的补充。结果,更好地计算被毁砖增加得分

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Build_the_brick_field", "Games/Workflows/2D_Breakout_game_Phaser/The_score")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/extra_lives/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/extra_lives/index.html new file mode 100644 index 0000000000..81143d4c14 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/extra_lives/index.html @@ -0,0 +1,124 @@ +--- +title: Extra lives +slug: Games/Tutorials/2D_breakout_game_Phaser/Extra_lives +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial + - lives +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Extra_lives +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Win_the_game", "Games/Workflows/2D_Breakout_game_Phaser/Animations_and_tweens")}}

+ +
+

这是Gamedev Phaser教程 16 第13步您可以在Gamedev-Phaser-Content-Kit / demos / lesson13.html完成本课程后找到源代码

+
+ +

我们可以通过增加生活使游戏更愉快。在这篇文章中,我们将实施一个生活系统,以便玩家可以继续玩,直到他们失去了三个生命,而不仅仅是一个人。

+ +

新变量

+ +

在代码中的现有添加下面添加以下新变量:

+ +
var lives = 3;
+var livesText;
+var lifeLostText;
+
+ +

这些分别将存储生命数,显示剩余生命数的文本标签,以及当玩家失去生命之后将在屏幕上显示的文本标签。

+ +

定义新的文本标签

+ +

定义文本看起来像我们已经在分数课上已经做scoreTextcreate()函数的现有定义下方添加以下行

+ +
livesText = game.add.text(game.world.width-5, 5, 'Lives: '+lives, { font: '18px Arial', fill: '#0095DD' });
+livesText.anchor.set(1,0);
+lifeLostText = game.add.text(game.world.width*0.5, game.world.height*0.5, 'Life lost, click to continue', { font: '18px Arial', fill: '#0095DD' });
+lifeLostText.anchor.set(0.5);
+lifeLostText.visible = false;
+
+ +

livesTextlifeLostText物体看起来非常相似的scoreText一个-它们定义在屏幕上的位置,显示实际文本和字体样式。前者被锚定在其右上边缘上,与屏幕正确对齐,后者位于中心位置,两者均使用anchor.set()

+ +

lifeLostText会表示,只有当生命消失,因此其知名度初始设置为false

+ +

使我们的文字造型干燥

+ +

正如你可能已经注意到,我们使用相同的造型为三种文本:scoreTextlivesTextlifeLostText如果我们想要更改字体大小或颜色,我们必须在多个地方进行。为了使我们更容易维护,将来我们可以创建一个单独的变量来保存我们的样式,让我们textStyle将其调用并放在文本定义之前:

+ +
textStyle = { font: '18px Arial', fill: '#0095DD' };
+
+ +

现在我们可以在使用文本标签的时候使用这个变量 - 更新你的代码,使文本样式的多个实例被替换为变量:

+ +
scoreText = game.add.text(5, 5, 'Points: 0', textStyle);
+livesText = game.add.text(game.world.width-5, 5, 'Lives: '+lives, textStyle);
+livesText.anchor.set(1,0);
+lifeLostText = game.add.text(game.world.width*0.5, game.world.height*0.5, 'Life lost, click to continue', textStyle);
+lifeLostText.anchor.set(0.5);
+lifeLostText.visible = false;
+
+ +

这样一来,改变一个变量中的字体将会将更改应用于每个使用的地方。

+ +

生活处理代码

+ +

为了在我们的游戏中实现生活,让我们先改变球对onOutOfBounds事件的影响。而不是执行匿名函数并立即显示警报:

+ +
ball.events.onOutOfBounds.add(function(){
+    alert('Game over!');
+    location.reload();
+}, this);
+
+ +

我们将分配一个所谓的新功能ballLeaveScreen删除以前的事件处理程序(如上所示),并将其替换为以下行:

+ +
ball.events.onOutOfBounds.add(ballLeaveScreen, this);
+
+ +

我们想减少每次球离开帆布的人数。ballLeaveScreen()在代码末尾添加函数定义:

+ +
function ballLeaveScreen() {
+    lives--;
+    if(lives) {
+        livesText.setText('Lives: '+lives);
+        lifeLostText.visible = true;
+        ball.reset(game.world.width*0.5, game.world.height-25);
+        paddle.reset(game.world.width*0.5, game.world.height-5);
+        game.input.onDown.addOnce(function(){
+            lifeLostText.visible = false;
+            ball.body.velocity.set(150, -150);
+        }, this);
+    }
+    else {
+        alert('You lost, game over!');
+        location.reload();
+    }
+}
+
+ +

而不是立即打印警报,当你失去了一生,我们首先从当前的数字减去一个生命,并检查它是否是一个非零值。如果是,那么玩家还是有一些生命剩下,可以继续玩 - 他们会看到生命中的消息,球和桨的位置将被重置在屏幕上和下一个输入(点击或触摸),消息将被隐藏球将再次开始移动。

+ +

当可用生活数量达到零时,游戏结束,并显示游戏过期警报消息。

+ +

事件

+ +

您可能已经注意到了add(),并addOnce()在上面的两个代码块的方法调用,并想知道它们的区别。不同之处在于,该add()方法绑定给定的函数,并使其在每次事件发生时执行,同时addOnce()当您希望绑定函数只执行一次,然后解除绑定时有用,因此不会再次执行。在我们的例子中,每个outOfBounds事件ballLeaveScreen都将被执行,但当球离开屏幕时,我们只想从屏幕上删除一次消息。

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/yk1c5n0b/","","400")}}

+ +

下一步

+ +

生活让游戏更加宽容 - 如果你失去一个生命,你还剩下两个,可以继续玩。现在让我们通过添加动画和补间来扩展游戏的外观和感觉

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Win_the_game", "Games/Workflows/2D_Breakout_game_Phaser/Animations_and_tweens")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/game_over/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/game_over/index.html new file mode 100644 index 0000000000..d91bcc5e3b --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/game_over/index.html @@ -0,0 +1,53 @@ +--- +title: Game over +slug: Games/Tutorials/2D_breakout_game_Phaser/Game_over +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial + - game over +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Game_over +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Player_paddle_and_controls", "Games/Workflows/2D_Breakout_game_Phaser/Build_the_brick_field")}}

+ +
+

这是Gamedev Phaser教程 16 第8步Gamedev-Phaser-Content-Kit / demos / lesson08.html完成本课后,您可以找到源代码

+
+ +

为了使游戏更有趣,我们可以引入失去的能力 - 如果在到达屏幕底部边缘之前没有击球,那么这个游戏将会结束。

+ +

如何输

+ +

为了提供丢失的能力,我们将禁用球与屏幕底部的碰撞。create()函数内添加下面的代码刚刚定义球的属性就好了:

+ +
game.physics.arcade.checkCollision.down = false;
+
+ +

这将使三个墙壁(顶部,左侧和右侧)弹回球,但是第四个(底部)将消失,如果桨错过,则球从屏幕上脱落。我们需要一种方法来检测并相应地采取行动。在以前的新的下方添加以下行:

+ +
ball.checkWorldBounds = true;
+ball.events.onOutOfBounds.add(function(){
+    alert('Game over!');
+    location.reload();
+}, this);
+
+ +

添加这些行将使得球检查世界(在我们的例子中是画布)边界并执行绑定到onOutOfBounds事件的函数当您点击生成的警报时,页面将被重新加载,以便您可以再次播放。

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/436bckb7/","","400")}}

+ +

下一步

+ +

现在的基本游戏就是让我们通过引入砖块来更有趣的是 - 现在是建造砖块的时候了

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Player_paddle_and_controls", "Games/Workflows/2D_Breakout_game_Phaser/Build_the_brick_field")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/index.html new file mode 100644 index 0000000000..9f283f7774 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/index.html @@ -0,0 +1,57 @@ +--- +title: 使用Phaser开发2D breakout game +slug: Games/Tutorials/2D_breakout_game_Phaser +tags: + - Phaser + - 教程 + - 游戏 +translation_of: Games/Tutorials/2D_breakout_game_Phaser +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{Next("Games/Workflows/2D_Breakout_game_Phaser/Initialize_the_framework")}}

+ +

在这个手把手的教程中,我们将使用Phaser框架制作一个使用JavaScript构建简单的MDN消除游戏。

+ +

教程的每一步骤都会有可供修改的样品来玩,所以你可以看到开发的每一步中间步骤。 您将学到如何使用Phaser框架来实现基础游戏机制的基本知识,诸如渲染和移动图像,碰撞检测,控制机制,框架特定的帮助器功能,动画和补间,以及获胜和失败状态等。

+ +

为了充分理解这一系列的文章,您应该确保已有基本的中级JavaScript知识。学完本教程,您将有能力用Phaser构建简单的Web游戏。

+ +

Gameplay screen from the game MDN Breakout created with Phaser where you can use your paddle to bounce the ball and destroy the brick field, with keeping the points and lives.

+ +

教学清单

+ +

所有的课程 — 以及我们接下来将一起做的各个版本的 MDN Breakout game  都能在 GitHub上找到

+ +
    +
  1. 初始化框架
  2. +
  3. 缩放
  4. +
  5. 加载资源并在屏幕上打印
  6. +
  7. 移动小球
  8. +
  9. 物理
  10. +
  11. 从墙上弹开
  12. +
  13. 弹块和控制
  14. +
  15. 游戏结束
  16. +
  17. 建立砖块
  18. +
  19. 碰撞检测
  20. +
  21. 得分
  22. +
  23. 胜利
  24. +
  25. 额外生命
  26. +
  27. 动画与补间
  28. +
  29. 按钮
  30. +
  31. 随机游戏
  32. +
+ +

学习路线的小提示 — 最好先熟悉使用原生JavaScript进行网页游戏开发,这样可以打下坚实的基础.如果你还不熟悉原生javascript开发,我们建议你先过一遍这个系列, 使用原生Javascript开发MDN消除游戏.

+ +

在那之后,你就能随意挑选框架并用在你的项目中;我们选择了Phaser这个稳定优越的框架,它有着好的支持和社区环境以及大量优秀的插件. 框架加速了开发并能帮你管理无趣的部分,让你专注于有意思的事务. 然而, 框架也有不好的地方, 所以当一些意想不到的事情发生了或者想实现一些框架没有提供的功能时,你就将需要原生的JavaScript知识了.

+ +
+

注意: 本系列文章可用作实际游戏开发的材料。 如果您想要使用Phaser讨论游戏开发,您还可以使用基于本教程的 Gamedev Phaser内容套件.

+
+ +

Next steps

+ +

好了,那我们就开始吧!前往系列第一部分 — 初始化框架.

+ +

{{Next("Games/Workflows/2D_Breakout_game_Phaser/Initialize_the_framework")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/initialize_the_framework/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/initialize_the_framework/index.html new file mode 100644 index 0000000000..ed6ef03718 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/initialize_the_framework/index.html @@ -0,0 +1,90 @@ +--- +title: Initialize the framework +slug: Games/Tutorials/2D_breakout_game_Phaser/Initialize_the_framework +tags: + - Canvas + - HTML + - JavaScript + - Phaser + - 二维 + - 入门 + - 教程 + - 游戏 +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Initialize_the_framework +--- +
{{GamesSidebar}}
{{IncludeSubnav("/zh-CN/docs/Games")}}
+ +

{{PreviousNext("Games/Tutorials/2D_Breakout_game_Phaser", "Games/Tutorials/2D_Breakout_game_Phaser/Scaling")}}

+ +
+

这是Gamedev Phaser教程系列的第一课. 在课程完成之后,你可以在Gamedev-Phaser-Content-Kit/demos/lesson01.html找到源码.

+
+ +

在我们开始写游戏的功能之前,我们需要创建一个用来内部渲染游戏的基础架构.使用HTML就能做到 — Parser框架将生成所需的 {{htmlelement("canvas")}} 元素.

+ +

游戏的HTML

+ +

HTML文档结构非常的简单,这个游戏将整个被渲染在框架生成的{{htmlelement("canvas")}} 元素上. 拿起你最爱的编辑器,挑一个好目录,创建一个HTML文档,存成index.html,然后写下下面的代码:

+ +
<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <title>Gamedev Phaser Workshop - lesson 01: Initialize the framework</title>
+    <style>* { padding: 0; margin: 0; }</style>
+    <script src="js/phaser.min.js"></script>
+</head>
+<body>
+<script>
+    var game = new Phaser.Game(480, 320, Phaser.AUTO, null, {
+      preload: preload, create: create, update: update
+    });
+    function preload() {}
+    function create() {}
+    function update() {}
+</script>
+</body>
+</html>
+
+ +

下载Phaser

+ +

下面我们将下载Phaser的代码,并应用到我们的HTML文档中.

+ +
    +
  1. 进入 Phaser 下载页面.
  2. +
  3. 选择最适合你的下载项 — 我们建议选择min.js,因为它最小,而且你不太可能想去看它的源码
  4. +
  5. 将Phaser的源码存到一个和index.html同级的 /js 的目录下
  6. +
  7. 在上面第一个 {{htmlelement("script")}} 标签里写下phaser的路径.
  8. +
+ +

捋一捋我们干了些啥

+ +

这个时候我们在 {{htmlelement("header")}} 里定义了 {{htmlelement("charset")}} ,{{htmlelement("title")}} 和一些基础的css来重置默认的margin和padding. 我们也用 {{htmlelement("script")}} 标签向页面引入了 Phaser 源码。{{htmlelement("body ")}} 里也有一个 {{htmlelement("script")}} 标签,我们将在里面写 JavaScript 代码来渲染和控制游戏。

+ +

{{htmlelement("canvas")}} 元素是由框架自动生成的。我们是通过 Phaser.Game 创建一个对象并赋给了 game 变量来完成初始化的。参数的含义是:

+ + + +

完整示例

+ +

以下是第一章的完整代码,可以直接在 JSFiddle 中运行:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/h6cwzv2b/","","400")}}

+ +

下一步

+ +

现在我们已经完成了一个简单的 HTML 页面,并且学习了如何安装 Phaser, 让我们继续学习第二章: scaling.

+ +

{{PreviousNext("Games/Tutorials/2D_Breakout_game_Phaser", "Games/Tutorials/2D_Breakout_game_Phaser/Scaling")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/load_the_assets_and_print_them_on_screen/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/load_the_assets_and_print_them_on_screen/index.html new file mode 100644 index 0000000000..135bcee403 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/load_the_assets_and_print_them_on_screen/index.html @@ -0,0 +1,71 @@ +--- +title: Load the assets and print them on screen +slug: >- + Games/Tutorials/2D_breakout_game_Phaser/Load_the_assets_and_print_them_on_screen +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Sprites + - Tutorial +translation_of: >- + Games/Tutorials/2D_breakout_game_Phaser/Load_the_assets_and_print_them_on_screen +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Scaling", "Games/Workflows/2D_Breakout_game_Phaser/Move the ball")}}

+ +
+

这是Gamedev Phaser教程 16 第三步您可以在Gamedev-Phaser-Content-Kit / demos / lesson03.html完成本课程后找到源代码

+
+ +

我们的游戏将围绕屏幕滚动,弹出一个桨,摧毁砖块赚取积分 - 熟悉吗?在本文中,我们将介绍如何将sprite添加到我们的gameworld中。

+ +

有一个球

+ +

我们开始创建一个JavaScript变量来表示我们的球 - 在游戏初始化代码(我们的var game...块)和preload()函数之间添加以下行

+ +
var ball;
+
+ +
+

注意:为了本教程,我们将使用全局变量。本教程的目的是教导Phaser特定的游戏开发方法,而不是主观的最佳方法。

+
+ +

加载球精灵

+ +

使用Phaser加载图像并将其打印在我们的画布上比使用纯JavaScript容易得多。要加载资产,我们将使用game由Phaser创建对象,执行其load.image()方法。preload()函数的底部添加以下新行

+ +
function preload() {
+    // ...
+    game.load.image('ball', 'img/ball.png');
+}
+
+ +

第一个参数是我们要提供资产的名称 - 这将在我们的游戏代码中使用,例如我们的ball变量名称,所以我们需要确保它是一样的。第二个参数是图形资源的相对路径。在我们的情况下,我们将加载我们的球的图像(请注意,文件名不一定是一致的,但我们建议,因为它使一切更容易遵循。)

+ +

当然,要加载图像,它需要在我们的代码目录中可用。从Github抓住球图像,并将其保存/img在与index.html文件相同位置目录中

+ +

现在,要在屏幕上显示,我们将使用另一种Phaser方法add.sprite()create()函数内添加以下新的代码行,如图所示:

+ +
function create() {
+    ball = game.add.sprite(50, 50, 'ball');
+}
+
+ +

这将添加球到游戏,并将其呈现在屏幕上。前两个参数是要添加的画布的x和y坐标,第三个是我们之前定义的资产的名称。就是这样 - 如果你加载你的index.html文件,你会看到已经加载并在画布上渲染的图像!

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/98xrv9x5/","","400")}}

+ +

下一步

+ +

打出球很容易; 接下来我们将尝试在屏幕上移动球

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Scaling", "Games/Workflows/2D_Breakout_game_Phaser/Move the ball")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/move_the_ball/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/move_the_ball/index.html new file mode 100644 index 0000000000..331d02cfab --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/move_the_ball/index.html @@ -0,0 +1,49 @@ +--- +title: Move the ball +slug: Games/Tutorials/2D_breakout_game_Phaser/Move_the_ball +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial + - moving +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Move_the_ball +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Load_the_assets_and_print_them_on_screen", "Games/Workflows/2D_Breakout_game_Phaser/Physics")}}

+ +
+

这是Gamedev Phaser教程 16 第4步Gamedev-Phaser-Content-Kit / demos / lesson04.html完成本课后,您可以找到源代码

+
+ +

我们在屏幕上打印了我们的蓝色球,但它什么都不做,这样做会很酷。本文介绍如何做到这一点。

+ +

在每个框架上更新球的位置

+ +

记住update()功能及其定义?其中的代码在每个框架上执行,所以它是一个完美的地方,将代码更新球的位置在屏幕上。在里面添加以下新行代码update(),如下所示:

+ +
function update() {
+    ball.x += 1;
+    ball.y += 1;
+}
+
+ +

上面的代码在每个框架上为表示画布上的球坐标的属性xy属性添加了一个。重新加载index.html,你应该看到球在屏幕上滚动。

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/g1cfp0vv/","","400")}}

+ +

下一步

+ +

下一步是添加一些基本的碰撞检测,所以我们的球可以从墙壁反弹。这将需要几行代码 - 一个比我们迄今为止看到的更复杂的步骤,特别是如果我们也想添加桨和砖碰撞 - 但是幸运的是Phaser使我们比我们想要使用纯粹的方法更容易做到这一点JavaScript的。

+ +

无论如何,在我们做所有的事情之前,我们将首先介绍Phaser的物理引擎,并做一些设置工作。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Load_the_assets_and_print_them_on_screen", "Games/Workflows/2D_Breakout_game_Phaser/Physics")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/physics/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/physics/index.html new file mode 100644 index 0000000000..4f908a9bc2 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/physics/index.html @@ -0,0 +1,99 @@ +--- +title: Physics +slug: Games/Tutorials/2D_breakout_game_Phaser/Physics +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial + - physics +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Physics +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Move_the_ball", "Games/Workflows/2D_Breakout_game_Phaser/Bounce_off_the_walls")}}

+ +
+

这是Gamedev Phaser教程 16 第5步您可以在Gamedev-Phaser-Content-Kit / demos / lesson05.html完成本课程后找到源代码

+
+ +

为了在我们的游戏中的对象之间进行正确的碰撞检测,我们将需要物理学; 本文将向您介绍Phaser中的可用内容,以及演示典型的简单设置。

+ +

添加物理效果

+ +

Phaser与三个不同的物理引擎(Arcade Physics,P2和Ninja Physics)捆绑在一起,第四个选项Box2D可作为商业插件使用。对于像我们这样的简单游戏,我们可以使用Arcade Physics引擎。我们不需要任何重的几何计算 - 毕竟只是一个球从墙壁和砖块弹起来。

+ +

首先,让我们在游戏中初始化Arcade Physics引擎。physics.startSystem()create函数开头添加方法(使其成为函数内的第一行),如下所示:

+ +
game.physics.startSystem(Phaser.Physics.ARCADE);
+
+ +

接下来,我们需要为物理系统启用我们的球 - 默认情况下,Phaser对象物理不启用。create()函数底部添加以下行

+ +
game.physics.enable(ball, Phaser.Physics.ARCADE);
+
+ +

接下来,如果我们要在屏幕上移动我们的球,我们可以设置velocitybody再次添加以下行create()

+ +
ball.body.velocity.set(150, 150);
+
+ +

删除我们以前的更新说明

+ +

记得删除添加值的我们的老方法x,并yupdate()功能:

+ +
function update() {
+    ball.x += 1;
+    ball.y += 1;
+}
+
+ +

我们正在使用物理引擎正确处理。

+ +

最终代码检查

+ +

最新的代码应该如下所示:

+ +
var ball;
+
+function preload() {
+    game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
+    game.scale.pageAlignHorizontally = true;
+    game.scale.pageAlignVertically = true;
+    game.stage.backgroundColor = '#eee';
+    game.load.image('ball', 'img/ball.png');
+}
+
+function create() {
+    game.physics.startSystem(Phaser.Physics.ARCADE);
+    ball = game.add.sprite(50, 50, 'ball');
+    game.physics.enable(ball, Phaser.Physics.ARCADE);
+    ball.body.velocity.set(150, 150);
+}
+
+function update() {
+}
+
+ +

尝试重新加载index.html- 球应该在给定的方向上不断移动。目前,物理引擎的重力和摩擦力设定为零。增加重力将导致球落下,同时摩擦力最终会停止球。

+ +

物理效果趣味

+ +

你可以用物理学来做更多的事情,例如添加ball.body.gravity.y = 100;你将设置球的垂直重力。因此,它将向上发射,但是由于重力的作用而下降。

+ +

这种功能只是冰山一角 - 有各种功能和变量可以帮助您操纵物理对象。查看官方物理文档,并使用ArcadeP2物理系统查看大量示例

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/bjto9nj8/","","400")}}

+ +

下一步

+ +

现在我们可以转到下一课,看看如何让球从墙上弹起

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Move_the_ball", "Games/Workflows/2D_Breakout_game_Phaser/Bounce_off_the_walls")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/player_paddle_and_controls/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/player_paddle_and_controls/index.html new file mode 100644 index 0000000000..07ee9e7ee7 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/player_paddle_and_controls/index.html @@ -0,0 +1,122 @@ +--- +title: Player paddle and controls +slug: Games/Tutorials/2D_breakout_game_Phaser/Player_paddle_and_controls +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Player_paddle_and_controls +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Bounce_off_the_walls", "Games/Workflows/2D_Breakout_game_Phaser/Game_over")}}

+ +
+

这是Gamedev Phaser教程 16 第7步您可以在Gamedev-Phaser-Content-Kit / demos / lesson07.html完成本课程后找到源代码

+
+ +

我们有球从墙上移动并弹跳,但它很快变得无聊 - 没有互动!我们需要一种介绍游戏的方法,所以在这篇文章中,我们将创建一个桨来移动并击中球。

+ +

渲染桨

+ +

从框架的角度看,桨非常类似于球 - 我们需要添加一个变量来表示它,加载相关的图像资源,然后做出魔法。

+ +

装载桨

+ +

首先,添加paddle我们将在我们的游戏中使用的ball变量,就在变量之后:

+ +
var paddle;
+
+ +

然后,在该preload功能中,paddle通过添加以下新load.image()调用来加载图像

+ +
function preload() {
+    // ...
+    game.load.image('ball', 'img/ball.png');
+    game.load.image('paddle', 'img/paddle.png');
+}
+
+ +

添加桨图形

+ +

所以我们不要忘记,在这一点上,你应该从Github 抓住这个图形,并保存在你的/img文件夹中。

+ +

渲染桨用物理引擎

+ +

接下来,我们将通过add.sprite()create()函数中添加以下调用来初始化我们的桨,将其添加到底部:

+ +
paddle = game.add.sprite(game.world.width*0.5, game.world.height-5, 'paddle');
+
+ +

我们可以使用world.widthworld.height值来将桨定位到我们想要的位置:game.world.width*0.5将在屏幕中间。在我们这个例子中,世界和画布是一样的,但是对于其他类型的游戏,例如侧滚滚,这个世界会变大,你可以修改它来创造有趣的效果。

+ +

你会注意到,如果你index.html在这一点上重新加载,那么桨是目前不完全在中间的。为什么?因为计算位置的锚总是从对象的左上角开始。我们可以改变它,使锚在桨的宽度的中间和它的高度的底部,所以更容易将其定位在底部边缘。添加以下新行以下的行:

+ +
paddle.anchor.set(0.5,1);
+
+ +

桨现在位于我们想要的地方。现在,为了使它与球碰撞,我们必须为桨提供物理效果。继续添加以下新行,再次在create()函数的底部

+ +
game.physics.enable(paddle, Phaser.Physics.ARCADE);
+
+ +

现在,魔法可以开始发生 - 该框架可以在每个框架上检查碰撞检测。要启用桨和球之间的碰撞检测,请将collide()方法添加到如下update()功能中:

+ +
function update() {
+    game.physics.arcade.collide(ball, paddle);
+}
+
+ +

第一个参数是我们感兴趣的对象之一 - 球 - 第二个是另一个,桨。这有效,但不如我们预期的那样 - 当球击中桨时,桨从屏幕上掉下来!我们想要的就是球从跳板上跳起来,而桨子停在同一个地方。我们可以将body设置成immovable球,所以当球击中它时不会移动。为此,请在create()函数底部添加以下行

+ +
paddle.body.immovable = true;
+
+ +

现在它按预期工作。

+ +

控制桨

+ +

接下来的问题是我们不能移动桨。要做到这一点,我们可以使用系统的默认输入(鼠标或触摸,取决于平台),并将桨位置设置到位置的input位置。将以下新行添加到update()函数中,如下所示:

+ +
function update() {
+    game.physics.arcade.collide(ball, paddle);
+    paddle.x = game.input.x;
+}
+
+ +

现在在每个新的一帧上,桨的x位置将根据输入的x位置进行调整,但是当我们开始游戏时,桨的位置不在中间。这是因为输入位置尚未定义。要修复,我们可以将默认位置(如果输入位置尚未定义)设置为屏幕中间。更新上一行如下:

+ +
paddle.x = game.input.x || game.world.width*0.5;
+
+ +

如果您还没有这样做,请重新加载index.html并尝试!

+ +

定位球

+ +

我们有桨按预期工作,所以我们把球放在上面。它非常类似于定位桨 - 我们需要将其放置在屏幕中间水平和垂直的底部,与底部有一点偏移。要按照我们想要的方式放置它,我们将把锚定位到球的正中间。找到现有的行,并将其替换为以下两行:ball = game.add.sprite( ... )

+ +
ball = game.add.sprite(game.world.width*0.5, game.world.height-25, 'ball');
+ball.anchor.set(0.5);
+ +

速度保持不变 - 我们只是将第二个参数的值从150改为-150,所以球将通过向上移动而不是下降来开始游戏。查找现有ball.body.velocity.set( ... )行并将其更新为以下内容:

+ +
ball.body.velocity.set(150, -150);
+
+ +

现在球将从桨的中间开始。

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/ogqza0ye/","","400")}}

+ +

下一步

+ +

我们可以移动桨,并将球反弹,但是如果球从屏幕的底部边缘反弹,那又有什么意义?我们来介绍丢失的可能性 - 也称为游戏逻辑。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Bounce_off_the_walls", "Games/Workflows/2D_Breakout_game_Phaser/Game_over")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/randomizing_gameplay/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/randomizing_gameplay/index.html new file mode 100644 index 0000000000..8642ed4eb7 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/randomizing_gameplay/index.html @@ -0,0 +1,61 @@ +--- +title: Randomizing gameplay +slug: Games/Tutorials/2D_breakout_game_Phaser/Randomizing_gameplay +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Randomizing_gameplay +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{Previous("Games/Workflows/2D_Breakout_game_Phaser/Buttons")}}

+ +
+

这是Gamedev Phaser教程 16中的16步您可以在Gamedev-Phaser-Content-Kit / demos / lesson16.html完成本课程后找到源代码

+
+ +

我们的游戏似乎已经完成了,但是如果你看起来足够近,你会发现球在整个游戏中都以相同的角度从桨上弹起。这意味着每个游戏都非常相似。为了解决这个问题,提高可玩性,我们应该使反弹角度更加随机,在本文中我们将介绍一下如何。

+ +

让篮板更随机

+ +

我们可以根据撞击桨的确切位置来改变球的速度,通过使用沿着下方的线路运行功能来修改x速度ballHitPaddle()现在添加这一行到您的代码,并尝试。

+ +
function ballHitPaddle(ball, paddle) {
+    ball.animations.play('wobble');
+    ball.body.velocity.x = -1*5*(paddle.x-ball.x);
+}
+ +

这有点魔法 - 新的速度越高,桨的中心和球撞到的地方之间的距离就越大。此外,方向(左或右)由该值确定 - 如果球击中桨的左侧,则其将向左反弹,而击球右侧将向右反弹。最终这样做是因为对某些值进行了一些实验,您可以进行自己的实验,看看会发生什么。这当然不是完全随机的,但它确实使游戏玩法变得更加不可预测,因此更有趣。

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/3yds5ege/","","400")}}

+ +

概要

+ +

你已经完成了所有的课程 - 恭喜你!在这一点上,您将了解到Phaser的基础知识和简单2D游戏背后的逻辑。

+ +

练习跟随

+ +

你可以在游戏中做更多的事情 - 添加任何你觉得最好的东西,使它更有趣和有趣。Phaser提供的无数有用的方法的基本介绍。以下是关于如何扩展我们的小游戏的一些建议,让您开始:

+ + + +

一定要检查越来越多的示例列表官方文档如果您需要任何帮助,请访问HTML5 Gamedevs论坛

+ +

您也可以返回本教程系列的索引页

+ +

{{Previous("Games/Workflows/2D_Breakout_game_Phaser/Buttons")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/scaling/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/scaling/index.html new file mode 100644 index 0000000000..063f95aba9 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/scaling/index.html @@ -0,0 +1,64 @@ +--- +title: Scaling +slug: Games/Tutorials/2D_breakout_game_Phaser/Scaling +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Scaling +--- +
{{GamesSidebar}}
{{IncludeSubnav("/zh-CN/docs/Games")}}
+ +

{{PreviousNext("Games/Tutorials/2D_Breakout_game_Phaser/Initialize_the_framework", "Games/Tutorials/2D_Breakout_game_Phaser/Load_the_assets_and_print_them_on_screen")}}

+ +
+

这是Gamedev Phaser教程系列的第二课. 在课程完成之后,你可以在Gamedev-Phaser-Content-Kit/demos/lesson02.html找到源码.

+
+ +

缩放是指游戏画布如何在不同的屏幕尺寸上进行显示。我们可以在预加载阶段自动使游戏规模适合任何屏幕尺寸,之后就可以不用再担心屏幕尺寸的问题了。

+ +

Phaser中scale对象

+ +

Phaser中有一个特殊的对象:scale它包含一些特别的方法和属性。让我们来更改一下上一节中创建的的preload()函数

+ +
function preload() {
+    game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
+    game.scale.pageAlignHorizontally = true;
+    game.scale.pageAlignVertically = true;
+}
+
+ +

scaleMode 有几个不同的选项来指定 Canvas 应该如何缩放:

+ + + +

preload()中的其他两行代码负责水平和垂直居中画布,所以它始终以屏幕为中心,无论大小如何。

+ +

设置背景颜色

+ +

我们还可以给画布设置背景颜色来替代磨人的黑色背景。通过更改stage对象的backgroundColor属性来添加,我们可以使用CSS颜色定义语法进行设置。我们在刚才的代码下面添加以下代码:

+ +
game.stage.backgroundColor = '#eee';
+
+ +

完整的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/6a64vecL/","","400")}}

+ +

下一步

+ +

现在我们设置了我们游戏的缩放比例,让我们继续第三课,并设计出如何加载资源并将其显示在屏幕上

+ +

{{PreviousNext("Games/Tutorials/2D_Breakout_game_Phaser/Initialize_the_framework", "Games/Tutorials/2D_Breakout_game_Phaser/Load_the_assets_and_print_them_on_screen")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/the_score/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/the_score/index.html new file mode 100644 index 0000000000..f71ded071f --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/the_score/index.html @@ -0,0 +1,76 @@ +--- +title: The score +slug: Games/Tutorials/2D_breakout_game_Phaser/The_score +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial + - scoring +translation_of: Games/Tutorials/2D_breakout_game_Phaser/The_score +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Collision_detection", "Games/Workflows/2D_Breakout_game_Phaser/Win_the_game")}}

+ +
+

这是Gamedev Phaser教程 16 第11步您可以在Gamedev-Phaser-Content-Kit / demos / lesson11.html完成本课程后找到源代码

+
+ +

得分也可以使游戏更有趣 - 你可以尝试击败自己的高分,或者你的朋友。在这篇文章中,我们将为我们的游戏添加一个评分系统。

+ +

我们将使用一个单独的变量来存储分数和Phaser的text()方法将其打印到屏幕上。

+ +

新变量

+ +

在以前定义的之后添加两个新变量:

+ +
// ...
+var scoreText;
+var score = 0;
+
+ +

将得分文字添加到游戏显示

+ +

现在在create()函数末尾添加这一行

+ +
scoreText = game.add.text(5, 5, 'Points: 0', { font: '18px Arial', fill: '#0095DD' });
+
+ +

text()方法可以采用四个参数:

+ + + +

最后一个参数与CSS样式非常相似。在我们的例子中,乐谱文字将为蓝色,大小为18像素,并使用Arial字体。

+ +

当砖块被破坏时更新分数

+ +

每当球击中砖块时,我们将增加点数,更新scoreText显示当前得分。这可以使用setText()方法 - 添加以下两行新ballHitBrick()功能:

+ +
function ballHitBrick(ball, brick) {
+    brick.kill();
+    score += 10;
+    scoreText.setText('Points: '+score);
+}
+
+ +

这是现在 - 重新加载你的,index.html并检查得分更新每个砖击。

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/n8o6rhrf/","","400")}}

+ +

下一步

+ +

我们现在有一个得分系统,但是如果你不能赢得,那么玩和保持分数是多少?让我们看看我们如何能够增加胜利的状态,让我们赢得比赛

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Collision_detection", "Games/Workflows/2D_Breakout_game_Phaser/Win_the_game")}}

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/win_the_game/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/win_the_game/index.html new file mode 100644 index 0000000000..acdcc8fba9 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/win_the_game/index.html @@ -0,0 +1,59 @@ +--- +title: Win the game +slug: Games/Tutorials/2D_breakout_game_Phaser/Win_the_game +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - Phaser + - Tutorial + - winning +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Win_the_game +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/The_score", "Games/Workflows/2D_Breakout_game_Phaser/Extra_lives")}}

+ +
+

这是Gamedev Phaser教程 16 第12步您可以在Gamedev-Phaser-Content-Kit / demos / lesson12.html完成本课程后找到源代码

+
+ +

在我们的游戏中实现获胜是相当容易的:如果你碰巧摧毁所有的砖块,那么你赢了。

+ +

如何取胜?

+ +

将以下新代码添加到您的ballHitBrick()函数中:

+ +
function ballHitBrick(ball, brick) {
+    brick.kill();
+    score += 10;
+    scoreText.setText('Points: '+score);
+
+    var count_alive = 0;
+    for (i = 0; i < bricks.children.length; i++) {
+      if (bricks.children[i].alive == true) {
+        count_alive++;
+      }
+    }
+    if (count_alive == 0) {
+      alert('You won the game, congratulations!');
+      location.reload();
+    }
+}
+
+ +

我们循环使用组中的砖块bricks.children,检查每个砖块的.alive() 方法的活力如果没有更多的砖块活着,那么我们会显示一个获胜的消息,一旦警报被关闭,重新启动游戏。

+ +

比较你的代码

+ +

您可以在下面的现场演示中查看本课程的完成代码,并使用它来更好地了解它的工作原理:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/u8waa4Lx/1/","","400")}}

+ +

下一步

+ +

失败和获胜都是实施的,所以我们的游戏的核心游戏就完成了。现在让我们添加一些额外的东西-我们会给玩家将3个生活的,而不是一个。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/The_score", "Games/Workflows/2D_Breakout_game_Phaser/Extra_lives")}}

-- cgit v1.2.3-54-g00ecf