窗口管理

概述

学习目标

  • 理解窗口管理的基本概念
  • 掌握窗口的创建和配置
  • 了解窗口属性的设置
  • 学会处理多窗口场景

前置知识要求

  • Bevy 快速入门
  • ECS 基础

核心概念

什么是窗口管理?

窗口管理是 Bevy 中用于创建和管理应用程序窗口的功能。Bevy 支持创建多个窗口、配置窗口属性、处理窗口事件等。

为什么需要窗口管理?

  1. 用户界面:窗口是应用程序的用户界面
  2. 多窗口支持:可以创建多个窗口来显示不同的内容
  3. 窗口配置:可以配置窗口的大小、标题、主题等属性
  4. 窗口事件:可以处理窗口事件,如关闭、调整大小等

窗口管理的核心组件

Bevy 窗口管理包含以下核心组件:

  • Window:窗口组件,包含窗口的配置信息
  • WindowPlugin:窗口插件,负责创建和管理窗口
  • WindowRef:窗口引用,用于引用特定的窗口
  • WindowLevel:窗口层级,控制窗口的显示顺序

基础用法

窗口创建和配置

创建和配置窗口。

源代码文件bevy/examples/window/window_settings.rs

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
use bevy::prelude::*;
use bevy::window::{PresentMode, WindowLevel, WindowTheme};

fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "我的窗口".into(),
name: Some("bevy.app".into()),
resolution: (800, 600).into(),
present_mode: PresentMode::AutoVsync,
window_theme: Some(WindowTheme::Dark),
enabled_buttons: bevy::window::EnabledButtons {
maximize: false,
..Default::default()
},
visible: false,
..default()
}),
..default()
}))
.add_systems(Update, make_visible)
.run();
}

fn make_visible(mut window: Single<&mut Window>, frames: Res<FrameCount>) {
if frames.0 == 3 {
window.visible = true;
}
}

关键要点

  • 可以通过 WindowPlugin 配置主窗口
  • 可以设置窗口的标题、大小、主题等属性
  • 可以控制窗口的可见性
  • 可以禁用窗口按钮(如最大化按钮)

说明
窗口创建和配置是应用程序的基础。通过配置窗口属性,可以创建符合需求的用户界面。

窗口属性设置

设置窗口的各种属性。

源代码文件bevy/examples/window/window_settings.rs

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
use bevy::prelude::*;
use bevy::window::{CursorGrabMode, CursorIcon, PresentMode, WindowLevel};

fn toggle_vsync(input: Res<ButtonInput<KeyCode>>, mut window: Single<&mut Window>) {
if input.just_pressed(KeyCode::KeyV) {
window.present_mode = if matches!(window.present_mode, PresentMode::AutoVsync) {
PresentMode::AutoNoVsync
} else {
PresentMode::AutoVsync
};
info!("PRESENT_MODE: {:?}", window.present_mode);
}
}

fn switch_level(input: Res<ButtonInput<KeyCode>>, mut window: Single<&mut Window>) {
if input.just_pressed(KeyCode::KeyT) {
window.window_level = match window.window_level {
WindowLevel::AlwaysOnBottom => WindowLevel::Normal,
WindowLevel::Normal => WindowLevel::AlwaysOnTop,
WindowLevel::AlwaysOnTop => WindowLevel::AlwaysOnBottom,
};
info!("WINDOW_LEVEL: {:?}", window.window_level);
}
}

fn toggle_cursor(input: Res<ButtonInput<KeyCode>>, mut window: Single<&mut Window>) {
if input.just_pressed(KeyCode::KeyC) {
window.cursor_options.grab_mode = match window.cursor_options.grab_mode {
CursorGrabMode::None => CursorGrabMode::Locked,
CursorGrabMode::Locked => CursorGrabMode::Confined,
CursorGrabMode::Confined => CursorGrabMode::None,
};
info!("CURSOR_GRAB_MODE: {:?}", window.cursor_options.grab_mode);
}
}

关键要点

  • 可以在运行时动态修改窗口属性
  • 可以切换 VSync 模式
  • 可以设置窗口层级
  • 可以控制鼠标光标的抓取模式

说明
窗口属性设置允许在运行时动态调整窗口行为。这对于创建交互式应用程序非常有用。

多窗口支持

创建和管理多个窗口。

源代码文件bevy/examples/window/multiple_windows.rs

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
use bevy::prelude::*;
use bevy::window::{RenderTarget, WindowRef};

fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
// 创建第一个窗口的相机
let first_window_camera = commands
.spawn((
Camera3d::default(),
Transform::from_xyz(0.0, 0.0, 6.0).looking_at(Vec3::ZERO, Vec3::Y),
))
.id();

// 创建第二个窗口
let second_window = commands
.spawn(Window {
title: "第二个窗口".to_owned(),
..default()
})
.id();

// 创建第二个窗口的相机
let second_window_camera = commands
.spawn((
Camera3d::default(),
Transform::from_xyz(6.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y),
Camera {
target: RenderTarget::Window(WindowRef::Entity(second_window)),
..default()
},
))
.id();
}

关键要点

  • 可以创建多个窗口
  • 每个窗口可以有独立的相机
  • 使用 RenderTarget::Window 来指定相机渲染到哪个窗口
  • 使用 WindowRef::Entity 来引用窗口实体

说明
多窗口支持允许创建复杂的应用程序界面。例如,可以创建一个主窗口显示游戏内容,另一个窗口显示调试信息。

进阶用法

窗口事件处理

处理窗口事件,如关闭、调整大小等。

源代码文件bevy/examples/window/window_resizing.rs

关键信息

  • 可以监听窗口关闭事件
  • 可以监听窗口调整大小事件
  • 可以监听窗口焦点变化事件
  • 可以使用 EventReader 来处理窗口事件

说明
窗口事件处理允许应用程序响应窗口状态的变化。这对于创建响应式应用程序非常重要。

透明窗口

创建透明窗口。

源代码文件bevy/examples/window/transparent_window.rs

关键信息

  • 可以创建透明窗口
  • 需要设置窗口的透明度属性
  • 透明窗口可以用于创建特殊效果
  • 某些平台可能不支持透明窗口

说明
透明窗口可以用于创建特殊的视觉效果,如覆盖层、HUD 等。

窗口截图

捕获窗口截图。

源代码文件bevy/examples/window/screenshot.rs

关键信息

  • 可以捕获窗口截图
  • 可以使用 Window::screenshot() 方法
  • 截图可以保存为文件
  • 可以捕获特定帧的截图

说明
窗口截图功能可以用于创建游戏截图、调试信息等。

实际应用

在游戏开发中的应用场景

窗口管理在游戏开发中有广泛的应用:

  1. 游戏窗口:创建游戏主窗口
  2. 调试窗口:创建调试信息窗口
  3. 设置窗口:创建设置界面窗口
  4. 多显示器支持:在不同显示器上显示不同内容

常见问题

问题 1:如何创建全屏窗口?

解决方案:可以设置窗口的 mode 属性为 WindowMode::Fullscreen

问题 2:如何处理窗口关闭事件?

解决方案:可以监听 WindowCloseRequested 事件,并在事件处理中执行清理操作。

问题 3:如何在不同窗口之间切换?

解决方案:可以使用 WindowRef 来引用不同的窗口,并使用 Cameratarget 属性来指定渲染目标。

性能考虑

  1. 窗口数量:尽量减少窗口数量以提高性能
  2. 窗口大小:合理设置窗口大小以平衡性能和视觉效果
  3. VSync:根据需求启用或禁用 VSync
  4. 窗口事件:避免在窗口事件处理中执行耗时操作

相关资源

相关源代码文件

  • bevy/examples/window/window_settings.rs - 窗口设置示例
  • bevy/examples/window/multiple_windows.rs - 多窗口示例
  • bevy/examples/window/transparent_window.rs - 透明窗口示例
  • bevy/examples/window/window_resizing.rs - 窗口调整大小示例
  • bevy/examples/window/screenshot.rs - 窗口截图示例

官方文档链接

进一步学习建议

  • 学习 UI,了解如何在窗口中创建用户界面
  • 学习输入处理,了解如何处理窗口输入事件
  • 学习相机系统,了解如何在窗口中渲染内容

索引返回上级目录