本文档详细说明游戏系统的核心玩法、关卡机制和数据逻辑。


# 呆鸟修仙 游戏系统

3.png

本文档详细说明游戏系统的核心玩法、关卡机制和数据逻辑。

## 功能概述

游戏系统是呆鸟修仙的核心玩法,玩家控制小鸟收集灵气球、躲避敌人,通过关卡提升境界。

## 游戏架构

### 核心要素

1. **关卡系统** - 30个关卡,跨越10个修仙境界
2. **灵气收集** - 收集灵气球获得分数和成长
3. **敌人机制** - 躲避不同类型的敌人
4. **境界系统** - 通过关卡提升修仙境界
5. **体型系统** - 收集灵气球增加体型,撞击敌人减少体型
6. **排行榜** - 基于累计灵气值的排行榜

### 境界系统

| 境界 | 关卡范围 | 鸟皮肤 | 特点 |
|------|---------|--------|------|
| 练气期 | 1-3 | public/assets/bird-realms/bird_zjq_01.png | 基础境界 |
| 练气期 | 4-6 | public/assets/bird-realms/bird_zjq_02.png | 开启打坐冥想 |
| 练气期 | 7-9 | public/assets/bird-realms/bird_zjq_03.png | 道心初成 |
| 练气期 | 10-12 | public/assets/bird-realms/bird_zjq_04.png | 元神出窍 |
| 练气期 | 13-15 | public/assets/bird-realms/bird_zjq_05.png | 神识外放 |
| 练气期 | 16-18 | public/assets/bird-realms/bird_zjq_06.png | 虚空炼化 |
| 练气期 | 19-21 | public/assets/bird-realms/bird_zjq_07.png | 身魂合一 |
| 练气期 | 22-24 | public/assets/bird-realms/bird_zjq_08.png | 法力无边 |
| 练气期 | 25-27 | public/assets/bird-realms/bird_zjq_09.png | 天雷淬炼 |
| 练气期 | 28-30 | public/assets/bird-realms/bird_zjq_10.png | 飞升成仙 |

## 数据库表结构

### game_records 表

**字段说明**:

| 字段名 | 类型 | 约束 | 说明 |
|--------|------|------|------|
| id | varchar(36) | PRIMARY KEY | 记录UUID |
| user_id | varchar(36) | NOT NULL | 用户ID |
| level | int | NOT NULL | 关卡编号 |
| score | int | NOT NULL | 本次得分 |
| realm | varchar(50) | NOT NULL | 所属境界 |
| play_time | int | NOT NULL | 游戏时长(秒) |
| created_at | timestamp | DEFAULT NOW() | 游戏时间 |

**索引**:
- `game_records_user_idx`: user_id
- `game_records_score_idx`: score(用于排行榜)

### level_configs 表

**字段说明**:

| 字段名 | 类型 | 约束 | 说明 |
|--------|------|------|------|
| id | varchar(36) | PRIMARY KEY | 配置UUID |
| level | int | UNIQUE, NOT NULL | 关卡编号 |
| realm | varchar(50) | NOT NULL | 所属境界 |
| game_mode | varchar(20) | NOT NULL | 游戏模式 |
| target_score | int | NOT NULL | 目标分数 |
| is_open | boolean | DEFAULT true | 关卡是否开放 |
| spirit_interval | int | DEFAULT 1000 | 灵气生成间隔(毫秒) |
| spirit_max_count | int | DEFAULT 8 | 灵气最大数量 |
| spirit_life_time | int | DEFAULT 15000 | 灵气生命周期(毫秒) |
| enemy_count | int | DEFAULT 2 | 敌人数量 |
| enemy_speed_multiplier | int | DEFAULT 100 | 敌人速度倍率 |
| enemy_tracking_strength | int | DEFAULT 0 | 追踪强度(0-100) |
| enemy_types | jsonb | NOT NULL | 敌人种类配置 |
| player_max_lives | int | DEFAULT 5 | 主角最大生命值 |
| player_speed_multiplier | int | DEFAULT 100 | 主角速度倍率 |
| player_size_multiplier | int | DEFAULT 100 | 主角大小倍率 |
| bird_size_growth_rate | int | DEFAULT 8 | 收集灵气球增加体型百分比 |
| bird_size_shrink_rate | int | DEFAULT 20 | 撞击敌人减少体型百分比 |
| bird_max_size | int | DEFAULT 330 | 最大体型百分比 |

## 游戏模式

### 1. 经典模式 (classic)

**目标**: 收集灵气球,达到目标分数

**特点**:
- 无生命值限制
- 体型成长机制
- 累计灵气值

### 2. 生存模式 (survival)

**目标**: 尽可能长时间生存

**特点**:
- 生命值机制
- 敌人逐渐增强
- 难度递增

### 3. 挑战模式 (challenge)

**目标**: 在限定时间内达到目标

**特点**:
- 时间限制
- 高难度
- 特殊奖励

## 游戏机制

### 灵气收集

**灵气球属性**:
- **分值**: 1-50分(根据稀有度)
- **稀有度**: common, rare, epic, legendary
- **颜色**: 不同稀有度对应不同颜色
- **生命周期**: 15秒后消失
- **移动轨迹**: 左右飘动 + 上下浮动

**收集效果**:
```typescript
// 增加分数
setScore((s) => s + spirit.points);

// 增加体型(根据关卡配置)
setBirdSize(prev => {
  const newSize = prev + birdSizeGrowthRate;
  const maxSize = 330;
  return Math.min(newSize, maxSize);
});

// 增加灵气收集数量
setCollectedSpiritsCount(prev => prev + 1);
```

**稀有度概率**:
- 普通 (common): 60% - 1-10分
- 稀有 (rare): 25% - 11-30分
- 史诗 (epic): 12% - 31-40分
- 传说 (legendary): 3% - 41-50分

### 敌人机制

**敌人属性**:
- **速度**: 基础速度 × 速度倍率
- **追踪强度**: 0-100(100为完全追踪)
- **碰撞伤害**: 减少体型
- **生命值**: 多次撞击后消失

**敌人类型**:
```typescript
interface EnemyType {
  emoji: string;
  name: string;
  health: number;
  speed: number;
  tracking: number;
}
```

**碰撞效果**:
```typescript
// 减少体型(根据关卡配置)
setBirdSize(prev => {
  const newSize = prev - birdSizeShrinkRate;
  const minSize = 20;
  return Math.max(newSize, minSize);
});

// 减少生命值(如果启用)
setLives((l) => l - 1);
```

### 体型系统

**体型范围**: 20% - 150%

**成长规则**:
- 收集灵气球:+8%(可配置)
- 撞击敌人:-20%(可配置)

**体型效果**:
- 视觉变大
- 颜色变金(体型越大越金)
- 收集范围变大

**境界影响**:
```typescript
const realmFlapBonus = {
  "练气期": 0,
  "筑基期": 0.02,
  "金丹期": 0.03,
  // ... 境界越高,扇动越有力量
};
```

### 生命值系统

**初始生命值**: 5(可配置)

**生命值归零**:
- 游戏结束
- 记录分数
- 保存到数据库
- 返回菜单

### 控制方式

#### 支持的输入方式

游戏支持以下两种控制方式:

1. **鼠标控制** - 适用于桌面端
2. **触屏控制** - 适用于移动端

#### 鼠标控制

**操作方式**:
- 移动鼠标:小鸟会跟随鼠标位置移动
- 控制灵敏度:鼠标移动的位移 × 0.6
- 最大速度限制:基础速度 × 2.5

**关键代码** (src/app/page.tsx):
```typescript
// 鼠标移动事件处理
const handleMouseMove = (e: MouseEvent) => {
  if (gameState !== 'playing') return;

  const canvas = canvasRef.current;
  if (!canvas) return;

  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;

  // 计算位移增量(灵敏度 0.6)
  const deltaX = (x - bird.x) * 0.6;
  const deltaY = (y - bird.y) * 0.6;

  // 限制最大增量(2.5倍基础速度)
  const maxDelta = 2.5 * bird.baseSpeed;
  const clampedDeltaX = Math.max(-maxDelta, Math.min(maxDelta, deltaX));
  const clampedDeltaY = Math.max(-maxDelta, Math.min(maxDelta, deltaY));

  // 更新小鸟位置
  setBird({
    ...bird,
    x: bird.x + clampedDeltaX,
    y: bird.y + clampedDeltaY
  });
};
```

**注意事项**:
- 确保背景图片不拦截鼠标事件
  ```typescript
  // 为背景图片添加样式
  style={{ pointerEvents: 'none' }}
  ```

#### 触屏控制

**操作方式**:
- 手指触摸:小鸟会跟随触摸点移动
- 多点触控:支持多点触控(取最后触摸点)
- 控制灵敏度:触摸移动的位移 × 0.6
- 最大速度限制:基础速度 × 2.5

**关键代码** (src/app/page.tsx):
```typescript
// 触摸开始事件
const handleTouchStart = (e: React.TouchEvent) => {
  e.preventDefault();
  if (gameState !== 'playing') return;

  const canvas = canvasRef.current;
  if (!canvas) return;

  const rect = canvas.getBoundingClientRect();
  const touch = e.touches[0];
  const x = touch.clientX - rect.left;
  const y = touch.clientY - rect.top;

  // 更新触摸位置
  setTouchPosition({ x, y });
};

// 触摸移动事件
const handleTouchMove = (e: React.TouchEvent) => {
  e.preventDefault();
  if (gameState !== 'playing') return;

  const canvas = canvasRef.current;
  if (!canvas) return;

  const rect = canvas.getBoundingClientRect();
  const touch = e.touches[0];
  const x = touch.clientX - rect.left;
  const y = touch.clientY - rect.top;

  // 计算位移增量(灵敏度 0.6)
  const deltaX = (x - bird.x) * 0.6;
  const deltaY = (y - bird.y) * 0.6;

  // 限制最大增量(2.5倍基础速度)
  const maxDelta = 2.5 * bird.baseSpeed;
  const clampedDeltaX = Math.max(-maxDelta, Math.min(maxDelta, deltaX));
  const clampedDeltaY = Math.max(-maxDelta, Math.min(maxDelta, deltaY));

  // 更新小鸟位置
  setBird({
    ...bird,
    x: bird.x + clampedDeltaX,
    y: bird.y + clampedDeltaY
  });

  setTouchPosition({ x, y });
};
```

**注意事项**:
- 添加 `e.preventDefault()` 防止页面滚动
- 使用 `touch` 事件而非 `click` 事件以获得更好的响应速度
- 支持 `touchstart`、`touchmove`、`touchend` 事件

#### 控制灵敏度参数

**可调参数** (src/data/LevelConfig.ts):

| 参数 | 默认值 | 说明 |
|------|--------|------|
| `MOUSE_CONTROL_MULTIPLIER` | 0.6 | 鼠标/触屏控制灵敏度倍率 |
| `MAX_CONTROL_MULTIPLIER` | 2.5 | 最大速度倍率(相对于基础速度) |
| `BIRD_BASE_SPEED` | 3.5 | 小鸟基础速度(像素/帧) |
| `BIRD_MAX_SPEED` | 5.5 | 小鸟最大速度(像素/帧) |

**调整建议**:
- **更灵敏的控制**:增大 `MOUSE_CONTROL_MULTIPLIER`(0.6 → 0.8)
- **更平滑的控制**:减小 `MOUSE_CONTROL_MULTIPLIER`(0.6 → 0.4)
- **更快的飞行**:增大 `BIRD_BASE_SPEED`(3.5 → 5)
- **更慢的飞行**:减小 `BIRD_BASE_SPEED`(3.5 → 2)

**配置示例** (src/data/LevelConfig.ts):
```typescript
export const GAME_CONFIG = {
  // 控制灵敏度
  MOUSE_CONTROL_MULTIPLIER: 0.6,  // 鼠标/触屏控制倍率
  MAX_CONTROL_MULTIPLIER: 2.5,    // 最大控制倍率

  // 飞行速度
  BIRD_BASE_SPEED: 3.5,           // 基础速度(像素/帧)
  BIRD_MAX_SPEED: 5.5,            // 最大速度(像素/帧)
  SPEED_INCREMENT_PER_LEVEL: 0.04, // 每关卡速度增量

  // ... 其他配置
};
```

#### 控制最佳实践

**优化建议**:
1. **防止背景遮挡**:确保背景图片不拦截鼠标事件
   ```tsx
   <div
     style={{
       backgroundImage: `url(${bgImage})`,
       pointerEvents: 'none'  // 关键:防止拦截鼠标事件
     }}
   />
   ```

2. **响应式适配**:确保 Canvas 尺寸正确适配不同设备
   ```typescript
   // 获取 Canvas 尺寸
   const rect = canvas.getBoundingClientRect();

   // 计算触摸/鼠标在 Canvas 内的相对坐标
   const x = touch.clientX - rect.left;
   const y = touch.clientY - rect.top;
   ```

3. **边界检测**:防止小鸟移出 Canvas 边界
   ```typescript
   // 限制 X 轴范围
   bird.x = Math.max(birdSize, Math.min(canvasWidth - birdSize, bird.x));

   // 限制 Y 轴范围
   bird.y = Math.max(birdSize, Math.min(canvasHeight - birdSize, bird.y));
   ```

4. **性能优化**:使用 `requestAnimationFrame` 优化渲染
   ```typescript
   // 在游戏循环中使用
   useEffect(() => {
     let animationFrameId: number;

     const gameLoop = () => {
       // 更新小鸟位置
       // 更新灵气球位置
       // 检测碰撞
       // 绘制画面

       animationFrameId = requestAnimationFrame(gameLoop);
     };

     if (gameState === 'playing') {
       gameLoop();
     }

     return () => cancelAnimationFrame(animationFrameId);
   }, [gameState, ...]);
   ```

#### 常见问题

**Q1: 鼠标控制没反应?**

A: 检查以下几点:
1. 确保游戏状态为 `playing`
2. 检查背景图片是否拦截了鼠标事件(添加 `pointerEvents: 'none'`)
3. 确认 Canvas 是否正确挂载
4. 检查浏览器控制台是否有错误

**Q2: 触屏控制不流畅?**

A: 优化建议:
1. 使用 `e.preventDefault()` 防止页面滚动
2. 增大 `MOUSE_CONTROL_MULTIPLIER` 提升灵敏度
3. 使用 `touch` 事件而非 `click` 事件
4. 确保没有其他元素拦截触摸事件

**Q3: 如何调整控制灵敏度?**

A: 修改 `GAME_CONFIG` 中的参数:
```typescript
// 更灵敏:增大倍率
MOUSE_CONTROL_MULTIPLIER: 0.8,  // 从 0.6 增加到 0.8

// 更平滑:减小倍率
MOUSE_CONTROL_MULTIPLIER: 0.4,  // 从 0.6 减少到 0.4
```

**Q4: 小鸟飞得太快了?**

A: 降低基础速度:
```typescript
// 降低飞行速度
BIRD_BASE_SPEED: 2.5,      // 从 3.5 降低到 2.5
BIRD_MAX_SPEED: 4.0,       // 从 5.5 降低到 4.0
```

#### 相关代码位置

**主要实现文件**:
- **游戏主逻辑**: `src/app/page.tsx` (约 2000-2200 行)
- **关卡配置**: `src/data/LevelConfig.ts`
- **境界配置**: `src/data/RealmConfig.ts`

**关键函数**:
- `handleMouseMove()` - 鼠标移动处理
- `handleTouchStart()` - 触摸开始处理
- `handleTouchMove()` - 触摸移动处理
- `handleTouchEnd()` - 触摸结束处理

**历史优化记录**:
- 2026-01-19: 添加鼠标和触屏控制支持
- 2026-01-19: 修复背景图片拦截鼠标事件问题
- 2026-01-19: 提升控制灵敏度(0.35 → 0.6)
- 2026-01-19: 降低飞行速度(5 → 3.5)

## 关卡设计

### 关卡配置

**文件**: `src/data/LevelConfig.ts`

```typescript
export interface LevelConfig {
  level: number;
  realm: string;
  gameMode: "classic" | "survival" | "challenge";
  targetScore: number;
  isOpen: boolean;
  // ... 更多配置
}

export const LEVELS: LevelConfig[] = [
  {
    level: 1,
    realm: "练气期",
    gameMode: "classic",
    targetScore: 100,
    isOpen: true,
    spiritInterval: 1000,
    spiritMaxCount: 5,
    enemyCount: 1,
    // ...
  },
  // ... 30个关卡
];
```

### 关卡进度

**保存逻辑**:
```typescript
// 游戏结束时
if (score > user.maxScore) {
  await updateUser(user.id, { maxScore: score });
}

if (level > user.maxLevel) {
  await updateUser(user.id, { maxLevel: level });
}

// 保存游戏记录
await db.insert(gameRecords).values({
  userId: user.id,
  level: level,
  score: score,
  realm: realm,
  playTime: playTime,
});

// 更新累计灵气值(排行榜使用)
await db.execute(sql`
  UPDATE users
  SET total_score = total_score + ${score}
  WHERE id = ${userId}
`);
```

## 排行榜系统

### 排行榜类型

1. **好友排行榜** - 仅显示好友
2. **全服排行榜** - 显示所有玩家
3. **本周排行榜** - 按本周分数排名
4. **历史排行榜** - 按累计分数排名

### 排行榜查询

**SQL查询**:
```sql
-- 全服排行榜(按累计灵气值)
SELECT
  u.id,
  u.username,
  u.max_score,
  u.total_score,
  u.max_level,
  u.avatar
FROM users u
WHERE u.is_disabled = false
ORDER BY u.total_score DESC
LIMIT 100;

-- 好友排行榜
SELECT
  u.*,
  f.created_at as friendship_date
FROM users u
JOIN friendships f ON u.id = f.friend_id
WHERE f.user_id = ? AND f.status = 'accepted'
ORDER BY u.total_score DESC
LIMIT 50;
```

### 排行榜更新

**实时更新**:
- 游戏结束时立即更新
- 使用缓存优化查询
- 定时刷新全服排行榜(每小时)

## API接口

### 1. 保存游戏记录

**接口**: `POST /api/game/save-record`

**请求参数**:
```json
{
  "userId": "uuid",
  "level": 5,
  "score": 150,
  "realm": "金丹期",
  "playTime": 120
}
```

**响应示例**:
```json
{
  "success": true,
  "newMaxScore": true,
  "newMaxLevel": false,
  "totalScore": 150
}
```

### 2. 获取排行榜

**接口**: `GET /api/game/leaderboard`

**查询参数**:
- `type`: all/friends/weekly
- `page`: 页码
- `limit`: 每页数量

**响应示例**:
```json
{
  "success": true,
  "type": "all",
  "rankings": [
    {
      "rank": 1,
      "username": "玩家A",
      "totalScore": 50000,
      "maxLevel": 15,
      "avatar": "🦅"
    }
  ],
  "myRank": 10,
  "total": 1000
}
```

### 3. 获取关卡配置

**接口**: `GET /api/game/level/:id`

**响应示例**:
```json
{
  "success": true,
  "level": {
    "level": 1,
    "realm": "练气期",
    "gameMode": "classic",
    "targetScore": 100,
    "spiritInterval": 1000,
    "enemyCount": 1
  }
}
```

## 关键代码位置

### 游戏主循环

**文件**: `src/app/page.tsx`

```typescript
// 游戏循环(约2000-2200行)
useEffect(() => {
  const gameLoop = setInterval(() => {
    // 更新小鸟位置
    // 更新灵气球位置
    // 检测碰撞
    // 检测游戏结束
    // 绘制画面
  }, 1000 / 60); // 60 FPS

  return () => clearInterval(gameLoop);
}, [gameState, ...]);
```

### 关卡配置

**文件**: `src/data/LevelConfig.ts`

```typescript
export const LEVELS: LevelConfig[] = [
  // 30个关卡配置
];

export const GAME_CONFIG = {
  canvasWidth: 400,
  canvasHeight: 600,
  birdSize: 50,
  // ... 全局配置
};
```

### 境界配置

**文件**: `src/data/RealmConfig.ts`

```typescript
export const REALM_CONFIG: Record<string, RealmConfig> = {
  "练气期": { birdEmoji: "🐦", birdSkin: "/birds/bird_01.png", ... },
  "筑基期": { birdEmoji: "🦅", birdSkin: "/birds/bird_02.png", ... },
  // ... 10个境界
};
```

## 扩展功能建议

### 1. 成就系统

- 首次通关关卡
- 收集特定数量灵气
- 连续收集奖励
- 境界里程碑

### 2. 每日挑战

- 每日关卡
- 特殊规则
- 额外奖励

### 3. 多人对战

- 实时对战
- 排位系统
- 战队模式

### 4. 道具系统

- 护盾(无敌)
- 速度提升
- 体型增大
- 时间冻结

### 5. 剧情模式

- 境界剧情
- NPC对话
- 任务系统

## 性能优化

### 渲染优化

- 使用 Canvas API
- 限制最大灵气球数量
- 对象池复用
- 帧率控制(60 FPS)

### 数据库优化

- 游戏记录索引优化
- 排行榜缓存
- 批量保存记录
- 定时清理旧数据

## 常见问题

### Q1: 为什么游戏结束后分数没有增加?

A: 检查以下几点:
1. 游戏是否正常结束(生命值归零)
2. API调用是否成功
3. 数据库连接是否正常
4. 查看浏览器控制台错误

### Q2: 如何调整游戏难度?

A: 修改 `LevelConfig.ts` 中的关卡配置:
- `enemyCount`: 敌人数量
- `enemySpeedMultiplier`: 敌人速度
- `birdSizeShrinkRate`: 体型减少幅度
- `spiritInterval`: 灵气生成间隔

### Q3: 排行榜多久更新一次?

A: 当前为实时更新,建议优化:
- 好友排行榜:实时
- 全服排行榜:每小时
- 本周排行榜:每日重置

### Q4: 体型过大如何处理?

A: 限制最大体型为130% ,如果需要:
- 添加体型上限配置
- 体型过大时触发特殊效果
- 体型影响收集范围

## 维护记录

- 2026-01-19: 完善游戏系统文档
- 2026-01-19: 排行榜改为按累计灵气值排序
- 2026-01-19: 游戏结束自动累加灵气值


收藏

扫描二维码,在手机上阅读
文章目录


    呆鸟修仙 占卜、预测、人缘系统

    呆鸟修仙游戏 - 部署指南

    评 论
    评论已关闭