上一周与小伙伴们完成了一个飞机大战的项目,从中汲取到了许多项目经验。
例如如何在项目中分模块的开发,游戏登陆模块,创建房间模块,游戏逻辑模块等;以及对开发框架的普适性以及拓展性有了更多的理解。
1、
话不多说,先给你们j简单看看部分成果。(游戏场景)
图一
图二
从上图中可以看到有三架飞机,其中黄色的为普通战斗机;粉红色的为奶妈(技能和被动可加血),图二中可以看到由奶妈发射的爱心子弹,击中队友可以为队友增加50点血量;红色的为坦克,特点是血量多,防御力高,可以看到图一中坦克释放的主动技能—防护罩,可以在短暂时间内免疫伤害。
2、
接下来给大家分享一下这次项目中印象较深的一些技术细节。
应该有人会想问,道具(上图中带着降落伞的为小道具)是如何自动产生的,并且自动在场景中飘动的。
首先是服务器中对应道具产生的prop脚本:
const CREATE_WAIT = 40;
let g_Prop = new class CProp {
constructor() {
this.run();
}
doRun() {
if (!g_SE) {
return;
}
let roomList = g_SE.getAllRoom();
for (let roomID in roomList) { // 处理每个房间
let room = roomList[roomID];
if (room.state != 2) { //判断游戏是否开始
continue;
}
this.checkData(room); //检测数据完整
this.createProp(room); //创建道具
}
}
//轮询
run() {
setTimeout(() => {
this.doRun();
this.run();
}, 100);
}
/** 检测数据完整 */
checkData(room) {
if (!room.prop) { // prop是开始游戏才会加上去的
room.prop = {};
room.propNum = 0; //道具数量
}
if (room.propCreateWait == undefined) { //初始化创建道具的间隔
room.propCreateWait = CREATE_WAIT;
}
if (!room.propPid) { // enemyPid是创建新怪物时用到的递增变量
room.propPid = 20000;
}
}
//创建道具
createProp(room) {
room.propCreateWait--;
if (room.propCreateWait <= 0) {
room.propCreateWait = CREATE_WAIT;
room.propPid++;
room.propNum++;
let pid = room.propPid;
let x = 0;
if (Math.random() < 0.5) {
x = 0;
}
else if (Math.random() >= 0.5) {
x = 1;
}
let shape = Object.keys(g_Tb_Prop)[x];
let propInfo = {};
propInfo = g_Tb_Prop[shape];
room.prop[pid] = {
pid,
shape,
propInfo,
}
let info = {
key: "prop",
sub: 1,
data: {
propList: [
{
pid: room.prop[pid].pid,
shape: room.prop[pid].shape,
x: 0,
y: 600,
ratio: Math.random(),
}
]
}
}
for (let playerPid in room.player) {
let playerUid = room.player[playerPid].uid;
g_SE.send(playerUid, info);
}
}
}
当本脚本被导入时构造函数中的函数便会自动调用,从而run函数将会以100ms的间隔不断调用自身以及doRun函数;doRun函数中做的事情也很简单,为每个房间(四个玩家一个房间)检查数据完整性,以及产生道具(createProp())。
100ms的调用间隔这么短,想想若是100ms产生一个道具,那整个地图不是将很快被道具填满,那我们如何能够控制道具的产生速度合理呢?首先最容易想到的肯定是将100ms延长,但是我们某些功能要放到轮询(简单来说就是run函数中)要求较高的检测频率,因此频率不能更改,那我们还有什么办法呢?
相信有的伙伴看到了代码最开头的CREATE_WAIT这个常量,我们给它的值为40。在createProp中每次调用时createwait–,均会减一,而再判断createwait<=0时我们才会执行产生道具的操作。依此法我们便可以很轻松的了解到调用四十次这个函数才会成功产生一个道具,这样大概就是40*100ms也就是4s产生一个道具。
而接下来的Math.random就是产生一个随机数赋值给x,即x有百分之五十的几率为0,百分之五十几率为1。而我暂时做的是两种道具,如果x=0就产生第一种道具,x=1产生第二种道具。项目中我们经常用这种随机性来带给游戏惊喜,例如此函数后面一部分发给客户端的数据中有一项ratio存放的数据也是一个随机数,以同样的方式控制道具产生后随机向左飘或是向右飘。