PixiJS 资源加载 #
Assets 加载器概述 #
PixiJS 8 提供了全新的 Assets 加载器,用于加载和管理各种类型的资源。
text
┌─────────────────────────────────────────────────────────────┐
│ Assets 加载器 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 支持的资源类型 │
│ ├── 图片(PNG, JPG, WebP, SVG) │
│ ├── 精灵表(JSON, XML) │
│ ├── 字体(Bitmap Font, Web Font) │
│ ├── 音频(MP3, OGG, WAV) │
│ ├── 视频 │
│ ├── JSON 数据 │
│ └── 纹理 │
│ │
│ 核心功能 │
│ ├── 异步加载 │
│ ├── 进度回调 │
│ ├── 缓存管理 │
│ └── 批量加载 │
│ │
└─────────────────────────────────────────────────────────────┘
基本使用 #
加载单个资源 #
javascript
import { Assets } from 'pixi.js';
// 加载图片
const texture = await Assets.load('images/player.png');
// 创建精灵
const sprite = new PIXI.Sprite(texture);
app.stage.addChild(sprite);
加载多个资源 #
javascript
// 批量加载
const assets = await Assets.load([
'images/player.png',
'images/enemy.png',
'images/background.png'
]);
// 使用加载的资源
const player = new PIXI.Sprite(assets['images/player.png']);
const enemy = new PIXI.Sprite(assets['images/enemy.png']);
const background = new PIXI.Sprite(assets['images/background.png']);
使用别名 #
javascript
// 添加资源清单
Assets.add({
alias: 'player',
src: 'images/player.png'
});
Assets.add({
alias: 'enemy',
src: 'images/enemy.png'
});
// 使用别名加载
const playerTexture = await Assets.load('player');
const enemyTexture = await Assets.load('enemy');
批量添加资源 #
javascript
// 添加多个资源
Assets.addBundle('game-assets', {
player: 'images/player.png',
enemy: 'images/enemy.png',
background: 'images/background.png',
'spritesheet': 'sprites/game.json'
});
// 加载整个包
const bundle = await Assets.loadBundle('game-assets');
// 使用资源
const player = new PIXI.Sprite(bundle.player);
const enemy = new PIXI.Sprite(bundle.enemy);
加载进度 #
进度回调 #
javascript
// 监听加载进度
Assets.loadBundle('game-assets', (progress) => {
console.log(`加载进度: ${progress * 100}%`);
});
自定义加载界面 #
javascript
async function loadWithProgress() {
const progressBar = new Graphics();
const progressText = new Text({
text: '0%',
style: { fontFamily: 'Arial', fontSize: 24, fill: 0xffffff }
});
app.stage.addChild(progressBar, progressText);
const bundle = await Assets.loadBundle('game-assets', (progress) => {
const percent = Math.round(progress * 100);
progressBar.clear();
progressBar.rect(100, 280, 600 * progress, 40);
progressBar.fill({ color: 0x00ff00 });
progressText.text = `${percent}%`;
progressText.x = 400;
progressText.y = 290;
});
app.stage.removeChild(progressBar, progressText);
return bundle;
}
加载状态 #
javascript
// 检查资源是否已加载
const isLoaded = Assets.cache.has('player');
// 获取已缓存的资源
const cachedTexture = Assets.cache.get('player');
// 等待资源加载完成
const texture = await Assets.load('player');
图片加载 #
基本图片 #
javascript
// 加载 PNG
const pngTexture = await Assets.load('image.png');
// 加载 JPG
const jpgTexture = await Assets.load('image.jpg');
// 加载 WebP
const webpTexture = await Assets.load('image.webp');
// 加载 SVG
const svgTexture = await Assets.load('image.svg');
带选项加载 #
javascript
const texture = await Assets.load({
src: 'image.png',
data: {
alphaMode: 'premultiply-alpha-on-load',
resolution: 2,
scaleMode: 'linear'
}
});
跨域图片 #
javascript
const texture = await Assets.load({
src: 'https://example.com/image.png',
data: {
crossOrigin: 'anonymous'
}
});
精灵表加载 #
什么是精灵表 #
text
┌─────────────────────────────────────────────────────────────┐
│ 精灵表结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 精灵表图片(atlas.png) │
│ ┌────────────────────────────────────────┐ │
│ │ [frame1] [frame2] [frame3] [frame4] │ │
│ │ [frame5] [frame6] [frame7] [frame8] │ │
│ └────────────────────────────────────────┘ │
│ │
│ 精灵表数据(atlas.json) │
│ { │
│ "frames": { │
│ "frame1": { "x": 0, "y": 0, "w": 64, "h": 64 }, │
│ "frame2": { "x": 64, "y": 0, "w": 64, "h": 64 }, │
│ ... │
│ }, │
│ "meta": { "image": "atlas.png" } │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
加载精灵表 #
javascript
// 加载精灵表
const spritesheet = await Assets.load('sprites/game.json');
// 获取单个帧
const frame1 = spritesheet.textures['frame1.png'];
const sprite1 = new PIXI.Sprite(frame1);
// 获取动画帧序列
const frames = spritesheet.animations['walk'];
const animatedSprite = new PIXI.AnimatedSprite(frames);
animatedSprite.play();
创建精灵表 #
可以使用工具生成精灵表:
| 工具 | 说明 |
|---|---|
| TexturePacker | 专业工具,功能强大 |
| Shoebox | 免费工具 |
| Leshy SpriteSheet Tool | 在线工具 |
| PixiJS SpriteSheet Generator | 命令行工具 |
TexturePacker 导出设置 #
text
TexturePacker 设置:
├── Framework: PixiJS
├── Data Format: JSON (Hash)
├── Texture Format: PNG
├── Max Size: 2048x2048
├── Algorithm: MaxRects
└── Trim: Enable(去除透明边缘)
字体加载 #
Web 字体 #
javascript
// 加载 Google Fonts
await Assets.load({
src: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap',
data: {
family: 'Roboto',
display: 'swap'
}
});
// 使用字体
const text = new PIXI.Text({
text: 'Hello Roboto',
style: {
fontFamily: 'Roboto',
fontSize: 36
}
});
位图字体 #
javascript
// 加载位图字体
await Assets.load('fonts/desycel.xml');
// 使用位图字体
const bitmapText = new PIXI.BitmapText({
text: 'Hello Bitmap',
style: {
fontFamily: 'Desycel',
fontSize: 48
}
});
音频加载 #
基本音频 #
javascript
// 加载音频
const sound = await Assets.load('audio/bgm.mp3');
// 播放
sound.play();
// 暂停
sound.pause();
// 停止
sound.stop();
音频选项 #
javascript
const sound = await Assets.load({
src: 'audio/effect.mp3',
data: {
volume: 0.5,
loop: true,
speed: 1.0
}
});
使用 sound 库 #
javascript
// 安装
// npm install @pixi/sound
import { Sound } from '@pixi/sound';
// 加载并播放
const bgm = Sound.from('audio/bgm.mp3');
bgm.play({ loop: true });
// 音效
const effect = Sound.from('audio/effect.mp3');
effect.play();
JSON 数据加载 #
加载 JSON #
javascript
// 加载 JSON 数据
const data = await Assets.load('data/levels.json');
console.log(data.levels);
console.log(data.config);
游戏配置 #
javascript
// 加载游戏配置
const config = await Assets.load('config/game.json');
// 使用配置
const player = new PIXI.Sprite(
await Assets.load(config.player.sprite)
);
player.speed = config.player.speed;
player.health = config.player.health;
资源管理 #
缓存操作 #
javascript
// 检查缓存
const hasTexture = Assets.cache.has('player');
// 获取缓存
const texture = Assets.cache.get('player');
// 设置缓存
Assets.cache.set('custom-key', texture);
// 删除缓存
Assets.cache.remove('player');
// 清空缓存
Assets.cache.reset();
卸载资源 #
javascript
// 卸载单个资源
Assets.unload('player');
// 卸载多个资源
Assets.unload(['player', 'enemy', 'background']);
// 卸载整个包
Assets.unloadBundle('game-assets');
预加载 #
javascript
// 预加载资源
async function preload() {
Assets.addBundle('preload', {
loading: 'images/loading.png',
logo: 'images/logo.png'
});
const preloadAssets = await Assets.loadBundle('preload');
// 显示加载界面
showLoadingScreen(preloadAssets);
// 加载主资源
Assets.addBundle('main', {
player: 'images/player.png',
enemy: 'images/enemy.png'
});
await Assets.loadBundle('main', onProgress);
// 开始游戏
startGame();
}
高级用法 #
自定义加载器 #
javascript
import { Loader } from 'pixi.js';
// 创建自定义加载器
class CustomLoader extends Loader {
async load(url, options) {
// 自定义加载逻辑
console.log('自定义加载:', url);
return super.load(url, options);
}
}
// 注册自定义加载器
Assets.loader = new CustomLoader();
资源依赖 #
javascript
// 加载有依赖的资源
async function loadWithDependencies() {
// 先加载精灵表图片
const atlasTexture = await Assets.load('atlas.png');
// 再加载精灵表数据
const spritesheet = await Assets.load({
src: 'atlas.json',
data: {
texture: atlasTexture
}
});
return spritesheet;
}
动态资源 #
javascript
// 根据条件加载不同资源
async function loadPlatformSpecific() {
const isMobile = /Mobile/.test(navigator.userAgent);
const texture = await Assets.load(
isMobile ? 'images/player-mobile.png' : 'images/player-desktop.png'
);
return texture;
}
资源版本控制 #
javascript
// 添加版本号
Assets.add({
alias: 'player',
src: 'images/player.png?v=1.0.0'
});
// 或使用配置
const version = '1.0.0';
Assets.addBundle('game-assets', {
player: `images/player.png?v=${version}`,
enemy: `images/enemy.png?v=${version}`
});
实战示例 #
游戏资源管理器 #
javascript
class GameAssets {
constructor() {
this.loaded = false;
this.assets = {};
}
async load(progressCallback) {
if (this.loaded) return this.assets;
Assets.addBundle('game', {
// 图片
player: 'images/player.png',
enemy: 'images/enemy.png',
background: 'images/background.png',
// 精灵表
spritesheet: 'sprites/game.json',
// 字体
font: 'fonts/game-font.xml',
// 音频
bgm: 'audio/bgm.mp3',
effect: 'audio/effect.mp3',
// 数据
config: 'data/config.json'
});
this.assets = await Assets.loadBundle('game', progressCallback);
this.loaded = true;
return this.assets;
}
get(key) {
return this.assets[key];
}
unload() {
Assets.unloadBundle('game');
this.loaded = false;
this.assets = {};
}
}
const gameAssets = new GameAssets();
// 加载资源
await gameAssets.load((progress) => {
console.log(`加载中: ${Math.round(progress * 100)}%`);
});
// 使用资源
const player = new PIXI.Sprite(gameAssets.get('player'));
场景资源管理 #
javascript
class SceneAssets {
constructor(sceneName) {
this.sceneName = sceneName;
this.assets = {};
}
async load() {
const manifest = await Assets.load(`scenes/${this.sceneName}/manifest.json`);
Assets.addBundle(this.sceneName, manifest.assets);
this.assets = await Assets.loadBundle(this.sceneName);
return this.assets;
}
unload() {
Assets.unloadBundle(this.sceneName);
}
}
// 切换场景时加载/卸载资源
async function changeScene(sceneName) {
// 卸载当前场景资源
if (currentSceneAssets) {
currentSceneAssets.unload();
}
// 加载新场景资源
currentSceneAssets = new SceneAssets(sceneName);
await currentSceneAssets.load();
// 创建场景
createScene(currentSceneAssets.assets);
}
懒加载 #
javascript
class LazyLoader {
constructor() {
this.loaded = new Map();
}
async get(key, url) {
if (this.loaded.has(key)) {
return this.loaded.get(key);
}
const asset = await Assets.load(url);
this.loaded.set(key, asset);
return asset;
}
preload(keys, urls) {
return Promise.all(
keys.map((key, i) => this.get(key, urls[i]))
);
}
}
const lazyLoader = new LazyLoader();
// 按需加载
const playerTexture = await lazyLoader.get('player', 'images/player.png');
错误处理 #
加载错误 #
javascript
try {
const texture = await Assets.load('missing-image.png');
} catch (error) {
console.error('加载失败:', error);
// 使用默认资源
const texture = await Assets.load('images/default.png');
}
重试机制 #
javascript
async function loadWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await Assets.load(url);
} catch (error) {
console.log(`重试 ${i + 1}/${maxRetries}`);
if (i === maxRetries - 1) throw error;
}
}
}
超时处理 #
javascript
async function loadWithTimeout(url, timeout = 10000) {
return Promise.race([
Assets.load(url),
new Promise((_, reject) => {
setTimeout(() => reject(new Error('加载超时')), timeout);
})
]);
}
性能优化 #
资源压缩 #
text
优化建议:
├── 图片压缩
│ ├── 使用 TinyPNG 压缩 PNG
│ ├── 使用 WebP 格式(更小体积)
│ └── 适当降低分辨率
│
├── 精灵表优化
│ ├── 合并小图为精灵表
│ ├── 使用合适的精灵表尺寸
│ └── 去除透明边缘
│
└── 音频优化
├── 使用 MP3 格式
├── 降低比特率
└── 裁剪不必要的部分
按需加载 #
javascript
// 分阶段加载
async function loadGame() {
// 第一阶段:必要资源
await loadEssentialAssets();
showMainMenu();
// 第二阶段:游戏资源(后台加载)
loadGameAssets().then(() => {
enableStartButton();
});
// 第三阶段:可选资源
loadOptionalAssets();
}
内存管理 #
javascript
// 及时卸载不需要的资源
function cleanup() {
Assets.unload(['temp-image.png', 'old-spritesheet.json']);
}
// 在场景切换时清理
function onSceneChange() {
cleanup();
gc();
}
下一步 #
掌握了资源加载后,接下来学习 滤镜效果,了解如何使用滤镜创建炫酷的视觉效果!
最后更新:2026-03-29