game-development by miles990/claude-software-skills
npx skills add https://github.com/miles990/claude-software-skills --skill game-development跨平台构建游戏的模式与实践。涵盖架构、渲染、物理、AI、多人游戏和优化。
┌─────────────────────────────────────────────────────────────┐
│ 游戏循环 │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 输入 │ ─→ │ 更新 │ ─→ │ 物理 │ ─→ │ 渲染 │ │
│ │ 处理 │ │ 逻辑 │ │ 步进 │ │ 帧 │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ ↑ │ │
│ └─────────────────────────────────────────────┘ │
│ 下一帧 │
└─────────────────────────────────────────────────────────────┘
| 类型 | 使用场景 | 代码模式 |
|---|---|---|
| 固定 | 物理、确定性 | while (accumulator >= dt) { update(dt); } |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 可变 | 渲染、动画 | update(deltaTime); |
| 混合 | 大多数游戏 | 固定物理,可变渲染 |
// 混合游戏循环
let accumulator = 0;
const FIXED_DT = 1/60;
function gameLoop(currentTime: number) {
const deltaTime = currentTime - lastTime;
accumulator += deltaTime;
// 物理使用固定时间步长
while (accumulator >= FIXED_DT) {
physicsUpdate(FIXED_DT);
accumulator -= FIXED_DT;
}
// 渲染使用可变时间步长
const alpha = accumulator / FIXED_DT;
render(alpha); // 在状态之间插值
requestAnimationFrame(gameLoop);
}
┌─────────────────────────────────────────────────────────────┐
│ ECS 架构 │
│ │
│ 实体: 仅是一个 ID │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ 1 │ │ 2 │ │ 3 │ │
│ └─────┘ └─────┘ └─────┘ │
│ │
│ 组件: 纯数据 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 位置 │ │ 速度 │ │ 精灵 │ │
│ │ x, y, z │ │ vx, vy │ │ 纹理 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ 系统: 逻辑 │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ 移动系统 │ │ 渲染系统 │ │
│ │ 位置+速度 │ │ 位置+精灵 │ │
│ └────────────────┘ └────────────────┘ │
└─────────────────────────────────────────────────────────────┘
// 组件定义
interface Position { x: number; y: number; }
interface Velocity { vx: number; vy: number; }
interface Sprite { texture: string; width: number; height: number; }
// 系统
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;
}
}
}
interface Animation {
frames: string[]; // 纹理名称
frameDuration: number; // 每帧秒数
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];
}
}
| 方法 | 复杂度 | 使用场景 |
|---|---|---|
| AABB | O(n²) → O(n log n) | 盒子、简单形状 |
| 圆形 | O(n²) | 抛射物、角色 |
| SAT | O(n²) | 复杂凸多边形 |
| 像素完美 | 昂贵 | 精确碰撞 |
// AABB 碰撞
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;
}
// 用于宽阶段的空间哈希
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[] {
// 检查相邻单元格
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;
}
}
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();
}
}
// 示例: 巡逻 → 追逐 → 攻击
class PatrolState implements State {
enter() { this.setAnimation('walk'); }
update(dt: number) {
this.patrol();
if (this.canSeePlayer()) {
this.fsm.transition('chase');
}
}
exit() {}
}
┌─────────────────────────────────────────────────────────────┐
│ 行为树 │
│ │
│ [选择器] │
│ / \ │
│ [序列] [巡逻] │
│ / \ │
│ [看见玩家?] [攻击] │
│ │ │
│ [追逐] │
└─────────────────────────────────────────────────────────────┘
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 []; // 未找到路径
}
| 模型 | 延迟 | 复杂度 | 使用场景 |
|---|---|---|---|
| 点对点 | 低 | 中等 | 格斗游戏、小型房间 |
| 客户端-服务器 | 中等 | 高 | 大多数在线游戏 |
| 权威服务器 | 较高 | 最高 | 竞技游戏 |
// 客户端预测
class NetworkedPlayer {
private pendingInputs: Input[] = [];
private serverState: PlayerState;
update(input: Input) {
// 1. 本地应用输入(预测)
this.applyInput(input);
this.pendingInputs.push(input);
// 2. 发送到服务器
this.sendInput(input);
}
onServerUpdate(state: PlayerState, lastProcessedInput: number) {
// 3. 与服务器状态协调
this.serverState = state;
// 4. 重新应用未处理的输入
this.pendingInputs = this.pendingInputs.filter(i => i.id > lastProcessedInput);
for (const input of this.pendingInputs) {
this.applyInput(input);
}
}
}
// 增量压缩
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 实例化 |
// 对象池
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);
}
}
// 用法
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);
}
| 引擎 | 语言 | 最适合 | 平台 | 技能 |
|---|---|---|---|---|
| Unity | C# | 移动、独立、VR | 全部 | - |
| Unreal | C++, Blueprint | 3A、写实 | PC, 主机 | - |
| Godot | GDScript, C# | 独立、2D | 全部 | - |
| Flame | Dart | Flutter 2D, 休闲 | 全部 | flame/ |
| Phaser | JavaScript | Web 2D | 浏览器 | - |
| Three.js | JavaScript | Web 3D | 浏览器 | - |
| Bevy | Rust | 性能 | 桌面 | - |
| LÖVE | Lua | 简单 2D | 桌面 | - |
专为 Flutter 开发者设计的 2D 游戏引擎,详细文档请参考 flame/SKILL.md:
每周安装数
145
仓库
GitHub 星标数
7
首次出现
Jan 24, 2026
安全审计
安装于
opencode137
gemini-cli133
codex131
cursor125
github-copilot123
kimi-cli114
Laravel架构模式指南:生产级开发模式与最佳实践
1,100 周安装