mcpField
G
game-development

game-development

github.com/miles990开发26415 次安装41 周前更新
代码仓库

关于 game-development

面向跨平台游戏开发的实践指南,涵盖架构、渲染、物理、AI、多人游戏和优化。内容包含常见模式与代码示例,也列出不同引擎及相关技能。

主要功能

  1. 01游戏循环与 ECS 架构
  2. 022D 动画和碰撞检测
  3. 03有限状态机、行为树与寻路
  4. 04多人网络与状态同步
  5. 05渲染和内存优化
  6. 06游戏引擎参考

适用场景

  1. 01设计游戏主循环和实体系统
  2. 02实现 2D 碰撞及角色动画
  3. 03规划敌人 AI 与寻路逻辑
  4. 04优化渲染和对象内存使用

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/miles990/claude-software-skills --skill game-development

安装后在 Claude Code 中输入/game-development确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

flame/flame-templates/references/
platformer.md
roguelike.md
rpg.md

详细介绍

游戏开发

概述

跨平台游戏构建模式与实践。涵盖架构、渲染、物理、AI、多人游戏和优化。


游戏架构

游戏循环
┌─────────────────────────────────────────────────────────────┐
│                      Game Loop                              │
│                                                             │
│   ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐ │
│   │  Input  │ ─→ │ Update  │ ─→ │ Physics │ ─→ │ Render  │ │
│   │ Process │    │  Logic  │    │  Step   │    │  Frame  │ │
│   └─────────┘    └─────────┘    └─────────┘    └─────────┘ │
│        ↑                                             │      │
│        └─────────────────────────────────────────────┘      │
│                        Next Frame                           │
└─────────────────────────────────────────────────────────────┘
固定与可变时间步长
类型用例代码模式
固定物理、确定性while (accumulator >= dt) { update(dt); }
可变渲染、动画update(deltaTime);
混合大多数游戏固定物理、可变渲染
// Hybrid game loop
let accumulator = 0;
const FIXED_DT = 1/60;

function gameLoop(currentTime: number) {
  const deltaTime = currentTime - lastTime;
  accumulator += deltaTime;

  // Fixed timestep for physics
  while (accumulator >= FIXED_DT) {
    physicsUpdate(FIXED_DT);
    accumulator -= FIXED_DT;
  }

  // Variable timestep for rendering
  const alpha = accumulator / FIXED_DT;
  render(alpha); // Interpolate between states

  requestAnimationFrame(gameLoop);
}

实体组件系统(ECS)
┌─────────────────────────────────────────────────────────────┐
│                    ECS Architecture                         │
│                                                             │
│  Entity: Just an ID                                         │
│  ┌─────┐  ┌─────┐  ┌─────┐                                 │
│  │  1  │  │  2  │  │  3  │                                 │
│  └─────┘  └─────┘  └─────┘                                 │
│                                                             │
│  Components: Pure Data                                      │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐                  │
│  │ Position │  │ Velocity │  │  Sprite  │                  │
│  │ x, y, z  │  │ vx, vy   │  │ texture  │                  │
│  └──────────┘  └──────────┘  └──────────┘                  │
│                                                             │
│  Systems: Logic                                             │
│  ┌────────────────┐  ┌────────────────┐                    │
│  │ MovementSystem │  │ RenderSystem   │                    │
│  │ Position+Vel   │  │ Position+Sprite│                    │
│  └────────────────┘  └────────────────┘                    │
└─────────────────────────────────────────────────────────────┘
// Component definitions
interface Position { x: number; y: number; }
interface Velocity { vx: number; vy: number; }
interface Sprite { texture: string; width: number; height: number; }

// System
function movementSystem(entities: Entity[], dt: number) {
  for (const entity of entities) {
    if (entity.has(Position) && entity.has(Velocity)) {
      const pos = entity.get(Position);
      const vel = entity.get(Velocity);
      pos.x += vel.vx * dt;
      pos.y += vel.vy * dt;
    }
  }
}

2D 游戏开发

精灵动画
interface Animation {
  frames: string[];       // Texture names
  frameDuration: number;  // Seconds per frame
  loop: boolean;
}

class AnimatedSprite {
  private currentFrame = 0;
  private elapsed = 0;

  update(dt: number) {
    this.elapsed += dt;
    if (this.elapsed >= this.animation.frameDuration) {
      this.elapsed = 0;
      this.currentFrame++;
      if (this.currentFrame >= this.animation.frames.length) {
        this.currentFrame = this.animation.loop ? 0 : this.animation.frames.length - 1;
      }
    }
  }

  get texture(): string {
    return this.animation.frames[this.currentFrame];
  }
}
碰撞检测
方法复杂度用例
AABBO(n²) → O(n log n)方框、简单形状
圆形O(n²)投射物、角色
SATO(n²)复杂凸多边形
像素级精确开销较大精确碰撞
// AABB collision
function aabbIntersect(a: AABB, b: AABB): boolean {
  return a.x < b.x + b.width &&
         a.x + a.width > b.x &&
         a.y < b.y + b.height &&
         a.y + a.height > b.y;
}

// Spatial hash for broad phase
class SpatialHash {
  private cells = new Map<string, Entity[]>();
  private cellSize: number;

  insert(entity: Entity) {
    const key = this.getKey(entity.position);
    if (!this.cells.has(key)) this.cells.set(key, []);
    this.cells.get(key)!.push(entity);
  }

  query(position: Vector2): Entity[] {
    // Check neighboring cells
    const nearby: Entity[] = [];
    for (let dx = -1; dx <= 1; dx++) {
      for (let dy = -1; dy <= 1; dy++) {
        const key = this.getKey({ x: position.x + dx * this.cellSize, y: position.y + dy * this.cellSize });
        nearby.push(...(this.cells.get(key) || []));
      }
    }
    return nearby;
  }
}

游戏 AI

有限状态机
interface State {
  enter(): void;
  update(dt: number): void;
  exit(): void;
}

class EnemyAI {
  private states = new Map<string, State>();
  private currentState: State;

  transition(stateName: string) {
    this.currentState?.exit();
    this.currentState = this.states.get(stateName)!;
    this.currentState.enter();
  }
}

// Example: Patrol → Chase → Attack
class PatrolState implements State {
  enter() { this.setAnimation('walk'); }
  update(dt: number) {
    this.patrol();
    if (this.canSeePlayer()) {
      this.fsm.transition('chase');
    }
  }
  exit() {}
}
行为树
┌─────────────────────────────────────────────────────────────┐
│                    Behavior Tree                            │
│                                                             │
│                      [Selector]                             │
│                     /          \                            │
│              [Sequence]      [Patrol]                       │
│              /        \                                     │
│        [CanSee?]    [Attack]                               │
│            │                                                │
│         [Chase]                                             │
└─────────────────────────────────────────────────────────────┘
寻路(A*)
function aStar(start: Node, goal: Node): Node[] {
  const openSet = new PriorityQueue<Node>();
  const cameFrom = new Map<Node, Node>();
  const gScore = new Map<Node, number>();
  const fScore = new Map<Node, number>();

  gScore.set(start, 0);
  fScore.set(start, heuristic(start, goal));
  openSet.enqueue(start, fScore.get(start)!);

  while (!openSet.isEmpty()) {
    const current = openSet.dequeue()!;

    if (current === goal) {
      return reconstructPath(cameFrom, current);
    }

    for (const neighbor of getNeighbors(current)) {
      const tentativeG = gScore.get(current)! + distance(current, neighbor);

      if (tentativeG < (gScore.get(neighbor) ?? Infinity)) {
        cameFrom.set(neighbor, current);
        gScore.set(neighbor, tentativeG);
        fScore.set(neighbor, tentativeG + heuristic(neighbor, goal));
        openSet.enqueue(neighbor, fScore.get(neighbor)!);
      }
    }
  }

  return []; // No path found
}

多人游戏

网络架构
模型延迟复杂度用例
点对点低中格斗游戏、小型大厅
客户端-服务器中高大多数在线游戏
权威服务器较高最高竞技游戏
延迟补偿
// Client-side prediction
class NetworkedPlayer {
  private pendingInputs: Input[] = [];
  private serverState: PlayerState;

  update(input: Input) {
    // 1. Apply input locally (prediction)
    this.applyInput(input);
    this.pendingInputs.push(input);

    // 2. Send to server
    this.sendInput(input);
  }

  onServerUpdate(state: PlayerState, lastProcessedInput: number) {
    // 3. Reconcile with server
    this.serverState = state;

    // 4. Re-apply unprocessed inputs
    this.pendingInputs = this.pendingInputs.filter(i => i.id > lastProcessedInput);
    for (const input of this.pendingInputs) {
      this.applyInput(input);
    }
  }
}
状态同步
// Delta compression
interface StateDelta {
  timestamp: number;
  changes: Map<EntityId, ComponentChanges>;
}

function computeDelta(prev: GameState, curr: GameState): StateDelta {
  const changes = new Map();
  for (const [id, entity] of curr.entities) {
    const prevEntity = prev.entities.get(id);
    if (!prevEntity || hasChanged(prevEntity, entity)) {
      changes.set(id, getChangedComponents(prevEntity, entity));
    }
  }
  return { timestamp: curr.timestamp, changes };
}

游戏优化

渲染优化
技术优势实现方式
批处理减少绘制调用合并使用相同纹理的精灵
剔除跳过不可见对象视锥剔除、遮挡剔除
LOD减少多边形数量基于距离切换模型
实例化高效处理重复对象对重复对象进行 GPU 实例化
内存优化
// Object pooling
class ObjectPool<T> {
  private pool: T[] = [];
  private factory: () => T;

  acquire(): T {
    return this.pool.pop() ?? this.factory();
  }

  release(obj: T) {
    this.reset(obj);
    this.pool.push(obj);
  }
}

// Usage
const bulletPool = new ObjectPool(() => new Bullet());

function fireBullet() {
  const bullet = bulletPool.acquire();
  bullet.init(position, direction);
  activeBullets.add(bullet);
}

function onBulletHit(bullet: Bullet) {
  activeBullets.delete(bullet);
  bulletPool.release(bullet);
}

游戏引擎参考

引擎语言最适用场景平台技能
UnityC#移动端、独立游戏、VR全部-
UnrealC++、BlueprintAAA、逼真画面PC、主机-
GodotGDScript、C#独立游戏、2D全部-
FlameDartFlutter 2D、休闲游戏全部flame/
PhaserJavaScriptWeb 2D浏览器-
Three.jsJavaScriptWeb 3D浏览器-
BevyRust高性能桌面端-
LÖVELua简单 2D桌面端-
Flame 引擎(Flutter)

专为 Flutter 开发者设计的 2D 游戏引擎,详细文档请参阅 flame/SKILL.md:

  • flame-core/ - 组件、输入、碰撞、相机、动画、音效、粒子
  • flame-systems/ - 14 个游戏系统(任务、对话、背包、战斗等)
  • flame-templates/ - RPG、平台游戏、Roguelike 模板

相关技能

  • [[performance-optimization]] - 通用优化
  • [[realtime-systems]] - WebSocket、网络
  • [[cpp]] - 性能关键型代码
  • [[javascript-typescript]] - Web 游戏

评论

支持 Markdown