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 是 0
9999 ,在档案数量里,就是 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 变量。其余两部分先不动。