#[repr(C)]pub struct Vector2<T> {
pub x: T,
pub y: T,
}Expand description
Utility type for manipulating 2-dimensional vectors.
Vector2 is a simple type that defines
a mathematical vector with two coordinates (x and y).
It can be used to represent anything that has two dimensions: a size, a point, a velocity, etc.
The type parameter T is the type of the coordinates.
You generally don’t have to care about the generic form (Vector2<T>), the most common
specializations have special type aliases:
The Vector2 type has a small and simple interface, its x and y members can be
accessed directly (there are no accessors like set_x(), get_x()) and it contains no
mathematical function like dot product, cross product, length, etc.
§Usage example
let mut v1 = Vector2f::new(16.5, 24.0);
v1.x = 18.2;
let y = v1.y;
let v2 = v1 * 5.0;
let v3 = v1 + v2;
assert_ne!(v2, v3);Note: for 3-dimensional vectors, see Vector3.
Fields§
§x: TX coordinate of the vector.
y: TY coordinate of the vector.
Implementations§
Source§impl<T> Vector2<T>
impl<T> Vector2<T>
Sourcepub const fn new(x: T, y: T) -> Self
pub const fn new(x: T, y: T) -> Self
Creates a new vector from its coordinates.
§Usage example
let v: Vector2<isize> = Vector2::new(6969, 6969);Examples found in repository?
24fn mouse_over(rect: &Rect<i32>, mouse_x: i32, mouse_y: i32) -> bool {
25 rect.contains(Vector2::new(mouse_x, mouse_y))
26}
27
28enum ButtonStyle {
29 Normal,
30 Highlighted,
31 Selected,
32 Error,
33}
34
35fn draw_button(
36 rect: &Rect<i32>,
37 shape: &mut RectangleShape,
38 text: &mut Text,
39 string: &str,
40 render_window: &mut RenderWindow,
41 style: ButtonStyle,
42) {
43 shape.set_position((rect.left as f32, rect.top as f32));
44 shape.set_size((rect.width as f32, rect.height as f32));
45 let (rect_fill, rect_outline, text_fill) = match style {
46 ButtonStyle::Normal => (Color::TRANSPARENT, Color::WHITE, Color::WHITE),
47 ButtonStyle::Highlighted => (Color::WHITE, Color::WHITE, Color::BLACK),
48 ButtonStyle::Selected => (Color::GREEN, Color::GREEN, Color::BLACK),
49 ButtonStyle::Error => (Color::RED, Color::BLACK, Color::BLACK),
50 };
51 shape.set_outline_color(rect_outline);
52 shape.set_fill_color(rect_fill);
53 text.set_position((rect.left as f32 + 12.0, rect.top as f32 + 8.0));
54 text.set_fill_color(text_fill);
55 text.set_string(string);
56 render_window.draw(shape);
57 render_window.draw(text);
58}
59
60fn bstyle(highlighted: bool, selected: bool, error: bool) -> ButtonStyle {
61 if error {
62 ButtonStyle::Error
63 } else if highlighted {
64 ButtonStyle::Highlighted
65 } else if selected {
66 ButtonStyle::Selected
67 } else {
68 ButtonStyle::Normal
69 }
70}
71
72fn main() -> SfResult<()> {
73 example_ensure_right_working_dir();
74
75 let mut cursor = Cursor::from_system(CursorType::Arrow)?;
76 let mut rw = RenderWindow::new(
77 (800, 800),
78 "SFML cursor example",
79 Style::CLOSE,
80 &ContextSettings::default(),
81 )?;
82 rw.set_vertical_sync_enabled(true);
83 let font = Font::from_file("sansation.ttf")?;
84 let mut failed_index = usize::MAX;
85 let mut selected_index = usize::MAX;
86 let set_button = Rect::new(348, 500, 100, 32);
87 let hotspot_button = Rect::new(458, 500, 100, 32);
88 let clear_button = Rect::new(568, 500, 100, 32);
89 let mut pixel_grid = [false; DRAW_GRID_WH as usize * DRAW_GRID_WH as usize];
90 let mut hotspot_selection = false;
91 let mut hotspot_selected = false;
92 let mut hotspot = Vector2::new(8, 8);
93 let mut modif = false;
94
95 let mut buttons = Vec::new();
96 let cursor_types = [
97 CursorType::Arrow,
98 CursorType::ArrowWait,
99 CursorType::Wait,
100 CursorType::Text,
101 CursorType::Hand,
102 CursorType::SizeHorizontal,
103 CursorType::SizeVertical,
104 CursorType::SizeTopLeftBottomRight,
105 CursorType::SizeBottomLeftTopRight,
106 CursorType::SizeLeft,
107 CursorType::SizeRight,
108 CursorType::SizeTop,
109 CursorType::SizeBottom,
110 CursorType::SizeTopLeft,
111 CursorType::SizeBottomRight,
112 CursorType::SizeBottomLeft,
113 CursorType::SizeTopRight,
114 CursorType::SizeAll,
115 CursorType::Cross,
116 CursorType::Help,
117 CursorType::NotAllowed,
118 ];
119 for i in 0..cursor_types.len() {
120 buttons.push(Rect::new(16, 16 + i as i32 * 36, 250, 32));
121 }
122
123 while rw.is_open() {
124 while let Some(ev) = rw.poll_event() {
125 match ev {
126 Event::Closed => rw.close(),
127 Event::MouseButtonPressed {
128 button: mouse::Button::Left,
129 x,
130 y,
131 } => {
132 for (i, b) in buttons.iter().enumerate() {
133 if mouse_over(b, x, y) {
134 match cursor.load_from_system(cursor_types[i]) {
135 Ok(()) => {
136 unsafe {
137 rw.set_mouse_cursor(&cursor);
138 }
139 selected_index = i;
140 }
141 Err(e) => {
142 eprintln!("{e}");
143 failed_index = i;
144 }
145 }
146 }
147 }
148 if mouse_over(&set_button, x, y) {
149 let mut pixels = [0; DRAW_GRID_WH as usize * DRAW_GRID_WH as usize * 4];
150 for (i, px) in pixel_grid.iter().enumerate() {
151 let offset = i * 4;
152 if *px {
153 pixels[offset] = 255;
154 pixels[offset + 1] = 255;
155 pixels[offset + 2] = 255;
156 pixels[offset + 3] = 255;
157 }
158 }
159 unsafe {
160 match cursor.load_from_pixels(
161 &pixels,
162 Vector2::new(DRAW_GRID_WH as u32, DRAW_GRID_WH as u32),
163 hotspot,
164 ) {
165 Ok(()) => {
166 rw.set_mouse_cursor(&cursor);
167 }
168 Err(e) => {
169 eprintln!("{e}");
170 }
171 }
172 }
173 modif = false;
174 }
175 if mouse_over(&clear_button, x, y) {
176 for px in pixel_grid.iter_mut() {
177 *px = false;
178 }
179 modif = true;
180 }
181 if mouse_over(&hotspot_button, x, y) {
182 hotspot_selection = true;
183 }
184 }
185 Event::MouseButtonReleased {
186 button: mouse::Button::Left,
187 ..
188 } => {
189 if hotspot_selected {
190 hotspot_selection = false;
191 hotspot_selected = false;
192 }
193 }
194 _ => {}
195 }
196 }
197 let mut set_button_highlighted = false;
198 let mut hotspot_button_highlighted = false;
199 let mut clear_button_highlighted = false;
200 // System cursor set button interactions
201 let mp = rw.mouse_position();
202 let mut highlight_index = usize::MAX;
203 for (i, b) in buttons.iter().enumerate() {
204 if mouse_over(b, mp.x, mp.y) {
205 highlight_index = i;
206 }
207 }
208 if mouse_over(&set_button, mp.x, mp.y) {
209 set_button_highlighted = true;
210 }
211 if mouse_over(&hotspot_button, mp.x, mp.y) {
212 hotspot_button_highlighted = true;
213 }
214 if mouse_over(&clear_button, mp.x, mp.y) {
215 clear_button_highlighted = true;
216 }
217 // Grid interactions
218 let rela_x = mp.x - DRAW_AREA_TOPLEFT.0 as i32;
219 let rela_y = mp.y - DRAW_AREA_TOPLEFT.1 as i32;
220 let (gx, gy) = (rela_x / DRAW_CELL_WH as i32, rela_y / DRAW_CELL_WH as i32);
221 if gx >= 0 && gy >= 0 {
222 if let Some(cell) = gridindex(&mut pixel_grid, gx as usize, gy as usize) {
223 if hotspot_selection {
224 hotspot_selected = true;
225 hotspot = Vector2::new(gx as u32, gy as u32);
226 modif = true;
227 } else if mouse::Button::Left.is_pressed() {
228 *cell = true;
229 modif = true;
230 } else if mouse::Button::Right.is_pressed() {
231 *cell = false;
232 modif = true;
233 }
234 }
235 }
236 rw.clear(Color::BLACK);
237 // Draw system cursor set buttons
238 let mut shape = RectangleShape::default();
239 let mut text = Text::new("", &font, 14);
240 shape.set_outline_thickness(-1.0);
241 shape.set_outline_color(Color::WHITE);
242 for (i, b) in buttons.iter().enumerate() {
243 let types = [
244 "ARROW",
245 "ARROW_WAIT",
246 "WAIT",
247 "TEXT",
248 "HAND",
249 "SIZE_HORIZONTAL",
250 "SIZE_VERTICAL",
251 "SIZE_TOP_LEFT_BOTTOM_RIGHT",
252 "SIZE_BOTTOM_LEFT_TOP_RIGHT",
253 "SIZE_LEFT",
254 "SIZE_RIGHT",
255 "SIZE_TOP",
256 "SIZE_BOTTOM",
257 "SIZE_TOP_LEFT",
258 "SIZE_BOTTOM_RIGHT",
259 "SIZE_BOTTOM_LEFT",
260 "SIZE_TOP_RIGHT",
261 "SIZE_ALL",
262 "CROSS",
263 "HELP",
264 "NOT_ALLOWED",
265 ];
266 draw_button(
267 b,
268 &mut shape,
269 &mut text,
270 types[i],
271 &mut rw,
272 bstyle(highlight_index == i, selected_index == i, failed_index == i),
273 );
274 }
275 // Draw pixel drawing grid
276 shape.set_fill_color(Color::TRANSPARENT);
277 for y in 0..DRAW_GRID_WH {
278 for x in 0..DRAW_GRID_WH {
279 if hotspot.x == x as u32 && hotspot.y == y as u32 {
280 shape.set_outline_color(Color::RED);
281 } else {
282 shape.set_outline_color(Color::rgb(180, 180, 180));
283 }
284 if gridindex(&mut pixel_grid, x as usize, y as usize).is_some_and(|bool| *bool) {
285 shape.set_fill_color(Color::WHITE);
286 } else {
287 shape.set_fill_color(Color::TRANSPARENT);
288 }
289 shape.set_size((DRAW_CELL_WH as f32, DRAW_CELL_WH as f32));
290 shape.set_position((
291 DRAW_AREA_TOPLEFT.0 as f32 + (x as f32 * DRAW_CELL_WH as f32),
292 DRAW_AREA_TOPLEFT.1 as f32 + (y as f32 * DRAW_CELL_WH as f32),
293 ));
294 rw.draw(&shape);
295 }
296 }
297 draw_button(
298 &set_button,
299 &mut shape,
300 &mut text,
301 if modif { "Set*" } else { "Set" },
302 &mut rw,
303 bstyle(set_button_highlighted, false, false),
304 );
305 draw_button(
306 &hotspot_button,
307 &mut shape,
308 &mut text,
309 "Hotspot",
310 &mut rw,
311 bstyle(hotspot_button_highlighted, hotspot_selection, false),
312 );
313 draw_button(
314 &clear_button,
315 &mut shape,
316 &mut text,
317 "Clear",
318 &mut rw,
319 bstyle(clear_button_highlighted, false, false),
320 );
321 rw.display();
322 }
323 Ok(())
324}More examples
110 fn update(&mut self, t: f32, x: f32, y: f32) -> SfResult<()> {
111 self.shader.set_uniform_float("wave_phase", t)?;
112 self.shader
113 .set_uniform_vec2("wave_amplitude", Vector2f::new(x * 40., y * 40.))?;
114 self.shader
115 .set_uniform_float("blur_radius", (x + y) * 0.008)
116 }
117 fn name(&self) -> &str {
118 "wave + blur"
119 }
120}
121
122struct StormBlink {
123 points: Vec<Vertex>,
124 shader: FBox<Shader<'static>>,
125}
126
127impl StormBlink {
128 fn new() -> SfResult<Self> {
129 let mut rng = SmallRng::seed_from_u64(1);
130
131 let mut points = Vec::new();
132 for _ in 0..40_000 {
133 let x = rng.random_range(0.0..800.);
134 let y = rng.random_range(0.0..600.);
135 let (red, green, blue) = (rng.random(), rng.random(), rng.random());
136 points.push(Vertex::with_pos_color(
137 Vector2f::new(x, y),
138 Color::rgb(red, green, blue),
139 ));
140 }
141
142 let shader = Shader::from_file_vert_frag("storm.vert", "blink.frag")?;
143 Ok(Self { points, shader })
144 }
145}
146
147impl Drawable for StormBlink {
148 fn draw<'a: 'shader, 'texture, 'shader, 'shader_texture>(
149 &'a self,
150 target: &mut dyn RenderTarget,
151 states: &RenderStates<'texture, 'shader, 'shader_texture>,
152 ) {
153 let mut states = *states;
154 states.shader = Some(&self.shader);
155 target.draw_primitives(&self.points, PrimitiveType::POINTS, &states);
156 }
157}
158
159impl Effect for StormBlink {
160 fn update(&mut self, t: f32, x: f32, y: f32) -> SfResult<()> {
161 let radius = 200. + t.cos() * 150.;
162 self.shader
163 .set_uniform_vec2("storm_position", Vector2f::new(x * 800., y * 600.))?;
164 self.shader
165 .set_uniform_float("storm_inner_radius", radius / 3.)?;
166 self.shader
167 .set_uniform_float("storm_total_radius", radius)?;
168 self.shader
169 .set_uniform_float("blink_alpha", 0.5 + (t * 3.).cos() * 0.25)
170 }34 fn with_font(font: &RcFont, up: bool, left: bool, speed: f32) -> Self {
35 let mut self_ = Self {
36 up,
37 left,
38 sprite: Default::default(),
39 text: RcText::new("", font, 16),
40 speed,
41 render_sprite: false,
42 };
43 self_.text.scale(Vector2f::new(2., 2.));
44
45 self_
46 }
47
48 fn render(&self, window: &mut RenderWindow) {
49 if self.render_sprite {
50 window.draw(&self.sprite)
51 } else {
52 window.draw(&self.text)
53 }
54 }
55
56 fn move_resources(&mut self, window_size: Vector2f) {
57 if self.render_sprite {
58 // Modify the sprite position freely
59 if self.sprite.position().y <= 0f32 {
60 self.up = false;
61 }
62 if self.sprite.position().y + self.sprite.global_bounds().height >= window_size.y {
63 self.up = true;
64 }
65 if self.sprite.position().x <= 0f32 {
66 self.left = false;
67 }
68 if self.sprite.position().x + self.sprite.global_bounds().width >= window_size.x {
69 self.left = true;
70 }
71
72 self.sprite.set_position(
73 self.sprite.position()
74 + Vector2f::new(
75 if self.left { -self.speed } else { self.speed },
76 if self.up { -self.speed } else { self.speed },
77 ),
78 );
79 } else {
80 // Modify the sprite position freely
81 if self.text.position().y <= 0f32 {
82 self.up = false;
83 }
84 if self.text.position().y + self.text.global_bounds().height >= window_size.y {
85 self.up = true;
86 }
87 if self.text.position().x <= 0f32 {
88 self.left = false;
89 }
90 if self.text.position().x + self.text.global_bounds().width >= window_size.x {
91 self.left = true;
92 }
93
94 self.text.set_position(
95 self.text.position()
96 + Vector2f::new(
97 if self.left { -self.speed } else { self.speed },
98 if self.up { -self.speed } else { self.speed },
99 ),
100 );
101 }
102 }
103}
104
105fn test_getting_rc_texture_from_texture() -> SfResult<RcTexture> {
106 Ok(RcTexture::from_texture(Texture::from_file("frank.jpeg")?))
107}
108
109fn get_set_smooth_rc_text(font: &RcFont) -> RcText {
110 let mut set_smooth_text = RcText::new(
111 "Press 's' to enable/disable font smoothing\n\
112 Press 't' to toggle showing font texture atlas",
113 font,
114 16,
115 );
116 set_smooth_text.scale(Vector2f::new(2., 2.));
117
118 set_smooth_text
119}
120
121fn main() -> SfResult<()> {
122 example_ensure_right_working_dir();
123
124 let mut window =
125 RenderWindow::new((800, 600), "SFML window", Style::CLOSE, &Default::default())?;
126 window.set_framerate_limit(60);
127
128 // Create a new texture.
129 let texture = RcTexture::from_file("logo.png")?;
130 let texture2 = test_getting_rc_texture_from_texture()?;
131
132 // Create a new font.
133 let font_path = match std::env::args().nth(1) {
134 Some(path) => path,
135 None => "sansation.ttf".into(),
136 };
137 let mut font = RcFont::from_file(&font_path)?;
138
139 // Load many resources with no lifetime contingencies
140 let mut floating_resources = Vec::from([
141 FloatingResource::with_texture(&texture2, true, true, 1.1f32),
142 FloatingResource::with_texture(&texture2, true, true, 1.2f32),
143 FloatingResource::with_texture(&texture, true, true, 1f32),
144 FloatingResource::with_texture(&texture, true, false, 1.5f32),
145 FloatingResource::with_texture(&texture, false, true, 2f32),
146 FloatingResource::with_texture(&texture, false, false, 2.5f32),
147 FloatingResource::with_font(&font, true, true, 1.25f32),
148 FloatingResource::with_font(&font, true, true, 1.75f32),
149 FloatingResource::with_font(&font, true, true, 2.25f32),
150 FloatingResource::with_font(&font, true, true, 2.75f32),
151 ]);
152
153 let set_smooth_text = get_set_smooth_rc_text(&font);
154 let mut show_texture_atlas = false;
155 let mut text_buf = String::from("SFML");
156
157 while window.is_open() {
158 while let Some(event) = window.poll_event() {
159 if event == Event::Closed {
160 window.close();
161 }
162
163 match event {
164 Event::Closed => window.close(),
165 Event::KeyPressed { code, ctrl, .. } => match code {
166 Key::S => {
167 let smooth = !font.is_smooth();
168 font.set_smooth(smooth);
169 }
170 Key::T => {
171 show_texture_atlas ^= true;
172 }
173 Key::V if ctrl => {
174 text_buf.push_str(&clipboard::get_string());
175 }
176 _ => {}
177 },
178 Event::TextEntered { unicode } if show_texture_atlas => {
179 if unicode == 0x8 as char {
180 text_buf.pop();
181 } else if !unicode.is_ascii_control() && unicode != 's' && unicode != 't' {
182 text_buf.push(unicode);
183 }
184 }
185 _ => {}
186 }
187 }
188
189 // Update floating_resource positions so they move around on the screen
190 for floating_resource in &mut floating_resources {
191 floating_resource.move_resources(Vector2f::new(800f32, 600f32));
192 floating_resource.text.set_string(&text_buf);
193 }
194
195 window.clear(Color::BLACK);
196
197 // Fetch and draw all the sprites in floating_resources
198 for floating_resource in &floating_resources {
199 floating_resource.render(&mut window);
200 }
201
202 window.draw(&set_smooth_text);
203 if show_texture_atlas {
204 let scale = 3.0;
205 let tex = font.texture(16);
206 let mut rs = RectangleShape::with_size(tex.size().as_other());
207 rs.set_fill_color(Color::MAGENTA);
208 rs.set_scale(scale);
209 window.draw(&rs);
210 let mut s = Sprite::with_texture(&tex);
211 s.set_scale(scale);
212 window.draw(&s);
213 }
214 window.display();
215 }
216 Ok(())
217}5fn main() -> SfResult<()> {
6 example_ensure_right_working_dir();
7
8 let mut window = RenderWindow::new(
9 (800, 600),
10 "Mouse events",
11 Style::CLOSE,
12 &Default::default(),
13 )?;
14 window.set_mouse_cursor_visible(false);
15 window.set_vertical_sync_enabled(true);
16
17 let font = Font::from_file("sansation.ttf")?;
18 let mut circle = CircleShape::new(4., 30);
19 let mut texts: Vec<Text> = Vec::new();
20 let mut mp_text = Text::new("", &font, 14);
21 let mut cursor_visible = false;
22 let mut grabbed = false;
23 macro_rules! push_text {
24 ($x:expr, $y:expr, $fmt:expr, $($arg:tt)*) => {
25 let mut text = Text::new(&format!($fmt, $($arg)*), &font, 14);
26 text.set_position(($x as f32, $y as f32));
27 texts.push(text);
28 }
29 }
30
31 'mainloop: loop {
32 while let Some(ev) = window.poll_event() {
33 match ev {
34 Event::Closed => break 'mainloop,
35 Event::MouseWheelScrolled { wheel, delta, x, y } => {
36 push_text!(x, y, "Scroll: {:?}, {}, {}, {}", wheel, delta, x, y);
37 }
38 Event::MouseButtonPressed { button, x, y } => {
39 push_text!(x, y, "Press: {:?}, {}, {}", button, x, y);
40 }
41 Event::MouseButtonReleased { button, x, y } => {
42 push_text!(x, y, "Release: {:?}, {}, {}", button, x, y);
43 }
44 Event::KeyPressed { code, .. } => {
45 if code == Key::W {
46 window.set_mouse_position(Vector2i::new(400, 300));
47 } else if code == Key::D {
48 let dm = VideoMode::desktop_mode();
49 let center = Vector2i::new(dm.width as i32 / 2, dm.height as i32 / 2);
50 mouse::set_desktop_position(center);
51 } else if code == Key::V {
52 cursor_visible = !cursor_visible;
53 window.set_mouse_cursor_visible(cursor_visible);
54 } else if code == Key::G {
55 grabbed = !grabbed;
56 window.set_mouse_cursor_grabbed(grabbed);
57 }
58 }
59 _ => {}
60 }
61 }
62
63 let mp = window.mouse_position();
64 let dmp = mouse::desktop_position();
65 let cur_vis_msg = if cursor_visible {
66 "visible"
67 } else {
68 "invisible"
69 };
70 let grab_msg = if grabbed { "grabbed" } else { "not grabbed" };
71 mp_text.set_string(&format!(
72 "x: {}, y: {} (Window)\n\
73 x: {}, y: {} (Desktop)\n\
74 [{cur_vis_msg}] [{grab_msg}] ('V'/'G') to toggle\n\
75 'W' to center mouse on window\n\
76 'D' to center mouse on desktop",
77 mp.x, mp.y, dmp.x, dmp.y
78 ));
79
80 circle.set_position((mp.x as f32, mp.y as f32));
81
82 window.clear(Color::BLACK);
83 // Push texts out of each other's way
84 for i in (0..texts.len()).rev() {
85 for j in (0..i).rev() {
86 if let Some(intersect) = texts[i]
87 .global_bounds()
88 .intersection(&texts[j].global_bounds())
89 {
90 texts[j].move_((0., -intersect.height));
91 }
92 }
93 }
94 texts.retain(|txt| txt.fill_color().a > 0);
95 for txt in &mut texts {
96 let mut color = txt.fill_color();
97 color.a -= 1;
98 txt.set_fill_color(color);
99 window.draw(txt);
100 }
101 if !cursor_visible {
102 window.draw(&circle);
103 }
104 window.draw(&mp_text);
105 window.display();
106 }
107 Ok(())
108}46fn main() -> Result<(), Box<dyn Error>> {
47 example_ensure_right_working_dir();
48
49 let mut rw = RenderWindow::new(
50 (800, 600),
51 "Positional audio demo",
52 Style::CLOSE,
53 &Default::default(),
54 )?;
55 rw.set_vertical_sync_enabled(true);
56 let font = Font::from_file("sansation.ttf")?;
57 let mut text = Text::new("", &font, 20);
58 let mut music = match std::env::args().nth(1) {
59 Some(music_path) => Music::from_file(&music_path)?,
60 None => Music::from_file("canary.wav")?,
61 };
62 if music.channel_count() != 1 {
63 return Err("Sorry, only sounds with 1 channel are supported.".into());
64 };
65 music.set_looping(true);
66 music.play();
67 music.set_position(Vector3::new(0., 0., 0.));
68
69 let mut listener_pos = Vector3::new(0.0, 0.0, 0.0);
70 let center = Vector2::new(400., 300.);
71 let [mut go_left, mut go_right, mut go_up, mut go_down] = [false; 4];
72 let clock = Clock::start()?;
73
74 while rw.is_open() {
75 while let Some(ev) = rw.poll_event() {
76 match ev {
77 Event::Closed => rw.close(),
78 Event::KeyPressed { code, .. } => match code {
79 Key::A => go_left = true,
80 Key::D => go_right = true,
81 Key::W => go_up = true,
82 Key::S => go_down = true,
83 _ => {}
84 },
85 Event::KeyReleased { code, .. } => match code {
86 Key::A => go_left = false,
87 Key::D => go_right = false,
88 Key::W => go_up = false,
89 Key::S => go_down = false,
90 _ => {}
91 },
92 _ => {}
93 }
94 }
95 let Vector2f { x: mx, y: my } = rw.mouse_position().as_other();
96 let speed = 0.05;
97 if go_left {
98 listener_pos.x -= speed;
99 }
100 if go_right {
101 listener_pos.x += speed;
102 }
103 if go_up {
104 listener_pos.y -= speed;
105 }
106 if go_down {
107 listener_pos.y += speed;
108 }
109 let scale = 20.0; // Scale the positions for better visualization
110 listener::set_position(listener_pos);
111 listener::set_direction(Vector3::new(
112 (mx - center.x) / scale,
113 (my - center.y) / scale,
114 -1.,
115 ));
116 let Vector3 {
117 x: lx,
118 y: ly,
119 z: lz,
120 } = listener::position();
121 let Vector3 {
122 x: dx,
123 y: dy,
124 z: dz,
125 } = listener::direction();
126 rw.clear(Color::BLACK);
127 let mut circle_shape = CircleShape::new(8.0, 32);
128 // Draw circle at center, representing position of music being played
129 circle_shape.set_position(center);
130 circle_shape.set_fill_color(Color::YELLOW);
131 let t = clock.elapsed_time().as_seconds();
132 let radius = 12.0 + t.sin() * 3.0;
133 circle_shape.set_radius(radius);
134 circle_shape.set_origin(radius);
135 rw.draw(&circle_shape);
136 // Draw circle representing listener
137 circle_shape.set_position((center.x + lx * scale, center.y + ly * scale));
138 circle_shape.set_origin(4.0);
139 circle_shape.set_radius(4.0);
140 circle_shape.set_fill_color(Color::GREEN);
141 rw.draw(&circle_shape);
142 // Draw line from listener to direction vector position
143 rw.draw_line(
144 circle_shape.position(),
145 (center.x + dx * scale, center.y + dy * scale).into(),
146 2.0,
147 );
148 text.set_string("WASD + mouse for movement of listener");
149 text.set_position(0.);
150 rw.draw(&text);
151 text.set_string(&format!("Listener position: {lx}, {ly}, {lz}"));
152 text.set_position((0., 20.0));
153 rw.draw(&text);
154 text.set_string(&format!("Listener direction: {dx}, {dy}, {dz}"));
155 text.set_position((0., 40.0));
156 rw.draw(&text);
157 rw.display();
158 }
159 Ok(())
160}62fn main() -> SfResult<()> {
63 example_ensure_right_working_dir();
64
65 let native_mode = VideoMode::desktop_mode();
66 let mut window = RenderWindow::new(
67 native_mode,
68 "Spritemark",
69 Style::default(),
70 &ContextSettings::default(),
71 )?;
72 window.set_position(Vector2::new(0, 0));
73 window.set_vertical_sync_enabled(true);
74 let font = Font::from_file("sansation.ttf")?;
75 let texture = Texture::from_file("devices.png")?;
76 let mut text = Text::new("", &font, 18);
77 text.set_outline_color(Color::BLACK);
78 text.set_outline_thickness(1.0);
79 let mut click_counter = 0;
80 let mut objects = Vec::new();
81 let mut rng = SmallRng::seed_from_u64(1);
82 let mut rs = RenderStates::default();
83 let mut buf = Vec::new();
84 let mut frames_rendered = 0;
85 let mut sec_clock = Clock::start()?;
86 let mut fps = 0;
87 let mut lmb_down = false;
88 let mut view = View::new()?;
89
90 while window.is_open() {
91 while let Some(event) = window.poll_event() {
92 match event {
93 Event::Closed
94 | Event::KeyPressed {
95 code: Key::Escape, ..
96 } => window.close(),
97 Event::MouseButtonPressed {
98 button: Button::Left,
99 ..
100 } => {
101 click_counter += 1;
102 lmb_down = true;
103 }
104 Event::MouseButtonReleased {
105 button: Button::Left,
106 ..
107 } => {
108 lmb_down = false;
109 }
110 Event::Resized { width, height } => {
111 view.reset(Rect::new(0., 0., width as f32, height as f32));
112 window.set_view(&view);
113 }
114 _ => {}
115 }
116 }
117
118 if lmb_down {
119 let mp = window.mouse_position();
120 for _ in 0..25 {
121 objects.push(Object {
122 position: fconv(mp),
123 speed: Vector2f::new(rng.random_range(-3.0..3.0), 0.0),
124 image_id: click_counter % N_IMAGES,
125 angle: 0.0,
126 rot_speed: rng.random_range(-2.0..2.0),
127 });
128 }
129 }
130
131 for obj in &mut objects {
132 let size = f32::from(SUBIMAGE_SIZE);
133 let tex_x = f32::from(obj.image_id) * size;
134 let mut tf = Transform::default();
135 tf.translate(obj.position.x, obj.position.y);
136 tf.rotate_with_center(obj.angle, size / 2.0, size / 2.0);
137 buf.push(Vertex {
138 color: Color::WHITE,
139 position: tf.transform_point(Vector2f::new(0., 0.)),
140 tex_coords: Vector2f::new(tex_x, 0.),
141 });
142 buf.push(Vertex {
143 color: Color::WHITE,
144 position: tf.transform_point(Vector2f::new(0., size)),
145 tex_coords: Vector2f::new(tex_x, size),
146 });
147 buf.push(Vertex {
148 color: Color::WHITE,
149 position: tf.transform_point(Vector2f::new(size, size)),
150 tex_coords: Vector2f::new(tex_x + size, size),
151 });
152 buf.push(Vertex {
153 color: Color::WHITE,
154 position: tf.transform_point(Vector2f::new(size, 0.)),
155 tex_coords: Vector2f::new(tex_x + size, 0.),
156 });
157 obj.update(window.size().y as f32, window.size().x as f32);
158 }
159 window.clear(Color::BLACK);
160 rs.texture = Some(&texture);
161 window.draw_primitives(&buf, PrimitiveType::QUADS, &rs);
162 rs.texture = None;
163 text.set_string(&format!("{} sprites\n{fps} fps", objects.len()));
164 window.draw_text(&text, &rs);
165 window.display();
166 buf.clear();
167 frames_rendered += 1;
168 if sec_clock.elapsed_time().as_milliseconds() >= 1000 {
169 fps = frames_rendered;
170 sec_clock.restart();
171 frames_rendered = 0;
172 }
173 }
174 Ok(())
175}Sourcepub fn into_other<U>(self) -> Vector2<U>where
T: Into<U>,
pub fn into_other<U>(self) -> Vector2<U>where
T: Into<U>,
Lossless conversion into Vector2<U>.
§Usage example
let vu: Vector2<u16> = Vector2::new(6969, 6969);
let vi: Vector2<i32> = vu.into_other();
assert_eq!(vu.x, vi.x.try_into().unwrap());
assert_eq!(vu.y, vu.y.try_into().unwrap());Sourcepub fn try_into_other<U>(self) -> Result<Vector2<U>, T::Error>where
T: TryInto<U>,
pub fn try_into_other<U>(self) -> Result<Vector2<U>, T::Error>where
T: TryInto<U>,
Fallible conversion into Vector2<U>
§Usage example
// Passing case
let vi: Vector2<i32> = Vector2::new(21, 21);
let vu: Vector2<u32> = vi.try_into_other().unwrap(); // or any other Result resolution
assert_eq!(u32::try_from(vi.x).unwrap(), vu.x);
assert_eq!(u32::try_from(vi.y).unwrap(), vu.y);
// Failing case
let vi: Vector2<i32> = Vector2::new(-21, -21);
let vu = vi.try_into_other::<u32>();
assert!(vu.is_err());Sourcepub fn as_other<U: 'static + Copy>(self) -> Vector2<U>where
T: AsPrimitive<U>,
pub fn as_other<U: 'static + Copy>(self) -> Vector2<U>where
T: AsPrimitive<U>,
Lossy conversion into Vector2<U>
§Usage example
let vf: Vector2<f32> = Vector2::new(696969.6969, 6969.6969);
let vi: Vector2<i32> = vf.as_other();
assert_eq!(vf.x as i32, vi.x);
assert_eq!(vf.y as i32, vi.y);Examples found in repository?
121fn main() -> SfResult<()> {
122 example_ensure_right_working_dir();
123
124 let mut window =
125 RenderWindow::new((800, 600), "SFML window", Style::CLOSE, &Default::default())?;
126 window.set_framerate_limit(60);
127
128 // Create a new texture.
129 let texture = RcTexture::from_file("logo.png")?;
130 let texture2 = test_getting_rc_texture_from_texture()?;
131
132 // Create a new font.
133 let font_path = match std::env::args().nth(1) {
134 Some(path) => path,
135 None => "sansation.ttf".into(),
136 };
137 let mut font = RcFont::from_file(&font_path)?;
138
139 // Load many resources with no lifetime contingencies
140 let mut floating_resources = Vec::from([
141 FloatingResource::with_texture(&texture2, true, true, 1.1f32),
142 FloatingResource::with_texture(&texture2, true, true, 1.2f32),
143 FloatingResource::with_texture(&texture, true, true, 1f32),
144 FloatingResource::with_texture(&texture, true, false, 1.5f32),
145 FloatingResource::with_texture(&texture, false, true, 2f32),
146 FloatingResource::with_texture(&texture, false, false, 2.5f32),
147 FloatingResource::with_font(&font, true, true, 1.25f32),
148 FloatingResource::with_font(&font, true, true, 1.75f32),
149 FloatingResource::with_font(&font, true, true, 2.25f32),
150 FloatingResource::with_font(&font, true, true, 2.75f32),
151 ]);
152
153 let set_smooth_text = get_set_smooth_rc_text(&font);
154 let mut show_texture_atlas = false;
155 let mut text_buf = String::from("SFML");
156
157 while window.is_open() {
158 while let Some(event) = window.poll_event() {
159 if event == Event::Closed {
160 window.close();
161 }
162
163 match event {
164 Event::Closed => window.close(),
165 Event::KeyPressed { code, ctrl, .. } => match code {
166 Key::S => {
167 let smooth = !font.is_smooth();
168 font.set_smooth(smooth);
169 }
170 Key::T => {
171 show_texture_atlas ^= true;
172 }
173 Key::V if ctrl => {
174 text_buf.push_str(&clipboard::get_string());
175 }
176 _ => {}
177 },
178 Event::TextEntered { unicode } if show_texture_atlas => {
179 if unicode == 0x8 as char {
180 text_buf.pop();
181 } else if !unicode.is_ascii_control() && unicode != 's' && unicode != 't' {
182 text_buf.push(unicode);
183 }
184 }
185 _ => {}
186 }
187 }
188
189 // Update floating_resource positions so they move around on the screen
190 for floating_resource in &mut floating_resources {
191 floating_resource.move_resources(Vector2f::new(800f32, 600f32));
192 floating_resource.text.set_string(&text_buf);
193 }
194
195 window.clear(Color::BLACK);
196
197 // Fetch and draw all the sprites in floating_resources
198 for floating_resource in &floating_resources {
199 floating_resource.render(&mut window);
200 }
201
202 window.draw(&set_smooth_text);
203 if show_texture_atlas {
204 let scale = 3.0;
205 let tex = font.texture(16);
206 let mut rs = RectangleShape::with_size(tex.size().as_other());
207 rs.set_fill_color(Color::MAGENTA);
208 rs.set_scale(scale);
209 window.draw(&rs);
210 let mut s = Sprite::with_texture(&tex);
211 s.set_scale(scale);
212 window.draw(&s);
213 }
214 window.display();
215 }
216 Ok(())
217}More examples
46fn main() -> Result<(), Box<dyn Error>> {
47 example_ensure_right_working_dir();
48
49 let mut rw = RenderWindow::new(
50 (800, 600),
51 "Positional audio demo",
52 Style::CLOSE,
53 &Default::default(),
54 )?;
55 rw.set_vertical_sync_enabled(true);
56 let font = Font::from_file("sansation.ttf")?;
57 let mut text = Text::new("", &font, 20);
58 let mut music = match std::env::args().nth(1) {
59 Some(music_path) => Music::from_file(&music_path)?,
60 None => Music::from_file("canary.wav")?,
61 };
62 if music.channel_count() != 1 {
63 return Err("Sorry, only sounds with 1 channel are supported.".into());
64 };
65 music.set_looping(true);
66 music.play();
67 music.set_position(Vector3::new(0., 0., 0.));
68
69 let mut listener_pos = Vector3::new(0.0, 0.0, 0.0);
70 let center = Vector2::new(400., 300.);
71 let [mut go_left, mut go_right, mut go_up, mut go_down] = [false; 4];
72 let clock = Clock::start()?;
73
74 while rw.is_open() {
75 while let Some(ev) = rw.poll_event() {
76 match ev {
77 Event::Closed => rw.close(),
78 Event::KeyPressed { code, .. } => match code {
79 Key::A => go_left = true,
80 Key::D => go_right = true,
81 Key::W => go_up = true,
82 Key::S => go_down = true,
83 _ => {}
84 },
85 Event::KeyReleased { code, .. } => match code {
86 Key::A => go_left = false,
87 Key::D => go_right = false,
88 Key::W => go_up = false,
89 Key::S => go_down = false,
90 _ => {}
91 },
92 _ => {}
93 }
94 }
95 let Vector2f { x: mx, y: my } = rw.mouse_position().as_other();
96 let speed = 0.05;
97 if go_left {
98 listener_pos.x -= speed;
99 }
100 if go_right {
101 listener_pos.x += speed;
102 }
103 if go_up {
104 listener_pos.y -= speed;
105 }
106 if go_down {
107 listener_pos.y += speed;
108 }
109 let scale = 20.0; // Scale the positions for better visualization
110 listener::set_position(listener_pos);
111 listener::set_direction(Vector3::new(
112 (mx - center.x) / scale,
113 (my - center.y) / scale,
114 -1.,
115 ));
116 let Vector3 {
117 x: lx,
118 y: ly,
119 z: lz,
120 } = listener::position();
121 let Vector3 {
122 x: dx,
123 y: dy,
124 z: dz,
125 } = listener::direction();
126 rw.clear(Color::BLACK);
127 let mut circle_shape = CircleShape::new(8.0, 32);
128 // Draw circle at center, representing position of music being played
129 circle_shape.set_position(center);
130 circle_shape.set_fill_color(Color::YELLOW);
131 let t = clock.elapsed_time().as_seconds();
132 let radius = 12.0 + t.sin() * 3.0;
133 circle_shape.set_radius(radius);
134 circle_shape.set_origin(radius);
135 rw.draw(&circle_shape);
136 // Draw circle representing listener
137 circle_shape.set_position((center.x + lx * scale, center.y + ly * scale));
138 circle_shape.set_origin(4.0);
139 circle_shape.set_radius(4.0);
140 circle_shape.set_fill_color(Color::GREEN);
141 rw.draw(&circle_shape);
142 // Draw line from listener to direction vector position
143 rw.draw_line(
144 circle_shape.position(),
145 (center.x + dx * scale, center.y + dy * scale).into(),
146 2.0,
147 );
148 text.set_string("WASD + mouse for movement of listener");
149 text.set_position(0.);
150 rw.draw(&text);
151 text.set_string(&format!("Listener position: {lx}, {ly}, {lz}"));
152 text.set_position((0., 20.0));
153 rw.draw(&text);
154 text.set_string(&format!("Listener direction: {dx}, {dy}, {dz}"));
155 text.set_position((0., 40.0));
156 rw.draw(&text);
157 rw.display();
158 }
159 Ok(())
160}Source§impl<T: Mul<Output = T> + Add<Output = T> + Copy> Vector2<T>
impl<T: Mul<Output = T> + Add<Output = T> + Copy> Vector2<T>
Source§impl<T: Div<Output = T> + CheckedDiv> Vector2<T>
impl<T: Div<Output = T> + CheckedDiv> Vector2<T>
Sourcepub fn cwise_checked_div(self, rhs: Self) -> Option<Vector2<T>>
pub fn cwise_checked_div(self, rhs: Self) -> Option<Vector2<T>>
Component-wise checked division of self and rhs. Returns None on divide by zero
§Usage example
// Passing case
let a = Vector2i::new(69, 69);
let b = Vector2i::new(3, 3);
assert_eq!(a.cwise_checked_div(b), Some(Vector2i::new(23, 23)));
// Failing case
let b = Vector2i::new(0, 3);
assert_eq!(a.cwise_checked_div(b), None);Source§impl<T: Neg<Output = T>> Vector2<T>
impl<T: Neg<Output = T>> Vector2<T>
Sourcepub fn perpendicular(self) -> Vector2<T>
pub fn perpendicular(self) -> Vector2<T>
Returns a perpendicular vector rotated +90 degrees
§Usage example
let a = Vector2i::new(21, -21);
assert_eq!(a.perpendicular(), Vector2i::new(21, 21));Source§impl<T: CheckedDiv> Vector2<T>
impl<T: CheckedDiv> Vector2<T>
Sourcepub fn checked_div(self, rhs: T) -> Option<Vector2<T>>
pub fn checked_div(self, rhs: T) -> Option<Vector2<T>>
checked_div for scalar division
§Usage Example
// Passing case
let a = Vector2i::new(420, 69);
assert_eq!(a.checked_div(1000), Some(Vector2i::new(0, 0)));
// Failing case
assert_eq!(a.checked_div(0), None);Trait Implementations§
Source§impl<T: Add> Add for Vector2<T>
impl<T: Add> Add for Vector2<T>
Source§impl<T: AddAssign> AddAssign for Vector2<T>
impl<T: AddAssign> AddAssign for Vector2<T>
Source§fn add_assign(&mut self, rhs: Self)
fn add_assign(&mut self, rhs: Self)
Performs component wise addition assignment
§Usage Example
let mut a = Vector2i::new(9, 10);
let b = Vector2i::new(10, 9);
a += b;
assert_eq!(a, Vector2i::new(19, 19));Source§impl<T: DivAssign + Copy> DivAssign<T> for Vector2<T>
impl<T: DivAssign + Copy> DivAssign<T> for Vector2<T>
Source§fn div_assign(&mut self, rhs: T)
fn div_assign(&mut self, rhs: T)
Performs scalar division assignment
§Usage Example
let mut a = Vector2i::new(9, 10);
a /= 3;
assert_eq!(a, Vector2i::new(3, 3));Source§impl<T: Clone> From<T> for Vector2<T>
Create a Vector2 with both fields initialized to the same value
impl<T: Clone> From<T> for Vector2<T>
Create a Vector2 with both fields initialized to the same value
Source§impl<T: MulAssign + Copy> MulAssign<T> for Vector2<T>
impl<T: MulAssign + Copy> MulAssign<T> for Vector2<T>
Source§fn mul_assign(&mut self, rhs: T)
fn mul_assign(&mut self, rhs: T)
Performs scalar multiplication assignment
§Usage Example
let mut a = Vector2i::new(9, 10);
a *= 420;
assert_eq!(a, Vector2i::new(3780, 4200));Source§impl<T: Sub> Sub for Vector2<T>
impl<T: Sub> Sub for Vector2<T>
Source§impl<T: SubAssign> SubAssign for Vector2<T>
impl<T: SubAssign> SubAssign for Vector2<T>
Source§fn sub_assign(&mut self, rhs: Self)
fn sub_assign(&mut self, rhs: Self)
Performs component wise subtraction assignment
§Usage Example
let mut a = Vector2i::new(9, 10);
let b = Vector2i::new(10, 9);
a -= b;
assert_eq!(a, Vector2i::new(-1, 1));