// input.js — Mouse and keyboard input handling class InputHandler { constructor(canvas, game) { this.canvas = canvas; this.game = game; this.mouseX = 0; this.mouseY = 0; canvas.addEventListener('click', (e) => this.handleClick(e)); canvas.addEventListener('mousemove', (e) => this.handleMouseMove(e)); canvas.addEventListener('contextmenu', (e) => e.preventDefault()); document.addEventListener('keydown', (e) => this.handleKey(e)); } handleClick(e) { const rect = this.canvas.getBoundingClientRect(); const mx = e.clientX - rect.left; const my = e.clientY - rect.top; // Convert screen to world coords const worldX = mx + this.game.camera.x - 480; const worldY = my + this.game.camera.y - 320; // Convert to tile coords const tile = this.game.map.screenToTile(worldX, worldY); // Check if clicking a monster for (const monster of this.game.monsters) { if (monster.tileX === tile.x && monster.tileY === tile.y) { this.game.player.attackTarget = monster; this.game.addEvent(`Targeting ${monster.name}`, 'combat'); return; } } // Check if clicking an NPC for (const npc of this.game.npcs) { if (npc.tileX === tile.x && npc.tileY === tile.y) { this.game.interactNPC(npc); return; } } // Otherwise, move to clicked tile if (!this.game.map.isSolid(tile.x, tile.y)) { const playerTile = { x: Math.floor(this.game.player.x), y: Math.floor(this.game.player.y) }; const path = this.game.findPath(playerTile, tile); if (path) { this.game.player.setPath(path); this.game.player.attackTarget = null; } } } handleMouseMove(e) { const rect = this.canvas.getBoundingClientRect(); this.mouseX = e.clientX - rect.left; this.mouseY = e.clientY - rect.top; } handleKey(e) { // Skill bar (1-0) if (e.key >= '0' && e.key <= '9') { const slot = e.key === '0' ? 10 : parseInt(e.key); this.game.useSkill(slot); } // Other keys switch(e.key) { case 'i': case 'I': this.game.toggleInventory(); break; case 'q': case 'Q': this.game.toggleQuestLog(); break; case 'Escape': this.game.closeMenus(); break; } } }