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
|
// Drag & drop utilities
|
||||||
export { dragDropEventEffect, DragDropEventType } from "./utils";
|
export { dragDropEventEffect, DragDropEventType } from "./utils";
|
||||||
export type { DragDropEvent, DragDropCallback } from "./utils";
|
export type { DragDropEvent, DragDropCallback } from "./utils";
|
||||||
|
export { hoverEffect } from "./utils";
|
||||||
|
|
||||||
// Data-driven object spawning
|
// Data-driven object spawning
|
||||||
export { spawnEffect } from "./spawner";
|
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 DragDropEvent,
|
||||||
type DragDropCallback,
|
type DragDropCallback,
|
||||||
} from "./dnd";
|
} from "./dnd";
|
||||||
|
export * from "./hover";
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,12 @@ export const NEGATIVE_EFFECTS = new Set([
|
||||||
"poison",
|
"poison",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
export const CARD_CONFIG = {
|
||||||
|
WIDTH: 140,
|
||||||
|
HEIGHT: 200,
|
||||||
|
CORNER_RADIUS: 8,
|
||||||
|
} as const;
|
||||||
|
|
||||||
export const GAME_CONFIG: Phaser.Types.Core.GameConfig = {
|
export const GAME_CONFIG: Phaser.Types.Core.GameConfig = {
|
||||||
width: 1920,
|
width: 1920,
|
||||||
height: 1080,
|
height: 1080,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import Phaser from "phaser";
|
import Phaser, { Tweens } from "phaser";
|
||||||
import type {
|
import type { GameCard } from "boardgame-core/samples/slay-the-spire-like";
|
||||||
CardData,
|
import { CARD_CONFIG } from "@/config";
|
||||||
GameCard,
|
import { hoverEffect } from "boardgame-phaser";
|
||||||
} from "boardgame-core/samples/slay-the-spire-like";
|
|
||||||
|
|
||||||
export interface CardContainerOptions {
|
export interface CardContainerOptions {
|
||||||
card: GameCard;
|
card: GameCard;
|
||||||
|
|
@ -10,9 +9,9 @@ export interface CardContainerOptions {
|
||||||
playable?: boolean;
|
playable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CARD_WIDTH = 140;
|
const CARD_WIDTH = CARD_CONFIG.WIDTH;
|
||||||
const CARD_HEIGHT = 200;
|
const CARD_HEIGHT = CARD_CONFIG.HEIGHT;
|
||||||
const CORNER_RADIUS = 8;
|
const CORNER_RADIUS = CARD_CONFIG.CORNER_RADIUS;
|
||||||
|
|
||||||
export class CardContainer extends Phaser.GameObjects.Container {
|
export class CardContainer extends Phaser.GameObjects.Container {
|
||||||
private bg!: Phaser.GameObjects.Rectangle;
|
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.input.cursor = options.playable ? "pointer" : "not-allowed";
|
||||||
}
|
}
|
||||||
|
|
||||||
this.on("pointerover", () => {
|
hoverEffect(this, (hovering) => {
|
||||||
if (options.playable && !this._selected) {
|
if (!options.playable) return;
|
||||||
this.hoverIn();
|
this.playHoverTween(hovering);
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.on("pointerout", () => {
|
|
||||||
if (!this._selected) {
|
|
||||||
this.hoverOut();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.on("pointerdown", () => {
|
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 {
|
setSelected(selected: boolean): void {
|
||||||
this._selected = selected;
|
this._selected = selected;
|
||||||
if (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 {
|
destroy(fromScene?: boolean): void {
|
||||||
this.highlight = null;
|
this.highlight = null;
|
||||||
super.destroy(fromScene);
|
super.destroy(fromScene);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue