
Lv.1
https://dao3.fun/play/8774c9b9fe19aa074245
签名:武汉eStarPro万岁! 花海万岁!
在 震惊!!!日本欲将百万吨核污染水喵大海 潜在威胁难以估量! 中回复
あなた達の日本のお母さんの追い込んだのは天に殺されたあなたのお母さんの追い込んだのは二百五百の生態環境をあなた達の自分の家のごみ場にしたのでしょうか?当初あなた達の日本に核ミサイルを投げる時もっといくつか投げて日本の犬を全部爆殺して生きたくないですか?俺様はあなた達をよく片付けます! ! !
私の偉大な中華人民共和国万歳です! ! !私の偉大な中華人民万歳です! ! !偉大な国際主義万歳です! ! !
2023-08-25T08:21:04 点赞:1
在 《怪物巡逻、吐蛋》 中回复
console.clear()
// 根据内鬼绿的需求, 这次教大家 lucifer 吐蛋的代码
// 可以看到lucifer的模型我已经提前放进来了
// 今天完成来个功能一直个lucifer 周围没有人的时候, 他就巡逻, 如果有人就吐蛋
// 封装一个类来 实现lucifer的功能
class Lucifer{
constructor(entity){
/**
* @type GameEntity
*/
this.entity = entity
//需要有一个自旋来驱动lucifer , 这个上节课讲过的
// 初始化 tick
// 60毫秒一帧 来驱动lucifer 运动
this.tick = 0
this.range = 20 // 距离初始化为20
this.rot = 0 // 初始化旋转的角度
this.rotSpeed = 0.2 // 初始化一个角度的增加量
this.walkSpeed = 0.3
// 素材是反正的,这里需要调一下
this.seftQuat = new GameQuaternion(0, 0, 0, 1).rotateY(Math.PI)
this.walk_motion = this.entity.motion.loadByName('walk')
this.is_walk = false
this.walk_motion.onFinish(()=>{
this.is_walk = false
})
this.egg_attack_motion = this.entity.motion.loadByName('skill_3')
this.is_attack = false
this.egg_attack_motion.onFinish(()=>{
this.is_attack = false
})
setInterval(()=>{
this.tick ++
this.onTick()
}, 60)
}
/**
* @param {GameVector3} pos
*/
async spitEgg(pos){
// 先让lucider停止运动
this.entity.velocity = new GameVector3(0, 0, 0)
// 然后让它转向玩家
// pos就是玩家的位置
const vel = pos.sub(this.entity.position)
// 要让lucider 朝向这个向量
this.entity.meshOrientation = this.seftQuat.rotateY(Math.atan2(vel.z, vel.x))
// 试试效果 ok
// 播放lucifer 模型上吐蛋的动作了 skill_3 就是它
// 还是刚才的问题, 要控制重复播放
// 需要一个状态控制
if(!this.is_attack){
this.is_attack = true
this.egg_attack_motion.play()
// 然后要吐蛋了
// 我们要create一个蛋出来
const egg = world.createEntity({
id:'egg',
mesh:'mesh/路西法特效1.vb',
position: this.entity.position.add(new GameVector3(0, 5,0)),
meshScale: new GameVector3(1/16, 1/16, 1/16) // 填这个就和你拖进来的大小是一样的, 为啥别问
})
// 需要给蛋一个速度, 要不然就成下蛋了
egg.velocity = vel.normalize().scale(2) // normalize是归一化。 就是让这个相关成为0~1的值
// 蛋飞的低了,
//和动作就对上了
// 接下来就是蛋落地, 过一段时间仆从就从蛋里孵化出来
// 首先让蛋仔落地后停下来
egg.onVoxelContact(()=>{
egg.velocity = new GameVector3(0,0,0)
})
// 等待6秒 然后变仆从
// await 只能在 async 的方法里用
await sleep(6000)
// 变仆从就是把蛋的实体移除,放上来一个仆从的实体
// 先在蛋的位置创建一个仆从
const entity = world.createEntity({
id:'footman',
mesh:'mesh/路西法男爵仆从.vb',
position: egg.position,
meshScale: new GameVector3(1/16, 1/16, 1/16)
})
egg.destroy()
new Footman(entity)
// 吉吉帮助完成测试
// 接着要完成 仆从的逻辑了哦
}
// 试试 大意了
}
onTick(){
// lucifer 要找周围有没有人, 上节课也讲过哦, 我们直接写
const players = this.queryNearByPlayer(this.range)
if(players.length > 0){
// 如果周围有人就要朝他吐蛋
// 然后就要朝你吐蛋了
this.spitEgg(players[0].position)
// ok
}else{
// 如果没有人, 就要巡逻, 这个上节课讲过, 先过一下
this.walkNoAim()
// 试试效果
// 转的有点快了a
// 因为lucider 是有动画的, 我们需要给它加一个行走的动画
// 新知识了哦
if(!this.is_walk){
this.walk_motion.play()
this.is_walk = true
// 要让动画一直循环播放
}
// ok lucider的巡逻就完成了哦
// 动画被重复调用了, 需要一个控制动画的状态
}
}
walkNoAim(){
// 首先定一个旋转的角度, 不断的增喵出这个角度在x和z轴上的向量
const xv = Math.cos(this.rot)
const zv = Math.sin(this.rot)
// 要定义lucifer 巡逻的速度
this.entity.velocity.x = xv * this.walkSpeed
this.entity.velocity.z = zv * this.walkSpeed
// lucifer 要一直面上走路的方向
this.entity.meshOrientation = this.seftQuat.rotateY(this.rot)
}
queryNearByPlayer(range){
const players = world.querySelectorAll('player')
return players.filter((e)=>{
return e.position.distance(this.entity.position) < range
})
}
}
class Footman{
constructor(entity){
this.entity = entity
// 普通也要巡逻
// 和lucifer是一个样的
// 要在写一边么
// 还记得上节课我们将的继承么
this.tick = 0
this.range = 20 // 距离初始化为20
this.rot = 0 // 初始化旋转的角度
this.rotSpeed = 0.2 // 初始化一个角度的增加量
this.walkSpeed = 0.3
// 素材是反正的,这里需要调一下
this.seftQuat = new GameQuaternion(0, 0, 0, 1).rotateY(Math.PI)
this.traceSpeed = 0.8
setInterval(()=>{
this.tick ++
this.onTick()
},60)
}
onTick(){
// lucifer 要找周围有没有人, 上节课也讲过哦, 我们直接写
const players = this.queryNearByPlayer(this.range)
if(players.length > 0){
// 刚才搬砖的电脑卡丢了一些代码
// 仆从也开始动了
// 然后让仆从追着吉吉跑
// 代码就讲到这里了哦
// 给大家留个作业,是搬砖没有做的
// 就是把lucider和 footman 公共的代码抽象到父类里, 上节课有讲过的
this.moveToTarget(players[0].position)
}else{
this.walkNoAim()
}
}
moveToTarget(pos){
const vel = pos.sub(this.entity.position).normalize()
this.entity.velocity.x = vel.x * this.traceSpeed
this.entity.velocity.z = vel.z * this.traceSpeed
const ori = this.seftQuat.rotateY(Math.atan2(vel.z, vel.x))
this.entity.meshOrientation = this.entity.meshOrientation.slerp(ori, 0.2)
}
queryNearByPlayer(range){
const players = world.querySelectorAll('player')
return players.filter((e)=>{
return e.position.distance(this.entity.position) < range
})
}
walkNoAim(){
// 首先定一个旋转的角度, 不断的增喵出这个角度在x和z轴上的向量
const xv = Math.cos(this.rot)
const zv = Math.sin(this.rot)
// 要定义lucifer 巡逻的速度
this.entity.velocity.x = xv * this.walkSpeed
this.entity.velocity.z = zv * this.walkSpeed
// lucifer 要一直面上走路的方向
this.entity.meshOrientation = this.seftQuat.rotateY(this.rot)
}
}
// 我们找到这个模型
const entity = world.querySelector('#路西法男爵-1')
const lucifer = new Lucifer(entity)2024-01-30T10:33:47 点赞:0
在 这个CIient是干嘛用的? 中回复
const Quat = new GameQuaternion(0, 0, 0, 1)
class Animal {
/**
* 需要参数提示可以这样
* @param {GameEntity} entity 绑定的实体
*/
constructor(entity) {
this.entity = entity
this.entity.collides = true
this.entity.gravity = true
this.entity.addTag('animal')
this.init()
this.onInit()
// 每一帧、动起来
this.interval = setInterval(() => {
this.tick++
this.onTick()
}, 60)
this.entity.onDie(({ attacker }) => {
this.onDie(attacker)
})
}
init() {
this.rot = 0 // 旋转值
this.rotSpeed = 1 // 旋转速度
this.tick = 0 // 帧循环的计数器
this.rotTick = 0 // 用来判定是否 改变旋转方向
this.walkSpeed = 0.1 // 巡逻速度
this.speedTick = 0 // 用来判定是否 改变巡逻速度
this.inIdle = false // 是否正在待机
this.beDead = false // 是否被打喵了
// 子类可重新赋值的字段
this.selfQuat = Quat // 模型对应的默认旋转四元数
this.findRange = 10 // 寻找半径
this.traceSpeed = 0.5 // 追踪速度
this.canFly = false
}
// 供子类重写
onInit() { }
async onDie(attacker) {
this.beDead = true
clearInterval(this.interval)
world.say(`${attacker.player.name} 打喵了 ${this.entity.id}`)
await sleep(2000)
this.entity.destroy()
this.entity = null
}
onTick() {
if (this.beDead) return
// 现在有人靠近它的领域,它需要主动跟踪。首先寻找附近是否有人
const players = this.getNearbyPlayers(this.findRange)
if (players.length > 0) {
if (this.inIdle) {
this.inIdle = false
this.turnToFight()
}
this.moveToTarget(players[0].position)
return true
} else {
if (!this.inIdle) {
this.inIdle = true
this.turnToIdle()
}
this.animateNoAim()
return false
}
}
// 将要转变为待机状态
turnToIdle() { console.log(' 转变为idle状态') }
// 转变为攻击状态
turnToFight() { console.log(' 转变为攻击状态') }
// 无目标时,巡逻的移动表现
animateNoAim() {
if (this.tick >= this.rotTick) {
this.rotSpeed = Math.PI * (Math.random() - 0.5) * 0.25
this.rotTick = this.tick + this.randomRange(2, 4) * 16
}
if (this.tick >= this.speedTick) {
this.walkSpeed = Math.random() * 0.3
this.speedTick = this.tick + this.randomRange(3, 5) * 16
}
this.rot += this.rotSpeed * this.walkSpeed
const 喵 = Math.cos(this.rot) * this.walkSpeed
const vz = Math.sin(this.rot) * this.walkSpeed
this.entity.velocity.x = 喵
this.entity.velocity.z = vz
this.entity.meshOrientation = this.selfQuat.rotateY(Math.atan2(vz, 喵))
}
// 向某个位置移动
moveToTarget(pos) {
const vel = pos.sub(this.entity.position).normalize()
if (!this.canFly) {
vel.y = 0
}
this.entity.velocity.x = vel.x * this.traceSpeed
this.entity.velocity.y = vel.y * this.traceSpeed
this.entity.velocity.z = vel.z * this.traceSpeed
const ori = this.getOrientationByVector(this.selfQuat, vel)
this.entity.meshOrientation = this.entity.meshOrientation.slerp(ori, 0.24)
}
// 获取附近的人,按距离排序,越近的优先
getNearbyPlayers(range) {
let players = world.querySelectorAll('player')
const pos = this.entity.position
players = players.filter(e => e.position.distance(pos) < range)
players.sort((a, b) => { return a.position.distance(pos) - b.position.distance(pos) })
return players
}
// 区域内随机,左闭右开
randomRange(start, end) {
return start + (end - start) * Math.random()
}
// 通过向量计算角度
getOrientationByVector(quat, vector3) {
const src = vector3
let dx = src.x
let dy = src.y
let dz = src.z
let dist = Math.sqrt(dx * dx + dz * dz)
const rotx = Math.atan2(dy, dist)
return quat.rotateX(rotx).rotateY(Math.atan2(dz, dx))
}
}
class CrazyAnimal extends Animal {
onInit() {
// 继承了CrazyAnimal的子类的onInit中,需调用super.onInit(),否则这里的设置都会失效
this.entity.enableDamage = true
this.attacking = false // 是否正在攻击
this.skillCount = 1 // 招式的个数
}
// 继承并重写Animal的帧更新函数、附加咬人功能
onTick() {
const result = super.onTick()
result && this.useSkill()
}
// 随机选择技能释放
async useSkill() {
if (this.attacking) return
this.entity.say('我要出招了!')
// ~~ 相当于向下取整
let randomIndex = ~~this.randomRange(0, this.skillCount)
if (!this['skill_' + randomIndex]) return
this.attacking = true
await this['skill_' + randomIndex]()
// 技能cd 3秒
await sleep(3 * 1000)
this.attacking = false
}
}
class Rabbit extends Animal {
onInit() {
this.traceSpeed = 0.8
}
// 将要转变为待机状态
turnToIdle() {
this.entity.say('啦啦啦啦~')
// 如果实体有动画 可以在这里切换成待机动画
// this.entity.motion.setDefaultMotionByName('idle')
}
// 转变为攻击状态
turnToFight() {
this.entity.say('嗷呜~')
// 如果实体有动画 可以在这里切换成走路动画
// this.entity.motion.setDefaultMotionByName('walk')
}
}
class Bird extends Animal {
onInit() {
this.entity.gravity = false
this.selfQuat = Quat.rotateY(-Math.PI / 2) // 模型对应的默认旋转四元数
this.canFly = true
}
}
class Dog extends CrazyAnimal {
onInit() {
super.onInit()
this.selfQuat = Quat.rotateY(-Math.PI / 2) // 模型对应的默认旋转四元数
this.findRange = 40
this.skillCount = 1 // 招式的个数
}
skill_0() {
this.entity.say(this.entity.id + ': 我要咬你一口!')
this.entity.position.y += 2
// 让最近的人 受伤
const entitys = this.getNearbyPlayers(4)
if (entitys.length > 0) {
entitys[0].hurt(10)
}
}
}
class DogPlus extends Dog {
onInit() {
super.onInit()
this.skillCount = 2 // 招式的个数
}
async skill_1() {
this.entity.say(this.entity.id + ': 我要变大了!')
this.entity.meshScale = this.entity.meshScale.scale(2)
await sleep(2000)
this.entity.meshScale = this.entity.meshScale.scale(0.5)
}
}
// 需确保有如此命名的实体在地图中
const rabbit = world.querySelector('#新年兔子房-1')
new Rabbit(rabbit)
const bird = world.querySelector('#愤怒的小鸟-1')
new Bird(bird)
const dog = world.querySelector('#大嘴狗-1')
new Dog(dog)
const dogPlus = world.querySelector('#大嘴狗-2')
new DogPlus(dogPlus)
// 让动物们之间不碰撞 喵tag过滤
world.addCollisionFilter('.animal', '.animal')
world.onPlayerJoin(({ entity }) => {
// 人物可被攻击
entity.enableDamage = true
entity.player.onPress(({ raycast, button }) => {
if (button != GameButtonType.ACTION0) return
if (raycast.hitEntity && raycast.hitEntity.hasTag('animal') && raycast.distance < 20) {
raycast.hitEntity.hurt(10, { attacker: entity })
}
})
})
2024-01-30T11:33:45 点赞:0
在 来个高手帮助我一下吧!(只限一人) 中回复
我~~~imgsrc="https://static.codemao.cn/emoji/codemao/%E7%BC%96%E7%A8%8B%E7%8C%AB_%E5%97%A8%E8%B5%B7%E6%9D%A5.gif"alt="emotion_编程猫_嗨起来"
2024-05-21T20:22:54 点赞:0