EVA.js学习笔记(六)实践fappy-bird游戏(下)
# EVA.js学习笔记(四)实践fappy-bird游戏(上)
# EVA.js学习笔记(五)实践fappy-bird游戏(中)
# VA.js学习笔记(六)实践fappy-bird游戏(下)
游戏的基本流程创建完成后,就可以开始增加游戏逻辑,添加管道来让小鸟躲避,躲避成功就获取得分,整个游戏就完成了
所以我们首先来创建管道
一、创建单组管道
\
createBar(distance, x, y, cWidth, cHeigt) {
const bar = new GameObject("bar", {
size: { width: cWidth, height: cHeigt },
origin: { x: 0.5, y: 0.5 },
position: {
x: x,
y: y,
},
anchor: {
x: 0,
y: 0,
},
});
bar.addComponent(
new Sprite({
resource: "bar",
spriteName: distance,
})
);
let physics = bar.addComponent(
new Physics({
type: PhysicsType.RECTANGLE,
bodyOptions: {
isStatic: true, // Whether the object is still, any force acting on the object in a static state will not produce any effect
restitution: 0,
frictionAir: 0,
friction: 0,
frictionStatic: 0,
force: {
x: 0,
y: 0,
},
stopRotation: true, // default false, usually do not need to be set
},
})
);
bar.addComponent(new Move());//添加移动功能,具体使用往下看
bar.addComponent(new Next());//添加创建新管道功能。具体使用往下看
bar.addComponent(
new Render({
alpha: 1,
zIndex: 8,
})
);
this.game.scene.addChild(bar);
return { bar, physics };
},
创建管道有几个需要注意的点:
1、创建一组管道,分为上管道和下管道,所以一组就是2个管道,以下的方法通过传参数来创建2个管道,所以需要调用2次来创建上下2个管道
写一个createBars方法
createBars() {
let allHeight = (this.sceneHeight * 3) / 4;
let barWidth = this.barWidthDefault;
let x = this.sceneWidth - barWidth * -0.5;
let topHeight = 802;
let space = 250;
let hard = 100; //起伏高度
let mixHeight = 40;
let bottomHeight = Math.random() * hard + space + mixHeight;
const top = this.createBar("bar_r.png", x, 0, barWidth, topHeight);
const bottom = this.createBar(
"bar.png",
x,
(this.sceneHeight * 3) / 4 - bottomHeight / 2,
barWidth,
bottomHeight
);
return { top, bottom };
},
2、管道需要添加物理属性,当鸟撞上的时候就可以通过鸟的监听来执行操作。
3、管理里面添加的new Move和new Next是采用了eva.js里的脚本组件功能,其中的update方法就是每帧执行的方法,在game对象中,game.ticker.add方法也是每一帧执行方法,但是官方建议在Component中的update方法实增加每帧执行的方法,也可以使用add 方法,该方法将会在所有System的lateUpdate执行后执行
二、移动
因为管道使用了物理属性,所以无法通过EVA自带的过渡动画来移动,所以需要通过物理属性里的Matter.Body.translate来进行移动
首先创建文件Move.js
import { Game, Component, GameObject } from '@eva/eva.js'
import { Physics } from '@eva/plugin-matterjs'
import Matter from 'matter-js'
export default class Move extends Component {
gameObject
static componentName = 'move'
constructor() {
super()
}
update() {
const physics = this.gameObject.getComponent(Physics)
if (window.game && physics.body) {
if (window.game.playing) {
let pushVec = Matter.Vector.create(-5, 0)//向左位移5
Matter.Body.translate(physics.body, pushVec)
}
}
}
}
引入后就能够使用
bar.addComponent(new Move());
来添加移动效果了。
三、创建多组管道
思路:
判断管道的位置,当管道移动到500的时候,就创建一个组新管道,当管道溢出屏幕后,就把自己删除
每一个管道只负责创建下一个管道,然后溢出屏幕后就被删除
首先创建Next.js
需要判断下,游戏在开始的时候,才执行操作
import { Game, Component, GameObject } from "@eva/eva.js";
import { Physics } from "@eva/plugin-matterjs";
import Matter from "matter-js";
export default class Next extends Component {
gameObject;
isAdd;
static componentName = "next";
constructor() {
super();
}
update() {
const physics = this.gameObject.getComponent(Physics);
if (window.game.playing) {
if (physics.body) {
let x = physics.body.position.x;//获取管道的位置
let isTop = physics.body.position.y == 0 ? true : false;
//溢出屏幕
if (x == -80) {
this.gameObject.getComponent(Physics).removeAllListeners();
window.game.scene.removeChild(this.gameObject);
this.gameObject.destroy();
}
this.isAdd = false; //防止重复添加
if (!this.isAdd && x == 500) {
this.isAdd = true;
//新建一组管道
//只判断下面的管道,否则会重复创建,因为该方法在上下管道都有,所以是执行2次的
if (isTop) {
window.game.emit("createBar", "down");
}
}
}
}
}
}
createBar的监听
this.game.on("createBar", (e) => {
this.createBars();
});
\
四、创建得分
首先通过eva.js中的Text来创建得分显示
createScore() {
const text = new GameObject("score", {
position: {
x: 40,
y: 80,
},
origin: {
x: 0,
y: 0,
},
anchor: {
x: 0,
y: 0,
},
});
text.addComponent(
new Text({
text: "得分:0",
style: {
fontFamily: "Arial",
fontSize: 36,
fontStyle: "italic",
fontWeight: "bold",
fill: "#fff",
stroke: "#000",
strokeThickness: 5,
dropShadow: true,
dropShadowColor: "#000000",
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6,
wordWrap: true,
wordWrapWidth: 400,
breakWords: true,
},
})
);
this.game.scene.addChild(text);
},
然后判断当小鸟通过了管道后增加得分
思路:
要判断小鸟通过管道得分,但是实际小鸟的X坐标不会变,变的是管道的 X坐标,可以通过管道的X位置小于小鸟的X位置,从而判断出小鸟通过了管道,所以可以在之前的Next.js中添加
....
update() {
const physics = this.gameObject.getComponent(Physics);
if (window.game.playing) {
...
//60是小鸟的位置,
if (x == 60) {
//只判断下面的管道
if (isTop) {
window.game.emit("getScore");
}
}
...
}
}
lateUpdate() {
if (window.game.playing) {
// console.log("得分lateUpdatelateUpdatelateUpdate");
}
}
}
getScore的监听方法
this.game.on("getScore", () => {
this.score++;
this.updateScode("score", this.score);
});
updateScode方法,先找到name叫score这个game对象,然后更改text的显示值
updateScode(name, value) {
const score = this.game.scene.gameObjects.find((item) => {
return item.name == name;
});
const text = score.getComponent(Text);
text.text = "得分:" + value;
},
五、完成游戏
到此为止游戏也差不多完成了,总的来说要完成一个简单的互动小游戏是非常方便的,官方也有很多参考的案例,这个demo做完后差不多也对常用的组件熟悉了,算刚好入门,等有时间会尝试做一些其他的游戏。