Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

You can choose a font for your text actor! #19

Merged
merged 1 commit into from
Dec 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ is the user-defined struct passed to `rusty_engine::init!()`, or `()` if nothing

- `AudioManager::music_playing()` will return whether or not music is currently playing (accessible
through `EngineState:audio_manager`)
- Custom fonts may now be set on a `TextActor` at creation time.
`EngineState::add_text_actor_with_font` was added for a convenience. The font specified should be
a `.ttf` or `.otf` file stored in `assets/fonts`

- (meta) Improved CI times by using sccache together with GitHub Actions caching

Expand Down
37 changes: 23 additions & 14 deletions examples/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,32 @@ rusty_engine::init!(GameState);

fn main() {
let mut game = Game::new();
let fps = game.add_text_actor("fps", "FPS: ");
let fps = game.add_text_actor_with_font("fps", "FPS: ", "FiraMono-Medium.ttf");
fps.translation = Vec2::new(0.0, 250.0);
fps.font_size = 60.0;

let mut msg = game.add_text_actor("msg", "Changing text and font size after creation is supported, but requires\nre-rendering the text image each time, so use it sparingly!\n\nChanging the text's translation, rotation*, and scale* is fast,\n so feel free to do that a lot.");
let zoom_msg = game.add_text_actor(
"zoom_msg",
"Changing font size re-renders the text smoothly at a different size,\nbut using this technique for animation is both jittery (character kerning) and expensive.",
);
zoom_msg.font_size = 35.0;
zoom_msg.translation = Vec2::new(0.0, 150.0);

let font_msg = game.add_text_actor_with_font(
"font_msg",
"You can choose a font at creation time by providing the filename of a font stored in assets/fonts.\n\"FiraSans-Bold.ttf\" is the default. \"FiraMono-Medium.ttf\" is also included in the asset pack.",
"FiraMono-Medium.ttf",
);
font_msg.font_size = 20.0;
font_msg.translation.y = 0.0;

let msg = game.add_text_actor("msg", "Changing the text's translation, rotation*, and scale* is fast,\n so feel free to do that a lot.");
msg.font_size = 24.0;
msg.translation.y = -150.0;

let mut msg2 = game.add_text_actor("msg2", "*Changing rotation and scale will not work until Bevy 0.6 is released,\nbut changing the translation works great already!");
let msg2 = game.add_text_actor("msg2", "*Changing rotation and scale will not work until Bevy 0.6 is released,\nbut changing the translation works great already!");
msg2.font_size = 20.0;

let mut msg3 = game.add_text_actor(
"msg3",
"Changing font size re-renders the text smoothly at a different size,\nbut using this technique for animation is both jittery (character kerning) and expensive.",
);
msg3.font_size = 35.0;
msg3.translation = Vec2::new(0.0, 150.0);

let game_state = GameState {
timer: Timer::from_seconds(0.2, true),
};
Expand All @@ -39,10 +48,10 @@ fn game_logic(engine_state: &mut EngineState, game_state: &mut GameState) -> boo
}

let msg2 = engine_state.text_actors.get_mut("msg2").unwrap();
msg2.translation.x = 75.0 * (engine_state.time_since_startup_f64 * 0.5).sin() as f32;
msg2.translation.y = 75.0 * (engine_state.time_since_startup_f64 * 0.5).cos() as f32 - 200.0;
msg2.translation.x = 50.0 * (engine_state.time_since_startup_f64 * 0.5).sin() as f32;
msg2.translation.y = 50.0 * (engine_state.time_since_startup_f64 * 0.5).cos() as f32 - 275.0;

let msg3 = engine_state.text_actors.get_mut("msg3").unwrap();
msg3.font_size = 10.0 * (engine_state.time_since_startup_f64 * 0.5).cos() as f32 + 20.0;
let msg3 = engine_state.text_actors.get_mut("zoom_msg").unwrap();
msg3.font_size = 10.0 * (engine_state.time_since_startup_f64 * 0.5).cos() as f32 + 25.0;
true
}
39 changes: 36 additions & 3 deletions src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ pub struct EngineState {
/// SYNCED - The state of all actors this frame. To add an actor, use the
/// [`add_actor`](EngineState::add_actor) method. Modify & remove text actors as you like.
pub actors: HashMap<String, Actor>,
/// SYNCED - The state of all text actors this frame. To add a text actor, use the
/// [`add_text_actor`](EngineState::add_text_actor) method. Modify & remove text actors as you like.
/// SYNCED - The state of all text actors this frame. For convenience adding text actor, use the
/// [`add_text_actor`](EngineState::add_text_actor) or
/// [`add_text_actor_with_font`](EngineState::add_text_actor_with_font) methods. Modify & remove
/// text actors as you like.
pub text_actors: HashMap<String, TextActor>,
/// INFO - All the collision events that occurred this frame. For collisions to be generated
/// between actors, both actors must have [`Actor.collision`] set to `true`. Collision events
Expand Down Expand Up @@ -123,6 +125,36 @@ impl EngineState {
// Unwrap: Can't crash because we just inserted the actor
self.text_actors.get_mut(&label).unwrap()
}

#[must_use]
/// Add a [`TextActor`]. Use the `&mut TextActor` that is returned to set the translation,
/// rotation, etc. Use a unique label for each text actor. Attempting to add two text actors
/// with the same label will crash. The `font` paramater should be the filename of a font
/// located in the assets/fonts directory. The default font is "FiraSans-Bold.ttf".
pub fn add_text_actor_with_font<L, T, F>(
&mut self,
label: L,
text: T,
font: F,
) -> &mut TextActor
where
L: Into<String>,
T: Into<String>,
F: Into<String>,
{
let label = label.into();
let text = text.into();
let font = font.into();
let text_actor = TextActor {
label: label.clone(),
text,
font,
..Default::default()
};
self.text_actors.insert(label.clone(), text_actor);
// Unwrap: Can't crash because we just inserted the actor
self.text_actors.get_mut(&label).unwrap()
}
}

// startup system - grab window settings, initialize all the starting actors
Expand Down Expand Up @@ -172,14 +204,15 @@ pub fn add_text_actors(
let transform = text_actor.bevy_transform();
let font_size = text_actor.font_size;
let text = text_actor.text.clone();
let font_path = format!("fonts/{}", text_actor.font);
commands
.spawn()
.insert(text_actor)
.insert_bundle(Text2dBundle {
text: Text::with_section(
text,
TextStyle {
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
font: asset_server.load(font_path.as_str()),
font_size,
color: Color::WHITE,
},
Expand Down
8 changes: 7 additions & 1 deletion src/text_actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ pub struct TextActor {
pub label: String,
/// SYNCED: The actual text you want to display.
pub text: String,
/// CREATION: The font to use when creating this text actor. Should be a file name of an .otf or
/// .ttf font located within the assets/fonts folder. Defaults to "FiraSans-Bold.ttf" (included
/// in the default asset pack).
pub font: String,
/// SYNCED: The font size of the text you want to display. WARNING: As font sizes get larger,
/// the sprites we generate for them get slower to create. Very large sizes will crash.
/// the sprites we generate for them get slower to create. Very large sizes will crash. The
/// default font size is `30.0`.
pub font_size: f32,
/// SYNCED: Where you are in 2D game space. Positive x is right. Positive y is up. (0.0, 0.0) is the
/// center of the screen.
Expand All @@ -36,6 +41,7 @@ impl Default for TextActor {
Self {
label: String::default(),
text: String::default(),
font: "FiraSans-Bold.ttf".to_string(),
font_size: TEXT_ACTOR_DEFAULT_FONT_SIZE,
translation: Vec2::default(),
layer: TEXT_ACTOR_DEFAULT_LAYER,
Expand Down