|
|
@@ -940,6 +940,16 @@ export class BlockManager extends Component {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 新增:教程阶段对场上已放置方块的移动控制
|
|
|
+ public canMovePlacedBlocks(): boolean {
|
|
|
+ try {
|
|
|
+ // 仅在第4步允许移动,或第6步完成(_tutorialStep >= 7)后恢复自由移动
|
|
|
+ return this._tutorialStep === 4 || this._tutorialStep >= 7;
|
|
|
+ } catch (e) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 新手引导下为第 i 个容器选择固定形状(I、S、L),并确保形状在该武器可用
|
|
|
*/
|
|
|
@@ -1292,6 +1302,50 @@ export class BlockManager extends Component {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // 扩展教程(第5-6步):只允许拖到指定格子
|
|
|
+ if (this._tutorialStep >= 5 && this._tutorialStep < 7) {
|
|
|
+ const basePair = this._tutorialStep >= 6 ? this._tutorialTargetGridsStep4 : this._tutorialTargetGridsStep2;
|
|
|
+ if (basePair && basePair.length === 2) {
|
|
|
+ const parse = (name: string) => {
|
|
|
+ const m = name.match(/^Grid_(\d+)_(\d+)$/);
|
|
|
+ return m ? { row: parseInt(m[1]), col: parseInt(m[2]) } : null;
|
|
|
+ };
|
|
|
+ const pairKey = (arr: string[]) => arr.slice().sort().join('|');
|
|
|
+ const p0 = parse(basePair[0]);
|
|
|
+ const p1 = parse(basePair[1]);
|
|
|
+ if (p0 && p1) {
|
|
|
+ let anchor = p0;
|
|
|
+ if (p0.row !== p1.row) {
|
|
|
+ anchor = p0.row < p1.row ? p0 : p1;
|
|
|
+ } else if (p0.col !== p1.col) {
|
|
|
+ anchor = p0.col < p1.col ? p0 : p1;
|
|
|
+ }
|
|
|
+ const horizontalPair = [`Grid_${anchor.row}_${anchor.col}`, `Grid_${anchor.row}_${anchor.col + 1}`];
|
|
|
+ const verticalPair = [`Grid_${anchor.row}_${anchor.col}`, `Grid_${anchor.row + 1}_${anchor.col}`];
|
|
|
+ const allowedPairs = new Set<string>([
|
|
|
+ pairKey(horizontalPair),
|
|
|
+ pairKey(verticalPair),
|
|
|
+ pairKey(basePair),
|
|
|
+ ]);
|
|
|
+ const targetRowCol = this.getGridRowCol(nearestGrid);
|
|
|
+ if (!targetRowCol) return false;
|
|
|
+ const parts = this.getBlockParts(block);
|
|
|
+ const occupiedNames: string[] = [];
|
|
|
+ for (let i = 0; i < parts.length; i++) {
|
|
|
+ const part = parts[i];
|
|
|
+ const row = targetRowCol.row - part.y;
|
|
|
+ const col = targetRowCol.col + part.x;
|
|
|
+ occupiedNames.push(`Grid_${row}_${col}`);
|
|
|
+ }
|
|
|
+ const occupiedKey = pairKey(occupiedNames);
|
|
|
+ if (!allowedPairs.has(occupiedKey)) {
|
|
|
+ console.log(`[BlockManager] 扩展教程:方块不能放置到此网格`);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
return this.tryPlaceBlockToSpecificGrid(block, nearestGrid);
|
|
|
}
|
|
|
@@ -2864,6 +2918,22 @@ export class BlockManager extends Component {
|
|
|
// 注意:参与合成的方块都在网格中,它们的db标签本来就应该是隐藏的
|
|
|
// 不需要调用hideDbLabel,因为这些方块已经不在block容器中了
|
|
|
|
|
|
+ // 在扩展教程(第5-6步)中,合成即可视为完成,触发教程完成判断
|
|
|
+ if (this.isExtendedTutorialEventContext()) {
|
|
|
+ let gridNode: Node | null = null;
|
|
|
+ const occupied = (target as any)['occupiedGrids'];
|
|
|
+ if (occupied && occupied.length > 0) {
|
|
|
+ const first = occupied[0];
|
|
|
+ if (first && this.gridNodes[first.row] && this.gridNodes[first.row][first.col]) {
|
|
|
+ gridNode = this.gridNodes[first.row][first.col];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 如果能定位到目标格子,则用源方块+该格子进行教程完成判定
|
|
|
+ if (gridNode) {
|
|
|
+ this.handleTutorialBlockPlacement(source, gridNode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 销毁被合并方块
|
|
|
source.destroy();
|
|
|
|
|
|
@@ -3101,6 +3171,43 @@ export class BlockManager extends Component {
|
|
|
console.log(`[BlockManager] 检查方块碰撞`);
|
|
|
if (this.rectIntersects(dragBB, targetBB)) {
|
|
|
console.log(`[BlockManager] 方块重叠,执行合成`);
|
|
|
+ // 扩展教程(第5-6步):仅允许在指定格子处合成
|
|
|
+ if (this._tutorialStep >= 5 && this._tutorialStep < 7) {
|
|
|
+ const basePair = this._tutorialStep >= 6 ? this._tutorialTargetGridsStep4 : this._tutorialTargetGridsStep2;
|
|
|
+ if (basePair && basePair.length === 2) {
|
|
|
+ const pairKey = (arr: string[]) => arr.slice().sort().join('|');
|
|
|
+ const occupied = (target as any)['occupiedGrids'] as { row: number, col: number }[] | undefined;
|
|
|
+ if (occupied && occupied.length >= 2) {
|
|
|
+ const occupiedNames = occupied.map(g => `Grid_${g.row}_${g.col}`);
|
|
|
+ const parse = (name: string) => {
|
|
|
+ const m = name.match(/^Grid_(\d+)_(\d+)$/);
|
|
|
+ return m ? { row: parseInt(m[1]), col: parseInt(m[2]) } : null;
|
|
|
+ };
|
|
|
+ const p0 = parse(basePair[0]);
|
|
|
+ const p1 = parse(basePair[1]);
|
|
|
+ if (p0 && p1) {
|
|
|
+ let anchor = p0;
|
|
|
+ if (p0.row !== p1.row) {
|
|
|
+ anchor = p0.row < p1.row ? p0 : p1;
|
|
|
+ } else if (p0.col !== p1.col) {
|
|
|
+ anchor = p0.col < p1.col ? p0 : p1;
|
|
|
+ }
|
|
|
+ const horizontalPair = [`Grid_${anchor.row}_${anchor.col}`, `Grid_${anchor.row}_${anchor.col + 1}`];
|
|
|
+ const verticalPair = [`Grid_${anchor.row}_${anchor.col}`, `Grid_${anchor.row + 1}_${anchor.col}`];
|
|
|
+ const allowedPairs = new Set<string>([
|
|
|
+ pairKey(horizontalPair),
|
|
|
+ pairKey(verticalPair),
|
|
|
+ pairKey(basePair),
|
|
|
+ ]);
|
|
|
+ const occupiedKey = pairKey(occupiedNames);
|
|
|
+ if (!allowedPairs.has(occupiedKey)) {
|
|
|
+ console.log(`[BlockManager] 扩展教程:目标位置不在要求格子,禁止合成`);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
// 执行合并:目标保留,拖拽方块销毁
|
|
|
this.performMerge(target, draggedBlock, rarity);
|
|
|
return true;
|