| class Character { |
| constructor(gameState, characterImg) { |
| this.gameState = gameState; |
| this.characterImg = characterImg; |
| this.characterPos = null; |
| this.previousPos = null; |
| this.path = []; |
| this.isMoving = false; |
| this.moveInterval = null; |
| this.img = characterImg; |
| this.speed = 270; |
| } |
|
|
| getCharacterPosition() { |
| return this.characterPos; |
| } |
|
|
| setCharacterPosition(pos) { |
| this.characterPos = pos; |
| } |
|
|
| getCurrentRoom() { |
| if (!this.characterPos) return null; |
|
|
| |
| for (const room of this.gameState.map_data.rooms) { |
| if (this.characterPos.x >= room.start_col && |
| this.characterPos.x <= room.end_col && |
| this.characterPos.y >= room.start_row && |
| this.characterPos.y <= room.end_row) { |
| return room.name; |
| } |
| } |
| return null; |
| } |
|
|
| drawPath(CELL_SIZE) { |
| if (this.path.length > 0 && this.isMoving) { |
| noFill(); |
| stroke(255, 0, 0); |
| strokeWeight(2); |
| line( |
| this.characterPos.x * CELL_SIZE + CELL_SIZE / 2, |
| this.characterPos.y * CELL_SIZE + CELL_SIZE / 2, |
| this.path[0].x * CELL_SIZE + CELL_SIZE / 2, |
| this.path[0].y * CELL_SIZE + CELL_SIZE / 2 |
| ); |
| for (let i = 0; i < this.path.length - 1; i++) { |
| line( |
| this.path[i].x * CELL_SIZE + CELL_SIZE / 2, |
| this.path[i].y * CELL_SIZE + CELL_SIZE / 2, |
| this.path[i + 1].x * CELL_SIZE + CELL_SIZE / 2, |
| this.path[i + 1].y * CELL_SIZE + CELL_SIZE / 2 |
| ); |
| } |
| strokeWeight(1); |
| } |
| } |
|
|
| moveCharacterAlongPath(callback=null) { |
| if (this.moveInterval) { |
| clearInterval(this.moveInterval); |
| } |
| this.isMoving = true; |
| this.moveInterval = setInterval(() => { |
| if (this.path.length === 0) { |
| this.isMoving = false; |
| clearInterval(this.moveInterval); |
| if (callback) callback(); |
| return; |
| } |
| this.previousPos = { ...this.characterPos }; |
| const nextPos = this.path.shift(); |
| this.characterPos = nextPos; |
| }, this.speed); |
| } |
|
|
| findPath(start, end) { |
| const queue = [[start]]; |
| const visited = new Set(); |
| const key = pos => `${pos.x},${pos.y}`; |
| visited.add(key(start)); |
|
|
| while (queue.length > 0) { |
| const currentPath = queue.shift(); |
| const current = currentPath[currentPath.length - 1]; |
|
|
| if (current.x === end.x && current.y === end.y) { |
| return currentPath; |
| } |
| const neighbors = [ |
| { x: current.x, y: current.y - 1 }, |
| { x: current.x + 1, y: current.y }, |
| { x: current.x, y: current.y + 1 }, |
| { x: current.x - 1, y: current.y } |
| ]; |
| for (const next of neighbors) { |
| if (next.x < 0 || next.x >= GRID_COLS || next.y < 0 || next.y >= GRID_ROWS) continue; |
| if (visited.has(key(next))) continue; |
|
|
| const cell = this.gameState.map_data.grid[next.y][next.x]; |
| if (cell.type === 'wall') continue; |
|
|
| visited.add(key(next)); |
| queue.push([...currentPath, next]); |
| } |
| } |
| return []; |
| } |
|
|
| moveToPosition(pos,callback=null) { |
| if (!pos || !this.characterPos) return false; |
|
|
| this.path = this.findPath(this.characterPos, pos); |
| if (this.path.length > 0) { |
| this.isMoving = true; |
| this.moveCharacterAlongPath(callback); |
| return true; |
| } |
| return false; |
| } |
| |
| moveToRoom(roomName) { |
| const targetRoom = this.gameState.map_data.rooms |
| .find(room => room.name.toLowerCase() === roomName.toLowerCase()); |
| if (!targetRoom || !this.characterPos) return false; |
|
|
| const destination = targetRoom.label_position; |
| if (!destination) return false; |
| this.moveToPosition(destination); |
| } |
|
|
| } |