激光门完毕

This commit is contained in:
COMPUTER\EDY
2026-10-20 15:44:17 +08:00
parent 06ef53017d
commit e8de598a12
4 changed files with 53 additions and 87 deletions
+47 -5
View File
@@ -1,5 +1,6 @@
import type MapController from "./Map";
import type Wall from "./Wall";
import type Block from "./Block";
import { LQCollide } from "./lq_collide_system/lq_collide";
import { LQCollideSystem } from "./lq_collide_system/lq_collide_system";
import { LQCollideShape } from "./lq_base/data/lq_const";
@@ -173,23 +174,64 @@ export default class LaserSystem {
}
}
private collectColliders(): { shape: LaserCollider; wall: cc.Node }[] {
const result: { shape: LaserCollider; wall: cc.Node }[] = [];
/** Prediction only: movable blockers may clear; actual reception still uses every solid. */
getPotentialExitIds(): Set<string> {
const fixed = this.collectColliders().filter(item => !this.canMoveBlocker(item.block));
const result = new Set<string>();
for (const group of this.groups) {
const obstacles = fixed.filter(item => item.wall !== group.emitter.node.parent
&& item.wall !== group.receiver.node.parent).map(item => item.shape);
// Scan to the receiver, including blockers hidden behind the visible beam's first hit.
if (!nearestLaserHit(group.source.getBeamOrigin(), group.target.getBeamOrigin(), obstacles)) {
result.add(group.config.id);
}
}
return result;
}
private canMoveBlocker(block: Block, visited = new Set<Block>()): boolean {
if (!block || block.over || visited.has(block)) return false;
visited.add(block);
const info = block.block_Info || {};
// Exit locks, question blocks and petal covers do not prevent dragging.
// Temporary input locks during spawning/opening also need no elimination to clear.
const hasAxis = (block.type !== 8 && info.vertical == null)
|| (block.type !== 7 && info.horizontal == null);
if ([3, 4, 10, 12].indexOf(block.type) < 0
&& (!info.floor || info.floorMove === true) && hasAxis) return true;
const drivers: cc.Node[] = [];
if (block.type === 10 && info.node) drivers.push(info.node);
if (info.floor && info.floorMove === true) drivers.push(...(block.teamBlocks || []));
// Adhesive followers can move even when they cannot be dragged directly.
for (const node of this.map.node.children) {
const driver = node.getComponent("Block") as Block;
if (driver && driver.type === 9 && driver.block_Info && driver.block_Info.node === block.node) {
drivers.push(node);
}
}
return drivers.some(node => cc.isValid(node, true) && node.activeInHierarchy
&& this.canMoveBlocker(node.getComponent("Block"), visited));
}
private collectColliders(): { shape: LaserCollider; wall: cc.Node; block: Block }[] {
const result: { shape: LaserCollider; wall: cc.Node; block: Block }[] = [];
for (const collider of LQCollideSystem.collide_arr) {
const node = collider.node;
if (!cc.isValid(node, true) || !node.activeInHierarchy || !collider.is_enable
|| !collider.enabled || collider.data_string === "-1" || collider.data_string === "-2") continue;
if (node.name === "rise" && this.map.riseFallBlock.indexOf(node.parent) >= 0) continue;
let ancestor = node, wall: cc.Node = null, transparent = false;
let ancestor = node, wall: cc.Node = null, owner: Block = null, transparent = false;
while (ancestor && ancestor !== this.map.node) {
const block = ancestor.getComponent("Block");
const block = ancestor.getComponent("Block") as Block;
if (block && !owner) owner = block;
if (block && (block.type === 22 || block.over)) transparent = true;
if (ancestor.getChildByName("wall") && ancestor.getChildByName("wall").getComponent("Wall")) wall = ancestor;
ancestor = ancestor.parent;
}
if (ancestor !== this.map.node || transparent) continue;
const shape = this.colliderShape(collider);
if (shape) result.push({ shape, wall });
if (shape) result.push({ shape, wall, block: owner });
}
return result;
}