SongSelector.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. // import PrefabManager from '../Manager/core/PrefabManager';
  2. import { EventType, ObserverManager } from '../Manager/core/EventManager';
  3. import PrefabManager from '../Manager/core/PrefabManager';
  4. import { UIID } from '../Manager/core/UIID';
  5. import CCUtils from '../Utiles/CCUtils';
  6. import Utiles from '../Utiles/Utiles';
  7. const { ccclass, property } = cc._decorator;
  8. @ccclass
  9. export default class SongSelector extends cc.Component {
  10. @property(cc.Prefab)
  11. itemPrefab: cc.Prefab = null;
  12. @property(cc.Node)
  13. content: cc.Node = null;
  14. /** 歌曲个数 可自定义 */
  15. private _itemCount: number = 25;
  16. /** 角度 */
  17. private commonAngle: number = 0;
  18. // 存储所有滚动元素的数组
  19. private items: cc.Node[] = [];
  20. /** 平均每首歌曲的弧度 */
  21. private _rAngle: number = 45;
  22. /** 圆的半径 */
  23. private r: number = 0;
  24. /** 圆的中心点在哪里 */
  25. private _circle: cc.Vec2 = cc.v2(0, 0);
  26. /** 当前显示在中心区域的元素下标 */
  27. private tempIndex: number = 0;
  28. /** 触摸层 */
  29. private touchLayer: cc.Node = null;
  30. /** 记录开始滑动坐标 */
  31. private _BeganPos: cc.Vec2 = cc.v2(0, 0);
  32. /** 最后滑动坐标 */
  33. private _lastpos: cc.Vec2 = cc.v2(0, 0);
  34. /** 是否在滑动 */
  35. private _cartouch: boolean = false;
  36. private _down: boolean = false;
  37. /** 避免滑动过程中,点击进入游戏 */
  38. private _clickTouch: boolean = true;
  39. private _recentcardi: number = 0;
  40. /** 选中时,容错范围 */
  41. private faultPx: number = 20;
  42. protected onLoad(): void {
  43. this.setLinsten();
  44. this.initList();
  45. }
  46. protected onEnable(): void {
  47. this.node.opacity = 255;
  48. this.schedule(this.updateMusicIconScale);
  49. }
  50. protected onDisable(): void {
  51. // 取消歌曲ICON缩放帧事件
  52. this.unschedule(this.updateMusicIconScale);
  53. }
  54. /**
  55. * 监听触摸层
  56. *
  57. * @private
  58. * @memberof SongSelector
  59. */
  60. private setLinsten(): void {
  61. this.touchLayer = CCUtils.findChild(this.content, 'touchLayer');
  62. this.touchLayer.on(cc.Node.EventType.TOUCH_START, this.onTouchBegan.bind(this), this);
  63. this.touchLayer.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMoved.bind(this), this);
  64. this.touchLayer.on(cc.Node.EventType.TOUCH_END, this.onTouchEnded.bind(this), this);
  65. this.touchLayer.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnded.bind(this), this);
  66. }
  67. private initList(): void {
  68. this.commonAngle = 360 / this._itemCount;
  69. this.r = this._rAngle * this._itemCount;
  70. this.faultPx = 31 - this._itemCount;
  71. // this.r = 900;
  72. /** 圆的半径偏左 50px*/
  73. this._circle.x = (this.r - 50) * -1;
  74. for (let i: number = 0; i < this._itemCount; i++) {
  75. let item: cc.Node = cc.instantiate(this.itemPrefab);
  76. item.parent = this.content;
  77. CCUtils.getLabel(item, 'label').string = i.toString();
  78. item.attr({ ao: i * this.commonAngle });
  79. this.items.push(item);
  80. item.setPosition(this.anglePos(item['ao']));
  81. }
  82. CCUtils.findChild(this.items[0], 'btn').runAction(cc.repeatForever(cc.rotateBy(12.0, 360)));
  83. }
  84. /**
  85. * 根据角度返回坐标
  86. * @param {*} angle 度数
  87. */
  88. private anglePos(angle: number): cc.Vec2 {
  89. var r = this.r;
  90. var x0 = this._circle.x;
  91. var y0 = this._circle.y;
  92. var ao = angle;
  93. var x1 = x0 + r * Math.cos((ao * 3.14) / 180);
  94. var y1 = y0 + r * Math.sin((ao * 3.14) / 180);
  95. return cc.v2(x1, y1);
  96. }
  97. /**
  98. * 检测歌曲是否在中心区域,自动缩放
  99. *
  100. * @param {*} dt
  101. * @memberof SongSelector
  102. */
  103. updateMusicIconScale(dt): void {
  104. for (let i: number = 0; i < this._itemCount; i++) {
  105. const music: cc.Node = this.items[i];
  106. const posy: number = music.y;
  107. /** 为什么是-25,我也忘记了 */
  108. var offesty = Math.abs(posy - 25);
  109. /** 估计140也是需要调的 */
  110. if (offesty < 140) {
  111. this.tempIndex = i;
  112. music.opacity = 255;
  113. music.setScale(1.2 - (offesty / 140) * 0.55);
  114. // TODO: 设置模式
  115. // Module.difficulty = Module.selectGateDifficulty[Module._recentcardi];
  116. } else {
  117. music.opacity = 150;
  118. music.setScale(0.5);
  119. }
  120. }
  121. }
  122. /**
  123. * 触摸开始
  124. *
  125. * @param {*} event
  126. * @return {*}
  127. * @memberof SongSelector
  128. */
  129. private onTouchBegan(event: any): void {
  130. // console.log("---start: " , this.gameFlag);
  131. const position: cc.Vec2 = event.getLocation();
  132. this._cartouch = true;
  133. this._down = true;
  134. this._lastpos = cc.v2(position.x, position.y);
  135. this._BeganPos = cc.v2(position.x, position.y);
  136. }
  137. /**
  138. *
  139. *
  140. * @private
  141. * @param {*} event
  142. * @return {*} {void}
  143. * @memberof SongSelector
  144. */
  145. private onTouchMoved(event: any): void {
  146. // console.log("---onTouchMoved---: " , this._down);
  147. if (!this._down) {
  148. event.stopPropagation();
  149. return;
  150. }
  151. var position = event.getLocation();
  152. if (position.x + position.y == this._lastpos.x + this._lastpos.y) {
  153. return;
  154. }
  155. this._clickTouch = false;
  156. var offesty = position.y - this._lastpos.y;
  157. // this.carPositionOff(0, offesty*1.3);
  158. this.musicPositionOff(offesty * 0.2);
  159. this._lastpos = position;
  160. }
  161. private updateUIColor(rgb: cc.Color): void {
  162. console.warn('===rgb==', rgb);
  163. this.updateColorAction(CCUtils.findChild(this.node.parent, 'bg') , rgb);
  164. this.updateColorAction(CCUtils.findChild(this.node.parent, 'headLayer') , rgb);
  165. }
  166. private updateColorAction(node: cc.Node , rgb: cc.Color): void {
  167. node.stopAllActions();
  168. cc.tween(node)
  169. .to(0.5, { color: rgb })
  170. .start();
  171. }
  172. /**
  173. * 滑动结束
  174. *
  175. * @private
  176. * @param {*} event
  177. * @return {*} {void}
  178. * @memberof SongSelector
  179. */
  180. private onTouchEnded(event: any): void {
  181. var position = event.getLocation();
  182. /** 是否点击组件内 */
  183. if (!this.touchMusic(event)) {
  184. const rgb: cc.Color = cc.color(Utiles.random(100, 255), Utiles.random(100, 255), Utiles.random(100, 255));
  185. this.updateUIColor(rgb);
  186. //点击直接切换到该歌曲
  187. if (position.x + position.y == this._BeganPos.x + this._BeganPos.y) {
  188. var node = this.items[this.getId(this._recentcardi + 1)];
  189. var node2 = this.items[this.getId(this._recentcardi - 1)];
  190. var node3 = this.items[this.getId(this._recentcardi + 2)];
  191. var node4 = this.items[this.getId(this._recentcardi - 2)];
  192. console.log('node: ', node);
  193. if (this.rectContainsPoint(node.getBoundingBoxToWorld(), event.getLocation())) {
  194. this.musicPositionOff(-150 * 0.2);
  195. } else if (this.rectContainsPoint(node2.getBoundingBoxToWorld(), event.getLocation())) {
  196. this.musicPositionOff(150 * 0.2);
  197. } else if (this.rectContainsPoint(node3.getBoundingBoxToWorld(), event.getLocation())) {
  198. this.musicPositionOff(-300 * 0.2);
  199. } else if (this.rectContainsPoint(node4.getBoundingBoxToWorld(), event.getLocation())) {
  200. this.musicPositionOff(300 * 0.2);
  201. } else {
  202. return;
  203. }
  204. }
  205. // this._lastpos=position;
  206. if (!this._down) {
  207. event.stopPropagation();
  208. return;
  209. }
  210. this._clickTouch = true;
  211. this._down = false;
  212. // this.carPostionSure();
  213. this.musicMoveToChange();
  214. }
  215. }
  216. /**
  217. * 是否点击歌曲在组件内
  218. *
  219. * @private
  220. * @param {*} event
  221. * @return {*} {void}
  222. * @memberof SongSelector
  223. */
  224. private touchMusic(event: any): boolean {
  225. if (this._clickTouch) {
  226. var node = this.items[this._recentcardi];
  227. if (this.rectContainsPoint(node.getBoundingBoxToWorld(), event.getLocation())) {
  228. // 点击在组件内的操作
  229. console.log('选中歌曲: ', this._recentcardi);
  230. this.intoGameMain(this._recentcardi);
  231. return true;
  232. }
  233. }
  234. return false;
  235. }
  236. /**
  237. * 进入游戏核心玩法
  238. *
  239. * @private
  240. * @memberof SongSelector
  241. */
  242. private intoGameMain(index: number): void {
  243. cc.tween(this.node).to(0.5, { opacity: 50 }).call((): void => {
  244. PrefabManager.close(this.node);
  245. ObserverManager.notify(EventType.OpenGame, { index: this._recentcardi });
  246. }).start();
  247. }
  248. /**
  249. * 获取歌曲id
  250. *
  251. * @private
  252. * @type {function(number)}
  253. * @memberof SongSelector
  254. */
  255. private getId(number: number): number {
  256. if (number > this._itemCount - 1) number = 0;
  257. if (number < 0) number = this._itemCount - 1;
  258. return number;
  259. }
  260. /**
  261. * 滑动选择歌曲
  262. *
  263. * @private
  264. * @param {*} val
  265. * @memberof SongSelector
  266. */
  267. private musicPositionOff(val: any): void {
  268. for (let i: number = 0; i < this.items.length; i++) {
  269. this.items[i]['ao'] += val;
  270. if (this.items[i]['ao'] < 0) this.items[i]['ao'] += 360;
  271. if (this.items[i]['ao'] > 360) this.items[i]['ao'] -= 360;
  272. this.items[i].setPosition(this.anglePos(this.items[i]['ao']));
  273. }
  274. }
  275. /**
  276. * 判定范围
  277. *
  278. * @private
  279. * @param {*} c
  280. * @param {*} t
  281. * @return {*} {*}
  282. * @memberof SongSelector
  283. */
  284. private rectContainsPoint(c, t): any {
  285. var n = !1;
  286. t.x >= c.x && t.x <= c.x + c.width && t.y >= c.y && t.y <= c.y + c.height && (n = !0);
  287. return n;
  288. }
  289. /**
  290. * 滑动选择
  291. *
  292. * @private
  293. * @memberof SongSelector
  294. */
  295. private musicMoveToChange(): void {
  296. var angle = [];
  297. for (var i = 0; i < this._itemCount + 1; i++) {
  298. angle.push(i * this.commonAngle);
  299. }
  300. var ao = Math.abs(this.items[0]['ao']);
  301. for (var i = 0; i < this.items.length; i++) {
  302. var ao = this.items[i]['ao'];
  303. for (var j = 0; j < angle.length - 1; j++) {
  304. if (Math.abs(ao) >= angle[j] && Math.abs(ao) <= angle[j + 1]) {
  305. var ao2 = 0;
  306. if (angle[j + 1] - Math.abs(ao) < this.faultPx) {
  307. ao2 = angle[j + 1];
  308. } else {
  309. ao2 = angle[j];
  310. }
  311. this.items[i]['ao'] > 0 ? (this.items[i]['ao'] = ao2) : (this.items[i]['ao'] = -ao2);
  312. break;
  313. }
  314. }
  315. }
  316. var lastIndex = this._recentcardi;
  317. for (var i = 0; i < this._itemCount; i++) {
  318. if (this.items[i]['ao'] == 0 || this.items[i]['ao'] == 360) {
  319. this._recentcardi = i;
  320. }
  321. }
  322. // console.log("--this._recentcardi--: " , Module._recentcardi);
  323. var flag = true;
  324. for (var i = 0; i < this._itemCount; i++) {
  325. var item = this.items[i];
  326. var pos = this.anglePos(this.items[i]['ao']);
  327. item.stopAllActions();
  328. var call = cc.callFunc(
  329. function (t, index) {
  330. // var sk = this.items[index].getChildByName("gd").getComponent(sp.Skeleton);
  331. // if (index == this._recentcardi) {
  332. // sk.animation = "01";
  333. // } else {
  334. // sk.animation = "02";
  335. // }
  336. // if (lastIndex != Module._recentcardi && flag) {
  337. // flag =false;
  338. // cc.audioEngine.stopAllEffects();
  339. // Utils.playMusic("sound/soung/audition/"+Module._recentcardi+".mp3",true);
  340. // }
  341. this.unschedule(this.musicScaleUpdate);
  342. },
  343. this,
  344. i
  345. );
  346. var call2 = cc.callFunc(
  347. function (t, index) {
  348. // var sk = this.items[index].getChildByName("gd").getComponent(sp.Skeleton);
  349. // if (sk.animation == "01") sk.animation = "02";
  350. },
  351. this,
  352. i
  353. );
  354. // TODO: 运行动画,暂时还不需要
  355. item.runAction(cc.sequence(cc.moveTo(0.2, pos), call, cc.delayTime(99 / 30), call2));
  356. if (i == this._recentcardi) {
  357. CCUtils.findChild(item, 'btn').runAction(cc.repeatForever(cc.rotateBy(12.0, 360)));
  358. } else {
  359. CCUtils.findChild(item, 'btn').rotation = 0;
  360. CCUtils.findChild(item, 'btn').stopAllActions();
  361. }
  362. }
  363. }
  364. }