錆でゲームを作る-パート9 -メインメニュー画面
36867 ワード
今日、我々はbeisでUISについて学ぶつもりです.私たちの主な目標は、2つのボタンは、1つのゲームを起動し、別のアプリケーションを終了するには、メインメニューで終わることです.この記事では、UI要素を画面に表示する方法、およびボタンイベントを聞く方法について説明します.
ノードとスタイル
BevyのUIをHTMLに簡単に比較することができました:あなたは、要素/ノードの階層を作成し、いくつかのスタイルを適用します、そして、Bevyのエンジンはあなたが求めたものをレンダリングするのに注意します.いくつかの「バンドル」は、あなたのUIを構築するのに役立つようにbevyによって公開されます. NodeBar :基本ノード
ボタンをレンダリングするには
TextBar :テキストをレンダリングするには
この マージンとパディング:UI要素の周囲にスペースを追加するには PositionRank型:相対的または絶対的な位置決めの場合 大部分のflexbox プロパティ:Bevyのレンダリングエンジンは、Flexbox この2つのノードもあります
テキストスタイル
The
上記のテキストノードを見てみると、
それを使用するには、我々はプロジェクトのルートに新しいフォルダを作成し、それを命名
色
ノードとボタンには
ノード階層の定義
UI要素を追加することができます
配線
すべてを配線するには、新しい錆モジュールを
相互作用に異なるスタイルを適用する
システムでボタンの外観を変更することができます.
ボタンをクリックする
ボタンスタイルを変更したときと同じように、クリック時にシステムボタンをクリックすることで反応できます.
ここで、プレス
コードの最終ビット
我々は今、新しいゲームを開始するハンドルをメニューがあるので、我々は
ノードとスタイル
BevyのUIをHTMLに簡単に比較することができました:あなたは、要素/ノードの階層を作成し、いくつかのスタイルを適用します、そして、Bevyのエンジンはあなたが求めたものをレンダリングするのに注意します.いくつかの「バンドル」は、あなたのUIを構築するのに役立つようにbevyによって公開されます.
fn root(materials: &Res<MenuMaterials>) -> NodeBundle {
NodeBundle {
style: Style {
size: Size::new(Val::Percent(100.0), Val::Percent(100.0)),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..Default::default()
},
material: materials.root.clone(),
..Default::default()
}
}
fn button(materials: &Res<MenuMaterials>) -> ButtonBundle {
ButtonBundle {
style: Style {
size: Size::new(Val::Percent(100.0), Val::Percent(100.0)),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..Default::default()
},
material: materials.button.clone(),
..Default::default()
}
}
fn button_text(asset_server: &Res<AssetServer>, materials: &Res<MenuMaterials>, label: &str) -> TextBundle {
return TextBundle {
style: Style {
margin: Rect::all(Val::Px(10.0)),
..Default::default()
},
text: Text::with_section(
label,
TextStyle {
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
font_size: 30.0,
color: materials.button_text.clone(),
},
Default::default(),
),
..Default::default()
};
}
これらの要素の各々はstyle
ノードのレンダリング方法を表すプロパティ.この
style
プロパティは、CSS
. 他にも、fn border(materials: &Res<MenuMaterials>) -> NodeBundle {
NodeBundle {
style: Style {
size: Size::new(Val::Px(400.0), Val::Auto),
border: Rect::all(Val::Px(8.0)),
..Default::default()
},
material: materials.border.clone(),
..Default::default()
}
}
fn menu_background(materials: &Res<MenuMaterials>) -> NodeBundle {
NodeBundle {
style: Style {
size: Size::new(Val::Percent(100.0), Val::Percent(100.0)),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
flex_direction: FlexDirection::ColumnReverse,
padding: Rect::all(Val::Px(5.0)),
..Default::default()
},
material: materials.menu.clone(),
..Default::default()
}
}
テキストスタイル
The
TextBundle
, に加えてstyle
property 1 iプロパティを指定するtext
にはstyle
プロパティ.これは、テキストのフォントサイズ、色、フォントを変更する可能性を公開します.上記のテキストノードを見てみると、
Res<AssetServer>
. このユーティリティは、画像やフォントなどの非錆リソースを読み込むことができます.それを使用するには、我々はプロジェクトのルートに新しいフォルダを作成し、それを命名
assets
. リソースを読み込むためにアセットサーバーを使用する場合は、このフォルダーに関連するリソースのパスを渡します.EX :asset_server.load("fonts/FiraSans-Bold.ttf")
色
ノードとボタンには
material
プロパティ.このプロパティは、以前に我々のプレーヤーとマップに追加された材料と同じように動作します.メニューの開発を容易にするために、これらの色の定義をリソースに集約することができます.struct MenuMaterials {
root: Handle<ColorMaterial>,
border: Handle<ColorMaterial>,
menu: Handle<ColorMaterial>,
button: Handle<ColorMaterial>,
button_hovered: Handle<ColorMaterial>,
button_pressed: Handle<ColorMaterial>,
button_text: Color,
}
impl FromWorld for MenuMaterials {
fn from_world(world: &mut World) -> Self {
let mut materials = world.get_resource_mut::<Assets<ColorMaterial>>().unwrap();
MenuMaterials {
root: materials.add(Color::NONE.into()),
border: materials.add(Color::rgb(0.65, 0.65, 0.65).into()),
menu: materials.add(Color::rgb(0.15, 0.15, 0.15).into()),
button: materials.add(Color::rgb(0.15, 0.15, 0.15).into()),
button_hovered: materials.add(Color::rgb(0.25, 0.25, 0.25).into()),
button_pressed: materials.add(Color::rgb(0.35, 0.75, 0.35).into()),
button_text: Color::WHITE,
}
}
}
このリソースをインスタンス化するには、まだbevyに指示する必要があります.// on our AppBuilder
.init_resource::<MenuMaterials>()
ノード階層の定義
UI要素を追加することができます
AppBuilder.spawn_bundle
と子ノードをwith_children
メソッド:enum MenuButton {
Play,
Quit,
}
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
materials: Res<MenuMaterials>,
) {
commands.spawn_bundle(UiCameraBundle::default());
commands
.spawn_bundle(root(&materials))
.with_children(|parent| {
// left vertical fill (border)
parent
.spawn_bundle(border(&materials))
.with_children(|parent| {
// left vertical fill (content)
parent
.spawn_bundle(menu_background(&materials))
.with_children(|parent| {
parent.spawn_bundle(button(&materials))
.with_children(|parent| {
parent.spawn_bundle(button_text(&asset_server, &materials, "New Game"));
})
.insert(MenuButton::Play);
parent.spawn_bundle(button(&materials))
.with_children(|parent| {
parent.spawn_bundle(button_text(&asset_server, &materials, "Quit"));
})
.insert(MenuButton::Quit);
});
});
});
}
配線
すべてを配線するには、新しい錆モジュールを
main_menu
, にはMainMenuPlugin
.pub struct MainMenuPlugin;
impl Plugin for MainMenuPlugin {
fn build(&self, app: &mut AppBuilder) {
app.init_resource::<MenuMaterials>()
.add_system_set(
SystemSet::on_enter(AppState::MainMenu)
.with_system(cleanup.system())
.with_system(setup.system()),
)
.add_system_set(SystemSet::on_exit(AppState::MainMenu).with_system(cleanup.system()));
}
}
// main.rs
mod main_menu;
use main_menu::MainMenuPlugin;
// ...
.add_plugin(MainMenuPlugin)
ゲームの実行相互作用に異なるスタイルを適用する
システムでボタンの外観を変更することができます.
// MainMenuPlugin
.add_system(button_system.system())
// system implementation
fn button_system(
materials: Res<MenuMaterials>,
mut buttons: Query<
(&Interaction, &mut Handle<ColorMaterial>),
(Changed<Interaction>, With<Button>),
>
) {
for (interaction, mut material) in buttons.iter_mut() {
match *interaction {
Interaction::Clicked => *material = materials.button_pressed.clone(),
Interaction::Hovered => *material = materials.button_hovered.clone(),
Interaction::None => *material = materials.button.clone(),
}
}
}
この方法では、私たちのボタンが色を変更する必要がありますときにホバリングし、緑色に押されたときに押された.ボタンをクリックする
ボタンスタイルを変更したときと同じように、クリック時にシステムボタンをクリックすることで反応できます.
// main menu plugin
.add_system(button_press_system.system())
// System implementation
fn button_press_system(
buttons: Query<(&Interaction, &MenuButton), (Changed<Interaction>, With<Button>)>,
mut state: ResMut<State<AppState>>,
mut exit: EventWriter<AppExit>
) {
for (interaction, button) in buttons.iter() {
if *interaction == Interaction::Clicked {
match button {
MenuButton::Play => state
.set(AppState::InGame)
.expect("Couldn't switch state to InGame"),
MenuButton::Quit => exit.send(AppExit),
};
}
}
}
このシステムが動くために、我々はそれを確実にする必要がありますMenuButton
コンポーネントは、我々のボタンに加えられます.このシステムは、MenuButton
それは私たちのエンティティに追加されました.ここで、プレス
Play Game
新しいゲームを開始し、プレスQuit
ゲームを終了する必要があります.コードの最終ビット
我々は今、新しいゲームを開始するハンドルをメニューがあるので、我々は
main_menu_controls
で定義されたシステムmain.rs
. 代わりに、我々は新しいback_to_main_menu_controls
我々の中でgame
モジュール// GamePlugin
.add_system_set(SystemSet::on_update(AppState::InGame).with_system(back_to_main_menu_controls.system()))
// System implementation
fn back_to_main_menu_controls(mut keys: ResMut<Input<KeyCode>>, mut app_state: ResMut<State<AppState>>) {
if *app_state.current() == AppState::InGame {
if keys.just_pressed(KeyCode::Escape) {
app_state.set(AppState::MainMenu).unwrap();
keys.reset(KeyCode::Escape);
}
}
}
すべてのコードが利用可能ですhere . ゲームの最新バージョンをプレイすることができますhere .Reference
この問題について(錆でゲームを作る-パート9 -メインメニュー画面), 我々は、より多くの情報をここで見つけました https://dev.to/sbelzile/making-games-in-rust-part-9-main-menu-screen-2170テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol