boardgame-core/README.md

183 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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