|
|
@@ -1,13 +1,6 @@
|
|
|
-import { _decorator, Component, Node, Prefab, instantiate, Vec3, EventTouch, Vec2, UITransform, find } from 'cc';
|
|
|
+import { _decorator, Component, Node, Prefab, instantiate, Vec3, EventTouch, Vec2, UITransform, find, BoxCollider2D, Collider2D, Contact2DType, IPhysics2DContact, Intersection2D, Rect, PhysicsSystem2D } from 'cc';
|
|
|
const { ccclass, property } = _decorator;
|
|
|
|
|
|
-// 格子信息接口
|
|
|
-interface GridInfo {
|
|
|
- node: Node;
|
|
|
- position: Vec3;
|
|
|
- isOccupied: boolean;
|
|
|
-}
|
|
|
-
|
|
|
@ccclass('BlockManager')
|
|
|
export class BlockManager extends Component {
|
|
|
// 预制体数组,存储5个预制体
|
|
|
@@ -21,9 +14,11 @@ export class BlockManager extends Component {
|
|
|
})
|
|
|
public gridContainer: Node = null;
|
|
|
|
|
|
- // 网格大小
|
|
|
- @property
|
|
|
- public gridSize: number = 48;
|
|
|
+ // 是否启用物理碰撞检测
|
|
|
+ @property({
|
|
|
+ tooltip: '是否启用物理碰撞检测'
|
|
|
+ })
|
|
|
+ public usePhysicsCollision: boolean = true;
|
|
|
|
|
|
// 已经生成的块
|
|
|
private blocks: Node[] = [];
|
|
|
@@ -33,44 +28,25 @@ export class BlockManager extends Component {
|
|
|
private startPos = new Vec2();
|
|
|
// 块的起始位置
|
|
|
private blockStartPos: Vec3 = new Vec3();
|
|
|
- // 网格信息
|
|
|
- private grids: GridInfo[] = [];
|
|
|
- // 已放置的方块占用的格子
|
|
|
- private occupiedGrids: Set<string> = new Set();
|
|
|
+ // 已占用的网格位置
|
|
|
+ private occupiedPositions: Set<string> = new Set();
|
|
|
|
|
|
start() {
|
|
|
- // 初始化网格信息
|
|
|
- this.initGrids();
|
|
|
- // 生成随机的三个块
|
|
|
- this.generateRandomBlocks();
|
|
|
- }
|
|
|
-
|
|
|
- // 初始化网格信息
|
|
|
- initGrids() {
|
|
|
+ // 如果没有指定GridContainer,尝试找到它
|
|
|
if (!this.gridContainer) {
|
|
|
this.gridContainer = find('Canvas/GameLevelUI/GameArea/GridContainer');
|
|
|
if (!this.gridContainer) {
|
|
|
console.error('找不到GridContainer节点');
|
|
|
- return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 清空网格信息
|
|
|
- this.grids = [];
|
|
|
-
|
|
|
- // 遍历GridContainer的子节点,获取所有格子信息
|
|
|
- for (let i = 0; i < this.gridContainer.children.length; i++) {
|
|
|
- const grid = this.gridContainer.children[i];
|
|
|
- if (grid.name.startsWith('Grid_')) {
|
|
|
- this.grids.push({
|
|
|
- node: grid,
|
|
|
- position: grid.position.clone(),
|
|
|
- isOccupied: false
|
|
|
- });
|
|
|
- }
|
|
|
+ // 启用物理系统
|
|
|
+ if (this.usePhysicsCollision) {
|
|
|
+ PhysicsSystem2D.instance.enable = true;
|
|
|
}
|
|
|
|
|
|
- console.log(`初始化了 ${this.grids.length} 个网格`);
|
|
|
+ // 生成随机的三个块
|
|
|
+ this.generateRandomBlocks();
|
|
|
}
|
|
|
|
|
|
generateRandomBlocks() {
|
|
|
@@ -106,11 +82,70 @@ export class BlockManager extends Component {
|
|
|
// 添加到块数组
|
|
|
this.blocks.push(block);
|
|
|
|
|
|
+ // 添加碰撞组件
|
|
|
+ if (this.usePhysicsCollision) {
|
|
|
+ this.addColliders(block);
|
|
|
+ }
|
|
|
+
|
|
|
// 添加触摸事件
|
|
|
this.setupDragEvents(block);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 为方块的B1、B2、B3等节点添加碰撞组件
|
|
|
+ addColliders(block: Node) {
|
|
|
+ const blockParts = this.getBlockParts(block);
|
|
|
+
|
|
|
+ for (const part of blockParts) {
|
|
|
+ // 检查是否已有碰撞组件
|
|
|
+ let collider = part.getComponent(BoxCollider2D);
|
|
|
+ if (!collider) {
|
|
|
+ collider = part.addComponent(BoxCollider2D);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置碰撞组件属性
|
|
|
+ const uiTransform = part.getComponent(UITransform);
|
|
|
+ if (uiTransform) {
|
|
|
+ collider.size.width = uiTransform.contentSize.width * 0.8; // 稍微小一点,避免边缘碰撞
|
|
|
+ collider.size.height = uiTransform.contentSize.height * 0.8;
|
|
|
+ } else {
|
|
|
+ collider.size.width = 40; // 默认大小
|
|
|
+ collider.size.height = 40;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置碰撞组和掩码
|
|
|
+ collider.group = 1 << 0; // 默认组
|
|
|
+ collider.sensor = true; // 设为传感器,不影响物理行为
|
|
|
+
|
|
|
+ // 添加碰撞回调
|
|
|
+ collider.on(Contact2DType.BEGIN_CONTACT, this.onCollisionEnter, this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 碰撞开始回调
|
|
|
+ onCollisionEnter(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
|
|
|
+ // 如果当前正在拖拽方块,标记碰撞状态
|
|
|
+ if (this.currentDragBlock) {
|
|
|
+ const block = this.findBlockByPart(selfCollider.node);
|
|
|
+ if (block === this.currentDragBlock) {
|
|
|
+ block['isColliding'] = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据部件节点找到所属的方块
|
|
|
+ findBlockByPart(partNode: Node): Node | null {
|
|
|
+ for (const block of this.blocks) {
|
|
|
+ const blockParts = this.getBlockParts(block);
|
|
|
+ for (const part of blockParts) {
|
|
|
+ if (part === partNode) {
|
|
|
+ return block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
setupDragEvents(block: Node) {
|
|
|
// 添加触摸开始事件
|
|
|
block.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
|
|
|
@@ -124,8 +159,11 @@ export class BlockManager extends Component {
|
|
|
// 将块置于顶层
|
|
|
block.setSiblingIndex(this.node.children.length - 1);
|
|
|
|
|
|
- // 如果方块已经放置在网格中,则移除占用状态
|
|
|
+ // 如果方块已经放置在网格中,移除占用状态
|
|
|
this.removeBlockFromGrid(block);
|
|
|
+
|
|
|
+ // 重置碰撞状态
|
|
|
+ block['isColliding'] = false;
|
|
|
}, this);
|
|
|
|
|
|
// 添加触摸移动事件
|
|
|
@@ -143,16 +181,23 @@ export class BlockManager extends Component {
|
|
|
this.blockStartPos.y + deltaY,
|
|
|
this.blockStartPos.z
|
|
|
);
|
|
|
-
|
|
|
- // 显示吸附预览
|
|
|
- this.showSnapPreview(this.currentDragBlock);
|
|
|
}, this);
|
|
|
|
|
|
// 添加触摸结束事件
|
|
|
- block.on(Node.EventType.TOUCH_END, () => {
|
|
|
+ block.on(Node.EventType.TOUCH_END, (event: EventTouch) => {
|
|
|
if (this.currentDragBlock) {
|
|
|
- // 尝试将方块吸附到网格
|
|
|
- this.snapBlockToGrid(this.currentDragBlock);
|
|
|
+ // 检查是否有碰撞
|
|
|
+ if (this.usePhysicsCollision && this.currentDragBlock['isColliding']) {
|
|
|
+ // 有碰撞,返回原位
|
|
|
+ this.currentDragBlock.position = this.blockStartPos.clone();
|
|
|
+ console.log('方块放置失败:与其他方块碰撞');
|
|
|
+ } else {
|
|
|
+ // 尝试将方块放置到网格中
|
|
|
+ if (!this.tryPlaceBlockToGrid(this.currentDragBlock)) {
|
|
|
+ // 放置失败,返回原位
|
|
|
+ this.currentDragBlock.position = this.blockStartPos.clone();
|
|
|
+ }
|
|
|
+ }
|
|
|
this.currentDragBlock = null;
|
|
|
}
|
|
|
}, this);
|
|
|
@@ -160,85 +205,118 @@ export class BlockManager extends Component {
|
|
|
// 添加触摸取消事件
|
|
|
block.on(Node.EventType.TOUCH_CANCEL, () => {
|
|
|
if (this.currentDragBlock) {
|
|
|
- // 尝试将方块吸附到网格
|
|
|
- this.snapBlockToGrid(this.currentDragBlock);
|
|
|
+ // 触摸取消,返回原位
|
|
|
+ this.currentDragBlock.position = this.blockStartPos.clone();
|
|
|
this.currentDragBlock = null;
|
|
|
}
|
|
|
}, this);
|
|
|
}
|
|
|
|
|
|
- // 显示吸附预览
|
|
|
- showSnapPreview(block: Node) {
|
|
|
+ // 尝试将方块放置到网格中
|
|
|
+ tryPlaceBlockToGrid(block: Node): boolean {
|
|
|
+ if (!this.gridContainer) return false;
|
|
|
+
|
|
|
// 找到B1节点(吸附点)
|
|
|
const b1Node = this.findB1Node(block);
|
|
|
- if (!b1Node) return;
|
|
|
+ if (!b1Node) return false;
|
|
|
|
|
|
- // 计算B1节点在世界坐标系中的位置
|
|
|
- const blockWorldPos = this.node.getComponent(UITransform).convertToWorldSpaceAR(block.position);
|
|
|
- const b1LocalPos = b1Node.position;
|
|
|
+ // 获取B1节点在世界坐标中的位置
|
|
|
+ const blockWorldPos = block.parent.getComponent(UITransform).convertToWorldSpaceAR(block.position);
|
|
|
const b1WorldPos = new Vec3(
|
|
|
- blockWorldPos.x + b1LocalPos.x,
|
|
|
- blockWorldPos.y + b1LocalPos.y,
|
|
|
- blockWorldPos.z + b1LocalPos.z
|
|
|
+ blockWorldPos.x + b1Node.position.x,
|
|
|
+ blockWorldPos.y + b1Node.position.y,
|
|
|
+ blockWorldPos.z
|
|
|
);
|
|
|
|
|
|
- // 将B1节点的世界坐标转换为网格容器的本地坐标
|
|
|
- const gridContainerPos = this.gridContainer.getComponent(UITransform).convertToNodeSpaceAR(b1WorldPos);
|
|
|
-
|
|
|
- // 找到最近的网格
|
|
|
- const nearestGrid = this.findNearestGrid(gridContainerPos);
|
|
|
- if (nearestGrid && this.canPlaceBlockAt(block, nearestGrid)) {
|
|
|
- // 可以显示预览效果,例如高亮网格等
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 将方块吸附到网格
|
|
|
- snapBlockToGrid(block: Node) {
|
|
|
- // 找到B1节点(吸附点)
|
|
|
- const b1Node = this.findB1Node(block);
|
|
|
- if (!b1Node) return;
|
|
|
+ // 将B1节点的世界坐标转换为GridContainer的本地坐标
|
|
|
+ const gridPos = this.gridContainer.getComponent(UITransform).convertToNodeSpaceAR(b1WorldPos);
|
|
|
|
|
|
- // 计算B1节点在世界坐标系中的位置
|
|
|
- const blockWorldPos = this.node.getComponent(UITransform).convertToWorldSpaceAR(block.position);
|
|
|
- const b1LocalPos = b1Node.position;
|
|
|
- const b1WorldPos = new Vec3(
|
|
|
- blockWorldPos.x + b1LocalPos.x,
|
|
|
- blockWorldPos.y + b1LocalPos.y,
|
|
|
- blockWorldPos.z + b1LocalPos.z
|
|
|
- );
|
|
|
+ // 检查是否在GridContainer范围内
|
|
|
+ const gridSize = this.gridContainer.getComponent(UITransform).contentSize;
|
|
|
+ const halfWidth = gridSize.width / 2;
|
|
|
+ const halfHeight = gridSize.height / 2;
|
|
|
|
|
|
- // 将B1节点的世界坐标转换为网格容器的本地坐标
|
|
|
- const gridContainerPos = this.gridContainer.getComponent(UITransform).convertToNodeSpaceAR(b1WorldPos);
|
|
|
+ if (gridPos.x < -halfWidth || gridPos.x > halfWidth ||
|
|
|
+ gridPos.y < -halfHeight || gridPos.y > halfHeight) {
|
|
|
+ console.log('方块不在GridContainer范围内');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- // 找到最近的网格
|
|
|
- const nearestGrid = this.findNearestGrid(gridContainerPos);
|
|
|
- if (!nearestGrid) return;
|
|
|
+ // 找到最近的网格节点
|
|
|
+ const nearestGrid = this.findNearestGridNode(gridPos);
|
|
|
+ if (!nearestGrid) {
|
|
|
+ console.log('找不到合适的网格节点');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- // 检查是否可以放置
|
|
|
+ // 检查方块的所有部分是否会与已占用的格子重叠
|
|
|
if (!this.canPlaceBlockAt(block, nearestGrid)) {
|
|
|
- // 不能放置,恢复到原始位置
|
|
|
- block.position = this.blockStartPos.clone();
|
|
|
- return;
|
|
|
+ console.log('方块放置位置已被占用或超出边界');
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- // 计算方块应该移动到的位置
|
|
|
+ // 计算方块应该移动到的位置,使B1对齐到网格
|
|
|
const targetWorldPos = this.gridContainer.getComponent(UITransform).convertToWorldSpaceAR(nearestGrid.position);
|
|
|
- const targetNodePos = this.node.getComponent(UITransform).convertToNodeSpaceAR(targetWorldPos);
|
|
|
+ const targetPos = block.parent.getComponent(UITransform).convertToNodeSpaceAR(targetWorldPos);
|
|
|
|
|
|
- // 设置方块位置,使B1节点对齐到网格
|
|
|
+ // 设置方块位置
|
|
|
block.position = new Vec3(
|
|
|
- targetNodePos.x - b1LocalPos.x,
|
|
|
- targetNodePos.y - b1LocalPos.y,
|
|
|
+ targetPos.x - b1Node.position.x,
|
|
|
+ targetPos.y - b1Node.position.y,
|
|
|
block.position.z
|
|
|
);
|
|
|
|
|
|
// 标记占用的格子
|
|
|
- this.markOccupiedGrids(block, nearestGrid);
|
|
|
+ this.markOccupiedPositions(block, nearestGrid);
|
|
|
+
|
|
|
+ console.log('方块放置成功');
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查两个方块是否碰撞(使用几何碰撞检测)
|
|
|
+ checkBlocksCollision(block1: Node, block2: Node): boolean {
|
|
|
+ if (block1 === block2) return false;
|
|
|
+
|
|
|
+ const parts1 = this.getBlockParts(block1);
|
|
|
+ const parts2 = this.getBlockParts(block2);
|
|
|
+
|
|
|
+ // 检查每个部分之间的碰撞
|
|
|
+ for (const part1 of parts1) {
|
|
|
+ const rect1 = this.getNodeRect(part1);
|
|
|
+
|
|
|
+ for (const part2 of parts2) {
|
|
|
+ const rect2 = this.getNodeRect(part2);
|
|
|
+
|
|
|
+ // 检查矩形是否相交
|
|
|
+ if (Intersection2D.rectRect(rect1, rect2)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取节点的世界矩形
|
|
|
+ getNodeRect(node: Node): Rect {
|
|
|
+ const uiTransform = node.getComponent(UITransform);
|
|
|
+ if (!uiTransform) {
|
|
|
+ return new Rect(0, 0, 0, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ const size = uiTransform.contentSize;
|
|
|
+ const worldPos = node.parent.getComponent(UITransform).convertToWorldSpaceAR(node.position);
|
|
|
+
|
|
|
+ return new Rect(
|
|
|
+ worldPos.x - size.width * 0.5,
|
|
|
+ worldPos.y - size.height * 0.5,
|
|
|
+ size.width,
|
|
|
+ size.height
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
// 找到B1节点
|
|
|
findB1Node(block: Node): Node {
|
|
|
- // 遍历子节点,查找名为B1的节点
|
|
|
for (let i = 0; i < block.children.length; i++) {
|
|
|
const child = block.children[i];
|
|
|
if (child.name === 'B1') {
|
|
|
@@ -248,69 +326,61 @@ export class BlockManager extends Component {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- // 找到最近的网格
|
|
|
- findNearestGrid(position: Vec3): GridInfo {
|
|
|
- let nearestGrid: GridInfo = null;
|
|
|
+ // 找到最近的网格节点
|
|
|
+ findNearestGridNode(position: Vec3): Node {
|
|
|
+ if (!this.gridContainer) return null;
|
|
|
+
|
|
|
+ let nearestNode: Node = null;
|
|
|
let minDistance = Number.MAX_VALUE;
|
|
|
|
|
|
- for (const grid of this.grids) {
|
|
|
- const distance = Vec3.distance(position, grid.position);
|
|
|
- if (distance < minDistance && !grid.isOccupied) {
|
|
|
- minDistance = distance;
|
|
|
- nearestGrid = grid;
|
|
|
+ // 遍历所有网格节点
|
|
|
+ for (let i = 0; i < this.gridContainer.children.length; i++) {
|
|
|
+ const grid = this.gridContainer.children[i];
|
|
|
+ if (grid.name.startsWith('Grid_')) {
|
|
|
+ const distance = Vec3.distance(position, grid.position);
|
|
|
+ if (distance < minDistance) {
|
|
|
+ minDistance = distance;
|
|
|
+ nearestNode = grid;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 如果距离太远,不吸附
|
|
|
- if (minDistance > this.gridSize / 2) {
|
|
|
+ // 如果距离太远(超过网格大小的一半),不吸附
|
|
|
+ if (minDistance > 24) { // 假设网格大小为48x48
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- return nearestGrid;
|
|
|
+ return nearestNode;
|
|
|
}
|
|
|
|
|
|
- // 检查方块是否可以放置在指定网格
|
|
|
- canPlaceBlockAt(block: Node, grid: GridInfo): boolean {
|
|
|
- // 获取方块的所有子节点(B1, B2, B3...)
|
|
|
+ // 检查方块是否可以放置在指定位置
|
|
|
+ canPlaceBlockAt(block: Node, targetGrid: Node): boolean {
|
|
|
+ // 获取方块的所有部分(B1, B2, B3...)
|
|
|
const blockParts = this.getBlockParts(block);
|
|
|
|
|
|
- // 假设B1已经对齐到目标网格,计算其他部分的位置
|
|
|
+ // 找到B1节点
|
|
|
const b1Node = this.findB1Node(block);
|
|
|
if (!b1Node) return false;
|
|
|
|
|
|
- // 计算方块应该移动到的位置
|
|
|
- const targetWorldPos = this.gridContainer.getComponent(UITransform).convertToWorldSpaceAR(grid.position);
|
|
|
- const targetNodePos = this.node.getComponent(UITransform).convertToNodeSpaceAR(targetWorldPos);
|
|
|
+ // 计算B1与目标网格的偏移
|
|
|
+ const offsetX = targetGrid.position.x - b1Node.position.x;
|
|
|
+ const offsetY = targetGrid.position.y - b1Node.position.y;
|
|
|
|
|
|
- // 计算方块的新位置
|
|
|
- const newBlockPos = new Vec3(
|
|
|
- targetNodePos.x - b1Node.position.x,
|
|
|
- targetNodePos.y - b1Node.position.y,
|
|
|
- block.position.z
|
|
|
- );
|
|
|
-
|
|
|
- // 检查每个部分是否会与已占用的格子重叠
|
|
|
+ // 检查每个部分是否与已占用的格子重叠
|
|
|
for (const part of blockParts) {
|
|
|
- if (part === b1Node) continue; // B1已经对齐到目标网格
|
|
|
-
|
|
|
- // 计算部分在新位置下的世界坐标
|
|
|
- const partWorldPos = new Vec3(
|
|
|
- newBlockPos.x + part.position.x,
|
|
|
- newBlockPos.y + part.position.y,
|
|
|
- newBlockPos.z + part.position.z
|
|
|
- );
|
|
|
- const partWorldPosAR = this.node.getComponent(UITransform).convertToWorldSpaceAR(partWorldPos);
|
|
|
- const gridContainerPos = this.gridContainer.getComponent(UITransform).convertToNodeSpaceAR(partWorldPosAR);
|
|
|
+ // 计算部分在网格中的位置
|
|
|
+ const gridX = Math.round(offsetX + part.position.x);
|
|
|
+ const gridY = Math.round(offsetY + part.position.y);
|
|
|
+ const posKey = `${gridX},${gridY}`;
|
|
|
|
|
|
- // 找到该部分对应的网格
|
|
|
- const partGrid = this.findExactGrid(gridContainerPos);
|
|
|
- if (!partGrid) {
|
|
|
- // 超出网格范围
|
|
|
+ // 检查该位置是否已被占用
|
|
|
+ if (this.occupiedPositions.has(posKey)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- // 检查该网格是否已被占用
|
|
|
- if (partGrid.isOccupied) {
|
|
|
+ // 检查是否超出GridContainer边界
|
|
|
+ const gridNode = this.findGridAtPosition(gridX, gridY);
|
|
|
+ if (!gridNode) {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
@@ -318,14 +388,19 @@ export class BlockManager extends Component {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- // 找到精确匹配的网格
|
|
|
- findExactGrid(position: Vec3): GridInfo {
|
|
|
- for (const grid of this.grids) {
|
|
|
- const distance = Vec3.distance(position, grid.position);
|
|
|
- if (distance < this.gridSize / 2) {
|
|
|
- return grid;
|
|
|
+ // 根据坐标找到网格节点
|
|
|
+ findGridAtPosition(x: number, y: number): Node {
|
|
|
+ if (!this.gridContainer) return null;
|
|
|
+
|
|
|
+ for (let i = 0; i < this.gridContainer.children.length; i++) {
|
|
|
+ const grid = this.gridContainer.children[i];
|
|
|
+ if (grid.name.startsWith('Grid_')) {
|
|
|
+ if (Math.abs(grid.position.x - x) < 1 && Math.abs(grid.position.y - y) < 1) {
|
|
|
+ return grid;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
@@ -333,10 +408,9 @@ export class BlockManager extends Component {
|
|
|
getBlockParts(block: Node): Node[] {
|
|
|
const parts: Node[] = [];
|
|
|
|
|
|
- // 遍历子节点,查找名称以B开头的节点
|
|
|
for (let i = 0; i < block.children.length; i++) {
|
|
|
const child = block.children[i];
|
|
|
- if (child.name.startsWith('B') && child.name.length > 1) {
|
|
|
+ if (child.name.startsWith('B') && /^B\d+$/.test(child.name)) {
|
|
|
parts.push(child);
|
|
|
}
|
|
|
}
|
|
|
@@ -345,59 +419,47 @@ export class BlockManager extends Component {
|
|
|
}
|
|
|
|
|
|
// 标记方块占用的格子
|
|
|
- markOccupiedGrids(block: Node, mainGrid: GridInfo) {
|
|
|
+ markOccupiedPositions(block: Node, targetGrid: Node) {
|
|
|
// 获取方块的所有部分
|
|
|
const blockParts = this.getBlockParts(block);
|
|
|
|
|
|
- // 为每个部分找到对应的网格并标记为已占用
|
|
|
+ // 找到B1节点
|
|
|
+ const b1Node = this.findB1Node(block);
|
|
|
+ if (!b1Node) return;
|
|
|
+
|
|
|
+ // 计算B1与目标网格的偏移
|
|
|
+ const offsetX = targetGrid.position.x - b1Node.position.x;
|
|
|
+ const offsetY = targetGrid.position.y - b1Node.position.y;
|
|
|
+
|
|
|
+ // 为每个部分标记占用位置
|
|
|
for (const part of blockParts) {
|
|
|
- // 计算部分在世界坐标系中的位置
|
|
|
- const blockWorldPos = this.node.getComponent(UITransform).convertToWorldSpaceAR(block.position);
|
|
|
- const partLocalPos = part.position;
|
|
|
- const partWorldPos = new Vec3(
|
|
|
- blockWorldPos.x + partLocalPos.x,
|
|
|
- blockWorldPos.y + partLocalPos.y,
|
|
|
- blockWorldPos.z + partLocalPos.z
|
|
|
- );
|
|
|
+ // 计算部分在网格中的位置
|
|
|
+ const gridX = Math.round(offsetX + part.position.x);
|
|
|
+ const gridY = Math.round(offsetY + part.position.y);
|
|
|
+ const posKey = `${gridX},${gridY}`;
|
|
|
|
|
|
- // 将部分的世界坐标转换为网格容器的本地坐标
|
|
|
- const gridContainerPos = this.gridContainer.getComponent(UITransform).convertToNodeSpaceAR(partWorldPos);
|
|
|
+ // 记录占用信息
|
|
|
+ this.occupiedPositions.add(posKey);
|
|
|
|
|
|
- // 找到该部分对应的网格
|
|
|
- const grid = this.findExactGrid(gridContainerPos);
|
|
|
- if (grid) {
|
|
|
- grid.isOccupied = true;
|
|
|
- // 记录占用信息,格式为"blockID:gridID"
|
|
|
- this.occupiedGrids.add(`${block.uuid}:${grid.node.uuid}`);
|
|
|
- }
|
|
|
+ // 存储方块与位置的关联
|
|
|
+ block['occupiedPositions'] = block['occupiedPositions'] || [];
|
|
|
+ block['occupiedPositions'].push(posKey);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 移除方块占用的格子
|
|
|
removeBlockFromGrid(block: Node) {
|
|
|
- // 遍历所有占用记录,找到与当前方块相关的记录
|
|
|
- const toRemove: string[] = [];
|
|
|
+ // 获取方块占用的位置
|
|
|
+ const occupiedPositions = block['occupiedPositions'];
|
|
|
+ if (!occupiedPositions) return;
|
|
|
|
|
|
- this.occupiedGrids.forEach(record => {
|
|
|
- if (record.startsWith(`${block.uuid}:`)) {
|
|
|
- const gridId = record.split(':')[1];
|
|
|
-
|
|
|
- // 找到对应的网格并标记为未占用
|
|
|
- for (const grid of this.grids) {
|
|
|
- if (grid.node.uuid === gridId) {
|
|
|
- grid.isOccupied = false;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- toRemove.push(record);
|
|
|
- }
|
|
|
- });
|
|
|
+ // 移除占用标记
|
|
|
+ for (const posKey of occupiedPositions) {
|
|
|
+ this.occupiedPositions.delete(posKey);
|
|
|
+ }
|
|
|
|
|
|
- // 移除记录
|
|
|
- toRemove.forEach(record => {
|
|
|
- this.occupiedGrids.delete(record);
|
|
|
- });
|
|
|
+ // 清空方块的占用记录
|
|
|
+ block['occupiedPositions'] = [];
|
|
|
}
|
|
|
|
|
|
clearBlocks() {
|
|
|
@@ -412,10 +474,7 @@ export class BlockManager extends Component {
|
|
|
}
|
|
|
this.blocks = [];
|
|
|
|
|
|
- // 重置所有网格状态
|
|
|
- for (const grid of this.grids) {
|
|
|
- grid.isOccupied = false;
|
|
|
- }
|
|
|
- this.occupiedGrids.clear();
|
|
|
+ // 清空占用位置
|
|
|
+ this.occupiedPositions.clear();
|
|
|
}
|
|
|
}
|