Piston-2DGraphics(Rust)中文本换行与文本背景色处理问题
Hey there! As someone who’s tinkered with Piston for 2D projects before, let’s break down your two questions clearly—super common hurdles for new game devs, so no worries:
1. Automatic Line Wrapping for Text Beyond Window Bounds
Piston’s 2D text rendering doesn’t include built-in line wrapping, so you’ll need to handle it manually by splitting your text into lines that fit within your target width (like the window’s width). Here’s a straightforward way to do it:
First, use the Text object from piston2d-graphics to calculate the width of text segments. Then iterate through your content, building lines until adding the next word (or character) would exceed your maximum allowed width.
Here’s a working snippet:
use piston2d_graphics::{Graphics, Text, Transformed}; use piston_window::Window; fn draw_wrapped_text<G: Graphics>( text: &Text, content: &str, max_width: f64, position: [f64; 2], color: [f32; 4], g: &mut G, transform: [[f64; 3]; 2], ) { let mut current_line = String::new(); let mut y_offset = 0.0; let line_height = text.size * 1.2; // Adjust line spacing to your liking for word in content.split_whitespace() { let test_line = if current_line.is_empty() { word.to_string() } else { format!("{} {}", current_line, word) }; let line_width = text.width(test_line.as_str()); if line_width <= max_width { current_line = test_line; } else { // Draw the completed line text.draw( ¤t_line, text.font, &color, transform.trans(position[0], position[1] + y_offset), g, ); current_line = word.to_string(); y_offset += line_height; } } // Draw the last remaining line if !current_line.is_empty() { text.draw( ¤t_line, text.font, &color, transform.trans(position[0], position[1] + y_offset), g, ); } } // Usage in your draw loop: // let window_size = window.size(); // draw_wrapped_text( // &text, // "Your long text that needs wrapping here—this should split into multiple lines once it hits the window edge!", // window_size.width - 20.0, // Add padding to avoid touching window edges // [10.0, 10.0], // [1.0, 1.0, 1.0, 1.0], // White text color // &mut g, // transform, // );
This splits text by whitespace (adjust to split by characters if you need to handle non-word content) and checks each potential line’s width against your max limit.
2. Setting a Background Color for a Text Area
Adding a background to your text area is simple: just draw a filled rectangle before rendering your text—Piston draws objects in the order you call them, so the rectangle will sit behind the text.
Here’s how to implement it:
use piston2d_graphics::{Graphics, Rectangle, Text, Transformed}; fn draw_text_with_background<G: Graphics>( text: &Text, content: &str, text_pos: [f64; 2], bg_color: [f32; 4], text_color: [f32; 4], padding: f64, g: &mut G, transform: [[f64; 3]; 2], ) { // Calculate the full bounds of the single-line text let text_width = text.width(content); let text_height = text.size; // Define the background rectangle (add padding for breathing room) let bg_x = text_pos[0] - padding; let bg_y = text_pos[1] - padding; let bg_width = text_width + padding * 2.0; let bg_height = text_height + padding * 2.0; // Draw the background rectangle first Rectangle::new(bg_color).draw( [bg_x, bg_y, bg_width, bg_height], &g.draw_state(), transform, g, ); // Draw the text on top text.draw( content, text.font, &text_color, transform.trans(text_pos[0], text_pos[1]), g, ); } // For wrapped text: // Track the total height of all lines in your draw_wrapped_text function (final y_offset + line_height) // Then use that total height instead of text.size to calculate the background's height
For wrapped text, just adjust the background height calculation to use the total height of all your wrapped lines instead of a single line’s height.
内容的提问来源于stack exchange,提问作者Ritwik

