refactor: update to new version
This commit is contained in:
parent
706de4e33a
commit
f7a6154c68
|
|
@ -4,14 +4,15 @@ import {
|
||||||
placeItem,
|
placeItem,
|
||||||
getAdjacentItems,
|
getAdjacentItems,
|
||||||
parseShapeString,
|
parseShapeString,
|
||||||
heroItemFighter1Data,
|
data,
|
||||||
type GridInventory,
|
type GridInventory,
|
||||||
type InventoryItem,
|
type InventoryItem,
|
||||||
|
type GameItemMeta,
|
||||||
} from 'boardgame-core/samples/slay-the-spire-like';
|
} from 'boardgame-core/samples/slay-the-spire-like';
|
||||||
import { ReactiveScene } from 'boardgame-phaser';
|
import { ReactiveScene } from 'boardgame-phaser';
|
||||||
|
|
||||||
export class GridViewerScene extends ReactiveScene {
|
export class GridViewerScene extends ReactiveScene {
|
||||||
private inventory: GridInventory;
|
private inventory: GridInventory<GameItemMeta>;
|
||||||
private readonly CELL_SIZE = 60;
|
private readonly CELL_SIZE = 60;
|
||||||
private readonly GRID_WIDTH = 6;
|
private readonly GRID_WIDTH = 6;
|
||||||
private readonly GRID_HEIGHT = 4;
|
private readonly GRID_HEIGHT = 4;
|
||||||
|
|
@ -20,7 +21,7 @@ export class GridViewerScene extends ReactiveScene {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super('GridViewerScene');
|
super('GridViewerScene');
|
||||||
this.inventory = createGridInventory(this.GRID_WIDTH, this.GRID_HEIGHT);
|
this.inventory = createGridInventory<GameItemMeta>(this.GRID_WIDTH, this.GRID_HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
create(): void {
|
create(): void {
|
||||||
|
|
@ -29,26 +30,18 @@ export class GridViewerScene extends ReactiveScene {
|
||||||
this.gridOffsetX = (width - this.GRID_WIDTH * this.CELL_SIZE) / 2;
|
this.gridOffsetX = (width - this.GRID_WIDTH * this.CELL_SIZE) / 2;
|
||||||
this.gridOffsetY = (height - this.GRID_HEIGHT * this.CELL_SIZE) / 2 + 20;
|
this.gridOffsetY = (height - this.GRID_HEIGHT * this.CELL_SIZE) / 2 + 20;
|
||||||
|
|
||||||
// Place some sample items
|
|
||||||
this.placeSampleItems();
|
this.placeSampleItems();
|
||||||
|
|
||||||
// Draw grid
|
|
||||||
this.drawGrid();
|
this.drawGrid();
|
||||||
|
|
||||||
// Draw items
|
|
||||||
this.drawItems();
|
this.drawItems();
|
||||||
|
|
||||||
// Title
|
|
||||||
this.add.text(width / 2, 30, 'Grid Inventory Viewer (4x6)', {
|
this.add.text(width / 2, 30, 'Grid Inventory Viewer (4x6)', {
|
||||||
fontSize: '24px',
|
fontSize: '24px',
|
||||||
color: '#ffffff',
|
color: '#ffffff',
|
||||||
fontStyle: 'bold',
|
fontStyle: 'bold',
|
||||||
}).setOrigin(0.5);
|
}).setOrigin(0.5);
|
||||||
|
|
||||||
// Controls
|
|
||||||
this.createControls();
|
this.createControls();
|
||||||
|
|
||||||
// Info text
|
|
||||||
this.add.text(width / 2, height - 40, 'Hover over cells to see item details', {
|
this.add.text(width / 2, height - 40, 'Hover over cells to see item details', {
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
color: '#aaaaaa',
|
color: '#aaaaaa',
|
||||||
|
|
@ -56,22 +49,23 @@ export class GridViewerScene extends ReactiveScene {
|
||||||
}
|
}
|
||||||
|
|
||||||
private placeSampleItems(): void {
|
private placeSampleItems(): void {
|
||||||
// Place a few items from heroItemFighter1Data
|
const items = data.desert.items;
|
||||||
const sampleItems = [
|
const sampleItems = [
|
||||||
{ index: 0, x: 0, y: 0 }, // 剑
|
{ index: 0, x: 0, y: 0 },
|
||||||
{ index: 3, x: 3, y: 0 }, // 短刀
|
{ index: 3, x: 3, y: 0 },
|
||||||
{ index: 6, x: 0, y: 2 }, // 盾
|
{ index: 6, x: 0, y: 2 },
|
||||||
{ index: 12, x: 3, y: 2 }, // 披风
|
{ index: 12, x: 3, y: 2 },
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const { index, x, y } of sampleItems) {
|
for (const { index, x, y } of sampleItems) {
|
||||||
const data = heroItemFighter1Data[index];
|
if (index >= items.length) continue;
|
||||||
const shape = parseShapeString(data.shape);
|
const itemData = items[index];
|
||||||
const item: InventoryItem = {
|
const shape = parseShapeString(itemData.shape);
|
||||||
|
const item: InventoryItem<GameItemMeta> = {
|
||||||
id: `item-${index}`,
|
id: `item-${index}`,
|
||||||
shape,
|
shape,
|
||||||
transform: { offset: { x, y }, rotation: 0, flipX: false, flipY: false },
|
transform: { offset: { x, y }, rotation: 0, flipX: false, flipY: false },
|
||||||
meta: { name: data.name, data },
|
meta: { itemData, shape },
|
||||||
};
|
};
|
||||||
placeItem(this.inventory, item);
|
placeItem(this.inventory, item);
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +74,6 @@ export class GridViewerScene extends ReactiveScene {
|
||||||
private drawGrid(): void {
|
private drawGrid(): void {
|
||||||
const graphics = this.add.graphics();
|
const graphics = this.add.graphics();
|
||||||
|
|
||||||
// Draw cells
|
|
||||||
for (let y = 0; y < this.GRID_HEIGHT; y++) {
|
for (let y = 0; y < this.GRID_HEIGHT; y++) {
|
||||||
for (let x = 0; x < this.GRID_WIDTH; x++) {
|
for (let x = 0; x < this.GRID_WIDTH; x++) {
|
||||||
const px = this.gridOffsetX + x * this.CELL_SIZE;
|
const px = this.gridOffsetX + x * this.CELL_SIZE;
|
||||||
|
|
@ -102,7 +95,6 @@ export class GridViewerScene extends ReactiveScene {
|
||||||
const shape = item.shape;
|
const shape = item.shape;
|
||||||
const transform = item.transform;
|
const transform = item.transform;
|
||||||
|
|
||||||
// Get occupied cells
|
|
||||||
const cells: { x: number; y: number }[] = [];
|
const cells: { x: number; y: number }[] = [];
|
||||||
for (let y = 0; y < shape.height; y++) {
|
for (let y = 0; y < shape.height; y++) {
|
||||||
for (let x = 0; x < shape.width; x++) {
|
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 itemColor = this.getItemColor(itemId);
|
||||||
const graphics = this.add.graphics();
|
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);
|
graphics.fillRect(px + 2, py + 2, this.CELL_SIZE - 4, this.CELL_SIZE - 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Item name label (at first cell)
|
|
||||||
if (cells.length > 0) {
|
if (cells.length > 0) {
|
||||||
const firstCell = cells[0];
|
const firstCell = cells[0];
|
||||||
const px = this.gridOffsetX + firstCell.x * this.CELL_SIZE;
|
const px = this.gridOffsetX + firstCell.x * this.CELL_SIZE;
|
||||||
const py = this.gridOffsetY + firstCell.y * 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, {
|
this.add.text(px + this.CELL_SIZE / 2, py + this.CELL_SIZE / 2, itemName, {
|
||||||
fontSize: '11px',
|
fontSize: '11px',
|
||||||
|
|
@ -140,10 +130,9 @@ export class GridViewerScene extends ReactiveScene {
|
||||||
}).setOrigin(0.5);
|
}).setOrigin(0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjacent items info
|
|
||||||
const adjacent = getAdjacentItems(this.inventory, itemId);
|
const adjacent = getAdjacentItems(this.inventory, itemId);
|
||||||
if (adjacent.size > 0) {
|
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 firstCell = cells[0];
|
||||||
const px = this.gridOffsetX + firstCell.x * this.CELL_SIZE;
|
const px = this.gridOffsetX + firstCell.x * this.CELL_SIZE;
|
||||||
const py = this.gridOffsetY + firstCell.y * this.CELL_SIZE - 20;
|
const py = this.gridOffsetY + firstCell.y * this.CELL_SIZE - 20;
|
||||||
|
|
@ -157,7 +146,6 @@ export class GridViewerScene extends ReactiveScene {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getItemColor(itemId: string): number {
|
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 hash = itemId.split('').reduce((acc, c) => acc + c.charCodeAt(0), 0);
|
||||||
const colors = [0x4488cc, 0xcc8844, 0x44cc88, 0xcc4488, 0x8844cc, 0x44cccc];
|
const colors = [0x4488cc, 0xcc8844, 0x44cc88, 0xcc4488, 0x8844cc, 0x44cccc];
|
||||||
return colors[hash % colors.length];
|
return colors[hash % colors.length];
|
||||||
|
|
@ -166,18 +154,15 @@ export class GridViewerScene extends ReactiveScene {
|
||||||
private createControls(): void {
|
private createControls(): void {
|
||||||
const { width, height } = this.scale;
|
const { width, height } = this.scale;
|
||||||
|
|
||||||
// Back button
|
|
||||||
this.createButton('返回菜单', 100, 40, async () => {
|
this.createButton('返回菜单', 100, 40, async () => {
|
||||||
await this.sceneController.launch('IndexScene');
|
await this.sceneController.launch('IndexScene');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clear button
|
|
||||||
this.createButton('清空', width - 260, 40, async () => {
|
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();
|
await this.sceneController.restart();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Random fill button
|
|
||||||
this.createButton('随机填充', width - 130, 40, async () => {
|
this.createButton('随机填充', width - 130, 40, async () => {
|
||||||
this.randomFill();
|
this.randomFill();
|
||||||
await this.sceneController.restart();
|
await this.sceneController.restart();
|
||||||
|
|
@ -185,16 +170,15 @@ export class GridViewerScene extends ReactiveScene {
|
||||||
}
|
}
|
||||||
|
|
||||||
private randomFill(): void {
|
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;
|
let itemIndex = 0;
|
||||||
for (let y = 0; y < this.GRID_HEIGHT && itemIndex < heroItemFighter1Data.length; y++) {
|
for (let y = 0; y < this.GRID_HEIGHT && itemIndex < items.length; y++) {
|
||||||
for (let x = 0; x < this.GRID_WIDTH && itemIndex < heroItemFighter1Data.length; x++) {
|
for (let x = 0; x < this.GRID_WIDTH && itemIndex < items.length; x++) {
|
||||||
const data = heroItemFighter1Data[itemIndex];
|
const itemData = items[itemIndex];
|
||||||
const shape = parseShapeString(data.shape);
|
const shape = parseShapeString(itemData.shape);
|
||||||
|
|
||||||
// Check if placement is valid
|
|
||||||
const occupiedCells = new Set<string>();
|
const occupiedCells = new Set<string>();
|
||||||
for (let sy = 0; sy < shape.height; sy++) {
|
for (let sy = 0; sy < shape.height; sy++) {
|
||||||
for (let sx = 0; sx < shape.width; sx++) {
|
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;
|
let valid = true;
|
||||||
for (const cell of occupiedCells) {
|
for (const cell of occupiedCells) {
|
||||||
const [cx, cy] = cell.split(',').map(Number);
|
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;
|
valid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
const item: InventoryItem = {
|
const item: InventoryItem<GameItemMeta> = {
|
||||||
id: `item-${itemIndex}`,
|
id: `item-${itemIndex}`,
|
||||||
shape,
|
shape,
|
||||||
transform: { offset: { x, y }, rotation: 0, flipX: false, flipY: false },
|
transform: { offset: { x, y }, rotation: 0, flipX: false, flipY: false },
|
||||||
meta: { name: data.name, data },
|
meta: { itemData, shape },
|
||||||
};
|
};
|
||||||
placeItem(this.inventory, item);
|
placeItem(this.inventory, item);
|
||||||
itemIndex++;
|
itemIndex++;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import Phaser from 'phaser';
|
import Phaser from 'phaser';
|
||||||
import { ReactiveScene } from 'boardgame-phaser';
|
import { ReactiveScene } from 'boardgame-phaser';
|
||||||
import { generatePointCrawlMap, type PointCrawlMap, type MapNode, MapNodeType } from 'boardgame-core/samples/slay-the-spire-like';
|
import { createRNG } from 'boardgame-core';
|
||||||
|
import { generatePointCrawlMap, data, type PointCrawlMap, type MapNode, MapNodeType } from 'boardgame-core/samples/slay-the-spire-like';
|
||||||
|
|
||||||
const NODE_COLORS: Record<MapNodeType, number> = {
|
const NODE_COLORS: Record<MapNodeType, number> = {
|
||||||
[MapNodeType.Start]: 0x44aa44,
|
[MapNodeType.Start]: 0x44aa44,
|
||||||
|
|
@ -143,7 +144,8 @@ export class MapViewerScene extends ReactiveScene {
|
||||||
}
|
}
|
||||||
|
|
||||||
private drawMap(): void {
|
private drawMap(): void {
|
||||||
this.map = generatePointCrawlMap(this.seed);
|
const rng = createRNG(this.seed);
|
||||||
|
this.map = generatePointCrawlMap(rng, data.desert.encounters);
|
||||||
|
|
||||||
const { width, height } = this.scale;
|
const { width, height } = this.scale;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ export class PlaceholderEncounterScene extends ReactiveScene {
|
||||||
|
|
||||||
// Item name
|
// Item name
|
||||||
const first = cells[0];
|
const first = cells[0];
|
||||||
const name = item.meta?.itemData?.name ?? item.id;
|
const name = item.meta?.itemData.name ?? item.id;
|
||||||
this.add.text(
|
this.add.text(
|
||||||
this.gridX + first.x * this.CELL_SIZE + this.CELL_SIZE / 2,
|
this.gridX + first.x * this.CELL_SIZE + this.CELL_SIZE / 2,
|
||||||
this.gridY + first.y * this.CELL_SIZE + this.CELL_SIZE / 2,
|
this.gridY + first.y * this.CELL_SIZE + this.CELL_SIZE / 2,
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
import Phaser from 'phaser';
|
import Phaser from 'phaser';
|
||||||
import { ReactiveScene } from 'boardgame-phaser';
|
import { ReactiveScene } from 'boardgame-phaser';
|
||||||
import { parseShapeString, heroItemFighter1Data, type ParsedShape } from 'boardgame-core/samples/slay-the-spire-like';
|
import { parseShapeString, data, type ParsedShape } from 'boardgame-core/samples/slay-the-spire-like';
|
||||||
|
|
||||||
export class ShapeViewerScene extends ReactiveScene {
|
export class ShapeViewerScene extends ReactiveScene {
|
||||||
private readonly CELL_SIZE = 40;
|
private readonly CELL_SIZE = 40;
|
||||||
private readonly ITEMS_PER_ROW = 4;
|
private readonly ITEMS_PER_ROW = 4;
|
||||||
private currentIndex = 0;
|
|
||||||
private currentRotation = 0;
|
|
||||||
private currentFlipX = false;
|
|
||||||
private currentFlipY = false;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super('ShapeViewerScene');
|
super('ShapeViewerScene');
|
||||||
|
|
@ -25,14 +21,12 @@ export class ShapeViewerScene extends ReactiveScene {
|
||||||
|
|
||||||
const { width, height } = this.scale;
|
const { width, height } = this.scale;
|
||||||
|
|
||||||
// Title
|
|
||||||
this.add.text(width / 2, 30, 'Shape Viewer - Item Shapes', {
|
this.add.text(width / 2, 30, 'Shape Viewer - Item Shapes', {
|
||||||
fontSize: '24px',
|
fontSize: '24px',
|
||||||
color: '#ffffff',
|
color: '#ffffff',
|
||||||
fontStyle: 'bold',
|
fontStyle: 'bold',
|
||||||
}).setOrigin(0.5);
|
}).setOrigin(0.5);
|
||||||
|
|
||||||
// Draw all shapes in a grid
|
|
||||||
this.drawAllShapes();
|
this.drawAllShapes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,12 +36,11 @@ export class ShapeViewerScene extends ReactiveScene {
|
||||||
const spacingX = 220;
|
const spacingX = 220;
|
||||||
const spacingY = 140;
|
const spacingY = 140;
|
||||||
|
|
||||||
// Show first 12 items for clarity
|
const itemsToShow = data.desert.items.slice(0, 12);
|
||||||
const itemsToShow = heroItemFighter1Data.slice(0, 12);
|
|
||||||
|
|
||||||
for (let i = 0; i < itemsToShow.length; i++) {
|
for (let i = 0; i < itemsToShow.length; i++) {
|
||||||
const data = itemsToShow[i];
|
const itemData = itemsToShow[i];
|
||||||
const shape = parseShapeString(data.shape);
|
const shape = parseShapeString(itemData.shape);
|
||||||
|
|
||||||
const col = i % this.ITEMS_PER_ROW;
|
const col = i % this.ITEMS_PER_ROW;
|
||||||
const row = Math.floor(i / this.ITEMS_PER_ROW);
|
const row = Math.floor(i / this.ITEMS_PER_ROW);
|
||||||
|
|
@ -55,32 +48,28 @@ export class ShapeViewerScene extends ReactiveScene {
|
||||||
const x = 60 + col * spacingX;
|
const x = 60 + col * spacingX;
|
||||||
const y = startY + row * spacingY;
|
const y = startY + row * spacingY;
|
||||||
|
|
||||||
this.drawSingleShape(x, y, data, shape);
|
this.drawSingleShape(x, y, itemData, shape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private drawSingleShape(startX: number, startY: number, data: any, shape: ParsedShape): void {
|
private drawSingleShape(startX: number, startY: number, itemData: any, shape: ParsedShape): void {
|
||||||
const graphics = this.add.graphics();
|
const graphics = this.add.graphics();
|
||||||
|
|
||||||
// Draw shape background
|
|
||||||
const shapeWidth = shape.width * this.CELL_SIZE;
|
const shapeWidth = shape.width * this.CELL_SIZE;
|
||||||
const shapeHeight = shape.height * this.CELL_SIZE;
|
const shapeHeight = shape.height * this.CELL_SIZE;
|
||||||
|
|
||||||
// Title - item name
|
this.add.text(startX + shapeWidth / 2, startY - 20, itemData.name, {
|
||||||
this.add.text(startX + shapeWidth / 2, startY - 20, data.name, {
|
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
color: '#ffffff',
|
color: '#ffffff',
|
||||||
fontStyle: 'bold',
|
fontStyle: 'bold',
|
||||||
}).setOrigin(0.5);
|
}).setOrigin(0.5);
|
||||||
|
|
||||||
// Draw shape cells
|
|
||||||
for (let y = 0; y < shape.height; y++) {
|
for (let y = 0; y < shape.height; y++) {
|
||||||
for (let x = 0; x < shape.width; x++) {
|
for (let x = 0; x < shape.width; x++) {
|
||||||
if (shape.grid[y]?.[x]) {
|
if (shape.grid[y]?.[x]) {
|
||||||
const px = startX + x * this.CELL_SIZE;
|
const px = startX + x * this.CELL_SIZE;
|
||||||
const py = startY + y * this.CELL_SIZE;
|
const py = startY + y * this.CELL_SIZE;
|
||||||
|
|
||||||
// Determine if this is the origin cell
|
|
||||||
const isOrigin = x === shape.originX && y === shape.originY;
|
const isOrigin = x === shape.originX && y === shape.originY;
|
||||||
const color = isOrigin ? 0x88cc44 : 0x4488cc;
|
const color = isOrigin ? 0x88cc44 : 0x4488cc;
|
||||||
|
|
||||||
|
|
@ -89,7 +78,6 @@ export class ShapeViewerScene extends ReactiveScene {
|
||||||
graphics.lineStyle(2, 0xffffff);
|
graphics.lineStyle(2, 0xffffff);
|
||||||
graphics.strokeRect(px, py, this.CELL_SIZE, this.CELL_SIZE);
|
graphics.strokeRect(px, py, this.CELL_SIZE, this.CELL_SIZE);
|
||||||
|
|
||||||
// Mark origin with 'O'
|
|
||||||
if (isOrigin) {
|
if (isOrigin) {
|
||||||
this.add.text(px + this.CELL_SIZE / 2, py + this.CELL_SIZE / 2, 'O', {
|
this.add.text(px + this.CELL_SIZE / 2, py + this.CELL_SIZE / 2, 'O', {
|
||||||
fontSize: '16px',
|
fontSize: '16px',
|
||||||
|
|
@ -101,21 +89,18 @@ export class ShapeViewerScene extends ReactiveScene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shape string
|
this.add.text(startX + shapeWidth / 2, startY + shapeHeight + 10, `形状: ${itemData.shape}`, {
|
||||||
this.add.text(startX + shapeWidth / 2, startY + shapeHeight + 10, `形状: ${data.shape}`, {
|
|
||||||
fontSize: '11px',
|
fontSize: '11px',
|
||||||
color: '#aaaaaa',
|
color: '#aaaaaa',
|
||||||
}).setOrigin(0.5);
|
}).setOrigin(0.5);
|
||||||
|
|
||||||
// Type and cost
|
|
||||||
this.add.text(startX + shapeWidth / 2, startY + shapeHeight + 28,
|
this.add.text(startX + shapeWidth / 2, startY + shapeHeight + 28,
|
||||||
`类型: ${data.type} | 费用: ${data.costCount} ${data.costType}`, {
|
`类型: ${itemData.type} | 费用: ${itemData.costCount} ${itemData.costType}`, {
|
||||||
fontSize: '11px',
|
fontSize: '11px',
|
||||||
color: '#cccccc',
|
color: '#cccccc',
|
||||||
}).setOrigin(0.5);
|
}).setOrigin(0.5);
|
||||||
|
|
||||||
// Description
|
this.add.text(startX + shapeWidth / 2, startY + shapeHeight + 46, itemData.desc, {
|
||||||
this.add.text(startX + shapeWidth / 2, startY + shapeHeight + 46, data.desc, {
|
|
||||||
fontSize: '10px',
|
fontSize: '10px',
|
||||||
color: '#888888',
|
color: '#888888',
|
||||||
wordWrap: { width: shapeWidth },
|
wordWrap: { width: shapeWidth },
|
||||||
|
|
@ -125,12 +110,10 @@ export class ShapeViewerScene extends ReactiveScene {
|
||||||
private createControls(): void {
|
private createControls(): void {
|
||||||
const { width, height } = this.scale;
|
const { width, height } = this.scale;
|
||||||
|
|
||||||
// Back button
|
|
||||||
this.createButton('返回菜单', 100, height - 40, async () => {
|
this.createButton('返回菜单', 100, height - 40, async () => {
|
||||||
await this.sceneController.launch('IndexScene');
|
await this.sceneController.launch('IndexScene');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Info text
|
|
||||||
this.add.text(width / 2, height - 40,
|
this.add.text(width / 2, height - 40,
|
||||||
`Showing first 12 items | Green = Origin | Blue = Normal`, {
|
`Showing first 12 items | Green = Origin | Blue = Normal`, {
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { MutableSignal, mutableSignal } from 'boardgame-core';
|
import { MutableSignal, mutableSignal, createRNG } from 'boardgame-core';
|
||||||
import { createRunState, type RunState } from 'boardgame-core/samples/slay-the-spire-like';
|
import { createRunState, generatePointCrawlMap, data, type RunState, type ItemData } from 'boardgame-core/samples/slay-the-spire-like';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局游戏运行状态 Signal
|
* 全局游戏运行状态 Signal
|
||||||
|
|
@ -8,7 +8,12 @@ import { createRunState, type RunState } from 'boardgame-core/samples/slay-the-s
|
||||||
* 遭遇场景通过读取此 signal 的当前遭遇状态来构建 UI。
|
* 遭遇场景通过读取此 signal 的当前遭遇状态来构建 UI。
|
||||||
*/
|
*/
|
||||||
export function createGameState(seed?: number): MutableSignal<RunState> {
|
export function createGameState(seed?: number): MutableSignal<RunState> {
|
||||||
return mutableSignal<RunState>(createRunState(seed));
|
const actualSeed = seed ?? Date.now();
|
||||||
|
const rng = createRNG(actualSeed);
|
||||||
|
const encounters = data.desert.encounters;
|
||||||
|
const map = generatePointCrawlMap(rng, encounters);
|
||||||
|
const starterItems: ItemData[] = data.desert.items.slice(0, 3);
|
||||||
|
return mutableSignal<RunState>(createRunState(map, starterItems));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取当前遭遇数据(computed getter) */
|
/** 获取当前遭遇数据(computed getter) */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue