RoleController.ts 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. import { EventHandler, EventTouch, find, instantiate, JsonAsset, Prefab, random, Sprite, SpriteFrame, SystemEventType, tween, UITransform, Vec2, Vec3 } from 'cc';
  2. import { _decorator, Component, Node } from 'cc';
  3. import { Http } from '../core/net/Http';
  4. import { ResourcesUtils } from '../core/resourceManager/ResourcesUtils';
  5. import { WindowManager } from '../core/ui/window/WindowManager';
  6. import { WindowOpenMode } from '../core/ui/window/WindowOpenMode';
  7. import { GeometryUtils } from '../core/utils/GeometryUtils';
  8. import { Log } from '../core/utils/Log';
  9. import { Random } from '../core/utils/Random';
  10. import { ConfigData } from '../Data/ConfigData';
  11. import { g } from '../Data/g';
  12. import { GetTenfold } from '../Windows/GetTenfold';
  13. import { Role } from './Role';
  14. const { ccclass, property } = _decorator;
  15. /**
  16. * 神将控制器
  17. * @author SS
  18. */
  19. @ccclass('RoleController')
  20. export class RoleController extends Component {
  21. @property({ tooltip: "当角色可以出售", type: EventHandler })
  22. public onCanSell: EventHandler;
  23. @property({ type: Node, tooltip: "角色组" })
  24. roleGroup: Node;
  25. @property({ type: [Node], tooltip: "角色底" })
  26. roleBgList: Node[] = [];
  27. @property({ tooltip: "角色预制体根目录" })
  28. public rolePrefabPath = '';
  29. @property({ tooltip: "画布", type: Node })
  30. public canvas: Node;
  31. @property({ type: Node, tooltip: "出售按钮" })
  32. sellButton: Node;
  33. @property({ type: Http, tooltip: "Http服务" })
  34. http: Http;
  35. private rolesData = [];
  36. /**游戏场可显示神将节点 */
  37. private roles: Array<Role> = [];
  38. /**最大显示神将数 */
  39. private max: number = 12;
  40. /**当前选中的主角 */
  41. private currentRole: Role;
  42. /**当前选中的主角开始位置 */
  43. private beginTouchPoint: Vec2;
  44. /**当前选中的主角开始世界位置 */
  45. private beginRoleWorldPosition: Vec3;
  46. /**目标的主角 */
  47. private targetRole: Role;
  48. /**当前选中角色的位置索引 */
  49. private _currentRoleIndex: number = -1;
  50. /**目标位置的索引 */
  51. private targetRoleIndex: number = -1;
  52. /**是否已经拖动到出售按钮 */
  53. private isMoveIn: boolean = false;
  54. /**开始移动 */
  55. private startMove: boolean = false;
  56. start() {
  57. for (let i = 0; i < this.max; i++) {
  58. this.roles.push(null);
  59. this.rolesData.push(false);
  60. }
  61. let generals = g.gameData.getMyLocalData(g.userData.id).myLocalGenerals;
  62. for (let i = 0; i < generals.length; i++) {
  63. if (generals[i].index != -1) {
  64. this.createRole({ lv: generals[i].generalLv, index: generals[i].index, type: createType.Start });
  65. }
  66. }
  67. !this.canvas && (this.canvas = find("Canvas"));
  68. this.canvas.on(SystemEventType.TOUCH_START, this.onTouchBegin, this);
  69. this.canvas.on(SystemEventType.TOUCH_END, this.onTouchEnd, this);
  70. this.canvas.on(SystemEventType.TOUCH_CANCEL, this.onTouchEnd, this);
  71. this.canvas.on(SystemEventType.TOUCH_MOVE, this.onTouchMove, this);
  72. }
  73. update() {
  74. if (g.gameData.hasSellGeneral) {
  75. g.gameData.hasSellGeneral = false;
  76. this.targetRoleIndex = -1;
  77. this.currentRoleIndex = -1;
  78. let role = this.roles[g.gameData.sellGeneralData.index];
  79. if (role) {
  80. this.deleteRole(role, g.gameData.sellGeneralData.index, g.gameData.sellGeneralData.lv);
  81. this.checkNowRole();
  82. g.gameData.saveLocalData();
  83. } else {
  84. Log.warn('本地神将数据异常');
  85. }
  86. }
  87. if (g.gameData.cancleSellGeneral) {
  88. g.gameData.cancleSellGeneral = false;
  89. this.targetRoleIndex = -1;
  90. this.currentRoleIndex = -1;
  91. let role = this.roles[g.gameData.sellGeneralData.index];
  92. if (role) {
  93. role.node.worldPosition = this.beginRoleWorldPosition;
  94. }
  95. }
  96. if (g.gameData.isAddRole) {
  97. g.gameData.isAddRole = false;
  98. this.checkNowRole();
  99. }
  100. }
  101. private currentTouchId = -1;
  102. private async onTouchBegin(e: EventTouch) {
  103. if (g.gameData.isBuying) {
  104. return;
  105. }
  106. if (this.currentTouchId != -1 && this.currentTouchId != e.touch.getID()) {
  107. return;
  108. }
  109. if (WindowManager.getWindowList().length > 0) {
  110. console.log("当前打开窗口数:::::" + WindowManager.getWindowList().length);
  111. return;
  112. }
  113. if (this._currentRoleIndex != -1 || this.targetRoleIndex != -1) {
  114. return;
  115. }
  116. this.currentRole = this.findRole(e.getUILocation());
  117. if (this.currentRole) {
  118. g.gameData.isMoveing = true;
  119. let currentindex = this.currentRoleIndex;
  120. if (this.currentTouchId == - 1) {
  121. this.currentTouchId = e.touch.getID();
  122. }
  123. this.beginTouchPoint = e.getUILocation();
  124. this.currentRole.node.setSiblingIndex(this.roleGroup.children.length - 1);
  125. this.beginRoleWorldPosition = this.currentRole.node.worldPosition.clone();
  126. let img: SpriteFrame = await ResourcesUtils.load<SpriteFrame>("Roles/" + this.currentRole.generalBaseData.lv + "/spriteFrame", SpriteFrame, this.node);
  127. console.log("测试currentRoleIndex:::::" + this.currentRoleIndex);
  128. console.log(this.roleBgList[currentindex]);
  129. if (currentindex != -1) {
  130. let roleBg = this.roleBgList[currentindex].getChildByName("roleGray");
  131. roleBg.getComponent(Sprite).spriteFrame = img;
  132. roleBg.active = true;
  133. }
  134. this.startMove = true;
  135. }
  136. }
  137. private async onTouchEnd(e: EventTouch) {
  138. if (this.currentTouchId != e.touch.getID() || WindowManager.getWindowList().length > 0) {
  139. return;
  140. }
  141. this.currentTouchId = -1;
  142. if (this.currentRole) {
  143. if (this.isMoveIn) {//出售
  144. await WindowManager.open("Prefabs/Windows/SellGeneralWindow", WindowOpenMode.CloseAndAdd, { index: this.currentRoleIndex, lv: this.currentRole.generalLv, generalName: this.currentRole.generalBaseData.name });
  145. g.gameData.isMoveing = false;
  146. } else {
  147. this.targetRole = this.findRole(e.getUILocation());
  148. if (this.targetRole) {//目标位置有角色判断能否合与
  149. if (this.currentRole.generalBaseData.lv == this.targetRole.generalBaseData.lv) {//可以合成
  150. await this.promotionRole();
  151. } else {//不可合成,互换位置
  152. let temp = this.targetRole.node.worldPosition.clone();
  153. this.targetRole.node.worldPosition = this.beginRoleWorldPosition;
  154. this.currentRole.node.worldPosition = temp;
  155. let Temprole = this.roles[this.currentRoleIndex];
  156. this.roles[this.currentRoleIndex] = this.roles[this.targetRoleIndex];
  157. this.roles[this.targetRoleIndex] = Temprole;
  158. g.gameData.updateLocalGeneral(this.currentRoleIndex, this.targetRoleIndex);
  159. this.currentRoleIndex = -1;
  160. this.targetRoleIndex = -1;
  161. g.gameData.isMoveing = false;
  162. }
  163. } else {//没有目标角色则移动位置
  164. let roleBg = this.findNode(e.getUILocation());
  165. if (roleBg) {
  166. this.currentRole.node.position = roleBg.position;
  167. this.roles[this.targetRoleIndex] = this.roles[this.currentRoleIndex];
  168. this.rolesData[this.targetRoleIndex] = true;
  169. this.roles[this.currentRoleIndex] = null;
  170. this.rolesData[this.currentRoleIndex] = false;
  171. g.gameData.updateLocalGeneral(this.currentRoleIndex, this.targetRoleIndex);
  172. } else {
  173. this.currentRole.node.worldPosition = this.beginRoleWorldPosition;
  174. }
  175. g.gameData.isMoveing = false;
  176. this.currentRoleIndex = -1;
  177. this.targetRoleIndex = -1;
  178. }
  179. }
  180. this.onCanSell.emit([]);
  181. }
  182. }
  183. private onTouchMove(e: EventTouch) {
  184. if (WindowManager.getWindowList().length) {
  185. if (this.currentRole) {
  186. this.generalReset();
  187. return;
  188. }
  189. }
  190. if (this.currentTouchId != e.touch.getID()) {
  191. return;
  192. }
  193. if (this.currentRole) {
  194. if (this.startMove) {
  195. this.startMove = false;
  196. this.onCanSell.emit([1]);
  197. }
  198. this.currentRole.node.worldPosition = this.beginRoleWorldPosition.clone().add(GeometryUtils.V2ToV3(e.getUILocation().subtract(this.beginTouchPoint)));
  199. if (this.changeMoveToSell(e)) {
  200. if (!this.isMoveIn) {
  201. this.onCanSell.emit([2]);
  202. }
  203. this.isMoveIn = true;
  204. } else {
  205. if (this.isMoveIn) {
  206. this.onCanSell.emit([1]);
  207. }
  208. this.isMoveIn = false;
  209. }
  210. }
  211. }
  212. private findRole(point: Vec2) {
  213. for (let i = 0; i < this.roles.length; i++) {
  214. const role = this.roles[i];
  215. if (role && role.node.getComponent(UITransform) && role.node.getComponent(UITransform).isHit(point)) {
  216. if (role != this.currentRole) {
  217. if (this.currentRole) {
  218. this.targetRoleIndex = i;
  219. } else {
  220. this.currentRoleIndex = i;
  221. }
  222. return role;
  223. }
  224. }
  225. }
  226. return null;
  227. }
  228. private findNode(point: Vec2) {
  229. for (let i = 0; i < this.roleBgList.length; i++) {
  230. const node = this.roleBgList[i];
  231. if (node && node.getComponent(UITransform).isHit(point) && this.currentRoleIndex != i) {
  232. this.targetRoleIndex = i;
  233. return node;
  234. }
  235. }
  236. return null;
  237. }
  238. /**
  239. * 检测是否移动到出售按钮
  240. **/
  241. private changeMoveToSell(e: EventTouch) {
  242. // let offX = this.currentRole.node.position.x + this.currentRole.getComponent("roleImg").node.getComponent(UITransform).width + e.getLocationX();
  243. // let offY = this.currentRole.node.position.y + this.currentRole.getComponent("roleImg").node.getComponent(UITransform).height + e.getLocationY();
  244. // this.currentRole.getbo
  245. // if (this.sellButton.getComponent(UITransform).isHit(new Vec2(offX, offY))) {
  246. if (this.sellButton.getComponent(UITransform).isHit(e.getUILocation())) {
  247. return true;
  248. }
  249. return false;
  250. }
  251. /**
  252. * 神将合成
  253. */
  254. public async promotionRole() {
  255. if (ConfigData.configMap.get("systemConfig").maxMixLv <= this.currentRole.generalBaseData.lv) {
  256. WindowManager.showTips("合成失败");
  257. this.generalReset();
  258. return;
  259. }
  260. let result = await this.http.send("/api/general/GeneralMix", { generalLv: this.currentRole.generalBaseData.lv });
  261. if (!result.code) {
  262. if (!result.data) {
  263. this.generalReset();
  264. }
  265. else {
  266. g.gameData.buyLv = result.data.buyLv;
  267. g.gameData.buyPrice = result.data.buyPrice;
  268. g.userData.money = result.data.newMoney;
  269. // g.userData.moneyPower10 = result.data.newMoneyPower10;
  270. g.userData.lv = (result.data.generalLv + 1) > g.userData.lv ? result.data.generalLv + 1 : g.userData.lv;
  271. this.deleteRole(this.currentRole, this.currentRoleIndex, result.data.generalLv);
  272. this.currentRoleIndex = -1;
  273. this.deleteRole(this.targetRole, this.targetRoleIndex, result.data.generalLv, createType.Mix);
  274. this.createRole({ lv: result.data.generalLv + 1, index: this.targetRoleIndex, type: createType.Mix });
  275. g.gameData.isMoveing = false;
  276. g.gameData.openRecommend && this.checkMixRedPacket();
  277. }
  278. } else {
  279. this.generalReset();
  280. if (result.code == 105) {
  281. g.gameData.needSyncMoney = true;
  282. } else {
  283. WindowManager.showTips(g.CodeMsg[result.code]);
  284. }
  285. }
  286. }
  287. private generalReset() {
  288. if (this.currentRole) {
  289. this.currentRole.node.worldPosition = this.beginRoleWorldPosition;
  290. g.gameData.isMoveing = false;
  291. this.currentRoleIndex = -1;
  292. this.targetRoleIndex = -1;
  293. }
  294. }
  295. /**
  296. * 创建新角色
  297. * @param data 角色数据
  298. * @returns
  299. */
  300. public async createRole(data) {
  301. let index = data.index == - 1 ? this.getFreeIndex() : data.index;//如果是合成创建有固定位置,购买或增送按顺序排列
  302. this.rolesData[index] = true;
  303. g.gameData.addMyLocalGenral(index, data.lv);
  304. let preFabsData = await ResourcesUtils.load<Prefab>(this.rolePrefabPath, null, this.node);
  305. let targetPosition = this.roleBgList[index].position;
  306. var roleNode = instantiate(preFabsData);
  307. let role = roleNode.getComponent(Role);
  308. role.setData(data);
  309. this.roles[index] = role;
  310. roleNode.parent = this.roleGroup;
  311. if (data.type == createType.Start) {
  312. roleNode.position = new Vec3(targetPosition.x, targetPosition.y, 0);
  313. this.scheduleOnce(() => {
  314. roleNode.getComponent(Role).play();
  315. }, Math.random());
  316. return;
  317. } else if (data.type == createType.Buy) {
  318. roleNode.setPosition(this.beginPosition());
  319. roleNode.setScale(new Vec3(0.3, 0.3, 0.3));
  320. this.playBuyEffect(roleNode, new Vec3(targetPosition.x, targetPosition.y, 0));
  321. } else if (data.type == createType.Mix) {//合成
  322. roleNode.setScale(new Vec3(0.3, 0.3, 0.3));
  323. roleNode.position = new Vec3(targetPosition.x, targetPosition.y, 0);
  324. this.playMixEffect(roleNode);
  325. this.checkNowRole();
  326. } else if (data.type == createType.Reward) {//播放特效
  327. roleNode.position = new Vec3(targetPosition.x, targetPosition.y, 0);
  328. role.getComponent(Role).playPrize();
  329. this.scheduleOnce(() => {
  330. this.checkNowRole();
  331. }, 0.8);
  332. }
  333. }
  334. private playBuyEffect(role: Node, v3: Vec3) {
  335. tween(role).to(0.2, { position: v3, scale: new Vec3(1, 1, 1) }).call(() => {
  336. g.gameData.isBuying = false;
  337. role.getComponent(Role).play();
  338. }).start();
  339. }
  340. private playMixEffect(role: Node) {
  341. tween(role).to(0.2, { scale: new Vec3(1, 1, 1) }).call(() => {
  342. this.targetRoleIndex = -1;
  343. role.getComponent(Role).play();
  344. }).start();
  345. }
  346. private async deleteRole(role: Role, index: number, lv: number, type: number = -1) {
  347. if (role) {
  348. if (role.generalLv == lv) {
  349. g.gameData.deleteMyLocalGenral(index, lv);
  350. this.roleGroup.removeChild(role.node);
  351. role.destroy();
  352. if (type != createType.Mix) {
  353. this.roles[index] = null;
  354. this.rolesData[index] = false;
  355. }
  356. } else {
  357. WindowManager.showTips("数据异常");
  358. }
  359. }
  360. }
  361. public onAttackLoss(generals: Array<number>) {
  362. for (let j = 0; j < this.roles.length; j++) {//优先删除显示的神将
  363. if (this.roles[j] && generals.indexOf(this.roles[j].generalLv) != -1) {
  364. generals.splice(generals.indexOf(this.roles[j].generalLv), 1);
  365. this.deleteRole(this.roles[j], j, this.roles[j].generalLv);
  366. }
  367. }
  368. for (let i = 0; i < generals.length; i++) {//删除未显示的神将
  369. g.gameData.deleteMyLocalGenral(-1, generals[i]);
  370. }
  371. g.gameData.saveLocalData();
  372. }
  373. /**
  374. * 创建角色初始坐标
  375. * @returns
  376. */
  377. private beginPosition(): Vec3 {
  378. let transFrom = this.roleGroup.getComponent(UITransform);
  379. let clampX = 0;
  380. let clampY = this.roleGroup.getPosition().y + transFrom.height - 200;
  381. return new Vec3(clampX, -clampY, 0);
  382. }
  383. /**获取空位索引 */
  384. private getFreeIndex(): number {
  385. for (let i = 0; i < this.rolesData.length; i++) {
  386. if (!this.rolesData[i] && i != this.targetRoleIndex) {
  387. return i;
  388. }
  389. }
  390. return -1;
  391. }
  392. /**当前选中的位置索引 */
  393. private get currentRoleIndex(): number {
  394. return this._currentRoleIndex;
  395. }
  396. /**当前选中的位置索引 */
  397. private set currentRoleIndex(value: number) {
  398. if (value == -1) {
  399. this.currentRole = null;
  400. if (this._currentRoleIndex != -1) {
  401. this.roleBgList[this._currentRoleIndex].getChildByName("roleGray").active = false;
  402. }
  403. if (this.targetRoleIndex != -1) {
  404. this.roleBgList[this.targetRoleIndex].getChildByName("roleGray").active = false;
  405. }
  406. } else {
  407. this.roleBgList[value].getChildByName("roleGray").active = true;
  408. }
  409. this._currentRoleIndex = value;
  410. }
  411. /**检测未显示的神将 */
  412. private checkNowRole() {
  413. let generals = g.gameData.getMyLocalData(g.userData.id).myLocalGenerals;
  414. for (let i = 0; i < generals.length; i++) {
  415. let targetIndex = this.getFreeIndex();
  416. let index = generals[i].index;
  417. let lv = generals[i].generalLv;
  418. if (targetIndex == -1) {
  419. return;
  420. }
  421. if (generals[i].index == -1) {
  422. g.gameData.deleteMyLocalGenral(index, lv);
  423. g.gameData.isPlayPrizeRoleAnim = true;
  424. this.createRole({ index: targetIndex, lv: lv, type: createType.Reward });
  425. return;
  426. }
  427. }
  428. }
  429. private myRandom: Random;
  430. private checkMixRedPacket() {
  431. this.myRandom || (this.myRandom = (new Random(null)));
  432. if (this.myRandom.value <= 0.2) {
  433. WindowManager.open('Prefabs/Each/MixRedPacket', WindowOpenMode.NotCloseAndAdd);
  434. }
  435. }
  436. }
  437. /**购买,合成,初始 ,奖励*/
  438. export enum createType {
  439. Buy,
  440. Mix,
  441. Start,
  442. Reward
  443. }