| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- /*
- * @Author: mojunshou 1637302775@qq.com
- * @Date: 2025-04-20 10:00:00
- * @LastEditors: mojunshou 1637302775@qq.com
- * @LastEditTime: 2025-04-20 10:00:00
- * @Description: 消除游戏方块管理器
- */
- import { EventTouch, JsonAsset, Node, Prefab, UITransform, Vec2, Vec3, tween, instantiate } from "cc";
- import { oops } from "db://oops-framework/core/Oops";
- import { BrickData, GridConfigData, GridData } from "./EliminateTypes";
- export class EliminateBrickManager {
- private brickNode: Node | null = null; // 方块容器
- private rotateNode: Node | null = null; // 旋转容器
- private rotatePrefab: Node | null = null; // 旋转预制体
- private moveNode: Node | null = null; // 移动容器
- private itemSize: number = 76.25; // 格子大小
- private itemPrefabs: Prefab[] = []; // 方块预制体列表
- private rotateFaultTolerant = 10; // 旋转容错
- private yOffset = 100; // Y轴偏移
- private aniBrickRotate = 0; // 旋转动画时间
- private bricksList: BrickData[] = []; // 所有可用方块
- private brickConfig: { bricks?: any } = {}; // 方块配置
- constructor(
- brickNode: Node,
- rotateNode: Node,
- moveNode: Node,
- itemPrefabs: Prefab[],
- rotatePrefab: Node,
- itemSize: number
- ) {
- this.brickNode = brickNode;
- this.rotateNode = rotateNode;
- this.moveNode = moveNode;
- this.itemPrefabs = itemPrefabs;
- this.rotatePrefab = rotatePrefab;
- this.itemSize = itemSize;
- }
- /**
- * 加载方块配置文件
- */
- public async loadConfig(): Promise<void> {
- let json_name: string = "gui/eliminate/config/GridConfig";
- return new Promise<void>((resolve, reject) => {
- oops.res.load(json_name, JsonAsset, (err: Error | null, res: any) => {
- if (res) {
- this.brickConfig = res.json;
- resolve();
- } else {
- console.log("JSON数据加载失败,请检查文件");
- reject(err);
- }
- });
- });
- }
- /**
- * 初始化方块列表
- */
- public initBricks(count: number): void {
- if (this.brickNode) {
- this.brickNode.destroyAllChildren();
- }
- this.bricksList.length = 0;
- for (let i = 1; i <= count; i++) {
- this.addBrick(i);
- }
- }
- /**
- * 添加一个砖块
- */
- public addBrick(index: number, isGuideMode: boolean = false): BrickData {
- // 随机选择砖块类型
- const brickConfigs = Object.keys(this.brickConfig['bricks']);
- let brickKey;
- if (isGuideMode) {
- brickKey = "Brick1";
- } else {
- const randomIndex = Math.floor(Math.random() * brickConfigs.length);
- brickKey = brickConfigs[randomIndex];
- }
- // 随机选择颜色
- const randomColorIndex = Math.floor(Math.random() * 3) + 1;
- // 创建砖块
- const brickNode = this.generateBrick(brickKey, randomColorIndex);
- if (!brickNode || !this.brickNode) {
- throw new Error("无法生成砖块");
- }
- this.brickNode.addChild(brickNode);
- // 设置砖块位置
- const brickConfig = this.brickConfig['bricks'][brickKey];
- const rotateFlag = brickConfig.rotateFlag || false;
- // 创建砖块数据对象
- const brickData: BrickData = {
- index: index,
- brickKey: brickKey,
- rotateFlag: rotateFlag,
- gridConfig: JSON.parse(JSON.stringify(brickConfig.gridConfig)),
- deg: 0,
- brickNode: brickNode,
- brickInitPos: new Vec3(this.calculateInitPosition(index)),
- type: randomColorIndex,
- rotateNode: null
- };
- // 设置初始位置
- brickNode.setWorldPosition(brickData.brickInitPos);
- brickNode.scale.set(0.8, 0.8, 0.8);
- // 创建旋转节点
- if (rotateFlag) {
- this.createRotateNode(brickData);
- }
- // 添加到方块列表
- this.bricksList.push(brickData);
- return brickData;
- }
- /**
- * 生成方块节点
- */
- public generateBrick(brickKey: string, colorIndex: number): Node {
- const brickConfig = this.brickConfig['bricks'][brickKey];
- let rowMin = 0;
- let rowMax = 0;
- let columnMin = 0;
- let columnMax = 0;
- // 计算方块尺寸
- brickConfig['gridConfig'].forEach((gridConfigData: GridConfigData) => {
- if (gridConfigData.row < rowMin) {
- rowMin = gridConfigData.row;
- }
- else if (gridConfigData.row > rowMax) {
- rowMax = gridConfigData.row;
- }
- if (gridConfigData.column < columnMin) {
- columnMin = gridConfigData.column;
- }
- else if (gridConfigData.column > columnMax) {
- columnMax = gridConfigData.column;
- }
- });
- const rowNum = (rowMax - rowMin + 1);
- const columnNum = (columnMax - columnMin + 1);
- // 创建方块节点
- const brickNode = new Node();
- brickNode.name = brickKey;
- // 设置方块大小
- const transformCom: UITransform = brickNode.addComponent(UITransform);
- transformCom.setContentSize(
- this.itemSize * columnNum,
- this.itemSize * rowNum
- );
- transformCom.setAnchorPoint(0.5, 0.5);
- // 创建子格子
- const gridPrefab = this.itemPrefabs[colorIndex];
- brickConfig['gridConfig'].forEach((gridConfigData: GridConfigData) => {
- const gridNode = new Node();
- gridNode.name = 'grid';
- brickNode.addChild(gridNode);
- // 设置子格子大小
- gridNode.addComponent(UITransform).setContentSize(this.itemSize, this.itemSize);
- // 设置子格子位置
- const x = this.itemSize * gridConfigData.column - this.itemSize * columnMin;
- const y = this.itemSize * gridConfigData.row - this.itemSize * rowMin;
- gridNode.setPosition(x, y);
- // 创建格子显示节点
- const node = instantiate(gridPrefab);
- gridNode.addChild(node);
- // 设置格子显示节点大小
- const uiTransform = node.getComponent(UITransform);
- if (uiTransform) {
- uiTransform.setContentSize(
- this.itemSize,
- this.itemSize,
- );
- }
- // 设置位置
- node.setPosition(Vec3.ZERO);
- // 确保事件冒泡
- node.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
- event.preventSwallow = true;
- }, this);
- node.on(Node.EventType.TOUCH_MOVE, (event: EventTouch) => {
- event.preventSwallow = true;
- }, this);
- node.on(Node.EventType.TOUCH_END, (event: EventTouch) => {
- event.preventSwallow = true;
- }, this);
- });
- return brickNode;
- }
- /**
- * 创建引导砖块
- */
- public createGuideBrick(
- gridConfig: GridConfigData[],
- brickKey: string,
- colorIndex: number,
- index: number,
- rotateFlag = false
- ): BrickData {
- const brickData = {
- index,
- brickKey: brickKey,
- rotateFlag,
- gridConfig,
- deg: 0,
- brickNode: new Node(),
- gridColorKey: "colorKey",
- brickInitPos: new Vec3(),
- type: colorIndex,
- rotateNode: new Node(),
- };
- const node = this.generateBrick(brickKey, colorIndex);
- if (this.brickNode) {
- this.brickNode.addChild(node);
- }
- const transform = this.brickNode?.getComponent(UITransform);
- if (transform) {
- const midX = transform.width / 2;
- node.setPosition(0, 0);
- brickData.brickNode = node;
- brickData.brickInitPos = node.getWorldPosition();
- this.bricksList.push(brickData);
- this.brickAddEvent(brickData, () => { });
- }
- if (brickData.rotateFlag && this.rotatePrefab && this.rotateNode) {
- brickData.rotateNode = instantiate(this.rotatePrefab);
- this.rotateNode.addChild(brickData.rotateNode);
- //先隐藏
- brickData.rotateNode.active = false;
- brickData.rotateNode.setWorldPosition(this.brickNode!.getWorldPosition());
- }
- return brickData;
- }
- /**
- * 给砖块添加事件
- */
- public brickAddEvent(brickData: BrickData, onDragHandler: (brickData: BrickData, position: Vec3, startPos: Vec2, delta: Vec2) => void): void {
- const brickNode = brickData.brickNode;
- if (!brickNode) {
- console.error("brickNode为空,无法添加事件");
- return;
- }
- // 记录触摸开始位置
- let touchStartPos = new Vec2();
- // 触摸开始事件
- brickNode.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
- // 记录触摸起始位置
- touchStartPos.set(event.getUILocation());
- }, this);
- // 触摸移动事件
- brickNode.on(Node.EventType.TOUCH_MOVE, (event: EventTouch) => {
- const currentPos = event.getUILocation();
- const delta = new Vec2(
- currentPos.x - touchStartPos.x,
- currentPos.y - touchStartPos.y
- );
- // 如果移动距离太小,忽略
- if (delta.length() <= this.rotateFaultTolerant) {
- return;
- }
- // 调用拖动处理回调
- onDragHandler(brickData, event.getUILocation().toVec3().add3f(0, this.yOffset, 0), touchStartPos, delta);
- }, this);
- }
- /**
- * 旋转方块
- */
- public brickGridRotate(brickData: BrickData): Promise<boolean> {
- return new Promise((resolve) => {
- const next = this.nextGridRotate(brickData.gridConfig, brickData.deg);
- brickData.deg = next.deg;
- brickData.gridConfig = next.gridConfig;
- if (brickData.brickNode) {
- tween(brickData.brickNode)
- .to(this.aniBrickRotate, { angle: next.deg })
- .call(() => {
- resolve(true);
- })
- .start();
- } else {
- resolve(true);
- }
- });
- }
- /**
- * 计算下一个旋转状态
- */
- public nextGridRotate(gridConfig: GridConfigData[], deg: number): { gridConfig: GridConfigData[], deg: number } {
- const newGridConfig: GridConfigData[] = [];
- // 顺时针旋转
- let newDeg = deg - 90;
- gridConfig.forEach((gridConfigData) => {
- // 例如(1,2) => (-2,1),可以画图分析
- newGridConfig.push({
- row: -gridConfigData.column,
- column: gridConfigData.row
- });
- });
- return { gridConfig: newGridConfig, deg: newDeg };
- }
- /**
- * 获取所有方块
- */
- public getBricksList(): BrickData[] {
- return this.bricksList;
- }
- /**
- * 设置所有方块
- */
- public setBricksList(bricks: BrickData[]): void {
- this.bricksList = bricks;
- }
- /**
- * 移除方块
- */
- public removeBrick(brickData: BrickData): void {
- const index = this.bricksList.findIndex(item => item === brickData);
- if (index > -1) {
- this.bricksList.splice(index, 1);
- }
- }
- /**
- * 清理所有方块
- */
- public clearAllBricks(): void {
- if (this.brickNode) {
- this.brickNode.destroyAllChildren();
- }
- this.bricksList = [];
- }
- /**
- * 清理旋转节点
- */
- public clearAllRotateNodes(): void {
- if (this.rotateNode) {
- this.rotateNode.destroyAllChildren();
- }
- }
- /**
- * 给砖块添加拖动结束事件
- */
- public brickEndDrag(
- brickData: BrickData,
- onEndDragHandler: (brickData: BrickData, canPlace: boolean) => void
- ): void {
- const brickNode = brickData.brickNode;
- if (!brickNode) {
- console.error("brickNode为空,无法添加拖动结束事件");
- return;
- }
- // 添加触摸结束事件
- const touchEndHandler = (event: EventTouch) => {
- // 获取当前触摸位置
- const currentPos = event.getUILocation();
- // 调用处理函数
- onEndDragHandler(brickData, true);
- };
- brickNode.on(Node.EventType.TOUCH_END, touchEndHandler, this);
- brickNode.on(Node.EventType.TOUCH_CANCEL, touchEndHandler, this);
- }
- /**
- * 给砖块添加拖动开始事件
- */
- public brickStartDrag(
- brickData: BrickData,
- onStartDragHandler: (brickData: BrickData, startPos: Vec3) => void
- ): void {
- const brickNode = brickData.brickNode;
- if (!brickNode) {
- console.error("brickNode为空,无法添加拖动开始事件");
- return;
- }
- // 添加触摸开始事件
- brickNode.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
- // 记录触摸起始位置
- const startPos = brickNode.getWorldPosition().clone();
- // 调用处理函数
- onStartDragHandler(brickData, startPos);
- }, this);
- }
- /**
- * 计算初始位置
- */
- private calculateInitPosition(index: number): Vec3 {
- // 计算位置
- let offset = 220;
- const brickNum = this.bricksList.length + 1; // +1 因为当前砖块还未添加到列表
- if (brickNum % 2 === 1) {
- const middleNum = Math.floor(brickNum / 2) + 1;
- if (index < middleNum) {
- offset = -offset;
- }
- else if (index === middleNum) {
- offset = 0;
- }
- } else {
- const middleNum = brickNum / 2;
- if (index <= middleNum) {
- offset = -offset;
- }
- }
- return new Vec3(offset, 0, 0);
- }
- /**
- * 创建旋转节点
- */
- private createRotateNode(brickData: BrickData): void {
- if (!this.rotatePrefab || !this.rotateNode || !brickData.brickNode) {
- return;
- }
- brickData.rotateNode = instantiate(this.rotatePrefab);
- this.rotateNode.addChild(brickData.rotateNode);
- // 先隐藏
- brickData.rotateNode.active = false;
- brickData.rotateNode.setWorldPosition(brickData.brickNode.getWorldPosition());
- }
- }
|