select.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /// <reference path="typing.ts" />
  2. /// <reference path="../game.ts" />
  3. /// <reference path="../util.ts" />
  4. namespace game {
  5. export class SelectScreen implements Screen {
  6. readonly name: string = 'select';
  7. folderInfo: HTMLElement;
  8. songInfo: HTMLElement;
  9. songList: HTMLElement;
  10. currentFolderIndex: number;
  11. folderController: FolderSelectController;
  12. listControllers: SongListController[];
  13. init: boolean;
  14. get levelSets() {
  15. return this.controller.config.levelSets;
  16. }
  17. get currentLevelSet() {
  18. return this.levelSets[this.currentFolderIndex];
  19. }
  20. get activeListController() {
  21. return this.listControllers[this.currentFolderIndex];
  22. }
  23. constructor(private controller: MainController) {
  24. this.controller = controller;
  25. let container = controller.container;
  26. this.folderInfo = container.querySelector('#folder-info');
  27. this.songInfo = container.querySelector('#song-info');
  28. this.songList = container.querySelector('#song-list');
  29. this.listControllers = [];
  30. this.levelSets.forEach(levelSet => {
  31. let controller = new SongListController(
  32. levelSet.levels,
  33. (index) => this.selectSong(index),
  34. (index) => this.chooseSong(index)
  35. );
  36. this.listControllers.push(controller);
  37. });
  38. this.init = true;
  39. this.folderController = new FolderSelectController(
  40. this.folderInfo,
  41. this.levelSets,
  42. (index) => this.selectLevelSet(index)
  43. );
  44. this.init = false;
  45. }
  46. enter(): void {
  47. this.folderController.listeners.attach();
  48. }
  49. handleInput(key: string): void {
  50. this.activeListController.handleInput(key);
  51. this.folderController.handleInput(key);
  52. }
  53. selectSong(index: number): void {
  54. if (!this.init) {
  55. this.controller.assets.selectSound.play();
  56. }
  57. let songInfoComponent = new SongInfoComponent(this.currentLevelSet.levels[index]);
  58. util.clearChildren(this.songInfo);
  59. this.songInfo.appendChild(songInfoComponent.element);
  60. }
  61. chooseSong(index: number): void {
  62. this.controller.assets.decideSound.play();
  63. let level = this.currentLevelSet.levels[index];
  64. let gameScreen = new game.TypingScreen(this.controller, level, this);
  65. this.controller.switchScreen(gameScreen);
  66. }
  67. selectLevelSet(index: number): void {
  68. this.currentFolderIndex = index;
  69. util.clearChildren(this.songList);
  70. this.songList.appendChild(this.activeListController.element);
  71. this.selectSong(this.activeListController.currentIndex);
  72. }
  73. exit(): void {
  74. this.folderController.listeners.detach();
  75. }
  76. }
  77. class FolderSelectController {
  78. labelElement: HTMLElement;
  79. levelSets: level.LevelSet[];
  80. currentIndex: number;
  81. onFolderChange: (index: number) => void;
  82. listeners: util.ListenersManager;
  83. constructor(element: HTMLElement, levelSets: level.LevelSet[], onFolderChange: (index: number) => void) {
  84. this.labelElement = element.querySelector('.label');
  85. this.levelSets = levelSets;
  86. this.currentIndex = 0;
  87. this.onFolderChange = onFolderChange;
  88. this.listeners = new util.ListenersManager();
  89. this.listeners.add(
  90. element.querySelector('.left'),
  91. 'click',
  92. () => this.scroll(-1)
  93. );
  94. this.listeners.add(
  95. element.querySelector('.right'),
  96. 'click',
  97. () => this.scroll(1)
  98. );
  99. this.scroll(0);
  100. }
  101. handleInput(key: string): void {
  102. if (key === 'ArrowLeft') {
  103. this.scroll(-1);
  104. } else if (key === 'ArrowRight') {
  105. this.scroll(1);
  106. }
  107. }
  108. scroll(offset: number): void {
  109. this.currentIndex += offset;
  110. while (this.currentIndex < 0) {
  111. this.currentIndex += this.levelSets.length;
  112. }
  113. this.currentIndex %= this.levelSets.length;
  114. this.labelElement.textContent = this.levelSets[this.currentIndex].name;
  115. this.onFolderChange(this.currentIndex);
  116. }
  117. }
  118. class SongInfoComponent {
  119. element: DocumentFragment;
  120. constructor(level: level.Level) {
  121. this.element = util.loadTemplate('song-info');
  122. this.element.querySelector('.genre').textContent = level.genre;
  123. this.element.querySelector('.creator').textContent = level.creator;
  124. this.element.querySelector('.title').textContent = level.name;
  125. }
  126. }
  127. class SongListController {
  128. element: HTMLElement;
  129. levels: level.Level[];
  130. currentIndex: number;
  131. onSongChange: (index: number) => void;
  132. onSongChoose: (index: number) => void;
  133. constructor(
  134. levels: level.Level[],
  135. onSongChange: (index: number) => void,
  136. onSongChoose: (index: number) => void
  137. ) {
  138. this.element = document.createElement('div');
  139. this.levels = levels;
  140. this.currentIndex = 0;
  141. this.onSongChange = onSongChange;
  142. this.onSongChoose = onSongChoose;
  143. this.element.className = 'song-list';
  144. this.element.style.marginTop = '200px';
  145. this.levels.forEach((level, index) => {
  146. let element = util.loadTemplate('song-item');
  147. element.querySelector('.creator').textContent = level.creator;
  148. element.querySelector('.title').textContent = level.name;
  149. element.querySelector('.difficulty').textContent = level.difficulty;
  150. element.querySelector('.song-item').addEventListener('click', (event) => this.click(index));
  151. this.element.appendChild(element);
  152. });
  153. this.element.children[0].classList.add('selected');
  154. }
  155. handleInput(key: string): void {
  156. if (key === 'ArrowUp') {
  157. this.scroll(-1);
  158. } else if (key === 'ArrowDown') {
  159. this.scroll(1);
  160. } else if (key === 'PageUp') {
  161. this.scroll(-5);
  162. } else if (key === 'PageDown') {
  163. this.scroll(5);
  164. } else if (key === ' ') {
  165. this.choose();
  166. }
  167. }
  168. scroll(offset: number) {
  169. let target = this.currentIndex + offset;
  170. target = Math.max(0, Math.min(this.levels.length - 1, target));
  171. this.select(target);
  172. }
  173. click(index: number) {
  174. if (this.currentIndex === index) {
  175. this.choose();
  176. } else {
  177. this.select(index);
  178. }
  179. }
  180. select(index: number) {
  181. if (this.currentIndex === index) return;
  182. let offset = 200 - index * 40;
  183. this.element.style.marginTop = offset+'px';
  184. let nextElement = this.element.children[index] as HTMLElement;
  185. let currElement = this.element.children[this.currentIndex] as HTMLElement;
  186. currElement.classList.remove('selected');
  187. nextElement.classList.add('selected');
  188. this.currentIndex = index;
  189. this.onSongChange(index);
  190. }
  191. choose() {
  192. this.onSongChoose(this.currentIndex);
  193. }
  194. }
  195. }