2025-12-22#

Data: 2025-12-22 18:48:29

接下来的目标是:

今天把万数块的百数块完善。

万数块机制分区:
	 990_000 ~ 1_000_000 : 单数块 type = 3
	900_000 ~ 989_999 : 百数块 type = 2
	0 ~ 899_999 : 万数块 type = 1

业务逻辑模块:

// 四种模型
const x_m = get2data[0];  //+ 四种规格对应的模型文件
const m_m = get2data[2];
const m2_m = get2data[3];
const l_m =  [{"x":32.557,"y":9.101,"z":29.457 - 50,"w":36,"h":17,"d":30,b:"#ff0000ff"}];  // 红块
const ll_m = [{"x":32.557,"y":9.101,"z":29.457,"w":20,"h":17,"d":60,b:"#110d07ff"}];

// 触发器模型
const triggers = [
    { key: 'inGemZone',   dz: 3, name: '近景' },
    { key: 'inBoardZone', dz: 2, name: '中景' },
    { key: 'inHutZone',   dz: 1, name: '远景' }
];
const triggersPosData = [{ "x": 32.557, "y": 1.5, "z": 29.457, "w": 0.5, "h": 50, "d": 0.5 }];


tri();

tri(160);

let number = 3;
for (let i = 1; i <= number; i++) {
    for (let j = 1; j <= number; j++) {
        tri(160 + 40 * i, -40 * j);
    }
}



// gemini 生成的代码,太美了
function tri(zDis = 60, xDis = 0){
    const triggerState = {
        inGemZone: false,   // 宝石
        inBoardZone: false, // 木板
        inHutZone: false    // 小屋
    };
    let mvppos = -1;
    let requestStateUpdate, runBusinessLogic;
    let runGemfunc, runHutfunc, runBoardfunc, runSkylinefunc;

    // 四个激活函数
    if(1){
        let x, m, m2, l, ll;  // 分别对应 宝石、木板、小屋、天际线 的 wsk idx

        runGemfunc = () => {  // 宝石
            if(!x){
                x = dataProc.process(x_m, { x: xDis, z: zDis }, dls, 'gem');
            }
            if(!m){
                m = dataProc.process(m_m, { x: xDis, z: zDis }, dls, 'board');
                console.log(m);
            }
            // ----------
            if(!m2){
                m2 = dataProc.process(m2_m, { x: xDis, z: zDis }, dls, 'board2');
                console.log(m2);
            }
            if(l){
                k.deleteModBlock(l);
                l = null;
            }
            if(ll){
                k.deleteModBlock(ll);
                ll = null;
            }
        };
        runBoardfunc = () => {  // 木板
            if(!m){
                m = dataProc.process(m_m, { x: xDis, z: zDis }, dls, 'board');
            }
            if(!m2){
                m2 = dataProc.process(m2_m, { x: xDis, z: zDis }, dls, 'board2');
            }
            // ----------
            if(x){
                k.deleteModBlock(x);
                x = null;
            }
            if(l){
                k.deleteModBlock(l);
                l = null;
            }
            if(ll){
                k.deleteModBlock(ll);
                ll = null;
            }
        };
        runHutfunc = () => {  // 小屋
            if(!l){
                l = dataProc.process(l_m, { x: xDis, z: zDis }, dls, 'hut');
            }
            // ----------
            if(x){
                k.deleteModBlock(x);
                x = null;
            }
            if(m){
                k.deleteModBlock(m);
                m = null;
            }
            if(m2){
                k.deleteModBlock(m2);
                m2 = null;
            }
            if(ll){
                k.deleteModBlock(ll);
                ll = null;
            }
        };
        runSkylinefunc = () => {  // 天际线
            if(!ll){
                ll = dataProc.process(ll_m, { x: xDis,z: zDis }, dls, 'skyline');
            }
            // ----------
            if(x){
                k.deleteModBlock(x);
                x = null;
            }
            if(m){
                k.deleteModBlock(m);
                m = null;
            }
            if(m2){
                k.deleteModBlock(m2);
                m2 = null;
            }
            if(l){
                k.deleteModBlock(l);
                l = null;
            }
        };
    }

    // 计算当前状态
    if(1){
        let stateDebounceTimer = null;  // 防抖计时器变量
        requestStateUpdate = () => {  // 延时决策
            if (stateDebounceTimer) {  // 如果 xx 毫秒内,有新的函数被激活,则消除旧的,留下最新的
                clearTimeout(stateDebounceTimer);
            }
            stateDebounceTimer = setTimeout(() => {
                evaluateFinalState(); // 倒计时结束,执行最终裁判
                stateDebounceTimer = null;
            }, 15);  // 15ms 是一个比较安全的值,在 20 性能下,最久冲突为 13ms
        };
        const evaluateFinalState = () => {
            let targetState = 4;
            if (triggerState.inGemZone) {
                targetState = 1;
            } else if (triggerState.inBoardZone) {
                targetState = 2;
            } else if (triggerState.inHutZone) {
                targetState = 3;
            } else {
                targetState = 4;
            }
            if (mvppos !== targetState) {  // 如果最终状态等于当前状态,忽略
                mvppos = targetState;
                runBusinessLogic(targetState);  // 判断完毕,执行最终函数
            }
        };
    }

    // 执行
    if(1){
        runBusinessLogic = (state) => {
            switch (state) {
                case 1:
                    // console.log("📍 最终定位: 宝石 (Gem)");
                    runGemfunc();
                    break;
                case 2:
                    // console.log("📍 最终定位: 木板 (Board)");
                    runBoardfunc();
                    break;
                case 3:
                    // console.log("📍 最终定位: 小屋 (Hut)");
                    runHutfunc();
                    break;
                case 4:
                    // console.log("📍 最终定位: 天际线 (Skyline)");
                    runSkylinefunc();
                    break;
            }
        };
    }

    // 放置这三个定位块
    if(1){
        triggers.forEach(conf => {
            triggersPosData[0].dz = conf.dz;
            const idx = dataProc.process(triggersPosData, { x: xDis, z: zDis - 60 }, dls, 'setTriModel', false);  // 放置模型
            const args = k.indexToArgs.get(idx + 0);
            args.activeFunc = () => {  // 激活函数
                triggerState[conf.key] = true;
                requestStateUpdate();
            };
            args.deleteFunc = () => {  // 删除函数
                triggerState[conf.key] = false;
                requestStateUpdate();
            };
        });
    }
}

数据处理模块:

/**

  • 数据处理(等待被转化为插件)


  • 开始按照既定的规则,把 myData 给绘制出来

  • del: 完全删除没数据的 */ const dataProc = {

    // 一些参数 buildMode: 0, // 是否是建造模式,如果不是,则不渲染空模型 totalCube: 10000, // 总方块数 cubeIndex: 0, // 计数器 myCubeInstances: [], // 最终生成的实例数据,的容器 wskIdx: -1, // 当前万数块的 ID

    // 读取和理解单个数据,放入 myCubeInstances 里,返回 index readData : (data, isHidden = false, offset = {}) => { if(data.length > 10000){ console.error(‘申请 万数块 不能使用长度大于 10000 的数据!’); return -1; } if(data.del) { // 处理已被标记 删除 的数据,按照【空模型】处理默认参数 data = { x: 999999999, y: 999999999, z: 999999999, w: 0.001, d: 0.001, h: 0.001, }; } const result = { // 初始化一个模型,填充位置、大小、旋转,智能处理未定义的参数 x: data.x + (offset?.x ?? 0), y: (data?.y||1) + (offset?.y ?? 0), z: data.z + (offset?.z ?? 0), w: data?.w || 1, d: data?.d || 1, h: data?.h || 1, rx: data?.rx||0, ry:data?.ry||0, rz:data?.rz||0, }; if(data?.b) { // 有颜色参数 result.b = data.b; } dataProc.myCubeInstances.push(result); // 数据放入(填充)实例化容器 return dataProc.cubeIndex++; // 返回当前模型的索引 },

    // 填充 myCubeInstances fullInst: (data, offset)=>{ const len = data.length; for (let index = 0; index < len; index++) { // 实心数据,填充实例化容器 dataProc.readData(data[index], false, offset); } // console.log(‘共’, dataProc.cubeIndex, ‘个可见方块(包括 del)’); // console.log(’—–’);

     if(dataProc.buildMode) {  // 非建造模式,补全空模型
         for (let index = 0; index < dataProc.totalCube - dataProc.cubeIndex; index++) {  // 空模型,填充容器里多余的空间(建造模式)
             dataProc.readData({
                 x: 999999999, y: 999999999, z: 999999999,
                 w: 0.001, d: 0.001, h: 0.001,
             }, true);
         }
     }
    

    },

    // 遍历 instData,添加物理体 /**

    • 按照块儿来计算。
    • 一共是 100 万的数量,相当于 100 块,每个占用 1 万个索引
    • 比如:
    • 第一块的 index 是 09999 ,在档案数量里,就是 110000 个
    • 而 0 就是这个万数块儿的 ID。 */ addPhysical: (data, instData) => { const boxLen = instData.length; // 正常添加的数量 for (let index = 0; index < boxLen; index++) { // 入档案,添加物理体 const args = { DPZ : (data[index]?.dz) ? data[index]?.dz : 4, isPhysical: (data[index]?.st) ? false : true, // 是否有物理属性 mass: 0, background: ‘#4dff00ff’, // 调试时的高亮颜色 mixValue: 0.5, customIdx: dataProc.wskIdx + index, // 按照计算的索引 isShadow: false, X: instData[index].x, Y: instData[index].y, Z: instData[index].z, width: instData[index].w, depth: instData[index].d, height: instData[index].h, rX: instData[index].rx, rY: instData[index].ry, rZ: instData[index].rz, isInvisible: true, // 只被探测,而不可见 }; if(index === 0){ args.dataName = dataProc.dataName } // 只在第一个模型上添加。供删除时使用,防止错删 k.addTABox(args); } },

    // 计算当前的 万数块 idx // 从 0 开始,一万一万数,哪个空缺,哪个就申请为当前的 万数块 calWskIdx: () => { const len = k.MAX_BODIES; for(let index = 0; index < len; index += 10000){ if(k.indexToArgs.get(index) === undefined) { // 发现空缺 return index; } } return 0; // 理论上这行根本执行不到 },

    // 渲染实例化 /**

    • 每个实例 cube 容器,都使用 wsk_ + 万数块 ID 格式,方便删除 */ renderInst: (texture) => { k.W.cube({ // 渲染实例化 n: ‘wsk_’ + dataProc.wskIdx + ‘_’ + dataProc.dataName, t: texture, // 大理石 instances: dataProc.myCubeInstances, // 实例属性的数组 mix: 0.7, }); },

    // 数据处理总入口 // 默认的纹理是 dls,也就是大理石 process: (data, offset, texture = dls, name = ’noName’, isWskBlock = true) => { D = null; // 释放内存(删去临时数据产生的内存)后续不用这个了,先放着

     if(isWskBlock){
         dataProc.wskIdx = dataProc.calWskIdx();  //+ 马上计算 wsk id,并占位!
     } else {
         dataProc.wskIdx = -1;
         for(let idx = 990000; idx < k.MAX_BODIES; idx++){  // 非万数块,计算 990000~999999 之间的空闲索引
             if(k.indexToArgs.get(idx) === undefined){
                 dataProc.wskIdx = idx;
                 break;
             }
         }
         if(dataProc.wskIdx === -1){
             console.error('万数块不足,无法创建新的万数块,请删除一些万数块再试!');
             return -1;
         }
     }
    
     dataProc.dataName = Math.floor(Math.random() * 1000000);  // 防止冲突,防止错删
     k.indexToArgs.set(dataProc.wskIdx, {n: 'is has data'});
     dataProc.fullInst(data, offset);  // 填充实例化容器
     dataProc.addPhysical(data, dataProc.myCubeInstances);  // 添加物理体
     dataProc.renderInst(texture);  // 渲染实例化
     const wskID = dataProc.wskIdx;
    
     // 重新置空
     if(true){
         dataProc.myCubeInstances = [];
         dataProc.buildMode = 0;
         dataProc.totalCube = 10000;
         dataProc.cubeIndex = 0;
         dataProc.wskIdx = -1;
     }
    
     return wskID;
    

    }, }

数据删除模块:

/**

  • 按照块儿删除模型

  • wsk 删除机制

  • ========

  • 目前设定的块儿大小是 1_0000 个模型 */ export default function(ccgxkObj){ ccgxkObj.deleteModBlock = function(blockIndex, cobj = ccgxkObj){

     const dataName = cobj.indexToArgs.get(blockIndex).dataName;
    
     for(let i = blockIndex; i < blockIndex + 10000; i++){
         cobj.hiddenTABox(i);  //+ 档案删除大法
    
         // 删除在 spatialGrid 里的记录
         if(1){
             const gridkey = cobj.indexToArgs.get(i)?.initGridKey;
             if(gridkey){
                 cobj.spatialGrid.get(gridkey).delete(i);
             }
         }
         cobj.indexToArgs.delete(i);
    
     }
    
    
     cobj.W.delete('wsk_' + blockIndex + '_' + dataName);
    

    } }


是这样的。我现在正在用我稚嫩的技术,实现一个万数块 、 百数块、单数块机制。

我的数据总容量是 一百万 。

现在我已经实现了万数块,可以动态增删。但是 一百万 的容量,显然还是不够。所以我搞了单数块。目前单数块我只实现了增加,还未实现删除。

万数块机制分区:
	 990_000 ~ 1_000_000 : 单数块 type = 3
	900_000 ~ 989_999 : 百数块 type = 2
	0 ~ 899_999 : 万数块 type = 1

我现在想实现百数块。目前先不实现删除。只增加。慢慢来。

请返回 数据处理模块 的直接可用的代码,添加一个 type 变量。其余两部分先不动。

- end -#

© 2025 –   海牧羽工厂 HMY Factory