refactor: implement cell-based hit area for inventory items
Update `InventoryItemContainer` to use a custom hit area callback based on individual cell rectangles instead of a single bounding box. This allows for more precise interaction with non-rectangular item shapes.
This commit is contained in:
parent
b2862e34d9
commit
19dfafeb30
|
|
@ -7,8 +7,6 @@ import {
|
|||
Transform2D,
|
||||
transformShape,
|
||||
type GameItem,
|
||||
type GameItemMeta,
|
||||
type InventoryItem,
|
||||
} from "boardgame-core/samples/slay-the-spire-like";
|
||||
import { computed, signal, Signal } from "@preact/signals-core";
|
||||
import { DisposableBag } from "../../../framework/dist";
|
||||
|
|
@ -56,15 +54,12 @@ export class InventoryItemContainer extends Phaser.GameObjects.Container {
|
|||
const color = computed(() => {
|
||||
return this.getItemColor(this.item.value?.id ?? "");
|
||||
});
|
||||
let hasSize = false;
|
||||
disposables.addEffect(() => {
|
||||
graphics.clear();
|
||||
if (!shape.value) return;
|
||||
this.renderGraphics(graphics, shape.value, color.value);
|
||||
const cellRects = this.renderGraphics(graphics, shape.value, color.value);
|
||||
|
||||
if (hasSize) return;
|
||||
hasSize = true;
|
||||
this.setupInteractive();
|
||||
this.setupInteractive(cellRects);
|
||||
});
|
||||
|
||||
const transform = computed(() => {
|
||||
|
|
@ -84,8 +79,10 @@ export class InventoryItemContainer extends Phaser.GameObjects.Container {
|
|||
graphics: Phaser.GameObjects.Graphics,
|
||||
shape: ParsedShape,
|
||||
itemColor: number,
|
||||
): void {
|
||||
): { x: number; y: number }[] {
|
||||
const cells = transformShape(shape, IDENTITY_TRANSFORM);
|
||||
const cellRects: { x: number; y: number }[] = [];
|
||||
|
||||
for (const cell of cells) {
|
||||
const localX = (cell.x - cells[0].x) * GRID_CONFIG.VIEWER_CELL_SIZE;
|
||||
const localY = (cell.y - cells[0].y) * GRID_CONFIG.VIEWER_CELL_SIZE;
|
||||
|
|
@ -97,12 +94,11 @@ export class InventoryItemContainer extends Phaser.GameObjects.Container {
|
|||
GRID_CONFIG.VIEWER_CELL_SIZE - 4,
|
||||
GRID_CONFIG.VIEWER_CELL_SIZE - 4,
|
||||
);
|
||||
|
||||
cellRects.push({ x: localX, y: localY });
|
||||
}
|
||||
|
||||
this.setSize(
|
||||
GRID_CONFIG.VIEWER_CELL_SIZE * shape.width,
|
||||
GRID_CONFIG.VIEWER_CELL_SIZE * shape.height,
|
||||
);
|
||||
return cellRects;
|
||||
}
|
||||
|
||||
private getItemColor(itemId: string): number {
|
||||
|
|
@ -110,9 +106,26 @@ export class InventoryItemContainer extends Phaser.GameObjects.Container {
|
|||
return ITEM_COLORS[hash % ITEM_COLORS.length];
|
||||
}
|
||||
|
||||
private setupInteractive(): void {
|
||||
private setupInteractive(cellRects: { x: number; y: number }[]): void {
|
||||
this.setScrollFactor(0);
|
||||
this.setInteractive({ useHandCursor: true });
|
||||
const cellSize = GRID_CONFIG.VIEWER_CELL_SIZE;
|
||||
this.setInteractive({
|
||||
hitArea: cellRects,
|
||||
hitAreaCallback: (
|
||||
hitArea: { x: number; y: number }[],
|
||||
x: number,
|
||||
y: number,
|
||||
) => {
|
||||
return hitArea.some(
|
||||
(cell) =>
|
||||
x >= cell.x &&
|
||||
x < cell.x + cellSize &&
|
||||
y >= cell.y &&
|
||||
y < cell.y + cellSize,
|
||||
);
|
||||
},
|
||||
useHandCursor: true,
|
||||
} as Phaser.Types.Input.InputConfiguration);
|
||||
|
||||
let startX = 0;
|
||||
let startY = 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue