| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- import { _decorator, Component, Node, PhysicsSystem, Camera, EventTouch, find, geometry, Layers, Vec3, Vec2, quat, DirectionalLight, Quat, AudioSource, AudioClip } from 'cc';
- import { CreateMap } from './CreateMap';
- import { CubeInfo } from './CubeInfo';
- import { UpdateLayer } from './UpdateLayer';
- import { UpdateScore } from './UpdateScore';
- import { ShowTip } from './ShowTip';
- import { EasyColorStrategy, HardColorStrategy, NormalColorStrategy, StrategyManager } from './StrategyManager';
- import { GameState, PlayState, StateManager } from './StateManager';
- import { UIManager } from '../UIFrameWork/UIManager';
- import { LoadRes } from '../Config/LoadRes';
- import ch_audio from '../../ch/audio/audio';
- const { ccclass, property } = _decorator;
- @ccclass('PlayerCtl')
- export class PlayerCtl extends Component {
- public static instance: PlayerCtl = null;
- private cameraNode: Node = null;
- @property(Camera)
- private camera: Camera | null = null;
- private light: Node = null;
- private dir: number[][] = [[0, 0, 1], [0, 1, 0], [0, 0, -1], [0, -1, 0]];
- private waitDestroy: Vec3[] = [];//等待销毁的所有节点
- public layerIndex: number = 1;//已开启层数
- private surfaceLayer: number = 1;//表层
- private needMoveLayer: number = 0;//
- private totalDestroy: number = 0;
- private startTouchPos: Vec2 = null;
- private moveDistance: number = 0;
- private swipeThreshold: number = 50; // 滑动阈值
- public touchLock: boolean = true;//触摸锁定状态
- onLoad() {
- PlayerCtl.instance = this;
- // 获取场景中的主光源
- this.light = find('Main Light');
- // 获取场景中的主摄像头
- this.cameraNode = find('Main Camera');
- if (this.cameraNode) {
- this.camera = this.cameraNode.getComponent(Camera);
- }
- // 监听触摸开始事件
- this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
- this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
- this.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
- }
- onTouchStart(event: EventTouch) {
- // 确保获取的是第一个触摸点
- if (!this.touchLock&&StateManager.getInstance().getState() instanceof PlayState) {
- this.startTouchPos = event.getLocation();
- }
- }
- //滑动屏幕让当前层类似于2048游戏中的上下左右移动,并不合并/消除
- onTouchMove(event: EventTouch) {
- const currentTouchPos = event.getLocation();
- if (this.startTouchPos&&StateManager.getInstance().getState() instanceof PlayState) {
- const moveVector = new Vec2(currentTouchPos.x - this.startTouchPos.x, currentTouchPos.y - this.startTouchPos.y);
- this.moveDistance = moveVector.length(); // 更新滑动距离
- console.log("触摸屏幕");
- }
- }
- onTouchEnd(event: EventTouch) {
- if (!this.startTouchPos || this.touchLock || !(StateManager.getInstance().getState() instanceof PlayState)) return;
- //移动动画在执行时应关闭触摸判断
- const currentTouchPos = event.getLocation();
- const moveVector = new Vec2(currentTouchPos.x - this.startTouchPos.x, currentTouchPos.y - this.startTouchPos.y);
- if (this.moveDistance > this.swipeThreshold) {
- const direction = moveVector.normalize(); // 返回方向向量
- this.handleSwipe(direction); // 处理滑动
- }
- else {
- this.shootRay(event);
- }
- this.startTouchPos = null; // 重置触摸位置
- this.moveDistance = 0; // 重置滑动距离
- }
- handleSwipe(direction: Vec2) {
- // 确定滑动方向对应的索引
- let directionIndex = -1;
- const horizontalThreshold = 0.7;
- const verticalThreshold = 0.7;
- if (Math.abs(direction.x) > horizontalThreshold && Math.abs(direction.y) < verticalThreshold) {
- // 主要是水平方向移动
- if (direction.x < 0) {
- directionIndex = 3; // 向左
- }
- else if (direction.x > 0) {
- directionIndex = 1; // 向右
- // this.light.setRotationFromEuler(new Vec3(10, 0, 0));
- }
- } else if (Math.abs(direction.y) > verticalThreshold && Math.abs(direction.x) < horizontalThreshold) {
- // 主要是垂直方向移动
- if (direction.y < 0) directionIndex = 2; // 向下
- else if (direction.y > 0) directionIndex = 0; // 向上
- }
- if (directionIndex !== -1) {
- this.moveLayer(directionIndex);
- }
- }
- //已解锁的层都需要移动
- // moveLayer(directionIndex) {
- // this.touchLock = true;
- // let map = CreateMap.getInstance().GetMap();
- // let maxKIJ = CreateMap.getInstance().GetMaxKIJ();
- // for (let k = this.surfaceLayer - 1; k < this.layerIndex; k++) {
- // // 创建一个临时数组来存储移动后的方块状态
- // let tempMap = new Array(maxKIJ.y).fill(null).map(() => new Array(maxKIJ.z).fill(null));
- // // 左右移动
- // if (directionIndex === 3 || directionIndex === 1) {
- // for (let i = 0; i < maxKIJ.y; i++) {
- // let newRow = [];
- // for (let j = 0; j < maxKIJ.z; j++) {
- // let cube = map[k][i][j];
- // if (cube) {
- // newRow.push({ cube });
- // }
- // }
- // // 向左移动
- // if (directionIndex === 3) {
- // for (let j = 0; j < maxKIJ.z; j++) {
- // let item = newRow.shift(); // 取出最左边的方块
- // if (item) {
- // tempMap[i][j] = item.cube;
- // item.cube.getComponent(CubeInfo).setPos(k, i, j);
- // }
- // }
- // }
- // // 向右移动
- // else {
- // for (let j = maxKIJ.z - 1; j >= 0; j--) {
- // let item = newRow.pop(); // 取出最右边的方块
- // if (item) {
- // tempMap[i][j] = item.cube;
- // item.cube.getComponent(CubeInfo).setPos(k, i, j);
- // }
- // }
- // }
- // }
- // }
- // // 上下移动
- // else if (directionIndex === 0 || directionIndex === 2) {
- // for (let j = 0; j < maxKIJ.z; j++) {
- // let newCol = [];
- // for (let i = 0; i < maxKIJ.y; i++) {
- // let cube = map[k][i][j];
- // if (cube) {
- // newCol.push({ cube });
- // }
- // }
- // // 向上移动
- // if (directionIndex === 0) {
- // for (let i = 0; i < maxKIJ.y; i++) {
- // let item = newCol.shift(); // 取出最下面的方块
- // if (item) {
- // tempMap[i][j] = item.cube;
- // item.cube.getComponent(CubeInfo).setPos(k, i, j);
- // }
- // }
- // }
- // // 向下移动
- // else {
- // for (let i = maxKIJ.y - 1; i >= 0; i--) {
- // let item = newCol.pop(); // 取出最上面的方块
- // if (item) {
- // tempMap[i][j] = item.cube;
- // item.cube.getComponent(CubeInfo).setPos(k, i, j);
- // }
- // }
- // }
- // }
- // }
- // // // 更新地图数据
- // CreateMap.getInstance().setMap(tempMap, k, this.needMoveLayer);
- // }
- // //更新颜色
- // CreateMap.getInstance().changeColor(this.surfaceLayer-1,this.layerIndex);
- // }
- moveLayer(directionIndex) {
- this.touchLock = true;
- let map = CreateMap.getInstance().GetMap();
- let maxKIJ = CreateMap.getInstance().GetMaxKIJ();
- for (let k = this.surfaceLayer - 1; k < this.layerIndex; k++) {
- let tempMap = new Array(maxKIJ.y).fill(null).map(() => new Array(maxKIJ.z).fill(null));
- // 左右移动
- if (directionIndex === 3 || directionIndex === 1) {
- for (let i = 0; i < maxKIJ.y; i++) {
- let newRow = [];
- for (let j = 0; j < maxKIJ.z; j++) {
- let cube = map[k][i][j];
- if (cube) {
- newRow.push({ cube });
- }
- }
- // 向左移动
- if (directionIndex === 3) {
- for (let j = 0; j < maxKIJ.z; j++) {
- let item = newRow.shift(); // 取出最左边的方块
- if (item) {
- tempMap[i][j] = item.cube;
- item.cube.getComponent(CubeInfo).setPos(k, i, j);
- }
- }
- }
- // 向右移动
- else {
- for (let j = maxKIJ.z - 1; j >= 0; j--) {
- let item = newRow.pop(); // 取出最右边的方块
- if (item) {
- tempMap[i][j] = item.cube;
- item.cube.getComponent(CubeInfo).setPos(k, i, j);
- }
- }
- }
- }
- }
- // 上下移动
- else if (directionIndex === 0 || directionIndex === 2) {
- for (let j = 0; j < maxKIJ.z; j++) {
- let newCol = [];
- for (let i = 0; i < maxKIJ.y; i++) {
- let cube = map[k][i][j];
- if (cube) {
- newCol.push({ cube });
- }
- }
- // 向上移动
- if (directionIndex === 0) {
- for (let i = 0; i < maxKIJ.y; i++) {
- let item = newCol.shift(); // 取出最下面的方块
- if (item) {
- tempMap[i][j] = item.cube;
- item.cube.getComponent(CubeInfo).setPos(k, i, j);
- }
- }
- }
- // 向下移动
- else {
- for (let i = maxKIJ.y - 1; i >= 0; i--) {
- let item = newCol.pop(); // 取出最上面的方块
- if (item) {
- tempMap[i][j] = item.cube;
- item.cube.getComponent(CubeInfo).setPos(k, i, j);
- }
- }
- }
- }
- }
- CreateMap.getInstance().setMap(tempMap, k, this.needMoveLayer);
- }
- CreateMap.getInstance().changeColor(this.surfaceLayer - 1, this.layerIndex);
- }
- //发射射线检测判断物体是否可消除
- shootRay(event: EventTouch) {
- if (!this.camera) return;
- let ray = new geometry.Ray();
- this.camera.screenPointToRay(event.getLocationX(), event.getLocationY(), ray);
- const index = Layers.nameToLayer('Cube');
- const mask = 1 << index;
- const maxDistance = 10000000;
- const queryTrigger = true;
- if (PhysicsSystem.instance.raycastClosest(ray, mask, maxDistance, queryTrigger)) {
- const raycastClosestResult = PhysicsSystem.instance.raycastClosestResult;
- const hitPoint = raycastClosestResult.hitPoint;
- const hitNormal = raycastClosestResult.hitNormal;
- const collider = raycastClosestResult.collider;
- const distance = raycastClosestResult.distance;
- console.log(collider.node.name);
- //检测周边四个方向相同颜色的物体
- this.checkNearCube(collider.node.getComponent(CubeInfo).getPos());
- //拿取到所有连续颜色相同的物体,进行销毁
- this.destroyCollectedCubes();
- //最多允许同时存在3层,如果当前有三层未销毁完,但已开启第四层,消除最上层所有元素且不计分
- this.judgeSurface();//得出表层
- if (this.calcDifference())//超出三层
- {
- console.log("相差层数大于3层");
- //弹出广告界面,不看广告游戏结束
- UIManager.Instance.ShowUI("ad", LoadRes.getInstance().adPanel);
- }
- }
- console.log('发射了射线');
- }
- //多层堆叠的map,但是要从2d视角检测当前方块四方向是否有连续同色,采用BFS
- checkNearCube(Pos: Vec3) {
- console.log(Pos);
- let map = CreateMap.getInstance().GetMap();
- let maxKIJ = CreateMap.getInstance().GetMaxKIJ();
- let currentCubeInfo = map[Pos.x][Pos.y][Pos.z]?.getComponent(CubeInfo);
- if (!currentCubeInfo || Pos.x >= this.layerIndex) return;
- let cubeId = currentCubeInfo.getId();
- let count = 0;
- let toMarkAsNull: Vec3[] = [];
- let queue: Vec3[] = [];
- queue.push(Pos);
- let visited: boolean[][][] = new Array(maxKIJ.x).fill(false).map(() => new Array(maxKIJ.y).fill(false).map(() => new Array(maxKIJ.z).fill(false)));
- while (queue.length > 0) {
- let currentPos = queue.shift();
- if (!currentPos) continue;
- let x = currentPos.x;
- let y = currentPos.y;
- let z = currentPos.z;
- // 检查边界条件和是否已经访问过
- if (x < 0 || x >= maxKIJ.x || y < 0 || y >= maxKIJ.y || z < 0 || z >= maxKIJ.z || visited[x][y][z]) continue;
- let cubeInfo = map[x][y][z]?.getComponent(CubeInfo);
- if (cubeInfo && cubeInfo.getId() === cubeId) {
- count++;
- toMarkAsNull.push(new Vec3(x, y, z));
- this.dir.forEach(d => {
- let newX = x + d[0];
- let newY = y + d[1];
- let newZ = z + d[2];
- // 确保新的坐标在边界内,并且目标块不为空,并且是已解锁
- if (newX >= 0 && newX < maxKIJ.x && newY >= 0 && newY < maxKIJ.y && newZ >= 0 && newZ < maxKIJ.z && !visited[newX][newY][newZ] && map[newX][newY][newZ] && !map[newX][newY][newZ].getComponent(CubeInfo).getLock()) {
- queue.push(new Vec3(newX, newY, newZ));
- }
- //旁边无方块
- else {
- //判断更深层次
- for (let i = 1; i < 4; i++) {
- if (newX + i >= 0 && newX + i < maxKIJ.x && newY >= 0 && newY < maxKIJ.y && newZ >= 0 && newZ < maxKIJ.z && !visited[newX + i][newY][newZ] && map[newX + i][newY][newZ] && !map[newX + i][newY][newZ].getComponent(CubeInfo).getLock()) {
- queue.push(new Vec3(newX + i, newY, newZ));
- }
- }
- //判断更浅层次
- for (let i = 1; i < 4; i++) {
- if (newX - i >= 0 && newX - i < maxKIJ.x && newY >= 0 && newY < maxKIJ.y && newZ >= 0 && newZ < maxKIJ.z && !visited[newX - i][newY][newZ] && map[newX - i][newY][newZ] && !map[newX - i][newY][newZ].getComponent(CubeInfo).getLock()) {
- queue.push(new Vec3(newX - i, newY, newZ));
- }
- }
- }
- });
- visited[x][y][z] = true;
- }
- }
- //连续颜色相同方块大于等于三个时,将每个方块放入待销毁数组
- if (count >= 3) {
- toMarkAsNull.forEach(pos => {
- this.waitDestroy.push(new Vec3(pos.x, pos.y, pos.z));
- });
- }
- // else {
- // // 如果数量小于 3,确保不进行错误操作
- // toMarkAsNull.forEach(pos => {
- // // 检查 map 中对应位置是否为 null,如果为 null 则不进行任何操作
- // if (map[pos.x] && map[pos.x][pos.y] && map[pos.x][pos.y][pos.z]) {
- // if (!this.waitDestroy.some(item => item === map[pos.x][pos.y][pos.z])) {
- // // 保持方块状态不变
- // }
- // }
- // });
- // }
- }
- //销毁方块
- destroyCollectedCubes() {
- let map = CreateMap.getInstance().GetMap();
- if (this.waitDestroy.length >= 3) {
- if(ch_audio.getInstance().volumeEffect)
- {
- ch_audio.getInstance().playOneShot('Break');
- }
- this.waitDestroy.forEach(cube => {
- if (cube) {
- //调用爆炸特效
- // map[cube.x][cube.y][cube.z].getComponent(CubeInfo).triggerDissolve();
- CreateMap.getInstance().destroyNode(cube);
- if (cube.x + 1 === this.layerIndex) {
- this.totalDestroy++;
- console.log('当前层销毁了' + this.totalDestroy + '个');
- }
- // this.score += 10; // 假设每销毁一个块加10分
- }
- });
- this.calculateScore(this.waitDestroy.length);
- }
- this.waitDestroy = []; // 清空等待销毁的块列表
- let maxKIJ = CreateMap.getInstance().GetMaxKIJ();
- if (this.totalDestroy / (maxKIJ.y * maxKIJ.z) > 0.8)//消除表层80%,解锁下层
- {
- this.layerIndex++;
- UpdateLayer.instance.Update_Layer(this.layerIndex);
- this.totalDestroy = 0;
- console.log("调用新增实例层");
- }
- //如果表层被玩家自己消除完了,下面所有层都需要上移
- if (this.CalcSurface()) {
- CreateMap.getInstance().initNewLayer(maxKIJ.x, this.needMoveLayer);
- this.needMoveLayer++;//需移动的层数+1
- let maxK = CreateMap.getInstance().GetMaxKIJ().x;
- for (let k = this.surfaceLayer - 1; k < maxK; k++) {
- CreateMap.getInstance().setMap(map[k], k, this.needMoveLayer);
- }
- }
- //更新颜色
- CreateMap.getInstance().changeColor(this.surfaceLayer - 1, this.layerIndex);
- }
- //加分
- calculateScore(length: number) {
- let score = 0;
- //销毁后进行加分,3-5个为基础分每个方块5分,6-8个每个方块多算10分,9-15个每个方块多算20分,16个以上每个方块多算50分
- if (length >= 3 && length <= 5) {
- ShowTip.instance.Show_Tip('Good');
- score = length * 5;
- }
- else if (length >= 6 && length <= 8) {
- ShowTip.instance.Show_Tip('Great');
- score = length * 15;
- }
- else if (length >= 9 && length <= 15) {
- ShowTip.instance.Show_Tip('Unbeliveable');
- score = length * 25;
- } else if (length >= 16) {
- ShowTip.instance.Show_Tip('excellent');
- score = length * 55;
- }
- UpdateScore.instance.Update_Score(score);
- }
- //判断哪一层是表层
- judgeSurface() {
- let maxKIJ = CreateMap.getInstance().GetMaxKIJ();
- let map = CreateMap.getInstance().GetMap();
- for (let k = 0; k < this.layerIndex; k++) {
- for (let i = 0; i < maxKIJ.y; i++) {
- for (let j = 0; j < maxKIJ.z; j++) {
- if (map[k][i][j] !== null) {
- this.surfaceLayer = k + 1;//更新表层
- console.log("表层是" + this.surfaceLayer);
- return;
- }
- }
- }
- }
- }
- CalcSurface(): boolean {
- let maxKIJ = CreateMap.getInstance().GetMaxKIJ();
- let map = CreateMap.getInstance().GetMap();
- for (let i = 0; i < maxKIJ.y; i++) {
- for (let j = 0; j < maxKIJ.z; j++) {
- if (map[this.surfaceLayer - 1][i][j] !== null) {
- //表层没被消除完
- return false;
- }
- }
- }
- CreateMap.getInstance().setMap(map[this.surfaceLayer - 1], this.surfaceLayer - 1, this.needMoveLayer);
- this.surfaceLayer++;//更新表层
- return true;
- }
- //计算深度差
- calcDifference(): boolean {
- return (this.layerIndex - (this.surfaceLayer - 1)) > 1 ? true : false;
- }
- //弹出广告界面,销毁表层方块
- destroySurfaceCube(index: number) {
- let maxKIJ = CreateMap.getInstance().GetMaxKIJ();
- let map = CreateMap.getInstance().GetMap();
- for (let i = 0; i < maxKIJ.y; i++) {
- for (let j = 0; j < maxKIJ.z; j++) {
- if (map[index][i][j] !== null) {
- console.log("应该销毁第" + index + "层");
- //调用爆炸特效
- CreateMap.getInstance().destroyNode(new Vec3(index, i, j));
- }
- }
- }
- this.surfaceLayer++;//更新表层
- CreateMap.getInstance().initNewLayer(maxKIJ.x, this.needMoveLayer);
- this.needMoveLayer++;
- }
- //看了广告要执行的内容
- public onAdFinish() {
- //销毁表层
- this.destroySurfaceCube(this.surfaceLayer - 1);
- //下层所有层向上移动一层
- let maxKIJ = CreateMap.getInstance().GetMaxKIJ();
- let map = CreateMap.getInstance().GetMap();
- for (let k = this.surfaceLayer - 1; k < maxKIJ.x; k++) {
- CreateMap.getInstance().setMap(map[k], k, this.needMoveLayer);
- }
- }
- }
|