GameCtl.ts 16 KB

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