Kaynağa Gözat

Factor out screen manager from main controller

Thomas Dy 7 yıl önce
ebeveyn
işleme
92e76fa3aa
5 değiştirilmiş dosya ile 94 ekleme ve 64 silme
  1. 19 32
      src/game.ts
  2. 43 0
      src/game/common.ts
  3. 15 16
      src/game/loading.ts
  4. 8 9
      src/game/select.ts
  5. 9 7
      src/game/typing.ts

+ 19 - 32
src/game.ts

@@ -1,32 +1,29 @@
-/// <reference path="level.ts" />
 /// <reference path="audio.ts" />
 /// <reference path="background.ts" />
-/// <reference path="util.ts" />
+/// <reference path="game/common.ts" />
 /// <reference path="game/loading.ts" />
 
 namespace game {
-  interface GameSounds {
-    selectSound: audio.Track,
-    decideSound: audio.Track
-  }
+  export class MainController extends ScreenManager {
+    loadingScreen: Screen;
 
-  export interface Screen {
-    readonly name: string;
-    handleInput(key: string): void;
-    enter(): void;
-    exit(): void;
-  }
+    constructor(container: HTMLElement, configUrl: string) {
+      super(container);
 
-  export class MainController {
-    config: level.Config | null;
-    audioManager: audio.AudioManager;
-    bgManager: background.BackgroundManager;
-    assets: GameSounds | null;
-    activeScreen: Screen | null = null;
+      let self = this;
+      let bgLayer: HTMLElement = container.querySelector('#background');
+      let gameContext: GameContext = {
+        container: container,
+        audioManager: new audio.AudioManager(),
+        bgManager: new background.BackgroundManager(bgLayer),
+        assets: null,
+        config: null,
+        switchScreen(screen: Screen): void {
+          self.switchScreen(screen);
+        }
+      }
 
-    constructor(readonly container: HTMLElement, readonly configUrl: string) {
-      this.audioManager = new audio.AudioManager();
-      this.bgManager = new background.BackgroundManager(container.querySelector('#background'));
+      this.loadingScreen = new LoadingScreen(gameContext, configUrl);
 
       document.addEventListener('keydown', (event) => {
         if (!event.ctrlKey && !event.metaKey) {
@@ -35,18 +32,8 @@ namespace game {
       });
     }
 
-    switchScreen(nextScreen: Screen): void {
-      if (this.activeScreen != null) {
-        this.container.classList.remove(this.activeScreen.name);
-        this.activeScreen.exit();
-      }
-      this.activeScreen = nextScreen;
-      this.activeScreen.enter();
-      this.container.classList.add(this.activeScreen.name);
-    }
-
     start(): void {
-      this.switchScreen(new LoadingScreen(this));
+      this.switchScreen(this.loadingScreen);
     }
   }
 }

+ 43 - 0
src/game/common.ts

@@ -0,0 +1,43 @@
+/// <reference path="../audio.ts" />
+/// <reference path="../background.ts" />
+/// <reference path="../level.ts" />
+
+namespace game {
+  export interface Screen {
+    readonly name: string;
+    handleInput(key: string): void;
+    enter(): void;
+    exit(): void;
+  }
+
+  export class ScreenManager {
+    activeScreen: Screen | null = null;
+
+    constructor(readonly container: HTMLElement) {}
+
+    switchScreen(nextScreen: Screen): void {
+      if (this.activeScreen != null) {
+        this.container.classList.remove(this.activeScreen.name);
+        this.activeScreen.exit();
+      }
+      this.activeScreen = nextScreen;
+      this.activeScreen.enter();
+      this.container.classList.add(this.activeScreen.name);
+    }
+  }
+
+  interface GameSounds {
+    selectSound: audio.Track,
+    decideSound: audio.Track
+  }
+
+  export interface GameContext {
+    container: HTMLElement;
+    audioManager: audio.AudioManager;
+    bgManager: background.BackgroundManager;
+    assets: GameSounds | null;
+    config: level.Config | null;
+
+    switchScreen(screen: Screen): void;
+  }
+}

+ 15 - 16
src/game/loading.ts

@@ -1,29 +1,28 @@
 /// <reference path="select.ts" />
-/// <reference path="../game.ts" />
+/// <reference path="common.ts" />
 
 namespace game {
   export class LoadingScreen implements Screen {
     readonly name: string = 'loading';
 
-    constructor(private controller: MainController) {}
+    constructor(private context: GameContext, private configUrl: string) {}
 
     enter(): void {
       console.log('Loading assets...');
-      let configUrl = this.controller.configUrl;
       let configPromise;
-      if (configUrl.endsWith('.json')) {
-        configPromise = level.loadFromJson(configUrl);
+      if (this.configUrl.endsWith('.json')) {
+        configPromise = level.loadFromJson(this.configUrl);
       } else {
-        configPromise = level.loadFromTM(configUrl);
+        configPromise = level.loadFromTM(this.configUrl);
       }
       configPromise.then(config => {
-        this.controller.config = config;
+        this.context.config = config;
         this.loadAssets();
       })
     }
 
     loadAssets(): void {
-      let config = this.controller.config;
+      let config = this.context.config;
 
       Promise.all([
         this.loadImage(config.background),
@@ -32,7 +31,7 @@ namespace game {
       ]).then(v => {
         console.log('Loaded assets.');
         let [background, selectSound, decideSound] = v;
-        this.controller.assets = {
+        this.context.assets = {
           selectSound,
           decideSound
         }
@@ -41,8 +40,8 @@ namespace game {
     }
 
     finishLoading(): void {
-      this.controller.bgManager.setBackground(this.controller.config.background);
-      let loadingElement = this.controller.container.querySelector('#loading');
+      this.context.bgManager.setBackground(this.context.config.background);
+      let loadingElement = this.context.container.querySelector('#loading');
       loadingElement.addEventListener('transitionend', (event) => this.switchToSelect());
       loadingElement.classList.add('finished');
     }
@@ -51,7 +50,7 @@ namespace game {
       if (url == null) {
         return Promise.resolve(null);
       } else {
-        return this.controller.audioManager.loadTrack(url);
+        return this.context.audioManager.loadTrack(url);
       }
     }
 
@@ -68,15 +67,15 @@ namespace game {
     }
 
     switchToSelect(): void {
-      let selectScreen = new SelectScreen(this.controller);
-      this.controller.switchScreen(selectScreen);
+      let selectScreen = new SelectScreen(this.context);
+      this.context.switchScreen(selectScreen);
     }
 
     handleInput(key: string): void {}
 
     exit(): void {
-      let config = this.controller.config;
-      let containerStyle = this.controller.container.style;
+      let config = this.context.config;
+      let containerStyle = this.context.container.style;
       containerStyle.setProperty('--base-color', config.baseColor);
       containerStyle.setProperty('--highlight-color', config.highlightColor);
     }

+ 8 - 9
src/game/select.ts

@@ -1,5 +1,5 @@
+/// <reference path="common.ts" />
 /// <reference path="typing.ts" />
-/// <reference path="../game.ts" />
 /// <reference path="../util.ts" />
 
 namespace game {
@@ -14,7 +14,7 @@ namespace game {
     init: boolean;
 
     get levelSets() {
-      return this.controller.config.levelSets;
+      return this.context.config.levelSets;
     }
 
     get currentLevelSet() {
@@ -25,9 +25,8 @@ namespace game {
       return this.listControllers[this.currentFolderIndex];
     }
 
-    constructor(private controller: MainController) {
-      this.controller = controller;
-      let container = controller.container;
+    constructor(private context: GameContext) {
+      let container = context.container;
       this.folderInfo = container.querySelector('#folder-info');
       this.songInfo = container.querySelector('#song-info');
       this.songList = container.querySelector('#song-list');
@@ -64,7 +63,7 @@ namespace game {
 
     selectSong(index: number): void {
       if (!this.init) {
-        this.controller.assets.selectSound.play();
+        this.context.assets.selectSound.play();
       }
       let songInfoComponent = new SongInfoComponent(this.currentLevelSet.levels[index]);
       util.clearChildren(this.songInfo);
@@ -72,10 +71,10 @@ namespace game {
     }
 
     chooseSong(index: number): void {
-      this.controller.assets.decideSound.play();
+      this.context.assets.decideSound.play();
       let level = this.currentLevelSet.levels[index];
-      let gameScreen = new game.TypingScreen(this.controller, level, this);
-      this.controller.switchScreen(gameScreen);
+      let gameScreen = new game.TypingScreen(this.context, level, this);
+      this.context.switchScreen(gameScreen);
     }
 
     selectLevelSet(index: number): void {

+ 9 - 7
src/game/typing.ts

@@ -1,23 +1,25 @@
 /// <reference path="../display.ts" />
-/// <reference path="../game.ts" />
+/// <reference path="common.ts" />
 
 namespace game {
   import Level = level.Level;
 
-  export class TypingScreen implements Screen {
+  export class TypingScreen extends ScreenManager implements Screen {
     readonly name: string = 'game';
     gameController: display.LevelController;
 
     constructor(
-      readonly controller: MainController,
+      readonly context: GameContext,
       readonly level: Level,
       readonly prevScreen: Screen
-    ) {}
+    ) {
+      super(context.container);
+    }
 
     enter(): void {
-      let gameContainer = this.controller.container.querySelector('#game');
+      let gameContainer = this.context.container.querySelector('#game');
       util.clearChildren(gameContainer);
-      this.gameController = new display.LevelController(this.controller.audioManager, this.level);
+      this.gameController = new display.LevelController(this.context.audioManager, this.level);
       gameContainer.appendChild(this.gameController.element);
     }
 
@@ -30,7 +32,7 @@ namespace game {
     }
 
     returnToSelect(): void {
-      this.controller.switchScreen(this.prevScreen);
+      this.context.switchScreen(this.prevScreen);
     }
 
     exit(): void {