GameCtl.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. import { _decorator, BoxCollider, Camera, Component, director, EventTouch, find, Game, geometry, Layers, Node, PhysicsSystem, Quat, RigidBody, Size, tween, UITransform, v3, Vec3 } from 'cc';
  2. import { Cube_Infor, Cube_State } from './Cube_Infor';
  3. import { Container_Manager } from './Container_Manager';
  4. import { UI_Idioms } from '../module_game/ui/UI_Idioms/UI_Idioms';
  5. import { gui } from '../core/ui/ui';
  6. const { ccclass, property } = _decorator;
  7. @ccclass('GameCtl')
  8. export class GameCtl extends Component {
  9. static instance: GameCtl = null;
  10. @property(Camera)
  11. camera: Camera = null;
  12. @property([Node])
  13. Ani: Node[] = [];
  14. canTouch: boolean = true;
  15. onLoad() {
  16. GameCtl.instance = this;
  17. console.log(find('Ani'));
  18. console.log('Camera value in onLoad:', this.camera);
  19. this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
  20. this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
  21. this.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
  22. }
  23. update(deltaTime: number) {
  24. }
  25. onTouchStart(event: EventTouch) {
  26. }
  27. onTouchMove(event: EventTouch) {
  28. }
  29. onTouchEnd(event: EventTouch) {
  30. if (this.canTouch) {
  31. this.shootRay(event);
  32. }
  33. }
  34. //发射射线检测判断物体是否可消除
  35. shootRay(event: EventTouch) {
  36. if (!this.camera) return;
  37. let ray = new geometry.Ray();
  38. this.camera.screenPointToRay(event.getLocationX(), event.getLocationY(), ray);
  39. const index = Layers.nameToLayer('Cube');
  40. const cubeMask = 2 << index;
  41. const maxDistance = 100000;
  42. const queryTrigger = false;
  43. if (PhysicsSystem.instance.raycastClosest(ray, cubeMask, maxDistance, queryTrigger)) {
  44. const raycastClosestResult = PhysicsSystem.instance.raycastClosestResult;
  45. const hitPoint = raycastClosestResult.hitPoint;
  46. const hitNormal = raycastClosestResult.hitNormal;
  47. const collider = raycastClosestResult.collider;
  48. const distance = raycastClosestResult.distance;
  49. console.log(collider.node.name);
  50. //当前其余点击无效
  51. if (collider.node.getComponent(Cube_Infor).state === Cube_State.live) {
  52. this.entryContainer(collider.node);
  53. }
  54. }
  55. console.log('发射了射线');
  56. }
  57. entryContainer(node: Node) {
  58. // 判断容器剩余容量
  59. let startIndex = -1;
  60. let targetPos = new Vec3();
  61. let txt_length = node.getComponent(Cube_Infor).Text.length;
  62. console.log(txt_length);
  63. // 判断字长 并 判断是否还有空间可放置
  64. switch (txt_length) {
  65. case 1:
  66. for (let i = 0; i < Container_Manager.instance.node_isIdiom.length; i++) {
  67. if (Container_Manager.instance.node_isIdiom[i] === false) {
  68. startIndex = i; // 找到连续的三个 false,记录起始位置
  69. break; // 找到第一个符合条件的位置后停止
  70. }
  71. }
  72. if (startIndex !== -1) { // 如果找到了一个值为 false 的元素
  73. targetPos = Container_Manager.instance.nodes[startIndex].getWorldPosition().clone();
  74. Container_Manager.instance.node_isIdiom[startIndex] = true;
  75. console.log(targetPos);
  76. } else {
  77. console.log("没有空间了");
  78. }
  79. break;
  80. case 2: {
  81. for (let i = 0; i < Container_Manager.instance.node_isIdiom.length - 2; i++) {
  82. if (Container_Manager.instance.node_isIdiom[i] === false &&
  83. Container_Manager.instance.node_isIdiom[i + 1] === false) {
  84. startIndex = i; // 找到连续的两个 false,记录起始位置
  85. break; // 找到第一个符合条件的位置后停止
  86. }
  87. }
  88. if (startIndex !== -1) {
  89. console.log("找到连续的两个 false,起始索引是:", startIndex);
  90. // 可以在此使用 startIndex 进行后续操作,例如:
  91. let pos1 = Container_Manager.instance.nodes[startIndex].getWorldPosition();
  92. let pos2 = Container_Manager.instance.nodes[startIndex + 1].getWorldPosition();
  93. Container_Manager.instance.node_isIdiom[startIndex] = true;
  94. Container_Manager.instance.node_isIdiom[startIndex + 1] = true;
  95. targetPos.set(
  96. (pos1.x + pos2.x) / 2,
  97. (pos1.y + pos2.y) / 2,
  98. (pos1.z + pos2.z) / 2
  99. );
  100. console.log(targetPos);
  101. }
  102. break;
  103. }
  104. case 3: {
  105. for (let i = 0; i < Container_Manager.instance.node_isIdiom.length - 2; i++) {
  106. if (Container_Manager.instance.node_isIdiom[i] === false &&
  107. Container_Manager.instance.node_isIdiom[i + 1] === false &&
  108. Container_Manager.instance.node_isIdiom[i + 2] === false) {
  109. startIndex = i; // 找到连续的三个 false,记录起始位置
  110. break; // 找到第一个符合条件的位置后停止
  111. }
  112. }
  113. if (startIndex !== -1) {
  114. // 找到连续三个 false,startIndex 即为最前面的索引
  115. console.log("找到连续的三个 false,起始索引是:", startIndex);
  116. // 可以在此使用 startIndex 进行后续操作,例如:
  117. let pos1 = Container_Manager.instance.nodes[startIndex].getWorldPosition();
  118. let pos2 = Container_Manager.instance.nodes[startIndex + 1].getWorldPosition();
  119. let pos3 = Container_Manager.instance.nodes[startIndex + 2].getWorldPosition();
  120. Container_Manager.instance.node_isIdiom[startIndex] = true;
  121. Container_Manager.instance.node_isIdiom[startIndex + 1] = true;
  122. Container_Manager.instance.node_isIdiom[startIndex + 2] = true;
  123. targetPos.set(
  124. (pos1.x + pos2.x + pos3.x) / 3,
  125. (pos1.y + pos2.y + pos3.y) / 3,
  126. (pos1.z + pos2.z + pos3.z) / 3
  127. );
  128. console.log(targetPos);
  129. } else {
  130. console.log("没有找到连续的三个 false");
  131. }
  132. break;
  133. }
  134. default:
  135. return;
  136. }
  137. if (startIndex !== -1) {
  138. // node.getComponent(Cube_Infor).lock = true;
  139. node.getComponent(Cube_Infor).state = Cube_State.wait;
  140. node.getComponent(Cube_Infor).rigidbody.type = RigidBody.Type.STATIC; // 禁用重力
  141. let targetRotation = new Quat();
  142. Quat.fromEuler(targetRotation, -90, 0, 0);
  143. this.canTouch = false;
  144. tween(node)
  145. .to(0.5, { position: new Vec3(targetPos.x, targetPos.y, targetPos.z + 0.4), rotation: targetRotation })
  146. .call(() => {
  147. Container_Manager.instance.idiom_combine.set(node.getComponent(Cube_Infor), startIndex);
  148. // 执行判断成语合成逻辑
  149. let matchedCubes: Cube_Infor[] = [];
  150. let flag = Container_Manager.instance.checkIdiom_Combine(node.getComponent(Cube_Infor), matchedCubes);
  151. if (flag) {
  152. // 执行合成动画
  153. console.log("匹配的成语方块:", matchedCubes);
  154. this.combine_ani(matchedCubes[0], matchedCubes[1]);
  155. } else {
  156. //高亮
  157. gui.get(UI_Idioms).light_Show(node.getComponent(Cube_Infor));
  158. this.canTouch = true;
  159. }
  160. })
  161. .start();
  162. }
  163. }
  164. //合成动画
  165. combine_ani(cube1: Cube_Infor, cube2: Cube_Infor) {
  166. // 创建第一个 tween 动画
  167. const tween1 = tween(cube1.node)
  168. .to(0.5, { position: new Vec3(this.Ani[0].position.x, this.Ani[0].position.y, this.Ani[0].position.z + 0.4) })
  169. .call(() => {
  170. for (let i = Container_Manager.instance.idiom_combine.get(cube1); i < Container_Manager.instance.idiom_combine.get(cube1) + cube1.Text.length; i++) {
  171. Container_Manager.instance.node_isIdiom[i] = false;
  172. }
  173. Container_Manager.instance.idiom_combine.delete(cube1);
  174. setTimeout(() => {
  175. cube1.state=Cube_State.dead;
  176. Container_Manager.instance.recycleCube(cube1.node);
  177. }, 1000.0);
  178. });
  179. // 创建第二个 tween 动画
  180. const tween2 = tween(cube2.node)
  181. .to(0.5, { position: new Vec3(this.Ani[1].position.x, this.Ani[1].position.y, this.Ani[1].position.z + 0.4) })
  182. .call(() => {
  183. for (let i = Container_Manager.instance.idiom_combine.get(cube2); i < Container_Manager.instance.idiom_combine.get(cube2) + cube2.Text.length; i++) {
  184. Container_Manager.instance.node_isIdiom[i] = false;
  185. }
  186. Container_Manager.instance.idiom_combine.delete(cube2);
  187. setTimeout(() => {
  188. cube2.state=Cube_State.dead;
  189. //在nodeReferences中修改该节点属性
  190. // Container_Manager.instance.nodeReferences.forEach((node, index) => {
  191. // if (node === cube2.node) {
  192. // Container_Manager.instance.nodeReferences[index].getComponent(Cube_Infor).state = Cube_State.dead;
  193. // }
  194. // });
  195. Container_Manager.instance.recycleCube(cube2.node);
  196. }, 1000.0);
  197. });
  198. // 使用 tween 的并行组合功能
  199. tween(cube1.node)
  200. .parallel(tween1, tween2) // 并行执行 tween1 和 tween2
  201. .call(() => {
  202. // 取消相关字的高亮显示
  203. gui.get(UI_Idioms).light_Hide(cube1, cube2);
  204. this.adjustContainer();
  205. // 检测容器中哪些字需要高亮显示
  206. console.log(Container_Manager.instance.node_isIdiom); // 在所有动画结束后执行
  207. Container_Manager.instance.idioms = Container_Manager.instance.idioms.filter(c => c.idiom !== cube1.Text + cube2.Text);
  208. this.canTouch = true;
  209. })
  210. .start();
  211. }
  212. adjustContainer() {
  213. const container = Container_Manager.instance;
  214. // 新的 node_isIdiom 状态数组
  215. const newNodeIsIdiom = Array(container.node_isIdiom.length).fill(false);
  216. // 新的 idiom_combine 映射表
  217. const newIdiomCombine = new Map<Cube_Infor, number>();
  218. // 遍历 idiom_combine,重新计算位置
  219. for (const [cube, startIndex] of container.idiom_combine.entries()) {
  220. const txtLength = cube.Text.length; // 获取字长
  221. let targetIndex = -1; // 目标位置起始索引
  222. let targetPos = new Vec3();
  223. switch (txtLength) {
  224. case 1: {
  225. // 找到一个空位
  226. for (let i = 0; i < container.node_isIdiom.length; i++) {
  227. if (!newNodeIsIdiom[i]) {
  228. targetIndex = i;
  229. break;
  230. }
  231. }
  232. if (targetIndex !== -1) {
  233. targetPos = container.nodes[targetIndex].getWorldPosition().clone();
  234. newNodeIsIdiom[targetIndex] = true; // 占用位置
  235. } else {
  236. console.log("没有空位容纳单字 Cube_Infor");
  237. }
  238. break;
  239. }
  240. case 2: {
  241. // 找到连续两个空位
  242. for (let i = 0; i < container.node_isIdiom.length - 1; i++) {
  243. if (!newNodeIsIdiom[i] && !newNodeIsIdiom[i + 1]) {
  244. targetIndex = i;
  245. break;
  246. }
  247. }
  248. if (targetIndex !== -1) {
  249. const pos1 = container.nodes[targetIndex].getWorldPosition();
  250. const pos2 = container.nodes[targetIndex + 1].getWorldPosition();
  251. targetPos.set(
  252. (pos1.x + pos2.x) / 2,
  253. (pos1.y + pos2.y) / 2,
  254. (pos1.z + pos2.z) / 2
  255. );
  256. newNodeIsIdiom[targetIndex] = true;
  257. newNodeIsIdiom[targetIndex + 1] = true;
  258. } else {
  259. console.log("没有连续两个空位容纳双字 Cube_Infor");
  260. }
  261. break;
  262. }
  263. case 3: {
  264. // 找到连续三个空位
  265. for (let i = 0; i < container.node_isIdiom.length - 2; i++) {
  266. if (
  267. !newNodeIsIdiom[i] &&
  268. !newNodeIsIdiom[i + 1] &&
  269. !newNodeIsIdiom[i + 2]
  270. ) {
  271. targetIndex = i;
  272. break;
  273. }
  274. }
  275. if (targetIndex !== -1) {
  276. const pos1 = container.nodes[targetIndex].getWorldPosition();
  277. const pos2 = container.nodes[targetIndex + 1].getWorldPosition();
  278. const pos3 = container.nodes[targetIndex + 2].getWorldPosition();
  279. targetPos.set(
  280. (pos1.x + pos2.x + pos3.x) / 3,
  281. (pos1.y + pos2.y + pos3.y) / 3,
  282. (pos1.z + pos2.z + pos3.z) / 3
  283. );
  284. newNodeIsIdiom[targetIndex] = true;
  285. newNodeIsIdiom[targetIndex + 1] = true;
  286. newNodeIsIdiom[targetIndex + 2] = true;
  287. } else {
  288. console.log("没有连续三个空位容纳三字 Cube_Infor");
  289. }
  290. break;
  291. }
  292. default:
  293. return;
  294. }
  295. // 移动 Cube_Infor 到目标位置
  296. if (targetIndex !== -1) {
  297. tween(cube.node)
  298. .to(0.3, { position: new Vec3(targetPos.x, targetPos.y, targetPos.z + 0.4) })
  299. .start();
  300. newIdiomCombine.set(cube, targetIndex); // 更新新映射
  301. }
  302. }
  303. // 更新 container 状态
  304. container.node_isIdiom = newNodeIsIdiom;
  305. container.idiom_combine = newIdiomCombine;
  306. console.log("调整后的容器状态:", container.node_isIdiom);
  307. console.log("更新后的 idiom_combine:", [...container.idiom_combine.entries()]);
  308. }
  309. }