资源管线
从 AI 生成到游戏渲染的完整流程。
流程概览
Agnes API (AI 生成)
↓
下载 & 裁剪
↓
去背景处理
↓
按类别存入文件夹
↓
TexturePacker 打图集
↓
上传 R2 (Cloudflare)
↓
PixiJS 加载渲染1. AI 生成阶段
使用 Agnes Image 2.0 Flash 生成建筑素材。
ts
// scripts/generate-building.ts
const response = await fetch('https://apihub.agnes-ai.com/v1/images/generations', {
method: 'POST',
headers: {
'Authorization': `Bearer ${AGNES_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'agnes-image-2.0-flash',
prompt: buildingPrompt, // 基于 ai-prompt-guide.md 模板
size: '1024x1024',
extra_body: { response_format: 'url' },
}),
});2. 后处理阶段
ts
// scripts/process-building.ts
// 1. 下载图片
const image = await downloadImage(imageUrl);
// 2. 裁剪到目标尺寸
const cropped = cropToSize(image, targetWidth, targetHeight);
// 3. 去背景(如果非透明)
const cleaned = removeBackground(cropped, { threshold: 0.1 });
// 4. 保存到对应文件夹
await saveToFile(`public/assets/tiles/buildings/${category}/${name}.png`, cleaned);3. 目录结构
public/
├── assets/
│ └── tiles/
│ └── buildings/
│ ├── residential/ # 住宅类
│ │ ├── house_a.png
│ │ ├── house_b.png
│ │ ├── inn.png
│ │ └── home.png
│ ├── commercial/ # 商业类
│ │ ├── shop.png
│ │ ├── tavern.png
│ │ ├── herb_shop.png
│ │ ├── tailor.png
│ │ └── market.png
│ ├── public/ # 公共类
│ │ ├── plaza.png
│ │ ├── temple.png
│ │ ├── library.png
│ │ ├── watchtower.png
│ │ └── cemetery.png
│ ├── industrial/ # 工业类
│ │ └── workshop.png
│ └── nature/ # 自然类
│ ├── forest.png
│ ├── farm.png
│ └── dock.png
├── sprites/
│ ├── tileset.png # 主图集(地形/装饰)
│ └── tileset_grid.png # 带编号的参考图
└── effects/
├── rain.png
├── snow.png
└── petals.png4. 图集打包
使用 TexturePacker 将每个类别的单独图片打成图集:
输入:residential/*.png
输出:residential.png + residential.jsonTexturePacker 设置
json
{
"format": "pixijs",
"textureFormat": "png",
"maxWidth": 1024,
"maxHeight": 1024,
"padding": 2,
"extrude": 1,
"allowRotation": false,
"detectIdentical": true,
"trimMode": "trim"
}5. R2 上传
ts
// scripts/upload-to-r2.ts
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
const r2 = new S3Client({
region: 'auto',
endpoint: `https://${ACCOUNT_ID}.r2.cloudflarestorage.com`,
credentials: { accessKeyId: KEY_ID, secretAccessKey: SECRET },
});
async function uploadAtlas(category: string) {
const png = await readFile(`build/${category}.png`);
const json = await readFile(`build/${category}.json`);
await r2.send(new PutObjectCommand({
Bucket: 'ai-world-sim-assets',
Key: `buildings/${category}.png`,
Body: png,
ContentType: 'image/png',
CacheControl: 'public, max-age=31536000', // 1年缓存
}));
await r2.send(new PutObjectCommand({
Bucket: 'ai-world-sim-assets',
Key: `buildings/${category}.json`,
Body: json,
ContentType: 'application/json',
CacheControl: 'public, max-age=31536000',
}));
}6. 前端加载
ts
// src/utils/textureAtlas.ts
const R2_BASE = 'https://assets.openserve.cloud';
export async function loadBuildingAtlases() {
const categories = ['residential', 'commercial', 'public', 'industrial', 'nature'];
await Promise.all(
categories.map(cat =>
Assets.load(`${R2_BASE}/buildings/${cat}.json`)
)
);
}
// 使用
const texture = Assets.get('residential').textures['tavern'];
const sprite = new Sprite(texture);命名规范
| 类型 | 命名格式 | 示例 |
|---|---|---|
| Tile | {类别}_{变体} | grass_1, stone_crack |
| 建筑 | {类别}/{名称} | commercial/tavern |
| 角色 | {名字}_{动作}_{方向}_{帧号} | alice_walk_south_01 |
| 特效 | {效果}_{帧号} | rain_01 |
| 图集 | {类别}.png | residential.png |
季节化素材
自然类素材有4套季节变体:
public/assets/tiles/
├── terrain/
│ ├── spring_grass.png
│ ├── summer_grass.png
│ ├── autumn_grass.png
│ └── winter_grass.png
├── nature/
│ ├── spring_trees.png
│ ├── summer_trees.png
│ ├── autumn_trees.png
│ └── winter_trees.png
└── water/
├── spring_water.png
├── summer_water.png
├── autumn_water.png
└── winter_water.png建筑不需要4套,通过 PixiJS ColorMatrixFilter 做色调偏移。
完整构建脚本
json
// package.json
{
"scripts": {
"generate": "ts-node scripts/generate-buildings.ts",
"process": "ts-node scripts/process-buildings.ts",
"pack": "texturepacker --project tp-config.json",
"upload": "ts-node scripts/upload-to-r2.ts",
"build:assets": "npm run generate && npm run process && npm run pack && npm run upload"
}
}📐 建筑精灵规范见 建筑精灵规范 📐 AI Prompt 模板见 AI 出图 Prompt 指南 📐 TileSet 规范见 TileSet