-
-
Save bczhc/f423bee48452c2e9bdaecfbe917512b3 to your computer and use it in GitHub Desktop.
chatgpt使用macroquad写的李萨如图小玩具 #vibecoding #macroquad #cg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // [dependencies] | |
| // macroquad = "0.4.14" | |
| // palette = "0.7.6" | |
| use macroquad::hash; | |
| use macroquad::prelude::*; | |
| use macroquad::ui::{root_ui, widgets}; | |
| use palette::{FromColor, Hsl, Srgb}; | |
| fn window_conf() -> Conf { | |
| Conf { | |
| window_title: "Lissajous Explorer".to_string(), | |
| sample_count: 4, | |
| ..Default::default() | |
| } | |
| } | |
| fn gcd(mut a: i32, mut b: i32) -> i32 { | |
| while b != 0 { | |
| let r = a % b; | |
| a = b; | |
| b = r; | |
| } | |
| a.abs() | |
| } | |
| fn hsl_color(h: f32, s: f32, l: f32) -> Color { | |
| let hsl = Hsl::new(h, s, l); | |
| let rgb = Srgb::from_color(hsl); | |
| Color::new(rgb.red, rgb.green, rgb.blue, 1.0) | |
| } | |
| #[macroquad::main(window_conf)] | |
| async fn main() { | |
| let mut a: f32 = 3.0; | |
| let mut b: f32 = 2.0; | |
| let mut scale: f32 = 0.8; | |
| let mut speed: f32 = 1.0; | |
| let mut thickness: f32 = 1.5; | |
| let mut time: f32 = 0.0; | |
| let mut paused = false; | |
| let points: i32 = 10000; | |
| loop { | |
| if is_key_pressed(KeyCode::Q) { | |
| std::process::exit(0); | |
| } | |
| if is_key_pressed(KeyCode::Space) { | |
| paused = !paused; | |
| } | |
| if !paused { | |
| time += get_frame_time() * speed; | |
| } | |
| clear_background(BLACK); | |
| let cx = screen_width() / 2.0; | |
| let cy = screen_height() / 2.0; | |
| let base = screen_width().min(screen_height()) * 0.5 * scale; | |
| // ---- 最小闭合周期 ---- | |
| let ai = a.round().max(1.0) as i32; | |
| let bi = b.round().max(1.0) as i32; | |
| let lcm_ab = ai * bi / gcd(ai, bi); | |
| let total_t = std::f32::consts::TAU * lcm_ab as f32; | |
| // ---- HSL 颜色随时间变化 ---- | |
| let hue = (time * 30.0) % 360.0; | |
| let color = hsl_color(hue, 0.8, 0.6); | |
| let mut prev: Option<Vec2> = None; | |
| for i in 0..=points { | |
| let t = i as f32 / points as f32 * total_t; | |
| let x = (a * t + time).sin(); | |
| let y = (b * t).sin(); | |
| let p = vec2(cx + x * base, cy + y * base); | |
| if let Some(last) = prev { | |
| draw_line(last.x, last.y, p.x, p.y, thickness, color); | |
| } | |
| prev = Some(p); | |
| } | |
| widgets::Window::new(hash!(), vec2(20.0, 20.0), vec2(260.0, 280.0)) | |
| .label("Lissajous Parameters") | |
| .ui(&mut *root_ui(), |ui| { | |
| ui.label(None, "Frequency A"); | |
| ui.slider(hash!(), "", 1.0..10.0, &mut a); | |
| ui.label(None, "Frequency B"); | |
| ui.slider(hash!(), "", 1.0..10.0, &mut b); | |
| ui.label(None, "Scale (Screen Ratio)"); | |
| ui.slider(hash!(), "", 0.1..1.0, &mut scale); | |
| ui.label(None, "Speed"); | |
| ui.slider(hash!(), "", 0.0..5.0, &mut speed); | |
| ui.label(None, "Thickness"); | |
| ui.slider(hash!(), "", 0.5..6.0, &mut thickness); | |
| ui.separator(); | |
| ui.label( | |
| None, | |
| if paused { | |
| "Status: Paused (Space)" | |
| } else { | |
| "Status: Running (Space)" | |
| }, | |
| ); | |
| ui.label(None, "Quit: Q"); | |
| }); | |
| next_frame().await; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment