Phaser.js是一款JavaScript语言的网页游戏框架。它简洁易用、跨平台、功能强大、性能良好,是不可多得的游戏制作工具。
一、工具与代码模板
首先,我们需要一个在线编辑器。这里推荐使用菜鸟的前端工具:HTML/CSS/JS 在线工具 | 菜鸟工具
在打开的工具里,HTML一栏,输入下面的代码:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/phaser@3.15.1/dist/phaser-arcade-physics.min.js"></script>
</head>
<body>
<script>
</script>
</body>
</html>
这段代码可以用作模板,引用了一个CDN上的phaser库。我们后来要写的代码需要添加到<script></script>之间。
二、基本代码结构
Phaser代码的基本结果如下:
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
scene: {
preload: preload,
create: create,
update: update
}
};
var game = new Phaser.Game(config);
function preload ()
{
}
function create ()
{
}
function update ()
{
}
将上述代码放到模板中的<script></script>之间后,在线工具的效果预览处,将出现游戏的黑屏效果,上面暂时没有其他东西,是因为我们什么都没有往里面加。
三、加载图片
首先,我们把本课程要用到的图片上传到了这里,它们的路径如下:
1. 炸弹bomb: https://i-blog.csdnimg.cn/blog_migrate/9f875835edb1c3ec6239a163787e3f3f.png
2. 星星star: https://i-blog.csdnimg.cn/blog_migrate/2519a7231ea82436fad5045e8292aba9.png
3. 天空sky: https://i-blog.csdnimg.cn/blog_migrate/d36e262788bd2c05a6b7306c7b05518c.png
4. 地面/平台 ground: https://i-blog.csdnimg.cn/blog_migrate/a1c3cda55874e200db832ec9adab37e5.png
5. 游戏角色 dude: https://i-blog.csdnimg.cn/blog_migrate/2edf7a1016bd424459c591c531e1f9a9.png
有了上面的图片后,我们可以在preload函数中,添加下面的代码了:
function preload ()
{
this.load.image('sky', 'https://i-blog.csdnimg.cn/blog_migrate/d36e262788bd2c05a6b7306c7b05518c.png');
this.load.image('ground', 'https://i-blog.csdnimg.cn/blog_migrate/a1c3cda55874e200db832ec9adab37e5.png');
this.load.image('star', 'https://i-blog.csdnimg.cn/blog_migrate/2519a7231ea82436fad5045e8292aba9.png');
this.load.image('bomb', 'https://i-blog.csdnimg.cn/blog_migrate/9f875835edb1c3ec6239a163787e3f3f.png');
this.load.spritesheet('dude',
'https://i-blog.csdnimg.cn/blog_migrate/2edf7a1016bd424459c591c531e1f9a9.png',
{ frameWidth: 32, frameHeight: 48 }
);
}
在create函数中添加下面的代码,就能出来基本的天空和星星图片了:
function create ()
{
this.add.image(400, 300, 'sky');
this.add.image(400, 300, 'star');
}
四、添加地面平台
我们给游戏中所有地面、平台编到一个组里,它们都是静止的东西,位置不相同而已。
如下面的代码,创建全局变量platforms,再替换一下create函数里的内容:
var platforms;
function create ()
{
this.add.image(400, 300, 'sky');
platforms = this.physics.add.staticGroup();
platforms.create(400, 568, 'ground').setScale(2).refreshBody();
platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');
}
为了能够正常运行,还需要修改一下前面已经添加过的游戏config变量。需要配置一下physics属性:
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 300 },
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
这时,便有了几个平台一样的东西出现在游戏里了。
五、添加游戏角色
继续在create函数里添加创建player的代码,如下:
player = this.physics.add.sprite(100, 450, 'dude');
player.setBounce(0.2);
player.setCollideWorldBounds(true);
this.anims.create({
key: 'left',
frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'turn',
frames: [ { key: 'dude', frame: 4 } ],
frameRate: 20
});
this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
frameRate: 10,
repeat: -1
});
player.body.setGravityY(300);
this.physics.add.collider(player, platforms);
其中player.setBounce(0.2);设置角色的弹跳系数,接近0时弹跳次数越少,设为1时永远不停地弹。player.setCollideWorldBounds(true);设置角色碰到世界的边界时是否检测碰到,是否将角色活动范围局限于可视的世界中。后面的三段代码分别创建一个动画:按下左键、转身、按下右键时的帧,分别为dude图片中的编号为0-3、4、5-8帧。
接下来的两行,player.body.setGravityY(300)可以为角色单独设置一个向下的重力,this.physics.add.collider(player, platforms);为物理世界添加了一个角色和平台之间的碰撞检测,有了这行代码,角色才能站立在平台和地面上,否则会往下面掉。
六、用键盘控制角色移动
这时需要让角色动起来了!我们用下面的代码:
cursors = this.input.keyboard.createCursorKeys();
if (cursors.left.isDown)
{
player.setVelocityX(-160);
player.anims.play('left', true);
}
else if (cursors.right.isDown)
{
player.setVelocityX(160);
player.anims.play('right', true);
}
else
{
player.setVelocityX(0);
player.anims.play('turn');
}
if (cursors.up.isDown && player.body.touching.down)
{
player.setVelocityY(-330);
}
有了这段代码,角色可以左右走动,也可以跳跃上平台了。如果跳不上去,可以酌情修改一下前面设置的角色的重力。
七、添加星星
首先,生成一批星星从上方掉下来,为每一颗设置随机的弹跳系数,这样看起来会更有意思一些。
stars = this.physics.add.group({
key: 'star',
repeat: 11,
setXY: { x: 12, y: 0, stepX: 70 }
});
stars.children.iterate(function (child) {
child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
});
this.physics.add.collider(stars, platforms);
function collectStar (player, star)
{
star.disableBody(true, true);
}
this.physics.add.overlap(player, stars, collectStar, null, this);
一番操作后,移动角色,就可以摘到星星了。this.physics.add.collider(stars, platforms);指明了星星会掉落到平台上,而不会一直往下掉;this.physics.add.overlap(player, stars, collectStar, null, this); 可以让角色碰到星星时,执行一个叫collectStar的函数,这个函数里仅仅将触碰到的星星禁用隐藏了。
八、显示分数
如果能够显示即时分数,那就更好了!那就干活吧!
首先,定义两个全局变量,一个定义分数,一个定义显示的文本。
var score = 0;
var scoreText;
在create函数里,添加上这么一行:
scoreText = this.add.text(16, 16, 'score: 0', { fontSize: '32px', fill: '#000' });
这表示在游戏中加上一个文本显示。
在collectStar函数中,添加分数增加的代码,最后如下:
function collectStar (player, star)
{
star.disableBody(true, true);
score += 10;
scoreText.setText('Score: ' + score);
}
这时应该能够显示分数了。
九、增加炸弹
为了增强游戏的趣味性与挑战性,我们决定加上一个炸弹的元素。
继续在create函数代码上,增加这么几行:
bombs = this.physics.add.group();
this.physics.add.collider(bombs, platforms);
function hitBomb (player, bomb)
{
this.physics.pause();
player.setTint(0xff0000);
player.anims.play('turn');
gameOver = true;
}
this.physics.add.collider(player, bombs, hitBomb, null, this);
这段代码表示炸弹这个“组”加进来,也会与平台进行碰撞检测,弹跳。当角色碰到炸弹时,执行hitBomb函数,这时物理世界会暂停,角色变为红色,动画为正面像,gameOver变量为true。
刚才的代码只添加了bombs这个“组”,里面还没有炸弹呢。单个的炸弹什么时候出现呢?
我们决定在每一轮的星星接完之后出现一个新的炸弹。因此,把collectStar函数修改成下面这样,让每一次活跃的星星数为0时,重新将所有星星激活,移到屏幕上方再掉下来。与此同时,让炸弹“组”中随机产生一个炸弹,炸弹出现的位置为远离角色的一侧。
function collectStar (player, star)
{
star.disableBody(true, true);
score += 10;
scoreText.setText('Score: ' + score);
if (stars.countActive(true) === 0)
{
stars.children.iterate(function (child) {
child.enableBody(true, child.x, 0, true, true);
});
var x = (player.x < 400) ? Phaser.Math.Between(400, 800) : Phaser.Math.Between(0, 400);
var bomb = bombs.create(x, 16, 'bomb');
bomb.setBounce(1);
bomb.setCollideWorldBounds(true);
bomb.setVelocity(Phaser.Math.Between(-200, 200), 20);
}
}
到这里,游戏基本就能正常运行了!让我们一起来玩一玩吧!
最後,讓我們爲遊戲添加更多的角色,制造出更多的豐富劇情的玩法吧!
圖片库:
1. 苹果:https://i-blog.csdnimg.cn/blog_migrate/72b64d1b5d041f75881a547b29482054.png
2. 小球:https://i-blog.csdnimg.cn/blog_migrate/eb512c0ab17187b0bf6510b03c3125bc.png
3. 箱子:https://i-blog.csdnimg.cn/blog_migrate/d340cd36d65fac28aea4b85acc6b3726.png
4. 硬币:https://i-blog.csdnimg.cn/blog_migrate/7211ff2246b1083eed329320d96822e6.png
5. 爆炸:https://i-blog.csdnimg.cn/blog_migrate/e52817301c39506b5f6aed2e4aecc1a9.png
6. 神:https://i-blog.csdnimg.cn/blog_migrate/44456d08be1dcc98305eebcb47195e2d.png
7. 西瓜:https://i-blog.csdnimg.cn/blog_migrate/7151055090f7c8ccfb047b43bfeb0f03.png
8. 钻石:https://i-blog.csdnimg.cn/blog_migrate/f808c443a00fb11d3ad3304f74f08cc4.png
9. 箭头:https://i-blog.csdnimg.cn/blog_migrate/79a47232c59d38de74fec047f059a523.png
10. 水果:https://i-blog.csdnimg.cn/blog_migrate/6d1d41ac8f4e66e26dfa4b91f072ca63.png