fix: inventory interaction

This commit is contained in:
hypercross 2026-04-17 19:45:34 +08:00
parent 28a2623bd1
commit 0ecef16a4a
1 changed files with 77 additions and 8 deletions

View File

@ -33,11 +33,16 @@ interface DragState {
itemMeta: InventoryItem<GameItemMeta>['meta']; itemMeta: InventoryItem<GameItemMeta>['meta'];
ghostContainer: Phaser.GameObjects.Container; ghostContainer: Phaser.GameObjects.Container;
previewGraphics: Phaser.GameObjects.Graphics; previewGraphics: Phaser.GameObjects.Graphics;
dragOffsetX: number;
dragOffsetY: number;
} }
interface LostItem { interface LostItem {
id: string; id: string;
container: Phaser.GameObjects.Container; container: Phaser.GameObjects.Container;
shape: InventoryItem<GameItemMeta>['shape'];
transform: InventoryItem<GameItemMeta>['transform'];
meta: InventoryItem<GameItemMeta>['meta'];
} }
export class InventoryWidget { export class InventoryWidget {
@ -76,13 +81,13 @@ export class InventoryWidget {
this.container = this.scene.add.container(options.x, options.y); this.container = this.scene.add.container(options.x, options.y);
this.pointerMoveHandler = this.onPointerMove.bind(this);
this.pointerUpHandler = this.onPointerUp.bind(this);
this.drawGridBackground(inventory.width, inventory.height, gridW, gridH); this.drawGridBackground(inventory.width, inventory.height, gridW, gridH);
this.drawItems(); this.drawItems();
this.setupInput(); this.setupInput();
this.pointerMoveHandler = this.onPointerMove.bind(this);
this.pointerUpHandler = this.onPointerUp.bind(this);
this.scene.events.once('shutdown', () => this.destroy()); this.scene.events.once('shutdown', () => this.destroy());
} }
@ -205,7 +210,14 @@ export class InventoryWidget {
}); });
this.removeItemVisuals(itemId); this.removeItemVisuals(itemId);
const ghostContainer = this.scene.add.container(pointer.x, pointer.y).setDepth(1000); const cells = this.getItemCells(item);
const firstCell = cells[0];
const itemWorldX = this.container.x + this.gridX + firstCell.x * (this.cellSize + this.gridGap);
const itemWorldY = this.container.y + this.gridY + firstCell.y * (this.cellSize + this.gridGap);
const dragOffsetX = pointer.x - itemWorldX;
const dragOffsetY = pointer.y - itemWorldY;
const ghostContainer = this.scene.add.container(itemWorldX, itemWorldY).setDepth(1000);
const ghostGraphics = this.scene.add.graphics(); const ghostGraphics = this.scene.add.graphics();
const color = this.colorMap.get(itemId) ?? 0x888888; const color = this.colorMap.get(itemId) ?? 0x888888;
@ -230,6 +242,42 @@ export class InventoryWidget {
itemMeta: item.meta, itemMeta: item.meta,
ghostContainer, ghostContainer,
previewGraphics, previewGraphics,
dragOffsetX,
dragOffsetY,
};
}
private startLostItemDrag(itemId: string, pointer: Phaser.Input.Pointer): void {
const lost = this.lostItems.get(itemId);
if (!lost) return;
lost.container.destroy();
this.lostItems.delete(itemId);
const ghostContainer = this.scene.add.container(pointer.x, pointer.y).setDepth(1000);
const ghostGraphics = this.scene.add.graphics();
const color = this.colorMap.get(itemId) ?? 0x888888;
const cells = transformShape(lost.shape, lost.transform);
for (const cell of cells) {
ghostGraphics.fillStyle(color, 0.7);
ghostGraphics.fillRect(cell.x * (this.cellSize + this.gridGap), cell.y * (this.cellSize + this.gridGap), this.cellSize - 2, this.cellSize - 2);
ghostGraphics.lineStyle(2, 0xffffff);
ghostGraphics.strokeRect(cell.x * (this.cellSize + this.gridGap), cell.y * (this.cellSize + this.gridGap), this.cellSize, this.cellSize);
}
ghostContainer.add(ghostGraphics);
const previewGraphics = this.scene.add.graphics().setDepth(999).setAlpha(0.5);
this.dragState = {
itemId,
itemShape: lost.shape,
itemTransform: { ...lost.transform, offset: { ...lost.transform.offset } },
itemMeta: lost.meta,
ghostContainer,
previewGraphics,
dragOffsetX: 0,
dragOffsetY: 0,
}; };
} }
@ -265,9 +313,9 @@ export class InventoryWidget {
private onPointerMove(pointer: Phaser.Input.Pointer): void { private onPointerMove(pointer: Phaser.Input.Pointer): void {
if (!this.dragState) return; if (!this.dragState) return;
this.dragState.ghostContainer.setPosition(pointer.x, pointer.y); this.dragState.ghostContainer.setPosition(pointer.x - this.dragState.dragOffsetX, pointer.y - this.dragState.dragOffsetY);
const gridCell = this.getWorldGridCell(pointer.x, pointer.y); const gridCell = this.getWorldGridCell(pointer.x - this.dragState.dragOffsetX, pointer.y - this.dragState.dragOffsetY);
this.dragState.previewGraphics.clear(); this.dragState.previewGraphics.clear();
if (gridCell) { if (gridCell) {
@ -298,7 +346,7 @@ export class InventoryWidget {
private onPointerUp(pointer: Phaser.Input.Pointer): void { private onPointerUp(pointer: Phaser.Input.Pointer): void {
if (!this.dragState) return; if (!this.dragState) return;
const gridCell = this.getWorldGridCell(pointer.x, pointer.y); const gridCell = this.getWorldGridCell(pointer.x - this.dragState.dragOffsetX, pointer.y - this.dragState.dragOffsetY);
const inventory = this.getInventory(); const inventory = this.getInventory();
this.dragState.ghostContainer.destroy(); this.dragState.ghostContainer.destroy();
@ -345,6 +393,10 @@ export class InventoryWidget {
const cellX = Math.floor(localX / (this.cellSize + this.gridGap)); const cellX = Math.floor(localX / (this.cellSize + this.gridGap));
const cellY = Math.floor(localY / (this.cellSize + this.gridGap)); const cellY = Math.floor(localY / (this.cellSize + this.gridGap));
if (cellX < 0 || cellY < 0 || cellX >= this.getInventory().width || cellY >= this.getInventory().height) {
return null;
}
return { x: cellX, y: cellY }; return { x: cellX, y: cellY };
} }
@ -376,7 +428,24 @@ export class InventoryWidget {
}).setOrigin(0.5); }).setOrigin(0.5);
container.add(text); container.add(text);
this.lostItems.set(this.dragState.itemId, { id: this.dragState.itemId, container }); const hitRect = new Phaser.Geom.Rectangle(0, 0, this.cellSize, this.cellSize);
container.setInteractive(hitRect, Phaser.Geom.Rectangle.Contains);
container.on('pointerdown', (pointer: Phaser.Input.Pointer) => {
if (this.isLocked) return;
if (this.dragState) return;
if (pointer.button === 0) {
this.startLostItemDrag(this.dragState!.itemId, pointer);
}
});
this.lostItems.set(this.dragState.itemId, {
id: this.dragState.itemId,
container,
shape: this.dragState.itemShape,
transform: { ...this.dragState.itemTransform },
meta: this.dragState.itemMeta,
});
} }
private removeItemVisuals(itemId: string): void { private removeItemVisuals(itemId: string): void {