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,
|
Transform2D,
|
||||||
transformShape,
|
transformShape,
|
||||||
type GameItem,
|
type GameItem,
|
||||||
type GameItemMeta,
|
|
||||||
type InventoryItem,
|
|
||||||
} from "boardgame-core/samples/slay-the-spire-like";
|
} from "boardgame-core/samples/slay-the-spire-like";
|
||||||
import { computed, signal, Signal } from "@preact/signals-core";
|
import { computed, signal, Signal } from "@preact/signals-core";
|
||||||
import { DisposableBag } from "../../../framework/dist";
|
import { DisposableBag } from "../../../framework/dist";
|
||||||
|
|
@ -56,15 +54,12 @@ export class InventoryItemContainer extends Phaser.GameObjects.Container {
|
||||||
const color = computed(() => {
|
const color = computed(() => {
|
||||||
return this.getItemColor(this.item.value?.id ?? "");
|
return this.getItemColor(this.item.value?.id ?? "");
|
||||||
});
|
});
|
||||||
let hasSize = false;
|
|
||||||
disposables.addEffect(() => {
|
disposables.addEffect(() => {
|
||||||
graphics.clear();
|
graphics.clear();
|
||||||
if (!shape.value) return;
|
if (!shape.value) return;
|
||||||
this.renderGraphics(graphics, shape.value, color.value);
|
const cellRects = this.renderGraphics(graphics, shape.value, color.value);
|
||||||
|
|
||||||
if (hasSize) return;
|
this.setupInteractive(cellRects);
|
||||||
hasSize = true;
|
|
||||||
this.setupInteractive();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const transform = computed(() => {
|
const transform = computed(() => {
|
||||||
|
|
@ -84,8 +79,10 @@ export class InventoryItemContainer extends Phaser.GameObjects.Container {
|
||||||
graphics: Phaser.GameObjects.Graphics,
|
graphics: Phaser.GameObjects.Graphics,
|
||||||
shape: ParsedShape,
|
shape: ParsedShape,
|
||||||
itemColor: number,
|
itemColor: number,
|
||||||
): void {
|
): { x: number; y: number }[] {
|
||||||
const cells = transformShape(shape, IDENTITY_TRANSFORM);
|
const cells = transformShape(shape, IDENTITY_TRANSFORM);
|
||||||
|
const cellRects: { x: number; y: number }[] = [];
|
||||||
|
|
||||||
for (const cell of cells) {
|
for (const cell of cells) {
|
||||||
const localX = (cell.x - cells[0].x) * GRID_CONFIG.VIEWER_CELL_SIZE;
|
const localX = (cell.x - cells[0].x) * GRID_CONFIG.VIEWER_CELL_SIZE;
|
||||||
const localY = (cell.y - cells[0].y) * 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,
|
||||||
GRID_CONFIG.VIEWER_CELL_SIZE - 4,
|
GRID_CONFIG.VIEWER_CELL_SIZE - 4,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
cellRects.push({ x: localX, y: localY });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setSize(
|
return cellRects;
|
||||||
GRID_CONFIG.VIEWER_CELL_SIZE * shape.width,
|
|
||||||
GRID_CONFIG.VIEWER_CELL_SIZE * shape.height,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getItemColor(itemId: string): number {
|
private getItemColor(itemId: string): number {
|
||||||
|
|
@ -110,9 +106,26 @@ export class InventoryItemContainer extends Phaser.GameObjects.Container {
|
||||||
return ITEM_COLORS[hash % ITEM_COLORS.length];
|
return ITEM_COLORS[hash % ITEM_COLORS.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupInteractive(): void {
|
private setupInteractive(cellRects: { x: number; y: number }[]): void {
|
||||||
this.setScrollFactor(0);
|
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 startX = 0;
|
||||||
let startY = 0;
|
let startY = 0;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue