stanje 4am

This commit is contained in:
2025-12-07 04:19:57 +01:00
parent 521468c797
commit 03a9cd46a2
20 changed files with 619 additions and 168 deletions

View File

@@ -18,6 +18,7 @@ class NPC {
this.gridMoveTime = 300; // ms za premik (počasneje)
// Stanje
this.state = 'WANDER'; // WANDER, TAMED, FOLLOW
this.isMoving = false;
this.pauseTime = 0;
this.maxPauseTime = 2000; // Pavza med premiki (2s)
@@ -32,11 +33,51 @@ class NPC {
this.pauseTime = Math.random() * this.maxPauseTime;
}
createSprite() {
// Check for custom sprites first
let texKey = `npc_${this.type}`;
tame() {
if (this.state === 'TAMED' || this.type !== 'zombie') return;
if (this.type === 'zombie' && this.scene.textures.exists('zombie_sprite')) {
this.state = 'TAMED';
console.log('🧟❤️ Zombie TAMED!');
// Visual Feedback
const headX = this.sprite.x;
const headY = this.sprite.y - 40;
const heart = this.scene.add.text(headX, headY, '❤️', { fontSize: '20px' });
heart.setOrigin(0.5);
heart.setDepth(this.sprite.depth + 100);
this.scene.tweens.add({
targets: heart,
y: headY - 30,
alpha: 0,
duration: 1500,
onComplete: () => heart.destroy()
});
// Change color slightly to indicate friend
this.sprite.setTint(0xAAFFAA);
}
toggleState() {
if (this.state === 'WANDER') {
this.tame();
} else {
// Maybe command to stay/follow?
this.state = this.state === 'FOLLOW' ? 'STAY' : 'FOLLOW';
console.log(`Command: ${this.state}`);
}
}
createSprite() {
let texKey = `npc_${this.type}`;
let isAnimated = false;
// Check for animated sprites first
if (this.type === 'zombie' && this.scene.textures.exists('zombie_walk')) {
texKey = 'zombie_walk';
isAnimated = true;
} else if (this.type === 'zombie' && this.scene.textures.exists('zombie_sprite')) {
texKey = 'zombie_sprite';
} else if (this.type === 'merchant' && this.scene.textures.exists('merchant_sprite')) {
texKey = 'merchant_sprite';
@@ -52,17 +93,72 @@ class NPC {
texKey
);
this.sprite.setOrigin(0.5, 1);
this.sprite.setScale(0.3); // Optimized for visibility
if (isAnimated) {
this.sprite.setScale(1.5);
} else {
this.sprite.setScale(0.3);
}
// Depth sorting
this.updateDepth();
}
// ... loop update ...
moveToGrid(targetX, targetY) {
// Determine facing direction before moving
const dx = targetX - this.gridX;
const dy = targetY - this.gridY;
const movingRight = (dx > 0) || (dy > 0);
this.sprite.setFlipX(!movingRight);
this.isMoving = true;
this.gridX = targetX;
this.gridY = targetY;
const targetScreen = this.iso.toScreen(targetX, targetY);
// Animation
if (this.sprite.texture.key === 'zombie_walk') {
this.sprite.play('zombie_walk_anim', true);
}
// Tween za smooth gibanje
this.scene.tweens.add({
targets: this.sprite,
x: targetScreen.x + this.offsetX,
y: targetScreen.y + this.offsetY,
duration: this.gridMoveTime,
ease: 'Linear',
onComplete: () => {
this.isMoving = false;
// Stop Animation
if (this.sprite.texture.key === 'zombie_walk') {
this.sprite.stop();
this.sprite.setFrame(0);
}
}
});
// Posodobi depth
this.updateDepth();
}
update(delta) {
this.updateDepth(); // Continuous depth sorting
if (this.isMoving) {
return; // Že se premika
}
// Tamed logic
if (this.state === 'TAMED' || this.state === 'FOLLOW') {
this.followPlayer();
return;
}
// Random walk - pavza med premiki
this.pauseTime += delta;
@@ -72,6 +168,31 @@ class NPC {
}
}
followPlayer() {
if (!this.scene.player) return;
const playerPos = this.scene.player.getPosition();
const dist = Phaser.Math.Distance.Between(this.gridX, this.gridY, playerPos.x, playerPos.y);
// Če je precej dlje, se premakni k njemu
if (dist > 2) {
const dx = Math.sign(playerPos.x - this.gridX);
const dy = Math.sign(playerPos.y - this.gridY);
// Move 1 tile towards player
let targetX = this.gridX + dx;
let targetY = this.gridY + dy;
// Avoid occupying SAME tile as player
if (targetX === playerPos.x && targetY === playerPos.y) {
if (Math.random() < 0.5) targetX = this.gridX;
else targetY = this.gridY;
}
this.moveToGrid(targetX, targetY);
}
}
performRandomWalk() {
// Naključna smer (NSEW + možnost obstati)
const directions = [
@@ -103,28 +224,7 @@ class NPC {
}
}
moveToGrid(targetX, targetY) {
this.isMoving = true;
this.gridX = targetX;
this.gridY = targetY;
const targetScreen = this.iso.toScreen(targetX, targetY);
// Tween za smooth gibanje
this.scene.tweens.add({
targets: this.sprite,
x: targetScreen.x + this.offsetX,
y: targetScreen.y + this.offsetY,
duration: this.gridMoveTime,
ease: 'Linear',
onComplete: () => {
this.isMoving = false;
}
});
// Posodobi depth
this.updateDepth();
}
updatePosition() {
const screenPos = this.iso.toScreen(this.gridX, this.gridY);
@@ -136,8 +236,8 @@ class NPC {
}
updateDepth() {
const depth = this.iso.getDepth(this.gridX, this.gridY);
this.sprite.setDepth(depth + 1000); // +1000 da je nad terenom
// Pixel perfect sorting
if (this.sprite) this.sprite.setDepth(this.sprite.y);
}
getPosition() {

View File

@@ -31,13 +31,15 @@ class Player {
}
createSprite() {
// Use custom sprite if available, otherwise procedural
let texKey = 'player';
// Prefer animated sprite if available
let texKey = 'player_walk'; // Spritesheet
let isAnimated = this.scene.textures.exists(texKey);
if (this.scene.textures.exists('player_sprite')) {
texKey = 'player_sprite';
} else if (!this.scene.textures.exists(texKey)) {
TextureGenerator.createPlayerSprite(this.scene, 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
@@ -48,12 +50,67 @@ class Player {
texKey
);
this.sprite.setOrigin(0.5, 1);
this.sprite.setScale(0.3); // Optimized for visibility
// Scale logic
if (isAnimated) {
this.sprite.setScale(1.5); // 64px frame -> looks good around 96px total height relative to 48px tile
} 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, // Adjusted for new height
'item_axe'
);
this.handSprite.setOrigin(0.5, 0.5);
this.handSprite.setScale(0.25);
this.handSprite.setVisible(false);
// Depth sorting
this.updateDepth();
}
// ... setupControls ...
// ... update ...
moveToGrid(targetX, targetY) {
this.isMoving = true;
this.gridX = targetX;
this.gridY = targetY;
const targetScreen = this.iso.toScreen(targetX, targetY);
// Play Animation
if (this.sprite.texture.key === 'player_walk') {
this.sprite.play('player_walk_anim', true);
}
// Tween za smooth gibanje
this.scene.tweens.add({
targets: [this.sprite, this.handSprite], // Move both
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();
// Stop Animation
if (this.sprite.texture.key === 'player_walk') {
this.sprite.stop();
this.sprite.setFrame(0); // Idle frame
}
}
});
// Posodobi depth
this.updateDepth();
}
setupControls() {
// WASD kontrole
this.keys = this.scene.input.keyboard.addKeys({
@@ -65,41 +122,73 @@ class Player {
}
update(delta) {
this.updateDepth();
if (!this.isMoving) {
this.handleInput();
}
// Sync Held Item with Inventory
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; // Keep current
// WASD za isometric movement
if (this.keys.up.isDown) {
// W = North-West v isometric view
if (this.keys.up.isDown) { // North-West
targetX--;
moved = true;
this.direction = 'up';
} else if (this.keys.down.isDown) {
// S = South-East v isometric view
facingRight = false; // Left-ish
} else if (this.keys.down.isDown) { // South-East
targetX++;
moved = true;
this.direction = 'down';
facingRight = true; // Right-ish
}
if (this.keys.left.isDown) {
// A = South-West v isometric view
targetY--;
if (this.keys.left.isDown) { // South-West
targetY++; // SWAPPED: Was --
moved = true;
this.direction = 'left';
} else if (this.keys.right.isDown) {
// D = North-East v isometric view
targetY++;
facingRight = false; // Left-ish
} else if (this.keys.right.isDown) { // North-East
targetY--; // SWAPPED: Was ++
moved = true;
this.direction = 'right';
facingRight = true; // Right-ish
}
// Apply Facing
this.sprite.setFlipX(!facingRight);
// Update Hand Position based on facing
const handOffset = facingRight ? 10 : -10;
this.handSprite.setX(this.sprite.x + handOffset);
this.handSprite.setFlipX(!facingRight);
// Preveri kolizijo z robovi mape
const terrainSystem = this.scene.terrainSystem;
if (moved && terrainSystem) {
@@ -109,28 +198,7 @@ class Player {
}
}
moveToGrid(targetX, targetY) {
this.isMoving = true;
this.gridX = targetX;
this.gridY = targetY;
const targetScreen = this.iso.toScreen(targetX, targetY);
// Tween za smooth gibanje (brez animacije za zdaj)
this.scene.tweens.add({
targets: this.sprite,
x: targetScreen.x + this.offsetX,
y: targetScreen.y + this.offsetY,
duration: this.gridMoveTime,
ease: 'Linear',
onComplete: () => {
this.isMoving = false;
}
});
// Posodobi depth
this.updateDepth();
}
updatePosition() {
const screenPos = this.iso.toScreen(this.gridX, this.gridY);
@@ -138,12 +206,24 @@ class Player {
screenPos.x + this.offsetX,
screenPos.y + this.offsetY
);
// Update hand
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() {
const depth = this.iso.getDepth(this.gridX, this.gridY);
this.sprite.setDepth(depth + 1000); // +1000 da je nad terenom
// Pixel-perfect depth sorting based on screen Y
if (this.sprite) {
this.sprite.setDepth(this.sprite.y);
if (this.handSprite) this.handSprite.setDepth(this.sprite.y + 1);
}
}
getPosition() {
@@ -159,4 +239,19 @@ class Player {
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;
}
}