Phaser3入门示例
陆波
# Phaser3 入门示例
# 星星收集者
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Making your first Phaser 3 Game - Part 10</title>
<script src="//cdn.jsdelivr.net/npm/phaser@3.11.0/dist/phaser.js"></script>
<style type="text/css">
body {
margin: 0;
}
</style>
</head>
<body>
<script type="text/javascript">
var config = {
// 类型 canvas webgl
type: Phaser.AUTO,
// 宽
width: 800,
// 高
height: 600,
// 物理效果配置
physics: {
default: "arcade",
arcade: {
// 重力
gravity: { y: 300 },
debug: false,
},
},
// 场景配置
scene: {
// 预加载
preload: preload,
// 创建
create: create,
// 更新
update: update,
},
};
var player; // 玩家
var stars; // 星星
var bombs; // 炸弹
var platforms; // 地面及平台
var cursors; // 键盘控制
var score = 0; // 得分
var gameOver = false;
var scoreText; // 得分文字
var game = new Phaser.Game(config);
function preload() {
// 加载图片资源
this.load.image("sky", "assets/sky.png");
this.load.image("ground", "assets/platform.png");
this.load.image("star", "assets/star.png");
this.load.image("bomb", "assets/bomb.png");
// 加载精灵表单资源
this.load.spritesheet("dude", "assets/dude.png", {
frameWidth: 32,
frameHeight: 48,
});
}
function create() {
// A simple background for our game
// 添加游戏背景
this.add.image(400, 300, "sky");
// The platforms group contains the ground and the 2 ledges we can jump on
// 生成一个静态物理组(Group),并把这个组赋值给局部变量platforms。在Arcade物理系统中,有动态的和静态的两类物体(body)。
// 动态物体可以通过外力比如速度(velocity)、加速度(acceleration),得以四处移动。
// 它可以跟其他对象发生反弹(bounce)、碰撞(collide),此类碰撞受物体质量和其他因素影响。
platforms = this.physics.add.staticGroup();
// Here we create the ground.
// Scale it to fit the width of the game (the original sprite is 400x32 in size)
// 添加一张新的地面图像到400 x 568的位置(请记住,图像定位基于中心点)——问题是,我们需要这个平台撑满游戏的宽度。否则玩家就会掉出边界。
// 要做到这一点,我们用函数setScale(2)把它按x2(两倍)缩放。现在它的尺寸是800 x 64了,恰好符合我们的要求。
// 要调用refreshBody(),这是因为我们缩放的是一个 静态 物体,所以必须把所作变动告诉物理世界(physics world)。
platforms.create(400, 568, "ground").setScale(2).refreshBody();
// Now let's create some ledges
platforms.create(600, 400, "ground");
platforms.create(50, 250, "ground");
platforms.create(750, 220, "ground");
// The player and its settings
// 生成一个新的精灵,叫player(玩家),位于100 x 450像素,在游戏的下部。
// 精灵是通过物理游戏对象工厂函数(Physics Game Object Factory,即this.physics.add)生成的,这意味着它默认拥有一个动态物体。
player = this.physics.add.sprite(100, 450, "dude");
// Player physics properties. Give the little guy a slight bounce.
// 精灵生成后,被赋予0.2的一点点反弹(bounce)值。这意味着,它跳起后着地时始终会弹起那么一点点。
// 然后精灵设置了与世界边界(bound)的碰撞。——边界默认在游戏尺寸之外。
player.setBounce(0.2);
// 我们(通过player.setCollideWorldBounds(true))把游戏(的世界边界)设置为800 x 600后,玩家就不能不跑出这个区域了。
// 这样会让玩家停下来,不能跑出画面边界,或跳出顶边。
player.setCollideWorldBounds(true);
// Our player animations, turning, walking left and walking right.
// 'left'动画使用0, 1, 2, 3帧,跑动时每秒10帧。'repeat -1'告诉动画要循环播放。
this.anims.create({
key: "left",
frames: this.anims.generateFrameNumbers("dude", { start: 0, end: 3 }),
frameRate: 10,
repeat: -1,
});
// 动画键值用'turn'(转身)
this.anims.create({
key: "turn",
frames: [{ key: "dude", frame: 4 }],
frameRate: 20,
});
// 反方向的动画把这些重复一下,键值用'right'。
this.anims.create({
key: "right",
frames: this.anims.generateFrameNumbers("dude", { start: 5, end: 8 }),
frameRate: 10,
repeat: -1,
});
// Input Events
// Phaser有内置的键盘管理器,光标(cursor)对象有四个属性up, down, left, right(都是Key对象的实例)。
cursors = this.input.keyboard.createCursorKeys();
// Some stars to collect, 12 in total, evenly spaced 70 pixels apart along the x axis
// 首先,它设置纹理key(键值)为星星图像。这意味着配置对象生成的所有子项,都将被默认地赋予星星纹理。
// 然后,它设置重复值为11。因为它自动生成一个子项,重复11次就意味着我们总共将得到12颗,这正好是我们的游戏所需要的。
// 最后的部分是setXY——这用来设置组的12个子项的位置。每个子项都将如此放置:初始是x: 12,y: 0,然后x步进70。
// 这意味着第一个子项将位于12 x 0;第二个离开70像素,位于82 x 0;第三个在152 x 0,依次类推。
// 'step'(步进)值用于组生成子项时加以排布,真是很方便的手段。选用值70是因为,这意味着所有12个子项将完美地横跨着布满画面。
stars = this.physics.add.group({
key: "star",
repeat: 11,
setXY: { x: 12, y: 0, stepX: 70 },
});
// 遍历组中所有子项,给它们的bounce.y赋予0.4到0.8之间的随机值,反弹范围在0(不反弹)到1之间(完全反弹)。
// 因为星星都是在y等于0的位置产出的,重力将把它们往下拉,直到与平台或地面碰撞为止。反弹值意味着它们将随机地反弹上来,直到最终恢复安定为止。
stars.children.iterate(function (child) {
// Give each star a slightly different bounce
// 给每颗星一个稍微不同的反弹
child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
});
// 生成一个炸弹(bombs)组
bombs = this.physics.add.group();
// The score
// 16 x 16是显示文本的坐标位置。'score: 0'是要显示的默认字符串,接下来的对象包含字号、填充色。
// 因为没有指定字体,实际上将用Phaser默认的,即Courier。
scoreText = this.add.text(16, 16, "score: 0", { fontSize: "32px", fill: "#000" });
// Collide the player and the stars with the platforms
// 碰撞器(Collider)是施魔法的地方。它接收两个对象,检测二者之间的碰撞,并使二者分开。
this.physics.add.collider(player, platforms);
this.physics.add.collider(stars, platforms);
this.physics.add.collider(bombs, platforms);
// Checks to see if the player overlaps with any of the stars, if he does call the collectStar function
// 检查玩家是否与任何星星重叠,如果检测到就调用 collectStar 函数
this.physics.add.overlap(player, stars, collectStar, null, this);
// 检查玩家是否碰到炸弹
this.physics.add.collider(player, bombs, hitBomb, null, this);
}
function update() {
if (gameOver) {
return;
}
// 键盘事件 左右移动
if (cursors.left.isDown) {
// 设置水平速度
player.setVelocityX(-160);
// 播放left动画
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);
}
}
// 玩家碰到星星的回调
function collectStar(player, star) {
// 星星设置为不活动、不可见,即将它从显示中移除。
star.disableBody(true, true);
// Add and update the score
// 玩家捡到一颗星星时分数会提高,文本会更新以反映出新状态
score += 10;
scoreText.setText("Score: " + score);
// 使用一个组的方法countActive,看看有多少星星还活着。
// 如果没有了,那么玩家把它们收集完了,于是我们使用迭代函数重新激活所有星星,重置它们的y位置为0。这将使所有星星再次从画面顶部落下。
if (stars.countActive(true) === 0) {
// A new batch of stars to collect
// 新一批要收集的星星
stars.children.iterate(function (child) {
child.enableBody(true, child.x, 0, true, true);
});
// 生成一个炸弹。首先取一个随机x坐标给它,始终在玩家的对侧画面,以便给玩家个机会。然后生成炸弹,设置它跟世界碰撞,反弹,拥有随机速度。
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);
// 禁用炸弹的重力效果,这样可以一直弹跳
bomb.allowGravity = false;
}
}
// 玩家碰到炸弹的回调
function hitBomb(player, bomb) {
// 物理暂停
this.physics.pause();
// 让玩家变成红色
player.setTint(0xff0000);
player.anims.play("turn");
gameOver = true;
}
</script>
</body>
</html>