// Player Entity // Igralec z WASD kontrolami in isometrično podporo class Player { constructor(scene, gridX = 50, gridY = 50, offsetX = 0, offsetY = 0) { this.scene = scene; this.gridX = gridX; this.gridY = gridY; // Terrain offset this.offsetX = offsetX; this.offsetY = offsetY; this.iso = new IsometricUtils(48, 24); // Hitrost gibanja this.moveSpeed = 150; // px/s this.gridMoveTime = 200; // ms za premik na eno kocko // Stanje this.isMoving = false; this.direction = 'down'; this.lastDir = { x: 0, y: 1 }; // Default south // Kreira sprite this.createSprite(); // Setup kontrole this.setupControls(); // Space za napad this.scene.input.keyboard.on('keydown-SPACE', () => { this.attack(); }); // Začetna pozicija this.updatePosition(); } createSprite() { // Prefer animated sprite if available let texKey = 'player_walk'; // Spritesheet let isAnimated = this.scene.textures.exists(texKey); if (!isAnimated) { texKey = this.scene.textures.exists('player_sprite') ? 'player_sprite' : 'player'; if (!this.scene.textures.exists(texKey)) { TextureGenerator.createPlayerSprite(this.scene, texKey); } } // Kreira sprite const screenPos = this.iso.toScreen(this.gridX, this.gridY); this.sprite = this.scene.add.sprite( screenPos.x + this.offsetX, screenPos.y + this.offsetY, texKey ); this.sprite.setOrigin(0.5, 1); // Scale logic if (isAnimated) { this.sprite.setScale(1.5); } else { this.sprite.setScale(0.3); } // --- HAND / HELD ITEM SPRITE --- this.handSprite = this.scene.add.sprite( screenPos.x + this.offsetX + 10, screenPos.y + this.offsetY - 25, 'item_axe' ); this.handSprite.setOrigin(0.5, 0.5); this.handSprite.setScale(0.25); this.handSprite.setVisible(false); this.updateDepth(); } setupControls() { this.keys = this.scene.input.keyboard.addKeys({ up: Phaser.Input.Keyboard.KeyCodes.W, down: Phaser.Input.Keyboard.KeyCodes.S, left: Phaser.Input.Keyboard.KeyCodes.A, right: Phaser.Input.Keyboard.KeyCodes.D }); } attack() { console.log('⚔️ Player Attack!'); if (this.scene.interactionSystem) { const targetX = this.gridX + this.lastDir.x; const targetY = this.gridY + this.lastDir.y; this.scene.interactionSystem.handleInteraction(targetX, targetY, true); // true = attackMode } // Animation this.scene.tweens.add({ targets: this.handSprite, angle: 45, // Swing yoyo: true, duration: 100 }); // Player lunge const lungeX = this.sprite.x + (this.lastDir.x * 10); const lungeY = this.sprite.y + (this.lastDir.y * 5); this.scene.tweens.add({ targets: this.sprite, x: lungeX, y: lungeY, yoyo: true, duration: 50 }); } update(delta) { if (this.isMoving) { this.updateDepth(); } if (!this.isMoving) { this.handleInput(); } this.updateHeldItem(); } updateHeldItem() { const uiScene = this.scene.scene.get('UIScene'); const invSys = this.scene.inventorySystem; if (uiScene && invSys) { const selectedIdx = uiScene.selectedSlot; const slot = invSys.slots[selectedIdx]; if (slot && (slot.type === 'axe' || slot.type === 'pickaxe' || slot.type === 'hoe' || slot.type === 'sword')) { const texKey = `item_${slot.type}`; if (this.scene.textures.exists(texKey)) { this.handSprite.setTexture(texKey); this.handSprite.setVisible(true); } else { this.handSprite.setVisible(false); } } else { this.handSprite.setVisible(false); } } } handleInput() { let targetX = this.gridX; let targetY = this.gridY; let moved = false; let facingRight = !this.sprite.flipX; // WASD let dx = 0; let dy = 0; if (this.keys.up.isDown) { dx = -1; dy = 0; moved = true; facingRight = false; } else if (this.keys.down.isDown) { dx = 1; dy = 0; moved = true; facingRight = true; } if (this.keys.left.isDown) { dx = 0; dy = 1; moved = true; facingRight = false; } else if (this.keys.right.isDown) { dx = 0; dy = -1; moved = true; facingRight = true; } // Update target targetX = this.gridX + dx; targetY = this.gridY + dy; // Update Facing Direction and Last Dir if (moved) { // Keep diagonal input clean or prioritize one axis? // Just use the calculated dx/dy. // Note: If both UP and LEFT pressed, logic above overwrites dx/dy. // Let's refine to allow diagonal accumulation if needed, but existing logic prioritized axis. // Current logic: RIGHT/LEFT overwrites UP/DOWN. This is fine for now. this.lastDir = { x: dx, y: dy }; this.sprite.setFlipX(!facingRight); // Hand offset const handOffset = facingRight ? 10 : -10; this.handSprite.setX(this.sprite.x + handOffset); this.handSprite.setFlipX(!facingRight); } // Collision Check const terrainSystem = this.scene.terrainSystem; if (moved && terrainSystem) { if (this.iso.isInBounds(targetX, targetY, terrainSystem.width, terrainSystem.height)) { const tile = terrainSystem.tiles[targetY][targetX]; let isPassable = true; if (tile.type.name === 'water') isPassable = false; const key = `${targetX},${targetY}`; if (terrainSystem.decorationsMap.has(key)) { const decor = terrainSystem.decorationsMap.get(key); const solidTypes = ['tree', 'stone', 'bush', 'wall', 'ruin', 'fence', 'house', 'gravestone']; if (solidTypes.includes(decor.type)) { console.log('⛔ Blocked by:', decor.type); isPassable = false; } } if (isPassable) { this.moveToGrid(targetX, targetY); } } } } moveToGrid(targetX, targetY) { this.isMoving = true; this.gridX = targetX; this.gridY = targetY; const targetScreen = this.iso.toScreen(targetX, targetY); if (this.sprite.texture.key === 'player_walk') { this.sprite.play('player_walk_anim', true); } this.scene.tweens.add({ targets: [this.sprite, this.handSprite], x: '+=' + (targetScreen.x + this.offsetX - this.sprite.x), y: '+=' + (targetScreen.y + this.offsetY - this.sprite.y), duration: this.gridMoveTime, ease: 'Linear', onComplete: () => { this.isMoving = false; this.updatePosition(); if (this.sprite.texture.key === 'player_walk') { this.sprite.stop(); this.sprite.setFrame(0); } } }); this.updateDepth(); } updatePosition() { const screenPos = this.iso.toScreen(this.gridX, this.gridY); this.sprite.setPosition( screenPos.x + this.offsetX, screenPos.y + this.offsetY ); const facingRight = !this.sprite.flipX; const handOffset = facingRight ? 10 : -10; this.handSprite.setPosition( screenPos.x + this.offsetX + handOffset, screenPos.y + this.offsetY - 15 ); this.updateDepth(); } updateDepth() { if (this.sprite) { this.sprite.setDepth(this.sprite.y); if (this.handSprite) this.handSprite.setDepth(this.sprite.y + 1); } } getPosition() { return { x: this.gridX, y: this.gridY }; } getScreenPosition() { return { x: this.sprite.x, y: this.sprite.y }; } destroy() { if (this.sprite) this.sprite.destroy(); } dieAnimation() { this.sprite.setTint(0xff0000); this.scene.tweens.add({ targets: this.sprite, angle: 90, duration: 500, ease: 'Bounce.easeOut' }); } respawn() { this.sprite.clearTint(); this.sprite.angle = 0; } }