mirror of
https://github.com/tiennm99/nntv.git
synced 2026-10-16 02:15:39 +00:00
feat: localize
This commit is contained in:
1 parent
f766f7e3b8
commit
f7c504219a
8 files changed
+387
-53
No files matched your search
@@ -0,0 +1,174 @@
|
||||
// Localization system for Night Ninja: Twilight Voyage
|
||||
// Supports English and Vietnamese languages
|
||||
|
||||
// Default language is Vietnamese
|
||||
let currentLanguage = 'vi';
|
||||
|
||||
// Text data for all UI elements in the game
|
||||
const localizationData = {
|
||||
// Main Menu
|
||||
'gameTitle': {
|
||||
'en': 'NIGHT NINJA: TWILIGHT VOYAGE',
|
||||
'vi': 'NINJA ĐÊM: HÀNH TRÌNH HOÀNG HÔN'
|
||||
},
|
||||
'startGame': {
|
||||
'en': 'START GAME',
|
||||
'vi': 'BẮT ĐẦU CHƠI'
|
||||
},
|
||||
'levelSelect': {
|
||||
'en': 'LEVEL SELECT',
|
||||
'vi': 'CHỌN CẤP ĐỘ'
|
||||
},
|
||||
'settings': {
|
||||
'en': 'SETTINGS',
|
||||
'vi': 'CÀI ĐẶT'
|
||||
},
|
||||
'gameDescription': {
|
||||
'en': 'Guide the ninja through the shadows.\nAvoid light at all costs.\nRescue the princess... if you can.',
|
||||
'vi': 'Dẫn dắt ninja qua bóng tối.\nTránh ánh sáng bằng mọi giá.\nCứu công chúa... nếu bạn có thể.'
|
||||
},
|
||||
'instructions': {
|
||||
'en': 'Use arrow keys, WASD, or tap to move.',
|
||||
'vi': 'Sử dụng phím mũi tên, WASD, hoặc chạm để di chuyển.'
|
||||
},
|
||||
|
||||
// Settings Menu
|
||||
'languageSettings': {
|
||||
'en': 'Language',
|
||||
'vi': 'Ngôn ngữ'
|
||||
},
|
||||
'english': {
|
||||
'en': 'English',
|
||||
'vi': 'Tiếng Anh'
|
||||
},
|
||||
'vietnamese': {
|
||||
'en': 'Vietnamese',
|
||||
'vi': 'Tiếng Việt'
|
||||
},
|
||||
'back': {
|
||||
'en': 'Back',
|
||||
'vi': 'Quay lại'
|
||||
},
|
||||
|
||||
// Level Select
|
||||
'levelSelectTitle': {
|
||||
'en': 'SELECT LEVEL',
|
||||
'vi': 'CHỌN CẤP ĐỘ'
|
||||
},
|
||||
'levelNumber': {
|
||||
'en': 'Level',
|
||||
'vi': 'Cấp độ'
|
||||
},
|
||||
|
||||
// Game UI
|
||||
'lives': {
|
||||
'en': 'Lives: ',
|
||||
'vi': 'Mạng: '
|
||||
},
|
||||
'level': {
|
||||
'en': 'Level: ',
|
||||
'vi': 'Cấp độ: '
|
||||
},
|
||||
'pause': {
|
||||
'en': 'PAUSE',
|
||||
'vi': 'TẠM DỪNG'
|
||||
},
|
||||
'menu': {
|
||||
'en': 'MENU',
|
||||
'vi': 'MENU'
|
||||
},
|
||||
'paused': {
|
||||
'en': 'PAUSED',
|
||||
'vi': 'TẠM DỪNG'
|
||||
},
|
||||
'resume': {
|
||||
'en': 'RESUME',
|
||||
'vi': 'TIẾP TỤC'
|
||||
},
|
||||
'restartLevel': {
|
||||
'en': 'RESTART LEVEL',
|
||||
'vi': 'CHƠI LẠI CẤP ĐỘ'
|
||||
},
|
||||
'detected': {
|
||||
'en': 'You have been detected!',
|
||||
'vi': 'Bạn đã bị phát hiện!'
|
||||
},
|
||||
'playAgain': {
|
||||
'en': 'PLAY AGAIN',
|
||||
'vi': 'CHƠI LẠI'
|
||||
},
|
||||
'princessDetected': {
|
||||
'en': 'The princess has detected the ninja! The entire palace is lit up!',
|
||||
'vi': 'Công chúa phát hiện ra ninja! Toàn bộ cung điện sáng đèn!'
|
||||
},
|
||||
|
||||
// Game Over
|
||||
'gameOver': {
|
||||
'en': 'GAME OVER',
|
||||
'vi': 'GAME KẾT THÚC'
|
||||
},
|
||||
'theEnd': {
|
||||
'en': 'THE END',
|
||||
'vi': 'KẾT THÚC'
|
||||
},
|
||||
'caughtInLight': {
|
||||
'en': 'You were caught in the light!',
|
||||
'vi': 'Bạn đã bị bắt trong ánh sáng!'
|
||||
},
|
||||
'ninjaFailed': {
|
||||
'en': 'Unfortunately, in this life, the ninja cannot rescue the princess.',
|
||||
'vi': 'Thật tiếc, kiếp này ninja không thể giải cứu công chúa rồi.'
|
||||
},
|
||||
'tryAgain': {
|
||||
'en': 'TRY AGAIN',
|
||||
'vi': 'THỬ LẠI'
|
||||
},
|
||||
'mainMenu': {
|
||||
'en': 'MAIN MENU',
|
||||
'vi': 'MENU CHÍNH'
|
||||
}
|
||||
};
|
||||
|
||||
// Function to get text in the current language
|
||||
function getText(key) {
|
||||
if (localizationData[key] && localizationData[key][currentLanguage]) {
|
||||
return localizationData[key][currentLanguage];
|
||||
}
|
||||
// Fallback to English if the key or language is not found
|
||||
if (localizationData[key] && localizationData[key]['en']) {
|
||||
return localizationData[key]['en'];
|
||||
}
|
||||
// Return the key itself if no translation is found
|
||||
return key;
|
||||
}
|
||||
|
||||
// Function to change the language
|
||||
function setLanguage(language) {
|
||||
if (language === 'en' || language === 'vi') {
|
||||
currentLanguage = language;
|
||||
// Save the language preference to localStorage
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
localStorage.setItem('nntv-language', language);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Function to get the current language
|
||||
function getLanguage() {
|
||||
return currentLanguage;
|
||||
}
|
||||
|
||||
// Initialize language from localStorage if available
|
||||
function initLanguage() {
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
const savedLanguage = localStorage.getItem('nntv-language');
|
||||
if (savedLanguage === 'en' || savedLanguage === 'vi') {
|
||||
currentLanguage = savedLanguage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Export the functions and data
|
||||
export { getText, setLanguage, getLanguage, initLanguage };
|
||||
@@ -1,4 +1,5 @@
|
||||
import Phaser from 'phaser';
|
||||
import { initLanguage } from '../localization';
|
||||
|
||||
export class Boot extends Phaser.Scene {
|
||||
constructor() {
|
||||
@@ -8,6 +9,9 @@ export class Boot extends Phaser.Scene {
|
||||
preload() {
|
||||
// Load any assets needed for the preloader scene
|
||||
// For this game, we don't need any fancy preloader assets
|
||||
|
||||
// Initialize language settings
|
||||
initLanguage();
|
||||
}
|
||||
|
||||
create() {
|
||||
|
||||
+29
-11
@@ -5,6 +5,7 @@ import { TurnManager } from '../objects/TurnManager';
|
||||
import { LightingSystem } from '../objects/LightingSystem';
|
||||
import { StaticGuard, RotatingGuard, BlinkingGuard, PatrollingGuard } from '../objects/Guard';
|
||||
import { LevelManager } from '../levels/LevelManager';
|
||||
import { getText } from '../localization';
|
||||
|
||||
export class Game extends Phaser.Scene {
|
||||
constructor() {
|
||||
@@ -186,13 +187,13 @@ export class Game extends Phaser.Scene {
|
||||
const width = this.cameras.main.width;
|
||||
|
||||
// Lives display
|
||||
this.livesText = this.add.text(20, 20, `Lives: ${this.livesRemaining}`, {
|
||||
this.livesText = this.add.text(20, 20, `${getText('lives')}${this.livesRemaining}`, {
|
||||
font: '18px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
|
||||
// Level display
|
||||
this.levelText = this.add.text(width - 20, 20, `Level: ${this.currentLevel}`, {
|
||||
this.levelText = this.add.text(width - 20, 20, `${getText('level')}${this.currentLevel}`, {
|
||||
font: '18px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
@@ -202,7 +203,7 @@ export class Game extends Phaser.Scene {
|
||||
this.pauseButton = this.add.rectangle(width - 20, 60, 100, 30, 0x444444);
|
||||
this.pauseButton.setOrigin(1, 0);
|
||||
|
||||
this.pauseText = this.add.text(width - 70, 75, 'PAUSE', {
|
||||
this.pauseText = this.add.text(width - 70, 75, getText('pause'), {
|
||||
font: '16px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
@@ -213,6 +214,23 @@ export class Game extends Phaser.Scene {
|
||||
this.togglePause();
|
||||
});
|
||||
|
||||
// Return to Main Menu button
|
||||
this.returnButton = this.add.rectangle(width - 20, 100, 100, 30, 0x444444);
|
||||
this.returnButton.setOrigin(1, 0);
|
||||
|
||||
this.returnText = this.add.text(width - 70, 115, getText('menu'), {
|
||||
font: '16px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
this.returnText.setOrigin(0.5, 0.5);
|
||||
|
||||
this.returnButton.setInteractive({ useHandCursor: true })
|
||||
.on('pointerover', () => this.returnButton.fillColor = 0x666666)
|
||||
.on('pointerout', () => this.returnButton.fillColor = 0x444444)
|
||||
.on('pointerdown', () => {
|
||||
this.scene.start('MainMenu');
|
||||
});
|
||||
|
||||
// Create pause menu (initially hidden)
|
||||
this.createPauseMenu();
|
||||
}
|
||||
@@ -228,7 +246,7 @@ export class Game extends Phaser.Scene {
|
||||
const bg = this.add.rectangle(0, 0, 300, 250, 0x000000, 0.8);
|
||||
|
||||
// Title
|
||||
const title = this.add.text(0, -100, 'PAUSED', {
|
||||
const title = this.add.text(0, -100, getText('paused'), {
|
||||
font: 'bold 32px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
@@ -236,7 +254,7 @@ export class Game extends Phaser.Scene {
|
||||
|
||||
// Resume button
|
||||
const resumeButton = this.add.rectangle(0, -40, 200, 40, 0x444444);
|
||||
const resumeText = this.add.text(0, -40, 'RESUME', {
|
||||
const resumeText = this.add.text(0, -40, getText('resume'), {
|
||||
font: '20px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
@@ -244,7 +262,7 @@ export class Game extends Phaser.Scene {
|
||||
|
||||
// Restart button
|
||||
const restartButton = this.add.rectangle(0, 20, 200, 40, 0x444444);
|
||||
const restartText = this.add.text(0, 20, 'RESTART LEVEL', {
|
||||
const restartText = this.add.text(0, 20, getText('restartLevel'), {
|
||||
font: '20px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
@@ -252,7 +270,7 @@ export class Game extends Phaser.Scene {
|
||||
|
||||
// Main menu button
|
||||
const menuButton = this.add.rectangle(0, 80, 200, 40, 0x444444);
|
||||
const menuText = this.add.text(0, 80, 'MAIN MENU', {
|
||||
const menuText = this.add.text(0, 80, getText('mainMenu'), {
|
||||
font: '20px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
@@ -413,7 +431,7 @@ export class Game extends Phaser.Scene {
|
||||
bg.popup = 'detection'; // Đánh dấu phần tử thuộc về popup
|
||||
|
||||
// Thông báo
|
||||
const title = this.add.text(0, -60, 'Bạn đã bị phát hiện!', {
|
||||
const title = this.add.text(0, -60, getText('detected'), {
|
||||
font: 'bold 28px Arial',
|
||||
fill: '#FF0000'
|
||||
});
|
||||
@@ -424,7 +442,7 @@ export class Game extends Phaser.Scene {
|
||||
const restartButton = this.add.rectangle(0, 20, 200, 40, 0x444444);
|
||||
restartButton.popup = 'detection'; // Đánh dấu phần tử thuộc về popup
|
||||
|
||||
const restartText = this.add.text(0, 20, 'CHƠI LẠI', {
|
||||
const restartText = this.add.text(0, 20, getText('playAgain'), {
|
||||
font: '20px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
@@ -469,7 +487,7 @@ export class Game extends Phaser.Scene {
|
||||
|
||||
// Cập nhật hiển thị số mạng
|
||||
if (this.livesText) {
|
||||
this.livesText.setText(`Lives: ${this.livesRemaining}`);
|
||||
this.livesText.setText(`${getText('lives')}${this.livesRemaining}`);
|
||||
}
|
||||
|
||||
// Đảm bảo tất cả các popup đã được đóng
|
||||
@@ -546,7 +564,7 @@ export class Game extends Phaser.Scene {
|
||||
|
||||
if (!this.finalLevelMessage) {
|
||||
this.finalLevelMessage = this.add.text(width / 2, height / 4,
|
||||
'Công chúa phát hiện ra ninja! Toàn bộ cung điện sáng đèn!', {
|
||||
getText('princessDetected'), {
|
||||
font: 'bold 20px Arial',
|
||||
fill: '#FF0000',
|
||||
backgroundColor: '#000000',
|
||||
|
||||
+15
-14
@@ -1,4 +1,5 @@
|
||||
import Phaser from 'phaser';
|
||||
import { getText } from '../localization';
|
||||
|
||||
export class GameOver extends Phaser.Scene {
|
||||
constructor() {
|
||||
@@ -13,16 +14,16 @@ export class GameOver extends Phaser.Scene {
|
||||
create() {
|
||||
const width = this.cameras.main.width;
|
||||
const height = this.cameras.main.height;
|
||||
|
||||
|
||||
// Different message based on whether this is the final level or not
|
||||
let message = 'GAME OVER';
|
||||
let description = 'You were caught in the light!';
|
||||
|
||||
let message = getText('gameOver');
|
||||
let description = getText('caughtInLight');
|
||||
|
||||
if (this.isLastLevel) {
|
||||
message = 'THE END';
|
||||
description = 'Thật tiếc, kiếp này ninja không thể giải cứu công chúa rồi.';
|
||||
message = getText('theEnd');
|
||||
description = getText('ninjaFailed');
|
||||
}
|
||||
|
||||
|
||||
// Add game over title
|
||||
const title = this.add.text(width / 2, height / 3, message, {
|
||||
font: 'bold 48px Arial',
|
||||
@@ -30,7 +31,7 @@ export class GameOver extends Phaser.Scene {
|
||||
align: 'center'
|
||||
});
|
||||
title.setOrigin(0.5, 0.5);
|
||||
|
||||
|
||||
// Add description
|
||||
const descText = this.add.text(width / 2, height / 2, description, {
|
||||
font: '24px Arial',
|
||||
@@ -38,15 +39,15 @@ export class GameOver extends Phaser.Scene {
|
||||
align: 'center'
|
||||
});
|
||||
descText.setOrigin(0.5, 0.5);
|
||||
|
||||
|
||||
// Add restart button
|
||||
const restartButton = this.add.rectangle(width / 2, height * 0.7, 200, 50, 0x444444);
|
||||
const restartText = this.add.text(width / 2, height * 0.7, 'TRY AGAIN', {
|
||||
const restartText = this.add.text(width / 2, height * 0.7, getText('tryAgain'), {
|
||||
font: '24px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
restartText.setOrigin(0.5, 0.5);
|
||||
|
||||
|
||||
// Make button interactive
|
||||
restartButton.setInteractive({ useHandCursor: true })
|
||||
.on('pointerover', () => restartButton.fillColor = 0x666666)
|
||||
@@ -60,15 +61,15 @@ export class GameOver extends Phaser.Scene {
|
||||
this.scene.start('Game', { level: this.finalLevel, lives: 3 });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Add main menu button
|
||||
const menuButton = this.add.rectangle(width / 2, height * 0.8, 200, 50, 0x444444);
|
||||
const menuText = this.add.text(width / 2, height * 0.8, 'MAIN MENU', {
|
||||
const menuText = this.add.text(width / 2, height * 0.8, getText('mainMenu'), {
|
||||
font: '24px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
menuText.setOrigin(0.5, 0.5);
|
||||
|
||||
|
||||
// Make button interactive
|
||||
menuButton.setInteractive({ useHandCursor: true })
|
||||
.on('pointerover', () => menuButton.fillColor = 0x666666)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Phaser from 'phaser';
|
||||
import { getText } from '../localization';
|
||||
|
||||
export class LevelSelect extends Phaser.Scene {
|
||||
constructor() {
|
||||
@@ -9,29 +10,29 @@ export class LevelSelect extends Phaser.Scene {
|
||||
create() {
|
||||
const width = this.cameras.main.width;
|
||||
const height = this.cameras.main.height;
|
||||
|
||||
|
||||
// Add title
|
||||
const title = this.add.text(width / 2, 50, 'SELECT LEVEL', {
|
||||
const title = this.add.text(width / 2, 50, getText('levelSelectTitle'), {
|
||||
font: 'bold 32px Arial',
|
||||
fill: '#ffffff',
|
||||
align: 'center'
|
||||
});
|
||||
title.setOrigin(0.5, 0.5);
|
||||
|
||||
|
||||
// Create level buttons
|
||||
const buttonSize = 70;
|
||||
const padding = 20;
|
||||
const buttonsPerRow = 4;
|
||||
const startX = width / 2 - ((buttonsPerRow - 1) * (buttonSize + padding)) / 2;
|
||||
const startY = 150;
|
||||
|
||||
|
||||
for (let i = 0; i < this.totalLevels; i++) {
|
||||
const row = Math.floor(i / buttonsPerRow);
|
||||
const col = i % buttonsPerRow;
|
||||
|
||||
|
||||
const x = startX + col * (buttonSize + padding);
|
||||
const y = startY + row * (buttonSize + padding);
|
||||
|
||||
|
||||
// Create button
|
||||
const levelButton = this.add.rectangle(x, y, buttonSize, buttonSize, 0x444444);
|
||||
const levelText = this.add.text(x, y, `${i + 1}`, {
|
||||
@@ -39,7 +40,7 @@ export class LevelSelect extends Phaser.Scene {
|
||||
fill: '#ffffff'
|
||||
});
|
||||
levelText.setOrigin(0.5, 0.5);
|
||||
|
||||
|
||||
// Make button interactive
|
||||
levelButton.setInteractive({ useHandCursor: true })
|
||||
.on('pointerover', () => levelButton.fillColor = 0x666666)
|
||||
@@ -48,15 +49,15 @@ export class LevelSelect extends Phaser.Scene {
|
||||
this.scene.start('Game', { level: i + 1, lives: 3 });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Add back button
|
||||
const backButton = this.add.rectangle(width / 2, height - 70, 200, 50, 0x444444);
|
||||
const backText = this.add.text(width / 2, height - 70, 'BACK TO MENU', {
|
||||
const backText = this.add.text(width / 2, height - 70, getText('back'), {
|
||||
font: '20px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
backText.setOrigin(0.5, 0.5);
|
||||
|
||||
|
||||
// Make back button interactive
|
||||
backButton.setInteractive({ useHandCursor: true })
|
||||
.on('pointerover', () => backButton.fillColor = 0x666666)
|
||||
|
||||
+33
-17
@@ -1,4 +1,5 @@
|
||||
import Phaser from 'phaser';
|
||||
import { getText } from '../localization';
|
||||
|
||||
export class MainMenu extends Phaser.Scene {
|
||||
constructor() {
|
||||
@@ -8,34 +9,42 @@ export class MainMenu extends Phaser.Scene {
|
||||
create() {
|
||||
const width = this.cameras.main.width;
|
||||
const height = this.cameras.main.height;
|
||||
|
||||
|
||||
// Add game title
|
||||
const title = this.add.text(width / 2, height / 4, 'NIGHT NINJA: TWILIGHT VOYAGE', {
|
||||
const title = this.add.text(width / 2, height / 4, getText('gameTitle'), {
|
||||
font: 'bold 32px Arial',
|
||||
fill: '#ffffff',
|
||||
align: 'center'
|
||||
});
|
||||
title.setOrigin(0.5, 0.5);
|
||||
|
||||
|
||||
// Add ninja icon
|
||||
const ninjaCircle = this.add.circle(width / 2, height / 2 - 50, 30, 0x000000);
|
||||
|
||||
|
||||
// Add start button
|
||||
const startButton = this.add.rectangle(width / 2, height / 2 + 50, 200, 50, 0x444444);
|
||||
const startText = this.add.text(width / 2, height / 2 + 50, 'START GAME', {
|
||||
const startButton = this.add.rectangle(width / 2, height / 2 + 20, 200, 50, 0x444444);
|
||||
const startText = this.add.text(width / 2, height / 2 + 20, getText('startGame'), {
|
||||
font: '24px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
startText.setOrigin(0.5, 0.5);
|
||||
|
||||
|
||||
// Add level select button
|
||||
const levelButton = this.add.rectangle(width / 2, height / 2 + 120, 200, 50, 0x444444);
|
||||
const levelText = this.add.text(width / 2, height / 2 + 120, 'LEVEL SELECT', {
|
||||
const levelButton = this.add.rectangle(width / 2, height / 2 + 80, 200, 50, 0x444444);
|
||||
const levelText = this.add.text(width / 2, height / 2 + 80, getText('levelSelect'), {
|
||||
font: '24px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
levelText.setOrigin(0.5, 0.5);
|
||||
|
||||
|
||||
// Add settings button
|
||||
const settingsButton = this.add.rectangle(width / 2, height / 2 + 140, 200, 50, 0x444444);
|
||||
const settingsText = this.add.text(width / 2, height / 2 + 140, getText('settings'), {
|
||||
font: '24px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
settingsText.setOrigin(0.5, 0.5);
|
||||
|
||||
// Make buttons interactive
|
||||
startButton.setInteractive({ useHandCursor: true })
|
||||
.on('pointerover', () => startButton.fillColor = 0x666666)
|
||||
@@ -43,26 +52,33 @@ export class MainMenu extends Phaser.Scene {
|
||||
.on('pointerdown', () => {
|
||||
this.scene.start('Game', { level: 1, lives: 3 });
|
||||
});
|
||||
|
||||
|
||||
levelButton.setInteractive({ useHandCursor: true })
|
||||
.on('pointerover', () => levelButton.fillColor = 0x666666)
|
||||
.on('pointerout', () => levelButton.fillColor = 0x444444)
|
||||
.on('pointerdown', () => {
|
||||
this.scene.start('LevelSelect');
|
||||
});
|
||||
|
||||
|
||||
settingsButton.setInteractive({ useHandCursor: true })
|
||||
.on('pointerover', () => settingsButton.fillColor = 0x666666)
|
||||
.on('pointerout', () => settingsButton.fillColor = 0x444444)
|
||||
.on('pointerdown', () => {
|
||||
this.scene.start('Settings');
|
||||
});
|
||||
|
||||
// Add game description
|
||||
const description = this.add.text(width / 2, height * 0.8,
|
||||
'Guide the ninja through the shadows.\nAvoid light at all costs.\nRescue the princess... if you can.', {
|
||||
const description = this.add.text(width / 2, height * 0.8,
|
||||
getText('gameDescription'), {
|
||||
font: '18px Arial',
|
||||
fill: '#cccccc',
|
||||
align: 'center'
|
||||
});
|
||||
description.setOrigin(0.5, 0.5);
|
||||
|
||||
|
||||
// Add instructions
|
||||
const instructions = this.add.text(width / 2, height * 0.9,
|
||||
'Use arrow keys, WASD, or tap to move.', {
|
||||
const instructions = this.add.text(width / 2, height * 0.9,
|
||||
getText('instructions'), {
|
||||
font: '16px Arial',
|
||||
fill: '#aaaaaa',
|
||||
align: 'center'
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
import Phaser from 'phaser';
|
||||
import { getText, setLanguage, getLanguage } from '../localization';
|
||||
|
||||
export class Settings extends Phaser.Scene {
|
||||
constructor() {
|
||||
super('Settings');
|
||||
}
|
||||
|
||||
create() {
|
||||
const width = this.cameras.main.width;
|
||||
const height = this.cameras.main.height;
|
||||
|
||||
// Add settings title
|
||||
const title = this.add.text(width / 2, height / 4, getText('settings'), {
|
||||
font: 'bold 32px Arial',
|
||||
fill: '#ffffff',
|
||||
align: 'center'
|
||||
});
|
||||
title.setOrigin(0.5, 0.5);
|
||||
|
||||
// Add language settings label
|
||||
const languageLabel = this.add.text(width / 2, height / 2 - 50, getText('languageSettings'), {
|
||||
font: '24px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
languageLabel.setOrigin(0.5, 0.5);
|
||||
|
||||
// Add language options
|
||||
const currentLanguage = getLanguage();
|
||||
|
||||
// English button
|
||||
const englishButton = this.add.rectangle(width / 2 - 80, height / 2, 150, 50,
|
||||
currentLanguage === 'en' ? 0x666666 : 0x444444);
|
||||
const englishText = this.add.text(width / 2 - 80, height / 2, getText('english'), {
|
||||
font: '20px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
englishText.setOrigin(0.5, 0.5);
|
||||
|
||||
// Vietnamese button
|
||||
const vietnameseButton = this.add.rectangle(width / 2 + 80, height / 2, 150, 50,
|
||||
currentLanguage === 'vi' ? 0x666666 : 0x444444);
|
||||
const vietnameseText = this.add.text(width / 2 + 80, height / 2, getText('vietnamese'), {
|
||||
font: '20px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
vietnameseText.setOrigin(0.5, 0.5);
|
||||
|
||||
// Back button
|
||||
const backButton = this.add.rectangle(width / 2, height / 2 + 100, 200, 50, 0x444444);
|
||||
const backText = this.add.text(width / 2, height / 2 + 100, getText('back'), {
|
||||
font: '24px Arial',
|
||||
fill: '#ffffff'
|
||||
});
|
||||
backText.setOrigin(0.5, 0.5);
|
||||
|
||||
// Make buttons interactive
|
||||
englishButton.setInteractive({ useHandCursor: true })
|
||||
.on('pointerover', () => {
|
||||
if (currentLanguage !== 'en') englishButton.fillColor = 0x555555;
|
||||
})
|
||||
.on('pointerout', () => {
|
||||
if (currentLanguage !== 'en') englishButton.fillColor = 0x444444;
|
||||
})
|
||||
.on('pointerdown', () => {
|
||||
this.changeLanguage('en');
|
||||
});
|
||||
|
||||
vietnameseButton.setInteractive({ useHandCursor: true })
|
||||
.on('pointerover', () => {
|
||||
if (currentLanguage !== 'vi') vietnameseButton.fillColor = 0x555555;
|
||||
})
|
||||
.on('pointerout', () => {
|
||||
if (currentLanguage !== 'vi') vietnameseButton.fillColor = 0x444444;
|
||||
})
|
||||
.on('pointerdown', () => {
|
||||
this.changeLanguage('vi');
|
||||
});
|
||||
|
||||
backButton.setInteractive({ useHandCursor: true })
|
||||
.on('pointerover', () => backButton.fillColor = 0x666666)
|
||||
.on('pointerout', () => backButton.fillColor = 0x444444)
|
||||
.on('pointerdown', () => {
|
||||
this.scene.start('MainMenu');
|
||||
});
|
||||
|
||||
// Store UI elements that need to be updated when language changes
|
||||
this.uiElements = {
|
||||
title,
|
||||
languageLabel,
|
||||
englishText,
|
||||
vietnameseText,
|
||||
backText,
|
||||
englishButton,
|
||||
vietnameseButton
|
||||
};
|
||||
}
|
||||
|
||||
changeLanguage(language) {
|
||||
// Only update if the language actually changed
|
||||
if (getLanguage() !== language) {
|
||||
setLanguage(language);
|
||||
this.updateUIText();
|
||||
|
||||
// Update button colors
|
||||
this.uiElements.englishButton.fillColor = language === 'en' ? 0x666666 : 0x444444;
|
||||
this.uiElements.vietnameseButton.fillColor = language === 'vi' ? 0x666666 : 0x444444;
|
||||
}
|
||||
}
|
||||
|
||||
updateUIText() {
|
||||
// Update all text elements with the new language
|
||||
this.uiElements.title.setText(getText('settings'));
|
||||
this.uiElements.languageLabel.setText(getText('languageSettings'));
|
||||
this.uiElements.englishText.setText(getText('english'));
|
||||
this.uiElements.vietnameseText.setText(getText('vietnamese'));
|
||||
this.uiElements.backText.setText(getText('back'));
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -5,6 +5,7 @@ import { MainMenu } from './game/scenes/MainMenu';
|
||||
import { LevelSelect } from './game/scenes/LevelSelect';
|
||||
import { Game } from './game/scenes/Game';
|
||||
import { GameOver } from './game/scenes/GameOver';
|
||||
import { Settings } from './game/scenes/Settings';
|
||||
|
||||
const config = {
|
||||
type: Phaser.AUTO,
|
||||
@@ -12,7 +13,7 @@ const config = {
|
||||
height: 600,
|
||||
parent: 'app',
|
||||
backgroundColor: '#333333',
|
||||
scene: [Boot, Preloader, MainMenu, LevelSelect, Game, GameOver],
|
||||
scene: [Boot, Preloader, MainMenu, LevelSelect, Game, GameOver, Settings],
|
||||
physics: {
|
||||
default: 'arcade',
|
||||
arcade: {
|
||||
|
||||
Reference in new issue
Block a user