猫史档案馆


【神岛】如何让简单的跑酷地图变得更简单?

用户:蓝矮爱乐蓝矮爱乐查看:4 回复:11 评论:4 创建时间:2022-06-26T09:57:49


(以下操作可能会变简单)

自认为简单的跑酷,都是知道路线的,只要跑酷难度在自己的能力之内。跑酷再简单,哪怕不知道路线,都不会跑()

假如一个跑酷很简单,路线很难,可是你又想和其他人比赛,别人不知道路线,怎么比?

那么,你要带路!可是带路只能带一次,别人看不到就看不到了,怎么弄个永久的带路系统?

啊,带路的系统可不是那么好屑的()

所以,这个跑酷要什么样的代码?首先,必须有存档点和计时器和SQL排行榜()

然后,带路系统就要有,带路原理就是系统持续记录你的位置,然后别人要看的时候从上往下依次读取

那么,持续记录位置的代码来咯!

db.sql`CREATE TABLE IF NOT EXISTS learnboard(
    datas TEXT NOT NULL
)`;//因为带路要永久让别人看到你跑酷,所以要用SQL()
//下面这个之所以要用globalThis,因为要方便调用呗()
globalThis.seeWriterPlaying=/**
    @param {Box3Entity} e//参数e的类型是Box3Entity
*/async function seeWriterPlaying(e){
    //是异步函数,因为while循环就要用await才能不卡崩服务器,还有显示SQL数据就要用await
    try{//尝试执行这些代码,如果作者没有录制,那么就找不到录制数据,就会报错
        e.player.cameraMode='fixed';
        //第三人称固定视角,这可以一直让视角跟随读取的数据视角
        const d=JSON.parse((await db.sql`select*from learnboard`)[0].datas);
        /*存进SQL数据类型要TEXT纯文本类型,其他类型存进去会报错
这里用了JSON.parse是因为存进去时是用JSON.stringify存进去的
SQL显示的都会是数组,所以要用[0]获取第一项,作者录取的数据是存进datas这个字段*/
        var a=0;
        //变量a用于切换动画的位置,连起来才会有带路的效果
        e.et=world.createEntity({mesh:'mesh/互动机器人.vb',position:po,gravity:false,collides:false,fixed:true});//如果玩家用第三视角观看的话,那么就要用实体来表示位置
        e.et.enableInteract=true;//让机器人允许互动,好让其他玩家知道有人开启了观战模式
        e.et.interactHint=`观战模式的${e.player.name}`;//设置NPC的文字
        while(true){//持续切换视角位置就是要用到while循环
            var ad=JSON.parse(d[a%d.length].d);
            //读取位置时,还要读取作者当时拍摄的时候的前进一个单位
            var po=JSON.parse(d[a%d.length].p);
            e.player.cameraPosition.copy(po);
            //将玩家的视角位置切换到读取出来的位置
            e.player.cameraTarget.copy(ad);
            //让玩家面向作者当时录取时的位置前进一个单位,这样能让玩家视角跟随到作者的面向
            if(e.player.seeWriterCameraMode=='follow')e.player.cameraPosition.subEq({x:(ad.x-po.x)*4,y:(ad.y-po.y)*4,z:(ad.z-po.z)*4});
            //要单独拎出一个属性来表示视角模式,因为cameraMode已经是fixed了
            await world.nextTick();//等到下一个tick触发
            e.et.position.copy(po);//让实体来到读取的数据的位置
            e.et.meshOrientation.copy(Quat.rotateY(Math.atan2(toVector(ad).sub(po).z, toVector(ad).sub(po).x)));
            //让方向面向作者当时的方向
            e.et.enableDamage=true;
            e.et.maxHp=100;
            e.et.hp=d[a%d.length].h;
            //如果这个跑酷还要用到血量,那么就可以显示血量了
            a++;//因为是从上依次往下读取,所以要加上1,这个变量a就是读取的项数
            if(e.player.cameraMode!='fixed')break;//如果玩家取消了观看,就退出循环
        }
    }catch(error){
        e.player.directMessage('作者未录制通关动画');
        e.player.cameraMode='follow';//重新把视角调回默认视角
        console.log(error)//这个调试出错误是因为方便修bug,如果是找不到录制数据而发生的错误,就不用修复了。可以删除
    }
};
globalThis.Quat=new Box3Quaternion(0,0,0,1)//默认的旋转方向
function g(o) {
    return new Box3Vector3(o.player.facingDirection.x,Math.sin(-o.player.cameraPitch),o.player.facingDirection.z);
    //这个用函数来表示玩家摄像机xyz轴是因为要很麻烦,所以用函数来封装
}
function toVector(o) {return new Box3Vector3(o.x,o.y,o.z)}
//这个也比较麻烦,因为定义名要连续写3次,那如果定义名很长呢?
world.onPlayerJoin(({entity})=>{
    e=world.querySelector('player')//可以删除,这是方便调试而用
    entity.player.recording=function recording() {//录制通关的函数
        entity.posJ=[];//这个数组用于存玩家的位置
        entity.tickEvent=world.onTick(()=>{
            entity.posJ.push({p:JSON.stringify(entity.position),d:JSON.stringify(entity.position.add(g(entity))),h:entity.hp});
            //因为要做到动画效果,所以要持续往表格添加位置
        })
    };
    entity.player.unRecording=async function unRecording(parameter) {
        //取消录制,parameter这个参数如果是true的话,那么就会保存录制结果
        entity.tickEvent.cancel();
        if(parameter){
            await db.sql`DELETE FROM learnboard`;//e,其实可以用更新数据的
            await db.sql`INSERT INTO learnboard VALUES(${JSON.stringify(entity.posJ)})`
        }
        entity.posJ=undefined;
    };
    entity.player.seeWriterCameraMode='follow';
    //另外用一个观看的变量,因为玩家观看的时候就要用fixed固定视角观看
    entity.player.unseeing=function unseeing() {
        //停止观看
        entity.player.cameraMode='follow';//重新调回默认视角
        entity.et.destroy();//销毁跟随观看视角的实体
    }
})

这些代码写完了,总感觉漏了些什么?

哦!还有一些观看作者的操作:取消观看,切换观看视角,判断玩家是否观看等等

取消观看:entity.player.unseeing();
取消录制:entity.player.unRecording();
取消录制并保存:entity.player.unRecording(true);
判断玩家是否正在录制:Boolean(entity.posJ);
判断玩家是否观看:Boolean(world.querySelectorAll('*').filter(e=>e.interactHint==`观站模式的${entity.player.name}`).length);
切换观看第一视角:entity.player.seeingWriterCameraMode='fps';
切换观看第三视角:entity.player.seeingWriterCameraMode='follow';
开始录制:entity.player.recording();
开始观看:seeWriterPlaying(entity)

完结~

不要吞排版啊!()()

 


回复

上一页1 页 / 共 1下一页
tiger666250tiger666250

喵d

点赞0


评论


飞跃的流星丨冲四千粉飞跃的流星丨冲四千粉

赞一个

点赞0


评论


蓝矮爱乐蓝矮爱乐

az,帖主有一个字打错了,就是在判断玩家是否观看的那一个,“站”改成“战”

点赞1


评论


tiger666250tiger666250

entity.player.seeWriterCameraMode='follow';

这里看不太懂()

点赞0


评论


yee剑走天下yee剑走天下

喵!

点赞0


评论


蓝矮爱乐蓝矮爱乐

挖坟

点赞0


评论


仙之鹤仙之鹤

emotion_编程猫_点赞

点赞0


评论


搬码喵搬码喵

az,可读性不高吖

点赞0


评论


Star_Ink_sansStar_Ink_sans

谁挖上来的)不过nb啊()

点赞1


评论


蓝矮爱乐蓝矮爱乐

有个问题就是tick卡的时候流畅性会很低

点赞0


评论


名字送冷吖O名字送冷吖O

这个跑酷是不是就用到了(

点赞0


评论