feat(framework): add hoverEffect utility
Add a `hoverEffect` utility to `boardgame-phaser` to simplify handling pointerover and pointerout events. Refactor `CardContainer` in `sts-like-viewer` to use this new utility and centralize card dimensions in `CARD_CONFIG`.
This commit is contained in:
parent
5d84c42b78
commit
dda290bf9c
|
|
@ -5,6 +5,7 @@ export type { IDisposable, DisposableItem } from "./utils";
|
|||
// Drag & drop utilities
|
||||
export { dragDropEventEffect, DragDropEventType } from "./utils";
|
||||
export type { DragDropEvent, DragDropCallback } from "./utils";
|
||||
export { hoverEffect } from "./utils";
|
||||
|
||||
// Data-driven object spawning
|
||||
export { spawnEffect } from "./spawner";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
type HoverCallback = (hovering: boolean) => void;
|
||||
export function hoverEffect(
|
||||
gameObject: Phaser.GameObjects.GameObject,
|
||||
callback: HoverCallback,
|
||||
) {
|
||||
let isHovering = false;
|
||||
const onPointerOver = () => {
|
||||
if (isHovering) return;
|
||||
isHovering = true;
|
||||
callback(true);
|
||||
};
|
||||
const onPointerOut = () => {
|
||||
if (!isHovering) return;
|
||||
isHovering = false;
|
||||
callback(false);
|
||||
};
|
||||
|
||||
gameObject.on("pointerover", onPointerOver);
|
||||
gameObject.on("pointerout", onPointerOut);
|
||||
const cleanup = () => {
|
||||
gameObject.off("pointerover", onPointerOver);
|
||||
gameObject.off("pointerout", onPointerOut);
|
||||
gameObject.off("destroy", cleanup);
|
||||
};
|
||||
|
||||
gameObject.once("destroy", cleanup);
|
||||
return cleanup;
|
||||
}
|
||||
|
|
@ -6,3 +6,4 @@ export {
|
|||
type DragDropEvent,
|
||||
type DragDropCallback,
|
||||
} from "./dnd";
|
||||
export * from "./hover";
|
||||
|
|
|
|||
|
|
@ -156,6 +156,12 @@ export const NEGATIVE_EFFECTS = new Set([
|
|||
"poison",
|
||||
]);
|
||||
|
||||
export const CARD_CONFIG = {
|
||||
WIDTH: 140,
|
||||
HEIGHT: 200,
|
||||
CORNER_RADIUS: 8,
|
||||
} as const;
|
||||
|
||||
export const GAME_CONFIG: Phaser.Types.Core.GameConfig = {
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import Phaser from "phaser";
|
||||
import type {
|
||||
CardData,
|
||||
GameCard,
|
||||
} from "boardgame-core/samples/slay-the-spire-like";
|
||||
import Phaser, { Tweens } from "phaser";
|
||||
import type { GameCard } from "boardgame-core/samples/slay-the-spire-like";
|
||||
import { CARD_CONFIG } from "@/config";
|
||||
import { hoverEffect } from "boardgame-phaser";
|
||||
|
||||
export interface CardContainerOptions {
|
||||
card: GameCard;
|
||||
|
|
@ -10,9 +9,9 @@ export interface CardContainerOptions {
|
|||
playable?: boolean;
|
||||
}
|
||||
|
||||
const CARD_WIDTH = 140;
|
||||
const CARD_HEIGHT = 200;
|
||||
const CORNER_RADIUS = 8;
|
||||
const CARD_WIDTH = CARD_CONFIG.WIDTH;
|
||||
const CARD_HEIGHT = CARD_CONFIG.HEIGHT;
|
||||
const CORNER_RADIUS = CARD_CONFIG.CORNER_RADIUS;
|
||||
|
||||
export class CardContainer extends Phaser.GameObjects.Container {
|
||||
private bg!: Phaser.GameObjects.Rectangle;
|
||||
|
|
@ -110,16 +109,9 @@ export class CardContainer extends Phaser.GameObjects.Container {
|
|||
this.input.cursor = options.playable ? "pointer" : "not-allowed";
|
||||
}
|
||||
|
||||
this.on("pointerover", () => {
|
||||
if (options.playable && !this._selected) {
|
||||
this.hoverIn();
|
||||
}
|
||||
});
|
||||
|
||||
this.on("pointerout", () => {
|
||||
if (!this._selected) {
|
||||
this.hoverOut();
|
||||
}
|
||||
hoverEffect(this, (hovering) => {
|
||||
if (!options.playable) return;
|
||||
this.playHoverTween(hovering);
|
||||
});
|
||||
|
||||
this.on("pointerdown", () => {
|
||||
|
|
@ -129,28 +121,6 @@ export class CardContainer extends Phaser.GameObjects.Container {
|
|||
});
|
||||
}
|
||||
|
||||
private hoverIn(): void {
|
||||
this.scene.tweens.add({
|
||||
targets: this,
|
||||
y: this.y - 10,
|
||||
scale: 1.08,
|
||||
duration: 150,
|
||||
ease: "Power2",
|
||||
});
|
||||
this.bg.setStrokeStyle(3, 0x88aaff);
|
||||
}
|
||||
|
||||
private hoverOut(): void {
|
||||
this.scene.tweens.add({
|
||||
targets: this,
|
||||
y: this.y + 10,
|
||||
scale: 1,
|
||||
duration: 150,
|
||||
ease: "Power2",
|
||||
});
|
||||
this.bg.setStrokeStyle(2, 0x555577);
|
||||
}
|
||||
|
||||
setSelected(selected: boolean): void {
|
||||
this._selected = selected;
|
||||
if (selected) {
|
||||
|
|
@ -212,6 +182,20 @@ export class CardContainer extends Phaser.GameObjects.Container {
|
|||
});
|
||||
}
|
||||
|
||||
private playHoverTween(isHovering: boolean) {
|
||||
this.scene.tweens.add({
|
||||
targets: this,
|
||||
y: isHovering ? this.y - 10 : this.y + 10,
|
||||
scale: isHovering ? 1.08 : 1,
|
||||
duration: 150,
|
||||
ease: "Power2",
|
||||
});
|
||||
this.bg.setStrokeStyle(
|
||||
isHovering ? 3 : 2,
|
||||
isHovering ? 0x88aaff : 0x555577,
|
||||
);
|
||||
}
|
||||
|
||||
destroy(fromScene?: boolean): void {
|
||||
this.highlight = null;
|
||||
super.destroy(fromScene);
|
||||
|
|
|
|||
Loading…
Reference in New Issue