2D开发

概述

学习目标

  • 掌握精灵图集的使用
  • 学会创建精灵动画
  • 了解 2D 文本渲染
  • 掌握透明度的使用
  • 了解后处理效果(泛光)
  • 理解 2D 相机控制(视口到世界坐标转换)
  • 掌握像素完美渲染

前置知识要求

  • 2D 基础
  • ECS 基础
  • 资源管理基础

核心概念

什么是 2D 开发?

2D 开发是在二维平面上创建游戏和应用。Bevy 提供了强大的 2D 渲染系统,支持精灵、动画、文本、后处理等功能。

为什么需要 2D 开发?

  1. 游戏开发:大多数 2D 游戏需要 2D 开发
  2. UI 开发:用户界面通常使用 2D 渲染
  3. 性能优化:2D 渲染比 3D 渲染更高效
  4. 简单性:2D 开发通常比 3D 开发更简单

2D 开发的核心组件

Bevy 2D 开发系统包含以下核心组件:

  • Sprite:精灵,用于显示图像
  • TextureAtlas:纹理图集,用于管理多个精灵
  • Animation:动画,用于创建精灵动画
  • Text2d:2D 文本,用于显示文本
  • Camera2d:2D 相机,用于控制视图
  • Bloom:泛光效果,用于后处理

基础用法

精灵图集

使用精灵图集管理多个精灵。

源代码文件bevy/examples/2d/texture_atlas.rs

代码示例

use bevy::{asset::LoadedFolder, image::ImageSampler, prelude::*};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
        .add_systems(Startup, setup)
        .run();
}

fn setup(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    mut texture_atlases: ResMut<Assets<TextureAtlasLayout>>,
    mut textures: ResMut<Assets<Image>>,
) {
    // 从文件夹加载多个单独的精灵
    let loaded_folder = asset_server.load_folder("textures/rpg");

    // 创建纹理图集
    let (texture_atlas, sources, texture) = create_texture_atlas(
        loaded_folder,
        Some(UVec2::new(6, 6)), // 填充
        Some(ImageSampler::nearest()), // 采样方式
        &mut textures,
    );
    let atlas_handle = texture_atlases.add(texture_atlas);

    // 使用图集中的精灵
    commands.spawn((
        Sprite {
            texture_atlas: Some(atlas_handle),
            ..default()
        },
        Transform::from_xyz(0.0, 0.0, 0.0),
    ));
}

关键要点

  • 使用 TextureAtlasLayout 创建纹理图集
  • 可以从文件夹加载多个精灵
  • 可以设置填充和采样方式
  • 使用 Spritetexture_atlas 属性使用图集

说明: 精灵图集允许将多个精灵打包到一个纹理中,减少绘制调用和提高性能。

精灵动画

创建精灵动画。

源代码文件bevy/examples/2d/sprite_animation.rs

代码示例

use bevy::prelude::*;
use std::time::Duration;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
        .add_systems(Startup, setup)
        .add_systems(Update, execute_animations)
        .run();
}

#[derive(Component)]
struct AnimationConfig {
    first_sprite_index: usize,
    last_sprite_index: usize,
    fps: u8,
    frame_timer: Timer,
}

impl AnimationConfig {
    fn new(first: usize, last: usize, fps: u8) -> Self {
        Self {
            first_sprite_index: first,
            last_sprite_index: last,
            fps,
            frame_timer: Timer::new(Duration::from_secs_f32(1.0 / (fps as f32)), TimerMode::Repeating),
        }
    }
}

// 这个系统循环遍历 `TextureAtlas` 中的所有精灵,从 `first_sprite_index` 到 `last_sprite_index`
fn execute_animations(time: Res<Time>, mut query: Query<(&mut AnimationConfig, &mut Sprite)>) {
    for (mut config, mut sprite) in &mut query {
        // 跟踪当前精灵已显示的时间
        config.frame_timer.tick(time.delta());

        // 如果已显示用户定义的时间(fps)...
        if config.frame_timer.just_finished() {
            if let Some(atlas) = &mut sprite.texture_atlas {
                if atlas.index == config.last_sprite_index {
                    // ...并且是最后一帧,则回到第一帧
                    atlas.index = config.first_sprite_index;
                } else {
                    // ...并且不是最后一帧,则移动到下一帧
                    atlas.index += 1;
                }
            }
        }
    }
}

关键要点

  • 使用 AnimationConfig 配置动画
  • 使用 Timer 控制动画帧率
  • 通过更新 Spritetexture_atlas.index 来切换帧
  • 可以设置动画的起始帧和结束帧

说明: 精灵动画通过在不同帧之间切换来创建动画效果。通过控制帧切换的时间,可以创建流畅的动画。

2D 文本渲染

在 2D 场景中渲染文本。

源代码文件bevy/examples/2d/text2d.rs

代码示例

use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, (animate_translation, animate_rotation, animate_scale))
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    let font = asset_server.load("fonts/FiraSans-Bold.ttf");
    let text_font = TextFont {
        font: font.clone(),
        font_size: 50.0,
        ..default()
    };
    
    commands.spawn(Camera2d);
    
    // 演示变换
    commands.spawn((
        Text2d::new(" translation "),
        text_font.clone(),
        TextLayout::new_with_justify(Justify::Center),
        TextBackgroundColor(Color::BLACK.with_alpha(0.5)),
        Text2dShadow::default(),
        Transform::from_xyz(0.0, 0.0, 0.0),
    ));
    
    // 演示文本换行
    let box_size = Vec2::new(300.0, 200.0);
    commands.spawn((
        Sprite::from_color(Color::srgb(0.25, 0.25, 0.55), box_size),
        Transform::from_translation(Vec3::new(0.0, -250.0, 0.0)),
        children![(
            Text2d::new("this text wraps in the box\n(Unicode linebreaks)"),
            TextFont {
                font,
                font_size: 35.0,
                ..default()
            },
            TextLayout::new(Justify::Left, LineBreak::WordBoundary),
            // 在矩形中换行文本
            TextBounds::from(box_size),
            // 确保文本绘制在框的上方
            Transform::from_translation(Vec3::Z),
            Text2dShadow::default(),
        )],
    ));
}

关键要点

  • 使用 Text2d 在 2D 场景中渲染文本
  • 使用 TextFont 设置字体和大小
  • 使用 TextLayout 设置文本布局和对齐
  • 使用 TextBounds 设置文本边界和换行
  • 使用 Text2dShadow 添加文本阴影

说明: 2D 文本渲染允许在 2D 场景中显示文本。与 UI 文本不同,2D 文本是场景的一部分,可以应用变换、动画等效果。

透明度

使用透明度创建半透明效果。

源代码文件bevy/examples/2d/transparency_2d.rs

关键信息

  • 使用 Color::srgba() 创建带透明度的颜色
  • 使用 AlphaMode 控制透明度模式
  • AlphaMode::Blend 用于半透明对象
  • AlphaMode::Mask 用于带透明度的纹理
  • 透明对象需要正确的渲染顺序

说明: 透明度是 2D 渲染中的重要特性。Bevy 支持多种透明度模式,可以创建玻璃、水、烟雾等效果。

后处理效果(泛光)

使用泛光效果增强渲染效果。

源代码文件bevy/examples/2d/bloom_2d.rs

代码示例

use bevy::{
    core_pipeline::tonemapping::{DebandDither, Tonemapping},
    post_process::bloom::{Bloom, BloomCompositeMode},
    prelude::*,
};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, update_bloom_settings)
        .run();
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
    asset_server: Res<AssetServer>,
) {
    commands.spawn((
        Camera2d,
        Camera {
            clear_color: ClearColorConfig::Custom(Color::BLACK),
            ..default()
        },
        Tonemapping::TonyMcMapface, // 使用色调映射器
        Bloom::default(),           // 启用泛光效果
        DebandDither::Enabled,      // 可选:泛光会导致渐变,导致条带
    ));

    // 精灵
    commands.spawn(Sprite {
        image: asset_server.load("branding/bevy_bird_dark.png"),
        color: Color::srgb(5.0, 5.0, 5.0), // 在暗环境中放置明亮的东西以看到效果
        custom_size: Some(Vec2::splat(160.0)),
        ..default()
    });
}

关键要点

  • 使用 Bloom 组件添加泛光效果
  • 使用 Tonemapping 进行色调映射
  • 使用 DebandDither 减少条带
  • 泛光效果在暗环境中更明显

说明: 泛光效果可以在明亮区域周围创建光晕效果。这对于创建发光效果、增强视觉冲击力非常有用。

2D 相机控制(视口到世界坐标转换)

将视口坐标转换为世界坐标。

源代码文件bevy/examples/2d/2d_viewport_to_world.rs

关键信息

  • 使用 Cameraviewport_to_world() 方法
  • 可以将屏幕坐标转换为世界坐标
  • 适合处理鼠标点击、触摸输入等
  • 需要考虑相机的变换和投影

说明: 视口到世界坐标转换允许将屏幕坐标转换为游戏世界坐标。这对于处理鼠标点击、触摸输入等交互非常有用。

像素完美渲染

实现像素完美渲染。

源代码文件bevy/examples/2d/pixel_grid_snap.rs

关键信息

  • 使用 ImagePlugin::default_nearest() 禁用纹理过滤
  • 使用像素对齐确保精灵对齐到像素网格
  • 适合像素艺术风格的游戏
  • 可以避免模糊和抗锯齿

说明: 像素完美渲染确保精灵对齐到像素网格,避免模糊和抗锯齿。这对于像素艺术风格的游戏非常重要。

进阶用法

高级动画

创建复杂的动画效果。

关键信息

  • 可以创建多个动画轨道
  • 可以混合不同的动画
  • 可以使用动画事件
  • 可以控制动画的播放速度

说明: 高级动画允许创建复杂的动画效果。可以组合多个动画、控制播放速度、响应动画事件等。

性能优化

优化 2D 渲染性能。

关键信息

  • 使用精灵图集减少绘制调用
  • 使用批处理优化渲染
  • 使用剔除减少渲染对象
  • 合理使用透明度

说明: 性能优化对于 2D 游戏非常重要。通过使用精灵图集、批处理、剔除等技术,可以显著提高渲染性能。

实际应用

在游戏开发中的应用场景

2D 开发在游戏开发中有广泛的应用:

  1. 2D 游戏:创建 2D 平台游戏、RPG、策略游戏等
  2. UI 开发:创建游戏 UI 和 HUD
  3. 粒子效果:创建粒子效果和特效
  4. 菜单系统:创建游戏菜单和界面

常见问题

问题 1:如何优化精灵动画性能?

解决方案:使用精灵图集、批处理、剔除等技术来优化精灵动画性能。

问题 2:如何处理透明对象?

解决方案:透明对象需要正确的渲染顺序。Bevy 会自动处理透明对象的排序。

问题 3:如何实现像素完美渲染?

解决方案:使用 ImagePlugin::default_nearest() 禁用纹理过滤,并确保精灵对齐到像素网格。

性能考虑

  1. 精灵图集:使用精灵图集减少绘制调用
  2. 批处理:使用批处理优化渲染
  3. 剔除:使用剔除减少渲染对象
  4. 透明度:合理使用透明度以减少性能开销

相关资源

相关源代码文件

  • bevy/examples/2d/texture_atlas.rs - 精灵图集示例
  • bevy/examples/2d/sprite_animation.rs - 精灵动画示例
  • bevy/examples/2d/text2d.rs - 2D 文本渲染示例
  • bevy/examples/2d/transparency_2d.rs - 透明度示例
  • bevy/examples/2d/bloom_2d.rs - 泛光效果示例
  • bevy/examples/2d/2d_viewport_to_world.rs - 视口到世界坐标转换示例
  • bevy/examples/2d/pixel_grid_snap.rs - 像素完美渲染示例

官方文档链接

进一步学习建议

  • 学习动画系统,了解如何创建更复杂的动画
  • 学习 UI 系统,了解如何创建用户界面
  • 学习性能优化,了解如何优化 2D 渲染性能

索引返回上级目录