Character sprite switching - directionality - added dragon head
This commit is contained in:
@@ -4,7 +4,7 @@ import { TileType } from "../core/terrain";
|
||||
import { TILE_SIZE } from "../core/constants";
|
||||
import { idx, isWall } from "../engine/world/world-logic";
|
||||
import { GAME_CONFIG } from "../core/config/GameConfig";
|
||||
import { ALL_TEMPLATES } from "../core/config/Items";
|
||||
|
||||
import { FovManager } from "./FovManager";
|
||||
import { MinimapRenderer } from "./MinimapRenderer";
|
||||
import { FxRenderer } from "./FxRenderer";
|
||||
@@ -88,9 +88,10 @@ export class DungeonRenderer {
|
||||
|
||||
// Ensure player sprite exists
|
||||
if (!this.playerSprite) {
|
||||
this.playerSprite = this.scene.add.sprite(0, 0, "warrior", 0);
|
||||
this.playerSprite = this.scene.add.sprite(0, 0, "PriestessSouth");
|
||||
this.playerSprite.setDepth(100);
|
||||
this.playerSprite.play('warrior-idle');
|
||||
this.playerSprite.setDisplaySize(TILE_SIZE, TILE_SIZE); // Ensure it fits in 1 tile
|
||||
// No animation for simple sprites for now
|
||||
}
|
||||
|
||||
this.minimapRenderer.positionMinimap();
|
||||
@@ -288,6 +289,18 @@ export class DungeonRenderer {
|
||||
const ty = a.pos.y * TILE_SIZE + TILE_SIZE / 2;
|
||||
|
||||
if (this.playerSprite.x !== tx || this.playerSprite.y !== ty) {
|
||||
// Determine direction
|
||||
const dx = tx - this.playerSprite.x;
|
||||
const dy = ty - this.playerSprite.y;
|
||||
|
||||
if (Math.abs(dy) > Math.abs(dx)) {
|
||||
if (dy < 0) this.playerSprite.setTexture("PriestessNorth");
|
||||
else this.playerSprite.setTexture("PriestessSouth");
|
||||
} else if (Math.abs(dx) > 0) {
|
||||
if (dx > 0) this.playerSprite.setTexture("PriestessEast");
|
||||
else this.playerSprite.setTexture("PriestessWest");
|
||||
}
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: this.playerSprite,
|
||||
x: tx,
|
||||
@@ -465,7 +478,7 @@ export class DungeonRenderer {
|
||||
this.fxRenderer.showFloatingText(x, y, message, color);
|
||||
}
|
||||
|
||||
showProjectile(from: Vec2, to: Vec2, itemId: string, onComplete: () => void) {
|
||||
showProjectile(from: Vec2, to: Vec2, texture: string, frame: number, onComplete: () => void) {
|
||||
// World coords
|
||||
const startX = from.x * TILE_SIZE + TILE_SIZE / 2;
|
||||
const startY = from.y * TILE_SIZE + TILE_SIZE / 2;
|
||||
@@ -473,15 +486,22 @@ export class DungeonRenderer {
|
||||
const endY = to.y * TILE_SIZE + TILE_SIZE / 2;
|
||||
|
||||
// Create sprite
|
||||
// Look up sprite index from config
|
||||
const itemConfig = ALL_TEMPLATES[itemId as keyof typeof ALL_TEMPLATES];
|
||||
const texture = itemConfig?.textureKey ?? "items";
|
||||
const frame = itemConfig?.spriteIndex ?? 0;
|
||||
const isStandalone = frame === undefined || frame === 0;
|
||||
const sprite = isStandalone
|
||||
? this.scene.add.sprite(startX, startY, texture)
|
||||
: this.scene.add.sprite(startX, startY, texture, frame);
|
||||
|
||||
// Scale for standalone 24x24 image should be 1.0 (or matching world scale)
|
||||
// Other sprites are 16x16.
|
||||
if (isStandalone) {
|
||||
sprite.setDisplaySize(16, 16);
|
||||
} else {
|
||||
sprite.setScale(1.0);
|
||||
}
|
||||
|
||||
// Use 'items' spritesheet
|
||||
const sprite = this.scene.add.sprite(startX, startY, texture, frame);
|
||||
sprite.setDepth(2000);
|
||||
|
||||
|
||||
// Rotate?
|
||||
const angle = Phaser.Math.Angle.Between(startX, startY, endX, endY);
|
||||
sprite.setRotation(angle + Math.PI / 4); // Adjust for sprite orientation (diagonal usually)
|
||||
|
||||
@@ -47,11 +47,11 @@ export class FxRenderer {
|
||||
let textStr = amount.toString();
|
||||
let color = "#ff3333";
|
||||
let fontSize = "16px";
|
||||
|
||||
|
||||
if (isCrit) {
|
||||
textStr += "!";
|
||||
color = "#ffff00";
|
||||
fontSize = "22px";
|
||||
textStr += "!";
|
||||
color = "#ffff00";
|
||||
fontSize = "22px";
|
||||
}
|
||||
|
||||
const text = this.scene.add.text(screenX, screenY, textStr, {
|
||||
@@ -63,19 +63,19 @@ export class FxRenderer {
|
||||
}).setOrigin(0.5, 1).setDepth(200);
|
||||
|
||||
if (isBlock) {
|
||||
const blockText = this.scene.add.text(screenX + 10, screenY - 10, "Blocked", {
|
||||
fontSize: "10px",
|
||||
color: "#888888",
|
||||
fontStyle: "bold"
|
||||
}).setOrigin(0, 1).setDepth(200);
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: blockText,
|
||||
y: screenY - 34,
|
||||
alpha: 0,
|
||||
duration: 800,
|
||||
onComplete: () => blockText.destroy()
|
||||
});
|
||||
const blockText = this.scene.add.text(screenX + 10, screenY - 10, "Blocked", {
|
||||
fontSize: "10px",
|
||||
color: "#888888",
|
||||
fontStyle: "bold"
|
||||
}).setOrigin(0, 1).setDepth(200);
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: blockText,
|
||||
y: screenY - 34,
|
||||
alpha: 0,
|
||||
duration: 800,
|
||||
onComplete: () => blockText.destroy()
|
||||
});
|
||||
}
|
||||
|
||||
this.scene.tweens.add({
|
||||
@@ -132,7 +132,7 @@ export class FxRenderer {
|
||||
}
|
||||
|
||||
spawnCorpse(x: number, y: number, type: ActorType) {
|
||||
const textureKey = type === "player" ? "warrior" : type;
|
||||
const textureKey = type === "player" ? "PriestessSouth" : type;
|
||||
|
||||
const corpse = this.scene.add.sprite(
|
||||
x * TILE_SIZE + TILE_SIZE / 2,
|
||||
@@ -141,7 +141,23 @@ export class FxRenderer {
|
||||
0
|
||||
);
|
||||
corpse.setDepth(50);
|
||||
corpse.play(`${textureKey}-die`);
|
||||
// Use display size for Priestess sprites to match 1 tile
|
||||
if (textureKey.startsWith("Priestess")) {
|
||||
corpse.setDisplaySize(TILE_SIZE, TILE_SIZE);
|
||||
} else {
|
||||
corpse.setScale(1.0); // Reset to standard scale for spritesheet assets
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Only play animation if it's not a priestess sprite
|
||||
if (!textureKey.startsWith("Priestess")) {
|
||||
corpse.play(`${textureKey}-die`);
|
||||
} else {
|
||||
// Maybe rotate or fade for visual interest since there's no animation
|
||||
corpse.setAngle(90);
|
||||
}
|
||||
|
||||
this.corpseSprites.push({ sprite: corpse, x, y });
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ALL_VARIANTS, type ItemVariantId } from "../core/config/ItemVariants";
|
||||
* inventory, quick slots, and world drops.
|
||||
*/
|
||||
export class ItemSpriteFactory {
|
||||
|
||||
|
||||
/**
|
||||
* Creates an item sprite with optional glow effect for variants.
|
||||
* Returns a container with the glow (if applicable) and main sprite.
|
||||
@@ -21,7 +21,7 @@ export class ItemSpriteFactory {
|
||||
scale: number = 1
|
||||
): Phaser.GameObjects.Container {
|
||||
const container = scene.add.container(x, y);
|
||||
|
||||
|
||||
// Create glow effect if item has a variant
|
||||
if (item.variant) {
|
||||
const glowColor = this.getGlowColor(item.variant as ItemVariantId);
|
||||
@@ -30,21 +30,32 @@ export class ItemSpriteFactory {
|
||||
container.add(glow);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Create main item sprite
|
||||
const sprite = scene.add.sprite(0, 0, item.textureKey, item.spriteIndex);
|
||||
sprite.setScale(scale);
|
||||
// Standalone images don't use frame indices
|
||||
const isStandalone = item.spriteIndex === undefined || item.spriteIndex === 0;
|
||||
const sprite = isStandalone
|
||||
? scene.add.sprite(0, 0, item.textureKey)
|
||||
: scene.add.sprite(0, 0, item.textureKey, item.spriteIndex);
|
||||
|
||||
if (isStandalone) {
|
||||
sprite.setDisplaySize(16 * scale, 16 * scale);
|
||||
} else {
|
||||
sprite.setScale(scale);
|
||||
}
|
||||
|
||||
container.add(sprite);
|
||||
|
||||
|
||||
|
||||
// Add upgrade level badge if item has been upgraded
|
||||
if (item.upgradeLevel && item.upgradeLevel > 0) {
|
||||
const badge = this.createUpgradeBadge(scene, item.upgradeLevel, scale);
|
||||
container.add(badge);
|
||||
}
|
||||
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates just a sprite (no container) for simpler use cases like drag icons.
|
||||
* Does not include glow - use createItemSprite for full effect.
|
||||
@@ -56,11 +67,21 @@ export class ItemSpriteFactory {
|
||||
y: number,
|
||||
scale: number = 1
|
||||
): Phaser.GameObjects.Sprite {
|
||||
const sprite = scene.add.sprite(x, y, item.textureKey, item.spriteIndex);
|
||||
sprite.setScale(scale);
|
||||
const isStandalone = item.spriteIndex === undefined || item.spriteIndex === 0;
|
||||
const sprite = isStandalone
|
||||
? scene.add.sprite(x, y, item.textureKey)
|
||||
: scene.add.sprite(x, y, item.textureKey, item.spriteIndex);
|
||||
|
||||
if (isStandalone) {
|
||||
sprite.setDisplaySize(16 * scale, 16 * scale);
|
||||
} else {
|
||||
sprite.setScale(scale);
|
||||
}
|
||||
return sprite;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a soft glow effect behind the item using graphics.
|
||||
* Uses a radial gradient-like effect with multiple circles.
|
||||
@@ -72,26 +93,26 @@ export class ItemSpriteFactory {
|
||||
color: number
|
||||
): Phaser.GameObjects.Graphics {
|
||||
const glow = scene.add.graphics();
|
||||
|
||||
|
||||
// Base size for the glow (16x16 sprite scaled)
|
||||
const baseSize = 16 * scale;
|
||||
const glowRadius = baseSize * 0.8;
|
||||
|
||||
|
||||
// Extract RGB from hex color
|
||||
const r = (color >> 16) & 0xff;
|
||||
const g = (color >> 8) & 0xff;
|
||||
const b = color & 0xff;
|
||||
|
||||
|
||||
// Draw multiple circles with decreasing alpha for soft glow effect
|
||||
const layers = 5;
|
||||
for (let i = layers; i >= 1; i--) {
|
||||
const layerRadius = glowRadius * (i / layers) * 1.2;
|
||||
const layerAlpha = 0.15 * (1 - (i - 1) / layers);
|
||||
|
||||
|
||||
glow.fillStyle(Phaser.Display.Color.GetColor(r, g, b), layerAlpha);
|
||||
glow.fillCircle(0, 0, layerRadius);
|
||||
}
|
||||
|
||||
|
||||
// Add pulsing animation to the glow
|
||||
scene.tweens.add({
|
||||
targets: glow,
|
||||
@@ -103,10 +124,10 @@ export class ItemSpriteFactory {
|
||||
repeat: -1,
|
||||
ease: 'Sine.easeInOut'
|
||||
});
|
||||
|
||||
|
||||
return glow;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the glow color for a variant.
|
||||
*/
|
||||
@@ -114,7 +135,7 @@ export class ItemSpriteFactory {
|
||||
const variant = ALL_VARIANTS[variantId];
|
||||
return variant?.glowColor ?? null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a badge displaying the upgrade level (e.g., "+1").
|
||||
*/
|
||||
@@ -125,7 +146,7 @@ export class ItemSpriteFactory {
|
||||
): Phaser.GameObjects.Text {
|
||||
// Position at top-right corner, slightly inset
|
||||
const offset = 5 * scale;
|
||||
|
||||
|
||||
// Level text with strong outline for readability without background
|
||||
const text = scene.add.text(offset, -offset, `+${level}`, {
|
||||
fontSize: `${9 * scale}px`,
|
||||
@@ -136,7 +157,7 @@ export class ItemSpriteFactory {
|
||||
strokeThickness: 3
|
||||
});
|
||||
text.setOrigin(0.5);
|
||||
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user