refactor: update to new version

This commit is contained in:
2026-04-17 17:29:13 +08:00
parent 706de4e33a
commit f7a6154c68
5 changed files with 49 additions and 76 deletions
@@ -4,14 +4,15 @@ import {
placeItem,
getAdjacentItems,
parseShapeString,
heroItemFighter1Data,
data,
type GridInventory,
type InventoryItem,
type GameItemMeta,
} from 'boardgame-core/samples/slay-the-spire-like';
import { ReactiveScene } from 'boardgame-phaser';
export class GridViewerScene extends ReactiveScene {
private inventory: GridInventory;
private inventory: GridInventory<GameItemMeta>;
private readonly CELL_SIZE = 60;
private readonly GRID_WIDTH = 6;
private readonly GRID_HEIGHT = 4;
@@ -20,7 +21,7 @@ export class GridViewerScene extends ReactiveScene {
constructor() {
super('GridViewerScene');
this.inventory = createGridInventory(this.GRID_WIDTH, this.GRID_HEIGHT);
this.inventory = createGridInventory<GameItemMeta>(this.GRID_WIDTH, this.GRID_HEIGHT);
}
create(): void {
@@ -29,26 +30,18 @@ export class GridViewerScene extends ReactiveScene {
this.gridOffsetX = (width - this.GRID_WIDTH * this.CELL_SIZE) / 2;
this.gridOffsetY = (height - this.GRID_HEIGHT * this.CELL_SIZE) / 2 + 20;
// Place some sample items
this.placeSampleItems();
// Draw grid
this.drawGrid();
// Draw items
this.drawItems();
// Title
this.add.text(width / 2, 30, 'Grid Inventory Viewer (4x6)', {
fontSize: '24px',
color: '#ffffff',
fontStyle: 'bold',
}).setOrigin(0.5);
// Controls
this.createControls();
// Info text
this.add.text(width / 2, height - 40, 'Hover over cells to see item details', {
fontSize: '14px',
color: '#aaaaaa',
@@ -56,22 +49,23 @@ export class GridViewerScene extends ReactiveScene {
}
private placeSampleItems(): void {
// Place a few items from heroItemFighter1Data
const items = data.desert.items;
const sampleItems = [
{ index: 0, x: 0, y: 0 }, // 剑
{ index: 3, x: 3, y: 0 }, // 短刀
{ index: 6, x: 0, y: 2 }, // 盾
{ index: 12, x: 3, y: 2 }, // 披风
{ index: 0, x: 0, y: 0 },
{ index: 3, x: 3, y: 0 },
{ index: 6, x: 0, y: 2 },
{ index: 12, x: 3, y: 2 },
];
for (const { index, x, y } of sampleItems) {
const data = heroItemFighter1Data[index];
const shape = parseShapeString(data.shape);
const item: InventoryItem = {
if (index >= items.length) continue;
const itemData = items[index];
const shape = parseShapeString(itemData.shape);
const item: InventoryItem<GameItemMeta> = {
id: `item-${index}`,
shape,
transform: { offset: { x, y }, rotation: 0, flipX: false, flipY: false },
meta: { name: data.name, data },
meta: { itemData, shape },
};
placeItem(this.inventory, item);
}
@@ -80,7 +74,6 @@ export class GridViewerScene extends ReactiveScene {
private drawGrid(): void {
const graphics = this.add.graphics();
// Draw cells
for (let y = 0; y < this.GRID_HEIGHT; y++) {
for (let x = 0; x < this.GRID_WIDTH; x++) {
const px = this.gridOffsetX + x * this.CELL_SIZE;
@@ -102,7 +95,6 @@ export class GridViewerScene extends ReactiveScene {
const shape = item.shape;
const transform = item.transform;
// Get occupied cells
const cells: { x: number; y: number }[] = [];
for (let y = 0; y < shape.height; y++) {
for (let x = 0; x < shape.width; x++) {
@@ -114,7 +106,6 @@ export class GridViewerScene extends ReactiveScene {
}
}
// Draw item cells with a unique color per item
const itemColor = this.getItemColor(itemId);
const graphics = this.add.graphics();
@@ -126,12 +117,11 @@ export class GridViewerScene extends ReactiveScene {
graphics.fillRect(px + 2, py + 2, this.CELL_SIZE - 4, this.CELL_SIZE - 4);
}
// Item name label (at first cell)
if (cells.length > 0) {
const firstCell = cells[0];
const px = this.gridOffsetX + firstCell.x * this.CELL_SIZE;
const py = this.gridOffsetY + firstCell.y * this.CELL_SIZE;
const itemName = (item.meta?.name as string) ?? item.id;
const itemName = item.meta?.itemData.name ?? item.id;
this.add.text(px + this.CELL_SIZE / 2, py + this.CELL_SIZE / 2, itemName, {
fontSize: '11px',
@@ -140,10 +130,9 @@ export class GridViewerScene extends ReactiveScene {
}).setOrigin(0.5);
}
// Adjacent items info
const adjacent = getAdjacentItems(this.inventory, itemId);
if (adjacent.size > 0) {
const adjacentNames = Array.from(adjacent.values()).map(i => (i.meta?.name as string) ?? i.id).join(', ');
const adjacentNames = Array.from(adjacent.values()).map(i => i.meta?.itemData.name ?? i.id).join(', ');
const firstCell = cells[0];
const px = this.gridOffsetX + firstCell.x * this.CELL_SIZE;
const py = this.gridOffsetY + firstCell.y * this.CELL_SIZE - 20;
@@ -157,7 +146,6 @@ export class GridViewerScene extends ReactiveScene {
}
private getItemColor(itemId: string): number {
// Generate a consistent color based on item ID
const hash = itemId.split('').reduce((acc, c) => acc + c.charCodeAt(0), 0);
const colors = [0x4488cc, 0xcc8844, 0x44cc88, 0xcc4488, 0x8844cc, 0x44cccc];
return colors[hash % colors.length];
@@ -166,18 +154,15 @@ export class GridViewerScene extends ReactiveScene {
private createControls(): void {
const { width, height } = this.scale;
// Back button
this.createButton('返回菜单', 100, 40, async () => {
await this.sceneController.launch('IndexScene');
});
// Clear button
this.createButton('清空', width - 260, 40, async () => {
this.inventory = createGridInventory(this.GRID_WIDTH, this.GRID_HEIGHT);
this.inventory = createGridInventory<GameItemMeta>(this.GRID_WIDTH, this.GRID_HEIGHT);
await this.sceneController.restart();
});
// Random fill button
this.createButton('随机填充', width - 130, 40, async () => {
this.randomFill();
await this.sceneController.restart();
@@ -185,16 +170,15 @@ export class GridViewerScene extends ReactiveScene {
}
private randomFill(): void {
this.inventory = createGridInventory(this.GRID_WIDTH, this.GRID_HEIGHT);
this.inventory = createGridInventory<GameItemMeta>(this.GRID_WIDTH, this.GRID_HEIGHT);
const items = data.desert.items;
// Try to place random items
let itemIndex = 0;
for (let y = 0; y < this.GRID_HEIGHT && itemIndex < heroItemFighter1Data.length; y++) {
for (let x = 0; x < this.GRID_WIDTH && itemIndex < heroItemFighter1Data.length; x++) {
const data = heroItemFighter1Data[itemIndex];
const shape = parseShapeString(data.shape);
for (let y = 0; y < this.GRID_HEIGHT && itemIndex < items.length; y++) {
for (let x = 0; x < this.GRID_WIDTH && itemIndex < items.length; x++) {
const itemData = items[itemIndex];
const shape = parseShapeString(itemData.shape);
// Check if placement is valid
const occupiedCells = new Set<string>();
for (let sy = 0; sy < shape.height; sy++) {
for (let sx = 0; sx < shape.width; sx++) {
@@ -204,22 +188,21 @@ export class GridViewerScene extends ReactiveScene {
}
}
// Simple check if any cell is out of bounds or occupied
let valid = true;
for (const cell of occupiedCells) {
const [cx, cy] = cell.split(',').map(Number);
if (cx >= this.GRID_WIDTH || cy >= this.GRID_HEIGHT || this.inventory.occupiedCells.has(cell)) {
if (cx >= this.GRID_WIDTH || cy >= this.GRID_HEIGHT || this.inventory.occupiedCells.has(cell as `${number},${number}`)) {
valid = false;
break;
}
}
if (valid) {
const item: InventoryItem = {
const item: InventoryItem<GameItemMeta> = {
id: `item-${itemIndex}`,
shape,
transform: { offset: { x, y }, rotation: 0, flipX: false, flipY: false },
meta: { name: data.name, data },
meta: { itemData, shape },
};
placeItem(this.inventory, item);
itemIndex++;