pub fn measure_text(
text: impl AsRef<str>,
font: Option<&Font>,
font_size: u16,
font_scale: f32,
) -> TextDimensionsExamples found in repository?
examples/text_measures.rs (line 4)
3fn draw_text_annotated(text: &str, font: Option<&Font>, x: f32, baseline: f32) {
4 let size = measure_text(text, font, 100, 1.0);
5
6 // Full background rect
7 draw_rectangle(x, baseline - size.offset_y, size.width, size.height, BLUE);
8
9 // Base line
10 draw_rectangle(x, baseline - 2.0, size.width, 4.0, RED);
11
12 // Base line annotation
13 draw_rectangle(x + size.width, baseline - 1.0, 120.0, 1.0, GRAY);
14 draw_text(
15 "baseline",
16 x + size.width + 10.0,
17 baseline - 5.0,
18 30.0,
19 WHITE,
20 );
21
22 // Top line
23 draw_rectangle(x, baseline - 2.0 - size.offset_y, size.width, 4.0, RED);
24
25 // Top line annotation
26 draw_rectangle(
27 x + size.width,
28 baseline - size.offset_y - 1.0,
29 120.0,
30 1.0,
31 GRAY,
32 );
33 draw_text(
34 "topline",
35 x + size.width + 10.0,
36 baseline - size.offset_y - 5.0,
37 30.0,
38 WHITE,
39 );
40
41 // Bottom line
42 draw_rectangle(
43 x,
44 baseline - 2.0 - size.offset_y + size.height,
45 size.width,
46 4.0,
47 RED,
48 );
49
50 // Bottom line annotation
51 draw_rectangle(
52 x + size.width,
53 baseline - size.offset_y + size.height - 1.0,
54 120.0,
55 1.0,
56 GRAY,
57 );
58 draw_text(
59 "bottomline",
60 x + size.width + 10.0,
61 baseline - size.offset_y + size.height - 5.0,
62 30.0,
63 WHITE,
64 );
65
66 draw_text_ex(
67 text,
68 x,
69 baseline,
70 TextParams {
71 font_size: 100,
72 font,
73 ..Default::default()
74 },
75 );
76}More examples
examples/snake.rs (line 139)
16async fn main() {
17 let mut snake = Snake {
18 head: (0, 0),
19 dir: (1, 0),
20 body: LinkedList::new(),
21 };
22 let mut fruit: Point = (rand::gen_range(0, SQUARES), rand::gen_range(0, SQUARES));
23 let mut score = 0;
24 let mut speed = 0.3;
25 let mut last_update = get_time();
26 let mut navigation_lock = false;
27 let mut game_over = false;
28
29 let up = (0, -1);
30 let down = (0, 1);
31 let right = (1, 0);
32 let left = (-1, 0);
33
34 loop {
35 if !game_over {
36 if is_key_down(KeyCode::Right) && snake.dir != left && !navigation_lock {
37 snake.dir = right;
38 navigation_lock = true;
39 } else if is_key_down(KeyCode::Left) && snake.dir != right && !navigation_lock {
40 snake.dir = left;
41 navigation_lock = true;
42 } else if is_key_down(KeyCode::Up) && snake.dir != down && !navigation_lock {
43 snake.dir = up;
44 navigation_lock = true;
45 } else if is_key_down(KeyCode::Down) && snake.dir != up && !navigation_lock {
46 snake.dir = down;
47 navigation_lock = true;
48 }
49
50 if get_time() - last_update > speed {
51 last_update = get_time();
52 snake.body.push_front(snake.head);
53 snake.head = (snake.head.0 + snake.dir.0, snake.head.1 + snake.dir.1);
54 if snake.head == fruit {
55 fruit = (rand::gen_range(0, SQUARES), rand::gen_range(0, SQUARES));
56 score += 100;
57 speed *= 0.9;
58 } else {
59 snake.body.pop_back();
60 }
61 if snake.head.0 < 0
62 || snake.head.1 < 0
63 || snake.head.0 >= SQUARES
64 || snake.head.1 >= SQUARES
65 {
66 game_over = true;
67 }
68 for (x, y) in &snake.body {
69 if *x == snake.head.0 && *y == snake.head.1 {
70 game_over = true;
71 }
72 }
73 navigation_lock = false;
74 }
75 }
76 if !game_over {
77 clear_background(LIGHTGRAY);
78
79 let game_size = screen_width().min(screen_height());
80 let offset_x = (screen_width() - game_size) / 2. + 10.;
81 let offset_y = (screen_height() - game_size) / 2. + 10.;
82 let sq_size = (screen_height() - offset_y * 2.) / SQUARES as f32;
83
84 draw_rectangle(offset_x, offset_y, game_size - 20., game_size - 20., WHITE);
85
86 for i in 1..SQUARES {
87 draw_line(
88 offset_x,
89 offset_y + sq_size * i as f32,
90 screen_width() - offset_x,
91 offset_y + sq_size * i as f32,
92 2.,
93 LIGHTGRAY,
94 );
95 }
96
97 for i in 1..SQUARES {
98 draw_line(
99 offset_x + sq_size * i as f32,
100 offset_y,
101 offset_x + sq_size * i as f32,
102 screen_height() - offset_y,
103 2.,
104 LIGHTGRAY,
105 );
106 }
107
108 draw_rectangle(
109 offset_x + snake.head.0 as f32 * sq_size,
110 offset_y + snake.head.1 as f32 * sq_size,
111 sq_size,
112 sq_size,
113 DARKGREEN,
114 );
115
116 for (x, y) in &snake.body {
117 draw_rectangle(
118 offset_x + *x as f32 * sq_size,
119 offset_y + *y as f32 * sq_size,
120 sq_size,
121 sq_size,
122 LIME,
123 );
124 }
125
126 draw_rectangle(
127 offset_x + fruit.0 as f32 * sq_size,
128 offset_y + fruit.1 as f32 * sq_size,
129 sq_size,
130 sq_size,
131 GOLD,
132 );
133
134 draw_text(format!("SCORE: {score}").as_str(), 10., 20., 20., DARKGRAY);
135 } else {
136 clear_background(WHITE);
137 let text = "Game Over. Press [enter] to play again.";
138 let font_size = 30.;
139 let text_size = measure_text(text, None, font_size as _, 1.0);
140
141 draw_text(
142 text,
143 screen_width() / 2. - text_size.width / 2.,
144 screen_height() / 2. + text_size.height / 2.,
145 font_size,
146 DARKGRAY,
147 );
148
149 if is_key_down(KeyCode::Enter) {
150 snake = Snake {
151 head: (0, 0),
152 dir: (1, 0),
153 body: LinkedList::new(),
154 };
155 fruit = (rand::gen_range(0, SQUARES), rand::gen_range(0, SQUARES));
156 score = 0;
157 speed = 0.3;
158 last_update = get_time();
159 game_over = false;
160 }
161 }
162 next_frame().await;
163 }
164}examples/asteroids.rs (line 69)
46async fn main() {
47 let mut ship = Ship {
48 pos: Vec2::new(screen_width() / 2., screen_height() / 2.),
49 rot: 0.,
50 vel: Vec2::new(0., 0.),
51 };
52
53 let mut bullets = Vec::new();
54 let mut last_shot = get_time();
55 let mut asteroids = Vec::new();
56 let mut gameover = false;
57
58 let mut screen_center;
59
60 loop {
61 if gameover {
62 clear_background(LIGHTGRAY);
63 let mut text = "You Win!. Press [enter] to play again.";
64 let font_size = 30.;
65
66 if asteroids.len() > 0 {
67 text = "Game Over. Press [enter] to play again.";
68 }
69 let text_size = measure_text(text, None, font_size as _, 1.0);
70 draw_text(
71 text,
72 screen_width() / 2. - text_size.width / 2.,
73 screen_height() / 2. - text_size.height / 2.,
74 font_size,
75 DARKGRAY,
76 );
77 if is_key_down(KeyCode::Enter) {
78 ship = Ship {
79 pos: Vec2::new(screen_width() / 2., screen_height() / 2.),
80 rot: 0.,
81 vel: Vec2::new(0., 0.),
82 };
83 bullets = Vec::new();
84 asteroids = Vec::new();
85 gameover = false;
86 screen_center = Vec2::new(screen_width() / 2., screen_height() / 2.);
87 for _ in 0..10 {
88 asteroids.push(Asteroid {
89 pos: screen_center
90 + Vec2::new(rand::gen_range(-1., 1.), rand::gen_range(-1., 1.))
91 .normalize()
92 * screen_width().min(screen_height())
93 / 2.,
94 vel: Vec2::new(rand::gen_range(-1., 1.), rand::gen_range(-1., 1.)),
95 rot: 0.,
96 rot_speed: rand::gen_range(-2., 2.),
97 size: screen_width().min(screen_height()) / 10.,
98 sides: rand::gen_range(3, 8),
99 collided: false,
100 })
101 }
102 }
103 next_frame().await;
104 continue;
105 }
106 let frame_t = get_time();
107 let rotation = ship.rot.to_radians();
108
109 let mut acc = -ship.vel / 100.; // Friction
110
111 // Forward
112 if is_key_down(KeyCode::Up) {
113 acc = Vec2::new(rotation.sin(), -rotation.cos()) / 3.;
114 }
115
116 // Shot
117 if is_key_down(KeyCode::Space) && frame_t - last_shot > 0.5 {
118 let rot_vec = Vec2::new(rotation.sin(), -rotation.cos());
119 bullets.push(Bullet {
120 pos: ship.pos + rot_vec * SHIP_HEIGHT / 2.,
121 vel: rot_vec * 7.,
122 shot_at: frame_t,
123 collided: false,
124 });
125 last_shot = frame_t;
126 }
127
128 // Steer
129 if is_key_down(KeyCode::Right) {
130 ship.rot += 5.;
131 } else if is_key_down(KeyCode::Left) {
132 ship.rot -= 5.;
133 }
134
135 // Euler integration
136 ship.vel += acc;
137 if ship.vel.length() > 5. {
138 ship.vel = ship.vel.normalize() * 5.;
139 }
140 ship.pos += ship.vel;
141 ship.pos = wrap_around(&ship.pos);
142
143 // Move each bullet
144 for bullet in bullets.iter_mut() {
145 bullet.pos += bullet.vel;
146 }
147
148 // Move each asteroid
149 for asteroid in asteroids.iter_mut() {
150 asteroid.pos += asteroid.vel;
151 asteroid.pos = wrap_around(&asteroid.pos);
152 asteroid.rot += asteroid.rot_speed;
153 }
154
155 // Bullet lifetime
156 bullets.retain(|bullet| bullet.shot_at + 1.5 > frame_t);
157
158 let mut new_asteroids = Vec::new();
159 for asteroid in asteroids.iter_mut() {
160 // Asteroid/ship collision
161 if (asteroid.pos - ship.pos).length() < asteroid.size + SHIP_HEIGHT / 3. {
162 gameover = true;
163 break;
164 }
165
166 // Asteroid/bullet collision
167 for bullet in bullets.iter_mut() {
168 if (asteroid.pos - bullet.pos).length() < asteroid.size {
169 asteroid.collided = true;
170 bullet.collided = true;
171
172 // Break the asteroid
173 if asteroid.sides > 3 {
174 new_asteroids.push(Asteroid {
175 pos: asteroid.pos,
176 vel: Vec2::new(bullet.vel.y, -bullet.vel.x).normalize()
177 * rand::gen_range(1., 3.),
178 rot: rand::gen_range(0., 360.),
179 rot_speed: rand::gen_range(-2., 2.),
180 size: asteroid.size * 0.8,
181 sides: asteroid.sides - 1,
182 collided: false,
183 });
184 new_asteroids.push(Asteroid {
185 pos: asteroid.pos,
186 vel: Vec2::new(-bullet.vel.y, bullet.vel.x).normalize()
187 * rand::gen_range(1., 3.),
188 rot: rand::gen_range(0., 360.),
189 rot_speed: rand::gen_range(-2., 2.),
190 size: asteroid.size * 0.8,
191 sides: asteroid.sides - 1,
192 collided: false,
193 })
194 }
195 break;
196 }
197 }
198 }
199
200 // Remove the collided objects
201 bullets.retain(|bullet| bullet.shot_at + 1.5 > frame_t && !bullet.collided);
202 asteroids.retain(|asteroid| !asteroid.collided);
203 asteroids.append(&mut new_asteroids);
204
205 // You win?
206 if asteroids.len() == 0 {
207 gameover = true;
208 }
209
210 if gameover {
211 continue;
212 }
213
214 clear_background(LIGHTGRAY);
215
216 for bullet in bullets.iter() {
217 draw_circle(bullet.pos.x, bullet.pos.y, 2., BLACK);
218 }
219
220 for asteroid in asteroids.iter() {
221 draw_poly_lines(
222 asteroid.pos.x,
223 asteroid.pos.y,
224 asteroid.sides,
225 asteroid.size,
226 asteroid.rot,
227 2.,
228 BLACK,
229 )
230 }
231
232 let v1 = Vec2::new(
233 ship.pos.x + rotation.sin() * SHIP_HEIGHT / 2.,
234 ship.pos.y - rotation.cos() * SHIP_HEIGHT / 2.,
235 );
236 let v2 = Vec2::new(
237 ship.pos.x - rotation.cos() * SHIP_BASE / 2. - rotation.sin() * SHIP_HEIGHT / 2.,
238 ship.pos.y - rotation.sin() * SHIP_BASE / 2. + rotation.cos() * SHIP_HEIGHT / 2.,
239 );
240 let v3 = Vec2::new(
241 ship.pos.x + rotation.cos() * SHIP_BASE / 2. - rotation.sin() * SHIP_HEIGHT / 2.,
242 ship.pos.y + rotation.sin() * SHIP_BASE / 2. + rotation.cos() * SHIP_HEIGHT / 2.,
243 );
244 draw_triangle_lines(v1, v2, v3, 2., BLACK);
245
246 next_frame().await
247 }
248}