用户:
Vicent轩查看:4 回复:3 评论:4 创建时间:2020-08-28T16:26:35
总所周知
吉吉喵公布的僵尸代码打完就没了
那如何让他打完就再生成一次呢?
首先我们分析一下代码:
在一开始就有一行注释说:
//把生成僵尸的代码封装成函数
那么这个函数(spawn)里的代码
包含了一个僵尸的全部的代码,比如生成出僵尸模型
那么下面有几行代码:
for (let i = 0; i < 30; i++) {//开局生成一堆僵尸
spawn()
}
他实现的功能是重复执行30次执行函数spawn
讲到这,我们已经知道他是怎么复制僵尸了
只要在打完僵尸之后执行这个语句就OK
那么怎么判断僵尸打完了呢?
我们可以用变量(这里示例变量名为mb【目标】)来记录
在复制僵尸时,加上这样一句代码变成这样:
for (let i = 0; i < 30; i++) {//开局生成一堆僵尸
spawn()
mb = (typeof mb == 'number' ? mb : 0) + 1;
}
这样就可以知道复制了多少个僵尸
当然你也可以不这么做,直接在这个for循环后面加个mb=30
然后,在定义函数里面的实体喵亡这部分里面用一个变量(示例变量喵【杀灭】)记录击杀的僵尸个数
当有一个实体喵亡时,就把喵这个变量的值+1
然后判断,喵(杀灭个数)是否等于mb(目标杀灭个数)
如果等于,证明僵尸已经杀完
然后生成僵尸:
e.onDie(async()=>{
e.destroy()
喵 = (typeof 喵 == 'number' ? 喵 : 0) + 1;
if (喵 == mb) {
for (let i = 0; i < 30; i++) {
spawn()
}
}
})
那么这样就完成啦!
修改后的完整代码:
const MeshScale = [0.0625,0.0625,0.0625]
function spawn() {//把生成僵尸的代码封装成函数
const e = world.createEntity({
mesh:'mesh/僵尸.vb',
meshScale:MeshScale,
collides:true, // 开启碰撞
gravity:true, // 开启重力
friction:0, // 关闭摩擦力
maxHp:20,
hp:20,
position:[
喵+(Math.random()-0.5) * 60,
24 + Math.random() * 50,
喵+(Math.random()-0.5) * 60,
],
});
e.addTag('僵尸');
e.enableDamage = true;
e.onVoxelContact(({x,y,z,voxel})=>{
e.velocity.y = 0.3+Math.random()*0.7//碰到砖块就跳一下
})
e.onEntityContact(({other})=>{
if(other.isPlayer){//僵尸撞到玩家
other.hurt(40)//对玩家造成伤害
}
})
e.onDie(()=>{
e.destroy()//僵尸喵掉,实体消失!谢谢@1232RvE反馈
喵 = (typeof 喵 == 'number' ? 喵 : 0) + 1;
if (喵 == mb) {
for (let i = 0; i < 30; i++) {
spawn()
}
}
})
}
for (let i = 0; i < 30; i++) {//开局生成一堆僵尸
spawn()
mb = (typeof mb == 'number' ? mb : 0) + 1;
}
const Quat = new Box3Quaternion(0,0,0,1)// box引擎默认的旋转朝向
let allPlayers = []//所有玩家
let allZombies = []//所有僵尸
world.onTick(async ({tick}) => {//每秒16个tick
if(tick%16===0){//每16个tick运行一次, 而不是每个tick都运行,节省性能
allPlayers = world.querySelectorAll('player')
allZombies = world.querySelectorAll('.僵尸')
}
allZombies.forEach(async (e) => {
let zomPos = e.position
if(tick%11===0){//每11个tick运行一次, 而不是每个tick都运行,节省性能
let target = allPlayers.sort((a,b)=>{//僵尸寻找距离最近的玩家
return a.position.distance(zomPos)-b.position.distance(zomPos)
})[0]
if(target){//地图如果还有玩家
e.target = target//让僵尸记住要追杀的玩家
}
}
if(e.target && !e.target.destroyed){//如果要追杀的玩家还没有离开地图
var direction = e.target.position.sub(zomPos); //僵尸往玩家的方向矢量
var dist = direction.mag() //矢量的长度
var speed = 0.2+Math.random()*0.3 //速度0.2~0.5随机
e.velocity.x = direction.x*speed/dist
e.velocity.z = direction.z*speed/dist
// 让僵尸面向自己的前进方向
var orientation = Quat.rotateY(Math.atan2(e.velocity.z, e.velocity.x))
e.meshOrientation.copy(orientation)
}
})
})
world.onPlayerJoin(({entity})=>{
entity.enableDamage = true;
entity.onDie(async()=>{
world.say(`${entity.player.name} 被袭击身亡, 3秒后复活`)
await sleep(3000)
// 空中随机位置复活
entity.position.x = Math.random()*127
entity.position.z = Math.random()*127
entity.position.y = 100
await sleep(100) // 防止引擎延迟造成复活后受到喵前的伤害
entity.hp = entity.maxHp //恢复满血
})
})
world.onClick(({entity})=>{
entity.hurt(10) //被点中的实体会掉血
})
那么本期教程就到这里啦!
有啥问题欢迎在下方回帖提问!