🦀
chip3. "Hello, world!"の見た目をいじる
はじめに
2024/09/14時点の内容です。
- rustc 1.81.0
- bevy 0.14.2
bevyは開発初期段階のOSSで、まだまだ破壊的なアップデートが入ります。
でも、面白いですよ。
前回
文字の色を変えたりはどこで?
前々回では、"Hello, world!"をspawnするのに以下のコードを使いました。文字の大きさをTextStyle
のfont_size
で指定していることがわかります。
//2Dテキストをspawnする
let style = TextStyle { font_size: 100.0, ..default() };
let text = Text::from_section( "Hello, world!", style );
cmds.spawn( Text2dBundle { text, ..default() } );
情報を束ねているbevy::text::Text2dBundle
から順に見ていくと、装飾に使えそうなフィールドが複数の構造体に分散している様子がわかります。
Text2dBundle
pub struct Text2dBundle {
pub text: Text, //表示する文字列を格納している`text`
pub text_anchor: Anchor,
pub text_2d_bounds: Text2dBounds,
pub transform: Transform, //前回いろいろいじった`transform`
pub global_transform: GlobalTransform,
pub visibility: Visibility,
pub inherited_visibility: InheritedVisibility,
pub view_visibility: ViewVisibility,
pub text_layout_info: TextLayoutInfo,
pub sprite_source: SpriteSource,
}
Text
pub struct Text {
pub sections: Vec<TextSection>, //文字列は`Vec`に分割格納されている
pub justify: JustifyText, //ノードの内側における右・左・中央寄せ
pub linebreak_behavior: BreakLineOn,
}
TextSection
pub struct TextSection {
pub value: String, //表示する文字列
pub style: TextStyle, //装飾
}
TextStyle
pub struct TextStyle {
pub font: Handle<Font>, //フォント指定
pub font_size: f32, //文字の大きさ
pub color: Color, //文字の色
}
"Hello, world!"の見た目をいじる
前々回のソースコードを改造して、"Hello, world!"の1文字ごとに色と大きさを変えます。
けっこうハデ
use bevy::
{ prelude::*,
log::LogPlugin, //ログ出力の制御
};
use std::f32::consts::TAU; // TAU = 2π
//Componentの準備
#[derive( Component )] struct HelloWorld;
//メイン関数
fn main() -> AppExit
{ App::new()
.add_plugins
( //ウインドウやスケジュール等、各種の面倒を見てもらう
DefaultPlugins
.set( LogPlugin { filter: "warn".into(), ..default() } )
)
.add_systems( Startup, spawn_helloworld ) //テキストを表示する
.add_systems( Update, change_letter_style ) //文字の色と大きさを変える
.run()
}
//テキストを表示する
fn spawn_helloworld( mut cmds: Commands )
{ //2Dカメラをspawnする
cmds.spawn( Camera2dBundle::default() );
//"Hello, world!"を1文字ごとに分割した`Text`を作る
let mut sections = Vec::new();
for char in "Hello, world!".chars()
{ let value = char.to_string();
let style = TextStyle { font_size: 100.0, ..default() };
sections.push( TextSection { value, style } );
}
let text = Text { sections, ..default() };
//2Dテキストをspawnする
cmds.spawn( ( Text2dBundle { text, ..default() }, HelloWorld ) );
}
//文字の色と大きさを変える
fn change_letter_style
( mut qry_text: Query<&mut Text, With<HelloWorld>>,
time: Res<Time>,
mut angle: Local<f32>, //Local resource
)
{ let Ok ( mut text ) = qry_text.get_single_mut() else { return };
//前回からの経過時間により角度を進める
*angle += TAU * time.delta().as_secs_f32();
*angle -= if *angle > TAU { TAU } else { 0.0 };
//文字ごとに色を変える
for ( i, char ) in text.sections.iter_mut().enumerate()
{ //hue(色相)
let mut hue = *angle + i as f32 * 0.3;
hue -= if hue > TAU { TAU } else { 0.0 };
//sin()を使って文字の大きさを伸縮させる
let mut angle = *angle + i as f32 * 0.5;
angle -= if angle > TAU { TAU } else { 0.0 };
let size = ( ( 2.0 + angle.sin() ) * 500.0 ).floor() / 10.0 ;
//文字の色と大きさを変える
char.style.color = Color::hsl( hue.to_degrees(), 1.0, 0.5 );
char.style.font_size = size; //font_size 50~150
}
}
Text2dBundle
とTextBundle
おまけ:bevy::text::Text2dBundle
とbevy::ui::node_bundles::TextBundle
はどちらもテキストを表示するために使うバンドルです。2つの使い分けはたぶんこんな感じ。
- 2Dゲームのスプライトと同じ感覚でテキストを使いたい場合は
Text2dBundle
を使う。座標系がスプライトと同じだし、移動・回転・拡縮の操作も同じ。 - Webアプリの感覚でCSSによるイアウトを使いたい場合は
TextBundle
を利用する。flexレイアウトやgridレイアウトが使える。有効な属性はbevy::ui::Style
を参照のこと。
冒頭でも注意書きをしましたが、近々1年以内にUIは大改造されるので、あまり現在の仕様にこだわらない方がよさそうです。
Discussion