资讯专栏INFORMATION COLUMN

从零到一:用Phaser.js写意地开发小游戏(Chapter 5 - 游戏大功告成)

Jeff / 1837人阅读

摘要:回顾上一节我们完成了游戏核心场景的大部分工作,能操控主角,能随机掉落苹果了。于是我们修改之前的方法,也就是接到苹果后的方法。接到炸弹后结束和苹果掉地上的调用方式是一样的。

回顾

上一节我们完成了游戏核心场景play的大部分工作,能操控主角,能随机掉落苹果了。那么这一节我们来完成游戏剩余的部分,主要是计算分数、如何结束游戏等等。

正式开始
第一步:接住苹果得分

主角加入物理运动

检测接触事件

接到苹果后,让苹果消失,并加分

对主角的修改:

game.physics.enable(man); // 加入物理运动
man.body.allowGravity = false; // 清除重力影响

检测接触事件要写在play场景的update生命周期内,意思为每次更新视图都会去检测主角和苹果是否有接触,有的话,则执行pickApple方法。

this.update = function() {
    // 监听接触事件
    game.physics.arcade.overlap(man, apples, pickApple, null, this);
}

接触事件则非常简单,调用apple的kill方法,则可以让苹果从场景中清除。同时,我们更新一下分数。

// 接触事件
function pickApple(man, apple) {
    apple.kill();
    title.text = ++score;
}

示例代码:https://jsfiddle.net/Vincent_...

第二步:苹果掉地上,游戏结束

检测苹果与场景边缘的接触

一旦接触,则游戏结束,跳转到结束场景

布置结束场景,并显示分数

为结束场景添加点击事件,点击后再玩一次

onWorldBounds属性可设置为一个Phaser.Signal对象,当开启了collideWorldBounds并且接触到场景边缘时,将触发Signal的事件。另外,这个特殊的Signal提供了上下左右四个值来让我们判断物体到底接触的是哪条边,考虑到有些苹果会接触到左右两边,我们只在和下边界接触的时候才结束游戏。

// 设置苹果与游戏边缘碰撞,
apple.body.collideWorldBounds = true;
apple.body.onWorldBounds = new Phaser.Signal();
apple.body.onWorldBounds.add(function(apple, up, down, left, right) {
    if (down) {
        apple.kill();
        game.state.start("over", true, false, score);
    }
});

布置结束场景,和之前布置其他场景一样,添加背景、文本等等。不同的是这次多了init这个生命周期,主要是由于在play场景中跳转到这个场景时会带上score,这个score会传入init这个生命周期的方法中。

// 结束场景
over: function() {
    var score = 0;
    this.init = function() {
        score = arguments[0];
    }
    this.create = function() {
        // 添加背景
        var bg = game.add.image(0, 0, "bg");
        bg.width = game.world.width;
        bg.height = game.world.height;
        // 添加文本
        var title = game.add.text(game.world.centerX, game.world.height * 0.25, "游戏结束", {
            fontSize: "40px",
            fontWeight: "bold",
            fill: "#f2bb15"
        });
        title.anchor.setTo(0.5, 0.5);
        var scoreStr = "你的得分是:"+score+"分";
        var scoreText = game.add.text(game.world.centerX, game.world.height * 0.4, scoreStr, {
            fontSize: "30px",
            fontWeight: "bold",
            fill: "#f2bb15"
        });
        scoreText.anchor.setTo(0.5, 0.5);
    }
}

最后我们在结束场景添加一个点击事件,点击后跳转到play场景,再玩一次。

var remind = game.add.text(game.world.centerX, game.world.height * 0.6, "点击任意位置再玩一次", {
    fontSize: "20px",
    fontWeight: "bold",
    fill: "#f2bb15"
});
remind.anchor.setTo(0.5, 0.5);
// 添加点击事件
game.input.onTap.add(function() {
    game.state.start("play");
});

示例代码:https://jsfiddle.net/Vincent_...

第三步:添加得分效果

为不同苹果设置不同的得分

接到苹果时添加对应的得分图片到场景中

为得分图片添加过渡效果

先来介绍一下Phaser的过渡:

要使用过渡,首先要创建过渡对象,传入的是要应用过渡效果的对象,例如apple。

// 创建过渡对象
game.add.tween(obj);

然后使用得最多的是Tween的to方法,也就是过渡到指定状态的方法。可以指定过渡时间曲线,延迟、是否重复、过渡时间等等参数,使用Tween已经可以实现大部分的动画效果。

于是我们修改之前的pickApple方法,也就是接到苹果后的方法。

function pickApple(man, apple) {
    var point = 1;
    var img = "one";
    if (apple.type === "red") {
        point = 3;
        img = "three";
    } else if (apple.type === "yellow") {
        point = 5;
        img = "five";
    }
    // 添加得分图片
    var goal = game.add.image(apple.x, apple.y, img);
    var goalImg = game.cache.getImage(img);
    goal.width = apple.width;
    goal.height = goal.width / (goalImg.width / goalImg.height);
    goal.alpha = 0;
    // 添加过渡效果
    var showTween = game.add.tween(goal).to({
        alpha: 1,
        y: goal.y - 20
    }, 100, Phaser.Easing.Linear.None, true, 0, 0, false);
    showTween.onComplete.add(function() {
        var hideTween = game.add.tween(goal).to({
            alpha: 0,
            y: goal.y - 20
        }, 100, Phaser.Easing.Linear.None, true, 200, 0, false);
        hideTween.onComplete.add(function() {
            goal.kill();
        });
    });
    // 更新分数
    score += point;
    title.text = score;
    // 清除苹果
    apple.kill();
}

示例代码:https://jsfiddle.net/Vincent_...

第四步:加入炸弹,丰富音效

随机掉落炸弹

加入接到苹果或炸弹的音效

接到炸弹后游戏结束

要想随机掉落炸弹非常简单,只需要在之前的appleTypes里面加入bomb即可,同时如果有其他东西(例如梨子)要加入的话也可以这样。

var appleTypes = ["green", "red", "yellow", "bomb"];

同时,由于我们不接炸弹,因此炸弹掉到地上也不会导致游戏结束,因此修改一下代码:

apple.body.onWorldBounds.add(function(apple, up, down, left, right) {
    if (down) {
        apple.kill();
        if (apple.type !== "bomb") game.state.start("over", true, false, score);
    }
});

接到苹果和炸弹时播放音效,这个很简单,直接调用音频对象的play方法即可。接到炸弹后结束和苹果掉地上的调用方式是一样的。我们继续来修改pickApple方法:

function pickApple(man, apple) {
    if (apple.type === "bomb") {
        // 播放音效
        bombMusic.play();
        game.state.start("over", true, false, score);
    } else {
        var point = 1;
        var img = "one";
        if (apple.type === "red") {
            point = 3;
            img = "three";
        } else if (apple.type === "yellow") {
            point = 5;
            img = "five";
        }
        // 添加得分图片
        var goal = game.add.image(apple.x, apple.y, img);
        var goalImg = game.cache.getImage(img);
        goal.width = apple.width;
        goal.height = goal.width / (goalImg.width / goalImg.height);
        goal.alpha = 0;
        // 添加过渡效果
        var showTween = game.add.tween(goal).to({
            alpha: 1,
            y: goal.y - 20
        }, 100, Phaser.Easing.Linear.None, true, 0, 0, false);
        showTween.onComplete.add(function() {
            var hideTween = game.add.tween(goal).to({
                alpha: 0,
                y: goal.y - 20
            }, 100, Phaser.Easing.Linear.None, true, 200, 0, false);
            hideTween.onComplete.add(function() {
                goal.kill();
            });
        });
        // 更新分数
        score += point;
        title.text = score;
        // 清除苹果
        apple.kill();
        // 播放音效
        scoreMusic.play();
    }
}

示例代码:https://jsfiddle.net/Vincent_...

大功告成

游戏终于完成了它的逻辑,算是一个完整的游戏了。当然了,效果远未达到理想,要说的话,游戏水非常深,这个系列的教程只是从零到一,引导大家接触并上手Phaser.js。

这里可以抛出一些优化的方向,大家也可以当做Phaser的练习题目去做:

游戏中字体的更换

地面应该和小恐龙底部持平,而非屏幕底部,如何实现?

现在三种苹果和炸弹的出现概率是随机的,如何调整它们各自的出现概率?

现在苹果和炸弹出现的时间间隔是固定的,如何随着游戏进行加快节奏?

如何调整游戏难度梯度?

现在炸弹和苹果有可能会相邻出现,导致很难接到苹果而不碰到炸弹,如何避免?

……

本来没想写这么多点的,一不小心。可见游戏优化的空间还是很大的,希望大家能继续发掘Phaser.js的潜力,做出更多的优秀的小游戏~

Github地址:https://github.com/VincentPat...

扫描下面二维码的话也可以用手机查看效果了:

未完待续...?
回顾:

Chapter 1 - 认识Phaser.js

Chapter 2 - 搭建游戏的骨架

Chapter 3 - 加载游戏资源

Chapter 4 - 游戏即将开始

如果接下来有时间整理的话,会补充一篇Phaser.js的实战技巧和注意事项。本系列文章写作纯粹个人喜好,如有写得不严谨或不正确的地方,还请多多包涵。第一次花这么长时间写技术分享,还是用那句话勉励自己:

希望我是真的喜欢编程,由始至终。

如果你喜欢这几篇文章,或者说从零到一这个系列,给我点个赞,我就心满意足了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/91696.html

相关文章

  • 从零到一Phaser.js写意开发游戏Chapter 4 - 游戏即将开始)

    摘要:经过这一节,万事俱备只欠东风,下一节我们就来完成这个游戏的剩余逻辑,比如接苹果加分,接到炸弹或苹果掉到地上游戏结束,还有加入更丰富的音效。 showImg(https://segmentfault.com/img/bVM22H?w=900&h=500); 回顾 上一节我们介绍了加载场景,并利用加载好的资源,丰富了开始界面。现在点击屏幕后仍是一片黑暗,那么,这一节我们就来完成游戏最核心的...

    Miyang 评论0 收藏0
  • 从零到一Phaser.js写意开发游戏Chapter 1 - 认识Phaser.js

    摘要:由于公司项目转型,需要创造一个小游戏平台,需要使用一个比较成熟的前端游戏框架来快速开发小游戏。仅支持开发游戏,因为专注,所以高效。早在年的光棍节前一天晚上,这个游戏就诞生了。原型是一个之前很火的非常魔性的小游戏,叫寻找程序员。 showImg(https://segmentfault.com/img/bVMGY5?w=900&h=500); 写在前面 实际上我从未想过我会接触到H5小游...

    didikee 评论0 收藏0

发表评论

0条评论

Jeff

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<