| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073 |
- import { _decorator, Component, instantiate, Node, Prefab, Sprite, tween, UIOpacity, v3, Vec3, view } from 'cc';
- import { BlockController } from './Block/BlockController';
- import { BlockBaData, BlockConfig, BlocksAll, BlockState, BlockType, BlockWeights, ReConfig } from './Block/BlockData';
- import GlobalData from './GlobalData';
- import { LocalStorageMgr } from './LocalStorageMgr';
- import { MainGameLogic } from './MainGameLogic';
- import { TouchMgr } from './TouchMgr';
- import { AudioManager } from '../AudioManager';
- import { Url } from '../Url';
- import ResSprite from '../ResSprite';
- const { ccclass, property } = _decorator;
- @ccclass('GridBlockMgr')
- export class GridBlockMgr extends Component {
- /** 单例模式 */
- private static _ins: GridBlockMgr;
- constructor() {
- super();
- GridBlockMgr._ins = this;
- }
- public static get ins(): GridBlockMgr {
- if (!GridBlockMgr._ins) {
- GridBlockMgr._ins = new GridBlockMgr();
- }
- return GridBlockMgr._ins;
- }
- @property(Prefab)
- block: Prefab = null;
- @property(Node)
- gridcontainer: Node = null;
- @property(Node)
- selects: Node[] = [];
- @property(Node)
- SelectionContainer: Node = null;
- private boardSize: number = 8;
- private cellSize: number = 122.5;
- block_ba_data: BlockBaData[][];
- temp_block_ba_data: BlockBaData[][];
- temp_block_ba_data1: BlockBaData[][];
- selection_block_type: BlockType[];
- selection_block_config: BlockConfig[]
- protected onLoad(): void {
- this.temp_block_ba_data = this.initializeBlockData();
- this.temp_block_ba_data1 = this.initializeBlockData();
- }
- async start() {
- }
- protected update(dt: number): void {
- }
- // 初始化 temp_block_ba_data 的方法
- initializeBlockData(): BlockBaData[][] {
- const size = 8; // 根据实际情况设置
- const data: BlockBaData[][] = [];
- for (let i = 0; i < size; i++) {
- const row: BlockBaData[] = [];
- for (let j = 0; j < size; j++) {
- row.push({
- block_state: BlockState.HIDE,
- block_ba_node: null, // 根据实际情况初始化
- index_i: i,
- index_j: j,
- block_sprite: null, // 根据实际情况初始化
- block_color: Url.BLOCK.ORANGE
- });
- }
- data.push(row);
- }
- return data;
- }
- // 检测消除
- checkAndUpdateBlocks(): Vec3 | null {
- const size = 8;
- const rowsToClear = new Set<number>();
- const colsToClear = new Set<number>();
- let anyCleared = false;
- let eliminNum = 0; // 消除的总块数
- let totalRow = 0; // 累积的行索引总和
- let totalCol = 0; // 累积的列索引总和
- let clearedRowCount = 0; // 消除的行数
- let clearedColCount = 0; // 消除的列数
- // 检查每一行
- for (let i = 0; i < size; i++) {
- let rowAllOnes = true;
- for (let j = 0; j < size; j++) {
- if (this.block_ba_data[i][j].block_state !== BlockState.SHOW) {
- rowAllOnes = false;
- break;
- }
- }
- if (rowAllOnes) {
- rowsToClear.add(i);
- anyCleared = true;
- clearedRowCount++;
- }
- }
- // 检查每一列
- for (let j = 0; j < size; j++) {
- let colAllOnes = true;
- for (let i = 0; i < size; i++) {
- if (this.block_ba_data[i][j].block_state !== BlockState.SHOW) {
- colAllOnes = false;
- break;
- }
- }
- if (colAllOnes) {
- colsToClear.add(j);
- anyCleared = true;
- clearedColCount++;
- }
- }
- let centerX = null;
- let centerY = null;
- let centerPosition: Vec3 = null;
- // 统一处理需要消除的行和列
- rowsToClear.forEach((i) => {
- for (let j = 0; j < size; j++) {
- const node = this.block_ba_data[i][j].block_ba_node;
- node.getComponent(UIOpacity).opacity = 0;
- this.block_ba_data[i][j].block_state = BlockState.HIDE;
- MainGameLogic.ins.createOneBlockEfEffect(node, this.block_ba_data[i][j].block_color);
- eliminNum++;
- totalRow += i;
- totalCol += j;
- }
- });
- colsToClear.forEach((j) => {
- for (let i = 0; i < size; i++) {
- const node = this.block_ba_data[i][j].block_ba_node;
- node.getComponent(UIOpacity).opacity = 0;
- this.block_ba_data[i][j].block_state = BlockState.HIDE;
- MainGameLogic.ins.createOneBlockEfEffect(node, this.block_ba_data[i][j].block_color);
- eliminNum++;
- totalRow += i;
- totalCol += j;
- }
- });
- if (anyCleared) {
- AudioManager.ins.playOneShot(Url.AUDIO.SFX10, 1);
- // 计算最中间块的索引位置
- centerX = Math.floor(totalRow / eliminNum);
- centerY = Math.floor(totalCol / eliminNum);
- // 获取最中间块的实际位置
- const centerNode: Node = this.block_ba_data[centerX][centerY].block_ba_node;
- centerPosition = centerNode.getPosition(); // 获取世界坐标
- // 将消除的行数和列数相加,传递给 detectGuideAndElimiTimes
- // console.log(clearedRowCount, clearedColCount);
- const totalClearedLines = clearedRowCount + clearedColCount;
- MainGameLogic.ins.detectGuideAndElimiTimes(totalClearedLines);
- // MainGameLogic.ins.getElimitateCash();
- // console.log('消除格子数', eliminNum);
- // console.log('最中间块坐标', centerPosition);
- let baseScore = mtec.number.random(GlobalData.addScoreFloor, GlobalData.addScoreUp);
- MainGameLogic.ins.createConsecutiveEffect(centerPosition, totalClearedLines);
- this.scheduleOnce(() => {
- MainGameLogic.ins.createEleAddScoreEff(centerPosition, baseScore * eliminNum);
- }, 1)
- }
- this.scheduleOnce(() => {
- this.saveCurrentBoardState();
- }, 1)
- // 返回最中间块的世界坐标
- return centerPosition;
- }
- /** 保存当前地图数据的方法 */
- saveCurrentBoardState(): void {
- const size = 8;
- const currentBoardData = [];
- for (let i = 0; i < size; i++) {
- const row = [];
- for (let j = 0; j < size; j++) {
- row.push(this.block_ba_data[i][j].block_state === BlockState.SHOW ? 1 : 0);
- }
- currentBoardData.push(row);
- }
- LocalStorageMgr.setItem(LocalStorageMgr.lastGameBoardData_key, currentBoardData)
- }
- // 检测棋盘相连区域,并将最多块数的区域消除-----道具使用
- chechBlockArea() {
- // 根据this.block_ba_data棋盘数据,检测格子相互之间相连的区域
- // 计算每个区域相邻的格子有多少,得出格子最最多的区域,将这个区域的格子全部隐藏(消除)
- // 定义方向数组,用于移动上下左右四个方向
- const directions = [
- { x: 0, y: 1 }, // 上
- { x: 1, y: 0 }, // 右
- { x: 0, y: -1 }, // 下
- { x: -1, y: 0 } // 左
- ];
- // 用于记录已经访问过的格子
- const visited = new Array(this.boardSize).fill(false).map(() => new Array(this.boardSize).fill(false));
- let maxArea = 0;
- let maxAreaBlocks: BlockBaData[] = [];
- // 深度优先搜索,检测相连区域
- const dfs = (i: number, j: number, currentBlocks: BlockBaData[]) => {
- visited[i][j] = true;
- currentBlocks.push(this.block_ba_data[i][j]);
- for (const direction of directions) {
- const newRow = i + direction.x;
- const newCol = j + direction.y;
- if (
- newRow >= 0 && newRow < this.boardSize &&
- newCol >= 0 && newCol < this.boardSize &&
- !visited[newRow][newCol] &&
- this.block_ba_data[newRow][newCol].block_state === BlockState.SHOW
- ) {
- dfs(newRow, newCol, currentBlocks);
- }
- }
- };
- // 遍历棋盘,找到所有区域
- for (let i = 0; i < this.boardSize; i++) {
- for (let j = 0; j < this.boardSize; j++) {
- if (
- !visited[i][j] &&
- this.block_ba_data[i][j].block_state === BlockState.SHOW
- ) {
- const currentBlocks: BlockBaData[] = [];
- dfs(i, j, currentBlocks);
- if (currentBlocks.length > maxArea) {
- maxArea = currentBlocks.length;
- maxAreaBlocks = currentBlocks;
- }
- }
- }
- }
- // 消除最大区域的格子
- for (const block of maxAreaBlocks) {
- block.block_ba_node.getComponent(UIOpacity).opacity = 0;
- block.block_state = BlockState.HIDE;
- }
- // console.log('最大区域的格子数:', maxArea);
- // console.log('消除的格子:', maxAreaBlocks);
- }
- // 检查并消除2x2区域,并返回消除区域的中心坐标
- chechAndEliminateRandomArea(): boolean {
- const regions: { blocks: BlockBaData[], row: number, col: number }[] = [];
- // 遍历棋盘,以2x2区域为单位进行划分
- for (let i = 0; i < this.boardSize; i += 4) {
- for (let j = 0; j < this.boardSize; j += 4) {
- const currentRegion: BlockBaData[] = [];
- // 遍历当前2x2区域的格子
- for (let x = i; x < i + 4; x++) {
- for (let y = j; y < j + 4; y++) {
- if (this.block_ba_data[x][y].block_state === BlockState.SHOW) {
- currentRegion.push(this.block_ba_data[x][y]);
- }
- }
- }
- // 如果该区域内有显示状态的格子,记录下来
- if (currentRegion.length > 0) {
- regions.push({ blocks: currentRegion, row: i, col: j });
- }
- }
- }
- // 如果没有找到任何显示状态的区域,直接返回 null
- if (regions.length === 0) {
- // console.log('没有区域内有格子处于显示状态');
- MainGameLogic.ins.propInUse = false;
- MainGameLogic.ins.createOneTipTpast('game_tip_noblock')
- return false;
- }
- // 随机选择一个区域
- const randomIndex = Math.floor(Math.random() * regions.length);
- const selectedRegion = regions[randomIndex];
- // 计算四个格子中心位置的平均值
- let centerX = 0, centerY = 0, centerZ = 0;
- for (const block of selectedRegion.blocks) {
- const position = block.block_ba_node.getPosition();
- centerX += position.x;
- centerY += position.y;
- centerZ += position.z;
- }
- const centerPosition = new Vec3(centerX / selectedRegion.blocks.length, centerY / selectedRegion.blocks.length, centerZ / selectedRegion.blocks.length);
- let fun = () => {
- // 消除选中区域的格子
- for (const block of selectedRegion.blocks) {
- block.block_ba_node.getComponent(UIOpacity).opacity = 0;
- block.block_state = BlockState.HIDE;
- MainGameLogic.ins.createOneBlockEfEffect(block.block_ba_node, block.block_color);
- }
- MainGameLogic.ins.propInUse = false;
- // console.log(`消除了区域 [${selectedRegion.row}, ${selectedRegion.col}] 内的格子`);
- }
- this.saveCurrentBoardState();
- // MainGameLogic.ins.usePropHummerEffect(centerPosition, fun)
- return true;
- }
- // 根据数据设置棋盘格子
- async generateBoard(_boardData) {
- // 初始化block_ba_data二维数组
- this.block_ba_data = [];
- for (let i = 0; i < this.boardSize; i++) {
- this.block_ba_data[i] = [];
- for (let j = 0; j < this.boardSize; j++) {
- let state = _boardData[i][j];
- let name = (i + 1) + '_' + (j + 1);
- let _block_ba = this.gridcontainer.getChildByName(name);
- _block_ba.getComponent(UIOpacity).opacity = state == 1 ? 255 : 0;
- _block_ba.getComponent(ResSprite).setSpriteFrame(Url.BLOCK.ORANGE + '/spriteFrame');
- // 创建BlockBaData对象并赋值
- const blockBaData: BlockBaData = {
- index_i: i,
- index_j: j,
- block_ba_node: _block_ba,
- block_state: state == 1 ? BlockState.SHOW : BlockState.HIDE,
- block_sprite: _block_ba.getComponent(ResSprite),
- block_color: Url.BLOCK.ORANGE
- };
- // 将blockBaData对象保存到block_ba_data二维数组中
- this.block_ba_data[i][j] = blockBaData;
- }
- }
- }
- // 根据数据设置棋盘格子_带效果
- async generateBoard_effect(_boardData) {
- // 播放音效
- AudioManager.ins.playOneShot(Url.AUDIO.SFX12, 1);
- // 初始化block_ba_data二维数组,快速完成初始化,没有延迟
- this.block_ba_data = [];
- for (let i = 0; i < this.boardSize; i++) {
- this.block_ba_data[i] = [];
- for (let j = 0; j < this.boardSize; j++) {
- let name = (i + 1) + '_' + (j + 1);
- let _block_ba = this.gridcontainer.getChildByName(name);
- // 创建BlockBaData对象并初始化状态为隐藏
- const blockBaData: BlockBaData = {
- index_i: i,
- index_j: j,
- block_ba_node: _block_ba,
- block_state: BlockState.HIDE,
- block_sprite: _block_ba.getComponent(ResSprite),
- block_color: Url.BLOCK.ORANGE
- };
- // 将blockBaData对象保存到block_ba_data二维数组中
- this.block_ba_data[i][j] = blockBaData;
- }
- }
- // 设置透明度的逐行显示效果,添加延迟
- for (let i = this.boardSize - 1; i >= 0; i--) {
- for (let j = 0; j < this.boardSize; j++) {
- let _block_ba = this.block_ba_data[i][j].block_ba_node;
- tween(_block_ba.getComponent(UIOpacity))
- .to(0.1, { opacity: 255 }) // 显示块
- .start();
- }
- // 等待一段时间以便逐行显示
- await this.delay(100); // 可以调整延迟时间
- }
- // 根据数据设置状态,并从最上面一行开始逐行隐藏state为0的块
- for (let i = 0; i < this.boardSize; i++) {
- for (let j = 0; j < this.boardSize; j++) {
- let state = _boardData[i][j];
- this.block_ba_data[i][j].block_state = state == 1 ? BlockState.SHOW : BlockState.HIDE;
- // 如果状态是隐藏,调整透明度
- if (state == 0) {
- let _block_ba = this.block_ba_data[i][j].block_ba_node;
- tween(_block_ba.getComponent(UIOpacity))
- .to(0.1, { opacity: 0 }) // 隐藏块
- .start();
- }
- }
- // 等待一段时间以便逐行隐藏
- await this.delay(100); // 可以调整延迟时间
- }
- // 保存当前的棋盘状态
- this.saveCurrentBoardState();
- }
- // 延迟函数
- delay(ms: number): Promise<void> {
- return new Promise(resolve => setTimeout(resolve, ms));
- }
- // 更新棋盘
- updateBoard() {
- for (let i = 0; i < this.block_ba_data.length; i++) {
- for (let j = 0; j < this.block_ba_data[i].length; j++) {
- let state = this.block_ba_data[i][j].block_state
- this.block_ba_data[i][j].block_ba_node.getComponent(UIOpacity).opacity = state == 1 ? 255 : 0;
- }
- }
- }
- // 根据权重随机返回一个图块数据
- getRandomBlockConfig(): BlockConfig | undefined {
- let totalWeight = 0;
- const cumulativeWeights: { type: BlockType, weight: number }[] = [];
- // 累积权重
- for (const type in BlockWeights) {
- if (BlockWeights.hasOwnProperty(type)) {
- const blockType = Number(type) as BlockType;
- const weight = BlockWeights[blockType];
- totalWeight += weight;
- cumulativeWeights.push({ type: blockType, weight: totalWeight });
- }
- }
- const random = Math.random() * totalWeight;
- let selectedType: BlockType | undefined = undefined;
- let low = 0;
- let high = cumulativeWeights.length - 1;
- // 二分查找
- while (low <= high) {
- const mid = Math.floor((low + high) / 2);
- if (random < cumulativeWeights[mid].weight) {
- selectedType = cumulativeWeights[mid].type;
- high = mid - 1;
- } else {
- low = mid + 1;
- }
- }
- if (selectedType !== undefined) {
- const filteredBlocks = BlocksAll.filter(block => block.block_type === selectedType);
- // console.log('Filtered Blocks:', filteredBlocks);
- if (filteredBlocks.length > 0) {
- const randomIndex = Math.floor(Math.random() * filteredBlocks.length);
- let colorIandU = mtec.number.random(0, 6, 0);
- switch (colorIandU) {
- case 0:
- filteredBlocks[randomIndex].block_color = Url.BLOCK.BLUE;
- break;
- case 1:
- filteredBlocks[randomIndex].block_color = Url.BLOCK.DEEPBLUE;
- break;
- case 2:
- filteredBlocks[randomIndex].block_color = Url.BLOCK.GREEN;
- break;
- case 3:
- filteredBlocks[randomIndex].block_color = Url.BLOCK.ORANGE;
- break;
- case 4:
- filteredBlocks[randomIndex].block_color = Url.BLOCK.PURPLE;
- break;
- case 5:
- filteredBlocks[randomIndex].block_color = Url.BLOCK.RED;
- break;
- case 6:
- filteredBlocks[randomIndex].block_color = Url.BLOCK.YELLOW;
- break;
- default:
- filteredBlocks[randomIndex].block_color = Url.BLOCK.BLUE;
- break;
- }
- return filteredBlocks[randomIndex];
- }
- }
- return undefined;
- }
- /**
- * 选择区刷新生成三个图块
- * @param isPropFrash 是否使用道具刷新-用作效果判断
- * @param blockConfig 是否指定块,传块配置
- */
- generateSelectionBlock(isPropFrash: boolean, blockConfig?: BlockConfig[]) {
- let configs = [];
- if (blockConfig) {
- for (let i = 0; i < blockConfig.length; i++) {
- configs.push(blockConfig[i]);
- TouchMgr.ins.selectCanTouch[i] = true;
- }
- } else {
- for (let i = 0; i < 3; i++) {
- configs.push(GridBlockMgr.ins.getRandomBlockConfig())
- TouchMgr.ins.selectCanTouch[i] = true;
- }
- }
- if (isPropFrash) {
- this.selects.forEach((block, index) => {
- tween(block)
- .to(0.2, { scale: v3(0, 0, 1) })
- .call(() => {
- const blockConfig = configs[index];
- block.setPosition(new Vec3(0, 0, 0))
- block.getComponent(BlockController).updateBlockSet(true, blockConfig);
- block.getComponent(BlockController).addBlockOffset(4);
- block.active = true
- })
- .to(0.2, { scale: v3(0.5, 0.5, 1) })
- .start()
- })
- MainGameLogic.ins.propInUse = false;
- } else {
- this.SelectionContainer.setPosition(v3(view.getVisibleSize().width, 0, 0))
- this.SelectionContainer.setScale(0, 0, 1);
- tween(this.SelectionContainer)
- .parallel(
- tween().to(0.5, { position: v3(0, 0, 0) }),
- tween().to(0.5, { scale: v3(1, 1, 1) })
- )
- .start()
- this.selects.forEach((block, index) => {
- const blockConfig = configs[index];
- block.setPosition(new Vec3(0, 0, 0))
- block.getComponent(BlockController).updateBlockSet(true, blockConfig);
- block.getComponent(BlockController).addBlockOffset(4);
- block.active = true
- })
- }
- this.detectSelectsBlockCanUse(true);
- }
- // 选择区生成引导图块
- generareGuideSelectionBlock(blockConfig: BlockConfig[]) {
- let configs = [];
- for (let i = 0; i < blockConfig.length; i++) {
- configs.push(blockConfig[i]);
- }
- this.selects.forEach((block, index) => {
- const blockConfi = configs[index];
- block.setPosition(new Vec3(0, 0, 0))
- block.getComponent(BlockController).updateBlockSet(true, blockConfi);
- block.getComponent(BlockController).addBlockOffset(4);
- block.active = index == 0 || index == 2 ? false : true;
- })
- TouchMgr.ins.selectCanTouch = [false, true, false];
- }
- // 重置 temp_block_ba_data
- resetTempBlockData() {
- for (let i = 0; i < this.block_ba_data.length; i++) {
- for (let j = 0; j < this.block_ba_data[i].length; j++) {
- this.temp_block_ba_data[i][j] = {
- index_i: this.block_ba_data[i][j].index_i,
- index_j: this.block_ba_data[i][j].index_j,
- block_state: this.block_ba_data[i][j].block_state,
- block_ba_node: this.block_ba_data[i][j].block_ba_node,
- block_sprite: this.block_ba_data[i][j].block_ba_node.getComponent(ResSprite),
- block_color: this.block_ba_data[i][j].block_color
- };
- }
- }
- }
- // 获取选择区的图块数据,用于检测游戏结束
- getSelectionBlockConfig() {
- this.selection_block_config = []; // 清空之前的配置
- for (let i = 0; i < TouchMgr.ins.selectCanTouch.length; i++) {
- if (TouchMgr.ins.selectCanTouch[i]) {
- const element = this.selects[i].getComponent(BlockController).curBlockConfig;
- this.selection_block_config.push(element);
- }
- }
- }
- // 检测游戏结束, 结束返回 true,否则返回 false
- detectGameOver(): boolean {
- this.detectSelectsBlockCanUse(false);
- this.getSelectionBlockConfig();
- const results_block_config: BlockConfig[] = [];
- if (GlobalData.isRotate) {
- // 根据 this.selection_block_config 里的 block_type,从 blocks 中找到所有对应的 BlockConfig,存到 results 里
- for (let i = 0; i < this.selection_block_config.length; i++) {
- const blockType = this.selection_block_config[i];
- // results_block_config.push(blockType);
- for (let j = 0; j < BlocksAll.length; j++) {
- if (BlocksAll[j].block_type === blockType.block_type) {
- results_block_config.push(BlocksAll[j]);
- }
- }
- }
- } else {
- for (let i = 0; i < this.selection_block_config.length; i++) {
- results_block_config.push(this.selection_block_config[i])
- }
- }
- // console.log(results_block_config);
- // 循环遍历results里的BlockConfig能不能放置
- for (let i = 0; i < this.block_ba_data.length; i++) {
- for (let j = 0; j < this.block_ba_data[i].length; j++) {
- for (let k = 0; k < results_block_config.length; k++) {
- // 重置 temp_block_ba_data
- this.resetTempBlockData();
- const blockArr = results_block_config[k].block_arr;
- const date = this.temp_block_ba_data[i][j];
- // 检测放置的方法
- let config = this.getCenteredBlocks(date.index_i, date.index_j, blockArr);
- let isCanPlaced = config.iscanplaced;
- // 如果可以放置
- if (isCanPlaced) {
- return false;
- }
- }
- }
- }
- // 移除道具检查逻辑
- return true;
- }
- // 遍历检测每个块能否消除,并选择最优的三个块生成(生成特定选择块的方法)
- generateSpecificSelectionBlock(isPropFrash) {
- const results: { block: BlockConfig; totalEliminate: number }[] = [];
- for (let i = 0; i < this.block_ba_data.length; i++) {
- for (let j = 0; j < this.block_ba_data.length; j++) {
- for (let k = 0; k < BlocksAll.length; k++) {
- // 重置 temp_block_ba_data
- this.resetTempBlockData();
- const blockArr = BlocksAll[k].block_arr;
- const date = this.temp_block_ba_data[i][j];
- // 检测放置的方法
- let config = this.getCenteredBlocks(date.index_i, date.index_j, blockArr);
- let isCanPlaced = config.iscanplaced;
- let placedIndexArr = config.indexarr;
- // 如果可以放置
- if (isCanPlaced) {
- // 根据返回结果修改temp_block_ba_data对应位置的数据
- for (let idx = 0; idx < placedIndexArr.length; idx++) {
- let boardindex_i = placedIndexArr[idx][0];
- let boardindex_j = placedIndexArr[idx][1];
- this.temp_block_ba_data[boardindex_i][boardindex_j].block_state = BlockState.SHOW;
- }
- // 返回消除的行列数
- let totalEliminate = this.checkAndUpdateTempBlocks();
- // 只有在 totalEliminate > 0 时才保存到 results
- if (totalEliminate > 0) {
- // 检查是否已经存在相同 block_type 的数据
- const existingIndex = results.findIndex(result => result.block.block_type === BlocksAll[k].block_type);
- if (existingIndex !== -1) {
- // 如果存在且新的 totalEliminate 更大,则替换
- if (results[existingIndex].totalEliminate < totalEliminate) {
- results[existingIndex] = { block: BlocksAll[k], totalEliminate };
- }
- } else {
- // 如果不存在,则添加到 results
- results.push({ block: BlocksAll[k], totalEliminate });
- }
- }
- }
- }
- }
- }
- // console.log(this.temp_block_ba_data);
- // console.log(this.block_ba_data);
- // 按 totalEliminate 排序,totalEliminate 最大的数据排在最前面
- results.sort((a, b) => {
- if (b.totalEliminate !== a.totalEliminate) {
- return b.totalEliminate - a.totalEliminate;
- } else {
- // 如果 totalEliminate 相同,则按 block_arr 中 1 的数量排序,数量越少越排在前面
- const countOnesA = this.countOnes(a.block.block_arr);
- const countOnesB = this.countOnes(b.block.block_arr);
- return countOnesA - countOnesB;
- }
- });
- // console.log(results);
- let configs: BlockConfig[] = [];
- if (results.length >= 3) {
- for (let i = 0; i < 3; i++) {
- let colorIandU = mtec.number.random(0, 6, 0);
- switch (colorIandU) {
- case 0:
- results[i].block.block_color = Url.BLOCK.BLUE;
- break;
- case 1:
- results[i].block.block_color = Url.BLOCK.DEEPBLUE;
- break;
- case 2:
- results[i].block.block_color = Url.BLOCK.GREEN;
- break;
- case 3:
- results[i].block.block_color = Url.BLOCK.ORANGE;
- break;
- case 4:
- results[i].block.block_color = Url.BLOCK.PURPLE;
- break;
- case 5:
- results[i].block.block_color = Url.BLOCK.RED;
- break;
- case 6:
- results[i].block.block_color = Url.BLOCK.YELLOW;
- break;
- default:
- results[i].block.block_color = Url.BLOCK.BLUE;
- break;
- }
- configs.push(results[i].block)
- TouchMgr.ins.selectCanTouch[i] = true;
- }
- if (isPropFrash) {
- this.selects.forEach((block, index) => {
- tween(block)
- .to(0.2, { scale: v3(0, 0, 1) })
- .call(() => {
- const blockConfig = configs[index];
- block.setPosition(new Vec3(0, 0, 0))
- block.getComponent(BlockController).updateBlockSet(true, blockConfig);
- block.getComponent(BlockController).addBlockOffset(4);
- block.active = true;
- })
- .to(0.2, { scale: v3(0.5, 0.5, 1) })
- .start()
- })
- MainGameLogic.ins.propInUse = false;
- } else {
- this.SelectionContainer.setPosition(v3(view.getVisibleSize().width, 0, 0))
- this.SelectionContainer.setScale(0, 0, 1);
- tween(this.SelectionContainer)
- .parallel(
- tween().to(0.5, { position: v3(0, 0, 0) }),
- tween().to(0.5, { scale: v3(1, 1, 1) })
- )
- .start()
- this.selects.forEach((block, index) => {
- const blockConfig = configs[index];
- block.setPosition(new Vec3(0, 0, 0))
- block.getComponent(BlockController).updateBlockSet(true, blockConfig);
- block.getComponent(BlockController).addBlockOffset(4);
- block.active = true
- })
- }
- } else if (results.length == 2) {
- for (let i = 0; i < 2; i++) {
- let colorIandU = mtec.number.random(0, 6, 0);
- switch (colorIandU) {
- case 0:
- results[i].block.block_color = Url.BLOCK.BLUE;
- break;
- case 1:
- results[i].block.block_color = Url.BLOCK.DEEPBLUE;
- break;
- case 2:
- results[i].block.block_color = Url.BLOCK.GREEN;
- break;
- case 3:
- results[i].block.block_color = Url.BLOCK.ORANGE;
- break;
- case 4:
- results[i].block.block_color = Url.BLOCK.PURPLE;
- break;
- case 5:
- results[i].block.block_color = Url.BLOCK.RED;
- break;
- case 6:
- results[i].block.block_color = Url.BLOCK.YELLOW;
- break;
- default:
- results[i].block.block_color = Url.BLOCK.BLUE;
- break;
- }
- configs.push(results[i].block)
- TouchMgr.ins.selectCanTouch[i] = true;
- }
- configs.push(GridBlockMgr.ins.getRandomBlockConfig())
- TouchMgr.ins.selectCanTouch[2] = true;
- if (isPropFrash) {
- this.selects.forEach((block, index) => {
- tween(block)
- .to(0.2, { scale: v3(0, 0, 1) })
- .call(() => {
- const blockConfig = configs[index];
- block.setPosition(new Vec3(0, 0, 0))
- block.getComponent(BlockController).updateBlockSet(true, blockConfig);
- block.getComponent(BlockController).addBlockOffset(4);
- block.active = true
- })
- .to(0.2, { scale: v3(0.5, 0.5, 1) })
- .start()
- })
- MainGameLogic.ins.propInUse = false;
- } else {
- this.SelectionContainer.setPosition(v3(view.getVisibleSize().width, 0, 0));
- this.SelectionContainer.setScale(0, 0, 1);
- tween(this.SelectionContainer)
- .parallel(
- tween().to(0.5, { position: v3(0, 0, 0) }),
- tween().to(0.5, { scale: v3(1, 1, 1) })
- )
- .start()
- this.selects.forEach((block, index) => {
- const blockConfig = configs[index];
- block.setPosition(new Vec3(0, 0, 0))
- block.getComponent(BlockController).updateBlockSet(true, blockConfig);
- block.getComponent(BlockController).addBlockOffset(4);
- block.active = true
- })
- }
- } else if (results.length == 1) {
- let colorIandU = mtec.number.random(0, 6, 0);
- switch (colorIandU) {
- case 0:
- results[0].block.block_color = Url.BLOCK.BLUE;
- break;
- case 1:
- results[0].block.block_color = Url.BLOCK.DEEPBLUE;
- break;
- case 2:
- results[0].block.block_color = Url.BLOCK.GREEN;
- break;
- case 3:
- results[0].block.block_color = Url.BLOCK.ORANGE;
- break;
- case 4:
- results[0].block.block_color = Url.BLOCK.PURPLE;
- break;
- case 5:
- results[0].block.block_color = Url.BLOCK.RED;
- break;
- case 6:
- results[0].block.block_color = Url.BLOCK.YELLOW;
- break;
- default:
- results[0].block.block_color = Url.BLOCK.BLUE;
- break;
- }
- configs.push(results[0].block)
- TouchMgr.ins.selectCanTouch[0] = true;
- for (let i = 1; i < 3; i++) {
- configs.push(GridBlockMgr.ins.getRandomBlockConfig())
- TouchMgr.ins.selectCanTouch[i] = true;
- }
- if (isPropFrash) {
- this.selects.forEach((block, index) => {
- tween(block)
- .to(0.2, { scale: v3(0, 0, 1) })
- .call(() => {
- const blockConfig = configs[index];
- block.setPosition(new Vec3(0, 0, 0))
- block.getComponent(BlockController).updateBlockSet(true, blockConfig);
- block.getComponent(BlockController).addBlockOffset(4);
- block.active = true
- })
- .to(0.2, { scale: v3(0.5, 0.5, 1) })
- .start()
- })
- MainGameLogic.ins.propInUse = false;
- } else {
- this.SelectionContainer.setPosition(v3(view.getVisibleSize().width, 0, 0))
- this.SelectionContainer.setScale(0, 0, 1);
- tween(this.SelectionContainer)
- .parallel(
- tween().to(0.5, { position: v3(0, 0, 0) }),
- tween().to(0.5, { scale: v3(1, 1, 1) })
- )
- .start()
- this.selects.forEach((block, index) => {
- const blockConfig = configs[index];
- block.setPosition(new Vec3(0, 0, 0))
- block.getComponent(BlockController).updateBlockSet(true, blockConfig);
- block.getComponent(BlockController).addBlockOffset(4);
- block.active = true
- })
- }
- } else {
- this.generateSelectionBlock(isPropFrash)
- }
- this.detectSelectsBlockCanUse(true)
- }
- /**
- * 检测选择的三个块是否可以使用
- * @param switchF
- */
- detectSelectsBlockCanUse(switchF: boolean) {
- for (let i = 0; i < this.selects.length; i++) {
- const element = this.selects[i].getComponent(BlockController);
- if (switchF) {
- this.selects[i].parent.getChildByName('frash').active = false;
- }
- element.checkGray();
- }
- }
- // 重置 temp_block_ba_data1
- resetTempBlockData1() {
- for (let i = 0; i < this.block_ba_data.length; i++) {
- for (let j = 0; j < this.block_ba_data[i].length; j++) {
- this.temp_block_ba_data1[i][j] = {
- index_i: this.block_ba_data[i][j].index_i,
- index_j: this.block_ba_data[i][j].index_j,
- block_state: this.block_ba_data[i][j].block_state,
- block_ba_node: this.block_ba_data[i][j].block_ba_node,
- block_sprite: this.block_ba_data[i][j].block_ba_node.getComponent(ResSprite),
- block_color: this.block_ba_data[i][j].block_color
- };
- }
- }
- }
- // 检测传入的块能否放置棋盘,不能则置灰
- detectIsCanPlaced(block_arr: number[][], block_node: Node) {
- // 循环遍历results里的BlockConfig能不能放置
- for (let i = 0; i < this.block_ba_data.length; i++) {
- for (let j = 0; j < this.block_ba_data[i].length; j++) {
- // 重置 temp_block_ba_data1
- GridBlockMgr.ins.resetTempBlockData1();
- const blockArr = block_arr
- const date = this.temp_block_ba_data1[i][j];
- // 检测放置的方法
- let config = this.getCenteredBlocks(date.index_i, date.index_j, blockArr);
- let isCanPlaced = config.iscanplaced;
- // 如果可以放置
- if (isCanPlaced) {
- for (let i = 0; i < block_node.children.length; i++) {
- const element = block_node.children[i].getComponent(Sprite);
- element.grayscale = false;
- }
- return
- } else {
- for (let i = 0; i < block_node.children.length; i++) {
- const element = block_node.children[i].getComponent(Sprite);
- element.grayscale = true;
- }
- }
- }
- }
- }
- // 计算 block_arr 中 1 的数量的方法
- countOnes(blockArr: number[][]): number {
- let count = 0;
- for (let i = 0; i < blockArr.length; i++) {
- for (let j = 0; j < blockArr[i].length; j++) {
- if (blockArr[i][j] === 1) {
- count++;
- }
- }
- }
- return count;
- }
- // 检测temp格子 消除方法
- checkAndUpdateTempBlocks(): number {
- const size = this.temp_block_ba_data.length;
- let totalEliminated = 0;
- // 检查每一行
- for (let i = 0; i < size; i++) {
- let rowAllOnes = true;
- for (let j = 0; j < size; j++) {
- if (this.temp_block_ba_data[i][j].block_state !== BlockState.SHOW) {
- rowAllOnes = false;
- break;
- }
- }
- if (rowAllOnes) {
- totalEliminated++;
- for (let j = 0; j < size; j++) {
- this.temp_block_ba_data[i][j].block_state = BlockState.HIDE;
- }
- }
- }
- // 检查每一列
- for (let j = 0; j < size; j++) {
- let colAllOnes = true;
- for (let i = 0; i < size; i++) {
- if (this.temp_block_ba_data[i][j].block_state !== BlockState.SHOW) {
- colAllOnes = false;
- break;
- }
- }
- if (colAllOnes) {
- totalEliminated++;
- for (let i = 0; i < size; i++) {
- this.temp_block_ba_data[i][j].block_state = BlockState.HIDE;
- }
- }
- }
- return totalEliminated;
- }
- // 判断当前位置是否可以放置块
- getCenteredBlocks(index_i: number, index_j: number, curBlockArr: number[][]): ReConfig {
- if (!curBlockArr) {
- return
- }
- const blocks: (number | null)[][] = Array(5).fill(null).map(() => Array(5).fill(null));
- const blocks_ba_node: (Node | null)[][] = Array(5).fill(null).map(() => Array(5).fill(null));
- const blocks_index: (number[] | null)[][] = Array(5).fill(null).map(() => Array(5).fill(null));
- const startI = Math.max(index_i - 2, 0);
- const endI = Math.min(index_i + 2, this.temp_block_ba_data.length - 1);
- const startJ = Math.max(index_j - 2, 0);
- const endJ = Math.min(index_j + 2, this.temp_block_ba_data[0].length - 1);
- for (let i = startI; i <= endI; i++) {
- for (let j = startJ; j <= endJ; j++) {
- const block = this.temp_block_ba_data[i][j].block_state;
- const block_ba_node = this.temp_block_ba_data[i][j].block_ba_node;
- const block_index = [this.temp_block_ba_data[i][j].index_i, this.temp_block_ba_data[i][j].index_j];
- blocks[i - (index_i - 2)][j - (index_j - 2)] = block;
- blocks_ba_node[i - (index_i - 2)][j - (index_j - 2)] = block_ba_node;
- blocks_index[i - (index_i - 2)][j - (index_j - 2)] = block_index
- }
- }
- for (let i = 0; i < 5; i++) {
- for (let j = 0; j < 5; j++) {
- const block = blocks[i][j];
- const curBlock = curBlockArr[i][j];
- if ((block === 1 && curBlock === 1) || (block === null && curBlock === 1)) {
- return { iscanplaced: false, indexarr: null };
- }
- }
- }
- let returnIndexArr = [];
- // 显示提示位置
- for (let i = 0; i < 5; i++) {
- for (let j = 0; j < 5; j++) {
- const block = blocks[i][j];
- const curBlock = curBlockArr[i][j];
- if ((block === 0 && curBlock === 1)) {
- // blocks_ba_node[i][j].getComponent(UIOpacity).opacity = 150;
- returnIndexArr.push(blocks_index[i][j])
- }
- }
- }
- return { iscanplaced: true, indexarr: returnIndexArr };
- }
- // 生成一个展示的临时图块
- generateTempBlock(blockConfig: BlockConfig) {
- let tempblock = instantiate(this.block);
- tempblock.getComponent(BlockController).updateBlockSet(false, blockConfig);
- return tempblock;
- }
- }
|