fix: bug when get into level

This commit is contained in:
tiennm99 committed 2025-04-27 18:44:27 +07:00
1 parent 93f59a65ab
commit 5b75abdd88
4 files changed
+147 -89

No files matched your search

+6 -9
View File
@@ -150,9 +150,8 @@ export const LEVELS = [
type: "static",
position: { row: 1, col: 6 },
litCells: [
// Removed ALL lit cells to make level 5 completable
// { row: 1, col: 5 },
// { row: 1, col: 7 }
// Adding back one lit cell with a path still possible
{ row: 1, col: 7 }
]
},
{
@@ -230,9 +229,8 @@ export const LEVELS = [
type: "static",
position: { row: 1, col: 5 },
litCells: [
// Removed ALL lit cells to make level 7 completable
// { row: 1, col: 4 },
// { row: 1, col: 6 }
// Adding back one lit cell with a path still possible
{ row: 1, col: 6 }
]
},
{
@@ -244,9 +242,8 @@ export const LEVELS = [
type: "static",
position: { row: 5, col: 2 },
litCells: [
// Removed ALL lit cells to make level 7 completable
// { row: 5, col: 1 },
// { row: 5, col: 3 }
// Adding back one lit cell with a path still possible
{ row: 5, col: 1 }
]
}
]
+5 -3
View File
@@ -4,8 +4,10 @@ export class LightingSystem {
constructor(scene, grid) {
this.scene = scene;
this.grid = grid;
// Create graphics object for rendering light effects
this.graphics = this.scene.add.graphics();
}
// Xóa tất cả ánh sáng trên lưới
clearAllLight() {
for (let row = 0; row < this.grid.rows; row++) {
@@ -14,11 +16,11 @@ export class LightingSystem {
}
}
}
// Cập nhật ánh sáng từ tất cả các trạm gác
updateLightFromGuards(guards) {
this.clearAllLight();
if (guards && Array.isArray(guards)) {
guards.forEach(guard => {
guard.updateLight();
+11 -11
View File
@@ -13,12 +13,12 @@ export class Player {
createSprite() {
// Lấy vị trí pixel từ tọa độ lưới
const { x, y } = this.scene.gridToScreen(this.row, this.col);
// Tạo sprite người chơi (hình tròn đen)
this.sprite = this.scene.add.circle(
x,
y,
this.grid.cellSize / 3,
x,
y,
this.grid.cellSize / 3,
0x000000
);
}
@@ -31,10 +31,10 @@ export class Player {
this.row = row;
this.col = col;
// Lấy vị trí pixel mới
const { x, y } = this.scene.gridToScreen(this.row, this.col);
// Tạo hiệu ứng di chuyển
this.scene.tweens.add({
targets: this.sprite,
@@ -43,7 +43,7 @@ export class Player {
duration: 100,
ease: 'Linear'
});
return true;
}
@@ -51,7 +51,7 @@ export class Player {
move(direction) {
let newRow = this.row;
let newCol = this.col;
switch (direction) {
case 'up':
newRow--;
@@ -66,18 +66,18 @@ export class Player {
newCol++;
break;
}
return this.moveTo(newRow, newCol);
}
// Kiểm tra xem người chơi có đang ở ô sáng không
isInLitCell() {
return this.grid.getCell(this.row, this.col).isLit;
return this.grid.isLight(this.row, this.col);
}
// Kiểm tra xem người chơi có đến đích không
isAtGoal() {
return this.grid.getCell(this.row, this.col).isGoal;
return this.grid.isGoal(this.row, this.col);
}
// Cập nhật vị trí sprite
+125 -66
View File
@@ -37,40 +37,40 @@ export class Game extends Phaser.Scene {
// Calculate grid position to center it
const width = this.cameras.main.width;
const height = this.cameras.main.height;
this.gridOffsetX = (width - (this.gridSize * this.cellSize)) / 2;
this.gridOffsetY = (height - (this.gridSize * this.cellSize)) / 2;
// Create grid system
this.createGridSystem();
// Create lighting system
this.lightSystem = new LightingSystem(this, this.grid);
// Make guard classes available to LevelManager
this.StaticGuard = StaticGuard;
this.RotatingGuard = RotatingGuard;
this.BlinkingGuard = BlinkingGuard;
this.PatrollingGuard = PatrollingGuard;
// Create level manager
this.levelManager = new LevelManager(this);
// Create turn manager
this.turnManager = new TurnManager(this);
// Create player
this.createPlayer(0, 0); // Default position, will be updated by level data
// Setup input
this.setupInput();
// Create UI
this.createUI();
// Create mobile controls if needed
this.createMobileControls();
// Load level
this.levelManager.loadLevel(this.currentLevel);
}
@@ -80,16 +80,21 @@ export class Game extends Phaser.Scene {
if (!this.isPaused) {
// Check for keyboard input
this.handleKeyboardInput();
// Check for final level special condition
if (this.isFinalLevel) {
this.checkFinalLevelCondition();
}
}
}
createGridSystem() {
this.grid = new GridSystem(this, this.gridSize, this.gridSize, this.cellSize);
// Position the grid in the center of the screen
this.grid.graphics.x = this.gridOffsetX;
this.grid.graphics.y = this.gridOffsetY;
// Render the grid
this.grid.render();
}
@@ -101,7 +106,7 @@ export class Game extends Phaser.Scene {
setupInput() {
// Setup keyboard input
this.cursors = this.input.keyboard.createCursorKeys();
// WASD keys
this.wasd = {
up: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W),
@@ -109,18 +114,18 @@ export class Game extends Phaser.Scene {
down: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S),
right: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D)
};
// Add click/tap input for grid cells
this.input.on('pointerdown', (pointer) => {
if (this.isPaused || !this.inputEnabled || !this.turnManager.isPlayerTurn) return;
// Convert screen coordinates to grid coordinates
const gridPos = this.screenToGrid(pointer.x, pointer.y);
// Check if the clicked position is adjacent to the player
const rowDiff = Math.abs(gridPos.row - this.player.row);
const colDiff = Math.abs(gridPos.col - this.player.col);
// Only allow moving to adjacent cells (not diagonally)
if ((rowDiff === 1 && colDiff === 0) || (rowDiff === 0 && colDiff === 1)) {
if (this.player.moveTo(gridPos.row, gridPos.col)) {
@@ -133,15 +138,15 @@ export class Game extends Phaser.Scene {
handleKeyboardInput() {
// Only process input during player's turn and when input is enabled
if (!this.inputEnabled || !this.turnManager.isPlayerTurn) return;
// Use a cooldown to prevent multiple inputs in a single frame
if (this.inputCooldown > 0) {
this.inputCooldown--;
return;
}
let direction = null;
// Check arrow keys
if (this.cursors.up.isDown || this.wasd.up.isDown) {
direction = 'up';
@@ -152,7 +157,7 @@ export class Game extends Phaser.Scene {
} else if (this.cursors.right.isDown || this.wasd.right.isDown) {
direction = 'right';
}
if (direction) {
if (this.player.move(direction)) {
this.turnManager.nextTurn();
@@ -164,56 +169,56 @@ export class Game extends Phaser.Scene {
createUI() {
// Create UI elements
const width = this.cameras.main.width;
// Lives display
this.livesText = this.add.text(20, 20, `Lives: ${this.livesRemaining}`, {
font: '18px Arial',
fill: '#ffffff'
});
// Level display
this.levelText = this.add.text(width - 20, 20, `Level: ${this.currentLevel}`, {
font: '18px Arial',
fill: '#ffffff'
});
this.levelText.setOrigin(1, 0);
// Pause button
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', {
font: '16px Arial',
fill: '#ffffff'
});
this.pauseText.setOrigin(0.5, 0.5);
this.pauseButton.setInteractive({ useHandCursor: true })
.on('pointerdown', () => {
this.togglePause();
});
// Create pause menu (initially hidden)
this.createPauseMenu();
}
createPauseMenu() {
const width = this.cameras.main.width;
const height = this.cameras.main.height;
// Create container for pause menu
this.pauseMenu = this.add.container(width / 2, height / 2);
// Background
const bg = this.add.rectangle(0, 0, 300, 250, 0x000000, 0.8);
// Title
const title = this.add.text(0, -100, 'PAUSED', {
font: 'bold 32px Arial',
fill: '#ffffff'
});
title.setOrigin(0.5, 0.5);
// Resume button
const resumeButton = this.add.rectangle(0, -40, 200, 40, 0x444444);
const resumeText = this.add.text(0, -40, 'RESUME', {
@@ -221,7 +226,7 @@ export class Game extends Phaser.Scene {
fill: '#ffffff'
});
resumeText.setOrigin(0.5, 0.5);
// Restart button
const restartButton = this.add.rectangle(0, 20, 200, 40, 0x444444);
const restartText = this.add.text(0, 20, 'RESTART LEVEL', {
@@ -229,7 +234,7 @@ export class Game extends Phaser.Scene {
fill: '#ffffff'
});
restartText.setOrigin(0.5, 0.5);
// Main menu button
const menuButton = this.add.rectangle(0, 80, 200, 40, 0x444444);
const menuText = this.add.text(0, 80, 'MAIN MENU', {
@@ -237,10 +242,10 @@ export class Game extends Phaser.Scene {
fill: '#ffffff'
});
menuText.setOrigin(0.5, 0.5);
// Add all elements to container
this.pauseMenu.add([bg, title, resumeButton, resumeText, restartButton, restartText, menuButton, menuText]);
// Make buttons interactive
resumeButton.setInteractive({ useHandCursor: true })
.on('pointerover', () => resumeButton.fillColor = 0x666666)
@@ -248,7 +253,7 @@ export class Game extends Phaser.Scene {
.on('pointerdown', () => {
this.togglePause();
});
restartButton.setInteractive({ useHandCursor: true })
.on('pointerover', () => restartButton.fillColor = 0x666666)
.on('pointerout', () => restartButton.fillColor = 0x444444)
@@ -256,59 +261,59 @@ export class Game extends Phaser.Scene {
this.togglePause();
this.levelManager.loadLevel(this.currentLevel);
});
menuButton.setInteractive({ useHandCursor: true })
.on('pointerover', () => menuButton.fillColor = 0x666666)
.on('pointerout', () => menuButton.fillColor = 0x444444)
.on('pointerdown', () => {
this.scene.start('MainMenu');
});
// Hide pause menu initially
this.pauseMenu.setVisible(false);
}
togglePause() {
this.isPaused = !this.isPaused;
this.pauseMenu.setVisible(this.isPaused);
this.inputEnabled = !this.isPaused;
}
createMobileControls() {
// Create mobile control buttons
const width = this.cameras.main.width;
const height = this.cameras.main.height;
// Container for mobile controls
this.mobileControls = this.add.container(width / 2, height - 100);
// Create directional buttons
const buttonSize = 60;
const buttonSpacing = 70;
// Up button
const upButton = this.add.circle(0, -buttonSpacing, buttonSize / 2, 0x444444);
const upText = this.add.text(0, -buttonSpacing, '↑', { font: '32px Arial', fill: '#ffffff' });
upText.setOrigin(0.5, 0.5);
// Left button
const leftButton = this.add.circle(-buttonSpacing, 0, buttonSize / 2, 0x444444);
const leftText = this.add.text(-buttonSpacing, 0, '←', { font: '32px Arial', fill: '#ffffff' });
leftText.setOrigin(0.5, 0.5);
// Right button
const rightButton = this.add.circle(buttonSpacing, 0, buttonSize / 2, 0x444444);
const rightText = this.add.text(buttonSpacing, 0, '→', { font: '32px Arial', fill: '#ffffff' });
rightText.setOrigin(0.5, 0.5);
// Down button
const downButton = this.add.circle(0, buttonSpacing, buttonSize / 2, 0x444444);
const downText = this.add.text(0, buttonSpacing, '↓', { font: '32px Arial', fill: '#ffffff' });
downText.setOrigin(0.5, 0.5);
// Add buttons to container
this.mobileControls.add([upButton, upText, leftButton, leftText, rightButton, rightText, downButton, downText]);
// Make buttons interactive
upButton.setInteractive({ useHandCursor: true })
.on('pointerdown', () => {
@@ -318,7 +323,7 @@ export class Game extends Phaser.Scene {
}
}
});
leftButton.setInteractive({ useHandCursor: true })
.on('pointerdown', () => {
if (!this.isPaused && this.inputEnabled && this.turnManager.isPlayerTurn) {
@@ -327,7 +332,7 @@ export class Game extends Phaser.Scene {
}
}
});
rightButton.setInteractive({ useHandCursor: true })
.on('pointerdown', () => {
if (!this.isPaused && this.inputEnabled && this.turnManager.isPlayerTurn) {
@@ -336,7 +341,7 @@ export class Game extends Phaser.Scene {
}
}
});
downButton.setInteractive({ useHandCursor: true })
.on('pointerdown', () => {
if (!this.isPaused && this.inputEnabled && this.turnManager.isPlayerTurn) {
@@ -345,16 +350,16 @@ export class Game extends Phaser.Scene {
}
}
});
// Only show mobile controls on touch devices
this.mobileControls.setVisible(false);
// Check if device has touch capability
if (this.sys.game.device.input.touch) {
this.mobileControls.setVisible(true);
}
}
// Helper method to convert grid coordinates to screen coordinates
gridToScreen(row, col) {
const gridPos = this.grid.gridToPixel(row, col);
@@ -363,24 +368,24 @@ export class Game extends Phaser.Scene {
y: gridPos.y + this.gridOffsetY
};
}
// Helper method to convert screen coordinates to grid coordinates
screenToGrid(x, y) {
return this.grid.pixelToGrid(x - this.gridOffsetX, y - this.gridOffsetY);
}
// Xử lý khi người chơi bị bắt
handlePlayerCaught() {
this.livesRemaining--;
// Cập nhật hiển thị số mạng
if (this.livesText) {
this.livesText.setText(`Lives: ${this.livesRemaining}`);
}
if (this.livesRemaining <= 0) {
// Hết mạng, game over
this.scene.start('GameOver', {
this.scene.start('GameOver', {
level: this.currentLevel,
isLastLevel: false
});
@@ -389,30 +394,84 @@ export class Game extends Phaser.Scene {
this.levelManager.loadLevel(this.currentLevel);
}
}
// Xử lý khi người chơi hoàn thành màn chơi
handleLevelComplete() {
const nextLevel = this.currentLevel + 1;
// Kiểm tra xem có phải màn cuối không
if (this.isFinalLevel) {
// Đây là màn cuối với cái kết đặc biệt
this.scene.start('GameOver', {
this.scene.start('GameOver', {
level: this.currentLevel,
isLastLevel: true
});
} else if (nextLevel > this.levelManager.getTotalLevels()) {
// Đã hoàn thành tất cả các màn
this.scene.start('GameOver', {
this.scene.start('GameOver', {
level: this.currentLevel,
isLastLevel: false
});
} else {
// Chuyển đến màn tiếp theo
this.scene.start('Game', {
this.scene.start('Game', {
level: nextLevel,
lives: this.livesRemaining
});
}
}
// Kiểm tra điều kiện đặc biệt cho màn cuối
checkFinalLevelCondition() {
if (!this.isFinalLevel) return false;
// Kiểm tra xem người chơi có đang ở gần công chúa không
const playerRow = this.player.row;
const playerCol = this.player.col;
const goalRow = 9; // Vị trí công chúa ở màn cuối (row 9, col 9)
const goalCol = 9;
// Tính khoảng cách Manhattan từ người chơi đến công chúa
const distance = Math.abs(playerRow - goalRow) + Math.abs(playerCol - goalCol);
// Nếu người chơi đến gần công chúa (khoảng cách <= 2), kích hoạt cơ chế đặc biệt
if (distance <= 2) {
// Bật sáng toàn bộ bản đồ
this.lightUpEntireMap();
return true;
}
return false;
}
// Bật sáng toàn bộ bản đồ cho màn cuối
lightUpEntireMap() {
// Hiển thị thông báo
const width = this.cameras.main.width;
const height = this.cameras.main.height;
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!', {
font: 'bold 20px Arial',
fill: '#FF0000',
backgroundColor: '#000000',
padding: { x: 10, y: 5 }
});
this.finalLevelMessage.setOrigin(0.5, 0.5);
this.finalLevelMessage.setDepth(100);
}
// Bật sáng toàn bộ các ô
for (let row = 0; row < this.grid.rows; row++) {
for (let col = 0; col < this.grid.cols; col++) {
if (!this.grid.isWall(row, col)) {
this.grid.setLight(row, col, true);
}
}
}
// Vẽ lại lưới
this.grid.render();
}
}