预先加载方案1
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_state::<GameState>()
.add_systems(Startup, start_loading)
.add_systems(Update, (
check_loading_progress.run_if(in_state(GameState::Loading)),
))
.add_systems(OnEnter(GameState::Menu), setup_menu)
.add_systems(Update, handle_start_button.run_if(in_state(GameState::Menu)))
.add_systems(OnExit(GameState::Menu), cleanup_menu)
.add_systems(OnEnter(GameState::Playing), setup_game)
.run();
}
#[derive(States, Debug, Clone, PartialEq, Eq, Hash, Default)]
enum GameState {
#[default]
Loading,
Menu,
Playing,
}
#[derive(Resource)]
struct GameAssets {
font: Handle<Font>,
game_image: Handle<Image>,
}
#[derive(Resource)]
struct LoadingProgress {
font_loaded: bool,
image_loaded: bool,
}
impl LoadingProgress {
fn is_complete(&self) -> bool {
self.font_loaded && self.image_loaded
}
}
#[derive(Component)]
struct MenuUI;
#[derive(Component)]
struct StartButton;
fn start_loading(mut commands: Commands, asset_server: Res<AssetServer>) {
println!("开始加载游戏资源...");
let game_assets = GameAssets {
font: asset_server.load("fonts/SarasaFixedHC-Light.ttf"),
game_image: asset_server.load("Schematics.png"),
};
let loading_progress = LoadingProgress {
font_loaded: false,
image_loaded: false,
};
commands.insert_resource(game_assets);
commands.insert_resource(loading_progress);
commands.spawn(Camera2d);
}
fn check_loading_progress(
asset_server: Res<AssetServer>,
game_assets: Res<GameAssets>,
mut loading_progress: ResMut<LoadingProgress>,
mut next_state: ResMut<NextState<GameState>>,
) {
if !loading_progress.font_loaded {
match asset_server.get_load_state(game_assets.font.id()) {
Some(bevy::asset::LoadState::Loaded) => {
loading_progress.font_loaded = true;
println!("字体加载完成!");
}
Some(bevy::asset::LoadState::Failed(_)) => {
println!("字体加载失败!");
loading_progress.font_loaded = true;
}
_ => {
}
}
}
if !loading_progress.image_loaded {
match asset_server.get_load_state(game_assets.game_image.id()) {
Some(bevy::asset::LoadState::Loaded) => {
loading_progress.image_loaded = true;
println!("图片加载完成!");
}
Some(bevy::asset::LoadState::Failed(_)) => {
println!("图片加载失败!");
loading_progress.image_loaded = true;
}
_ => {
}
}
}
if loading_progress.is_complete() {
println!("所有资源加载完成,进入菜单!");
next_state.set(GameState::Menu);
}
}
fn setup_menu(mut commands: Commands, game_assets: Res<GameAssets>) {
println!("设置菜单界面");
commands.spawn((
Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
BackgroundColor(Color::srgb(0.1, 0.1, 0.2)),
MenuUI,
))
.with_children(|parent| {
parent.spawn((
Text::new("游戏菜单"),
TextFont {
font: game_assets.font.clone(),
font_size: 48.0,
..default()
},
TextColor(Color::WHITE),
Node {
margin: UiRect::bottom(Val::Px(50.0)),
..default()
},
));
parent.spawn((
Button,
Node {
width: Val::Px(200.0),
height: Val::Px(60.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
BackgroundColor(Color::srgb(0.2, 0.4, 0.8)),
StartButton,
MenuUI,
))
.with_children(|parent| {
parent.spawn((
Text::new("开始游戏"),
TextFont {
font: game_assets.font.clone(),
font_size: 24.0,
..default()
},
TextColor(Color::WHITE),
));
});
});
}
fn handle_start_button(
mut interaction_query: Query<
(&Interaction, &mut BackgroundColor),
(Changed<Interaction>, With<StartButton>),
>,
mut next_state: ResMut<NextState<GameState>>,
) {
for (interaction, mut color) in &mut interaction_query {
match *interaction {
Interaction::Pressed => {
println!("开始游戏按钮被点击!");
next_state.set(GameState::Playing);
}
Interaction::Hovered => {
*color = BackgroundColor(Color::srgb(0.3, 0.5, 0.9));
}
Interaction::None => {
*color = BackgroundColor(Color::srgb(0.2, 0.4, 0.8));
}
}
}
}
fn cleanup_menu(mut commands: Commands, menu_entities: Query<Entity, With<MenuUI>>) {
println!("清理菜单界面");
for entity in &menu_entities {
commands.entity(entity).despawn();
}
}
fn setup_game(mut commands: Commands, game_assets: Res<GameAssets>) {
println!("设置游戏界面");
commands.spawn((
Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
BackgroundColor(Color::srgb(0.2, 0.1, 0.1)),
))
.with_children(|parent| {
parent.spawn((
Text::new("游戏运行中"),
TextFont {
font: game_assets.font.clone(),
font_size: 36.0,
..default()
},
TextColor(Color::WHITE),
Node {
margin: UiRect::bottom(Val::Px(30.0)),
..default()
},
));
parent.spawn((
Node {
width: Val::Px(300.0),
height: Val::Px(300.0),
margin: UiRect::bottom(Val::Px(20.0)),
..default()
},
ImageNode::new(game_assets.game_image.clone()),
));
parent.spawn((
Text::new("这里显示预加载的图片和字体!"),
TextFont {
font: game_assets.font.clone(),
font_size: 20.0,
..default()
},
TextColor(Color::srgb(0.8, 0.8, 0.8)),
));
});
}