boardgame-core/README.md

183 lines
4.4 KiB
Markdown
Raw Normal View History

# boardgame-core
基于 Preact Signals 的桌游状态管理库。
## 特性
- **响应式状态管理**: 使用 [@preact/signals-core](https://preactjs.com/guide/v10/signals/) 实现细粒度响应式
- **类型安全**: 完整的 TypeScript 支持
- **核心概念**:
- **Part**: 游戏组件(棋子、卡牌、板块)
- **Region**: 容器区域(支持 keyed/unkeyed 两种模式)
- **Placement**: Part 在 Region 中的引用
## 安装
```bash
npm install
```
## 快速开始
### 1. 创建游戏状态
```typescript
import { createGameState } from 'boardgame-core';
const gameState = createGameState({
id: 'game-1',
name: 'My Board Game',
});
```
### 2. 创建 Parts游戏组件
```typescript
import { createMeepleAction, createCardAction, createTileAction } from 'boardgame-core';
// 创建棋子
const meeple = createMeepleAction(gameState, 'meeple-1', 'red', {
name: 'Player 1',
});
// 创建卡牌
const card = createCardAction(gameState, 'card-1', {
suit: 'hearts',
value: 10,
});
// 创建板块
const tile = createTileAction(gameState, 'tile-1', {
pattern: 'forest',
rotation: 90,
});
```
### 3. 创建 Regions区域
```typescript
import { createRegionAction, RegionType } from 'boardgame-core';
// Unkeyed Region - 适用于牌库、弃牌堆等
const deck = createRegionAction(gameState, {
id: 'deck',
type: RegionType.Unkeyed,
name: 'Draw Deck',
});
// Keyed Region - 适用于版图、玩家区域等有固定位置的区域
const board = createRegionAction(gameState, {
id: 'board',
type: RegionType.Keyed,
name: 'Game Board',
});
// 带容量的区域(如手牌限制)
const hand = createRegionAction(gameState, {
id: 'hand',
type: RegionType.Unkeyed,
capacity: 5,
});
```
### 4. 创建 Placements放置
```typescript
import { createPlacementAction } from 'boardgame-core';
// 将棋子放置在版图上
const placement = createPlacementAction(gameState, {
id: 'placement-1',
partId: 'meeple-1',
regionId: 'board',
position: { x: 3, y: 4 },
});
```
### 5. 使用 Actions 操作状态
```typescript
import {
movePlacementAction,
flipPlacementAction,
setSlotAction,
updatePartAction,
} from 'boardgame-core';
// 移动 Placement 到另一个区域
movePlacementAction(gameState, 'placement-1', 'hand');
// 翻转卡牌(面朝上/面朝下)
flipPlacementAction(gameState, 'placement-1');
// 在 Keyed Region 中设置槽位
setSlotAction(gameState, 'board', 'A1', 'placement-1');
// 更新 Part 属性
updatePartAction(gameState, 'meeple-1', { metadata: { score: 10 } });
```
## API 参考
### Part Actions
| Action | 描述 |
|--------|------|
| `createPartAction` | 创建通用 Part |
| `createMeepleAction` | 创建棋子 |
| `createCardAction` | 创建卡牌 |
| `createTileAction` | 创建板块 |
| `updatePartAction` | 更新 Part 属性 |
| `removePartAction` | 移除 Part |
| `getPartAction` | 获取 Part |
### Region Actions
| Action | 描述 |
|--------|------|
| `createRegionAction` | 创建 Region |
| `getRegionAction` | 获取 Region |
| `removeRegionAction` | 移除 Region |
| `addPlacementToRegionAction` | 添加 Placement 到 Unkeyed Region |
| `removePlacementFromRegionAction` | 从 Region 移除 Placement |
| `setSlotAction` | 设置 Keyed Region 的槽位 |
| `getSlotAction` | 获取 Keyed Region 的槽位 |
| `clearRegionAction` | 清空 Region |
| `getRegionPlacementCountAction` | 获取 Region 中 Placement 数量 |
| `isRegionEmptyAction` | 检查 Region 是否为空 |
| `isRegionFullAction` | 检查 Region 是否已满 |
### Placement Actions
| Action | 描述 |
|--------|------|
| `createPlacementAction` | 创建 Placement |
| `getPlacementAction` | 获取 Placement |
| `removePlacementAction` | 移除 Placement |
| `movePlacementAction` | 移动 Placement 到另一个 Region |
| `updatePlacementPositionAction` | 更新 Placement 位置 |
| `updatePlacementRotationAction` | 更新 Placement 旋转角度 |
| `flipPlacementAction` | 翻转 Placement |
| `updatePlacementPartAction` | 更新 Placement 的 Part 引用 |
| `swapPlacementsAction` | 交换两个 Placement 的位置 |
| `setPlacementFaceAction` | 设置 Placement 面朝上/下 |
| `getPlacementsInRegionAction` | 获取 Region 中的所有 Placements |
| `getPlacementsOfPartAction` | 获取 Part 的所有 Placements |
## 运行测试
```bash
npm test # 监视模式
npm run test:run # 运行一次
```
## 构建
```bash
npm run build
```
## 许可证
MIT