UNPKG

yukinovel

Version:

Yukinovel is a simple web visual novel engine.

204 lines (203 loc) 8.27 kB
import { MainMenuRenderer } from './ui/MainMenuRenderer.js'; import { DialogueRenderer } from './ui/DialogueRenderer.js'; import { SceneRenderer } from './ui/SceneRenderer.js'; import { ModalRenderer } from './ui/ModalRenderer.js'; import { SaveLoadRenderer } from './ui/SaveLoadRenderer.js'; import { ConfirmModal } from './ui/ConfirmModal.js'; export class UIRenderer { constructor(game) { this.game = game; } render(container) { this.container = container; this.container.id = 'container'; this.container.className = 'vn-container vn-no-select'; this.createUIStructure(); this.initializeRenderers(); this.attachEventListeners(); } createUIStructure() { /** * @description phần Main Menu container * Cha: container gốc */ this.mainMenuContainer = document.createElement('div'); this.mainMenuContainer.id = 'container-menu'; this.mainMenuContainer.className = 'vn-main-menu-container'; this.container.appendChild(this.mainMenuContainer); /** * @description phần Game container * Cha: container gốc */ this.gameContainer = document.createElement('div'); this.gameContainer.id = 'container-game'; this.gameContainer.className = 'vn-game-container'; this.container.appendChild(this.gameContainer); /** * @description phần Background Layer * Cha: gameContainer */ this.backgroundElement = document.createElement('div'); this.backgroundElement.id = 'background-game'; this.backgroundElement.className = 'vn-background'; this.gameContainer.appendChild(this.backgroundElement); /** * @description phần Character layout * Cha: gameContainer */ this.characterContainer = document.createElement('div'); this.characterContainer.id = 'container-character'; this.characterContainer.className = 'vn-character-container'; this.gameContainer.appendChild(this.characterContainer); /** * @description phần UI layer * Cha: gameContainer */ this.uiContainer = document.createElement('div'); this.uiContainer.id = 'container-ui'; this.uiContainer.className = 'vn-ui-container'; this.gameContainer.appendChild(this.uiContainer); /** * @description phần Dialogue container * Cha: uiContainer */ this.dialogueContainer = document.createElement('div'); this.dialogueContainer.id = 'container-dialogue'; this.dialogueContainer.className = 'vn-dialogue-container'; this.uiContainer.appendChild(this.dialogueContainer); /** * @description phần Choices container * Cha: uiContainer */ this.choicesContainer = document.createElement('div'); this.choicesContainer.id = 'container-choices'; this.choicesContainer.className = 'vn-choices-container'; this.uiContainer.appendChild(this.choicesContainer); /** * @description phần Controls container * Cha: uiContainer */ this.controlsContainer = document.createElement('div'); this.controlsContainer.id = 'container-controls'; this.controlsContainer.className = 'vn-controls-container'; this.uiContainer.appendChild(this.controlsContainer); this.createControlButtons(); /** * @description phần Log container * Cha: uiContainer */ this.logContainer = document.createElement('div'); this.logContainer.id = 'container-log'; this.logContainer.className = 'vn-log-container'; this.uiContainer.appendChild(this.logContainer); } initializeRenderers() { this.mainMenuRenderer = new MainMenuRenderer(this.game, this.mainMenuContainer); this.dialogueRenderer = new DialogueRenderer(this.game, this.dialogueContainer, this.choicesContainer); this.sceneRenderer = new SceneRenderer(this.game, this.backgroundElement, this.characterContainer); this.modalRenderer = new ModalRenderer(this.game, this.logContainer); this.saveLoadRenderer = new SaveLoadRenderer(this.game); this.saveLoadRenderer.render(this.container); this.confirmModal = ConfirmModal.getInstance(this.game); this.confirmModal.render(this.container); } createControlButtons() { const langManager = this.game.getLanguageManager(); const controls = [ { key: 'Enter', action: langManager.getText('ui.next'), onClick: () => this.handleNext() }, { key: 'Esc', action: langManager.getText('exit.title', 'Thoát'), onClick: () => this.modalRenderer.showExitConfirm() }, { key: 'S', action: langManager.getText('ui.save'), onClick: () => this.showSavePanel() }, { key: 'L', action: langManager.getText('ui.load'), onClick: () => this.showLoadPanel() }, { key: 'H', action: langManager.getText('ui.history'), onClick: () => this.modalRenderer.toggleLog() } ]; controls.forEach(control => { const controlDiv = document.createElement('div'); controlDiv.className = 'vn-control-item'; controlDiv.onclick = control.onClick; const keyDiv = document.createElement('div'); keyDiv.textContent = control.key; keyDiv.className = 'vn-control-key'; const actionDiv = document.createElement('div'); actionDiv.textContent = control.action; actionDiv.className = 'vn-control-action'; controlDiv.appendChild(keyDiv); controlDiv.appendChild(actionDiv); this.controlsContainer.appendChild(controlDiv); }); } handleNext() { this.dialogueRenderer.handleNext(); } attachEventListeners() { this.dialogueContainer.addEventListener('click', () => { this.handleNext(); }); const gameContainer = document.querySelector('#container-game'); document.addEventListener('keydown', (e) => { if (gameContainer.style.display === 'none') return; if (e.code === 'Space' || e.code === 'Enter') { e.preventDefault(); this.handleNext(); } else if (e.code === 'Escape') { e.preventDefault(); this.modalRenderer.showExitConfirm(); } else if (e.code === 'KeyS') { e.preventDefault(); this.showSavePanel(); } else if (e.code === 'KeyL') { e.preventDefault(); this.showLoadPanel(); } else if (e.code === 'KeyH') { e.preventDefault(); this.modalRenderer.toggleLog(); } }); } showMainMenu() { this.mainMenuRenderer.show(); this.gameContainer.style.display = 'none'; } hideMainMenu() { this.mainMenuRenderer.hide(); this.gameContainer.style.display = 'block'; } updateScene(scene) { this.sceneRenderer.updateScene(scene); } updateSceneWithFade(scene, shouldFadeBackground, backgroundAnimation) { this.sceneRenderer.updateSceneWithFade(scene, shouldFadeBackground, backgroundAnimation); } updateDialogue(dialogue) { this.dialogueRenderer.updateDialogue(dialogue); this.sceneRenderer.updateCharacterSprites(dialogue); } showChoices(choices) { this.dialogueRenderer.showChoices(choices); } getTypewriterSpeed() { return this.dialogueRenderer.getTypewriterSpeed(); } setTypewriterSpeed(speed) { this.dialogueRenderer.setTypewriterSpeed(speed); } getSceneRenderer() { return this.sceneRenderer; } showCredits() { console.log('Credits modal'); } showSavePanel() { this.saveLoadRenderer.showSavePanel(); } showLoadPanel() { this.saveLoadRenderer.showLoadPanel(); } getConfirmModal() { return this.confirmModal; } }