diff --git a/README.md b/README.md index 1bd4db6..8cb7586 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ To run these you will need to install Claudius via opam, and then you can `dune These examples just show a single feature of Claudius, and are a good place to start if you're trying to understand how Claudius works. * [Bounce](/bounce/) - example of a bouncing ball made from ellipses. +* [Flying Camels](/flying_camels/) - example of using image files to recreate a classic screen saver effect. * [Polygons](/polygons/) - rotating filled polygons. * [Red Hexagon](/red_hexagon/) - a different style of rotating polyons. * [Screen saver](/screen_saver/) - a recreation of a classic screen saver effect from the early Macintosh era. diff --git a/flying_camels/README.md b/flying_camels/README.md new file mode 100644 index 0000000..59b30e4 --- /dev/null +++ b/flying_camels/README.md @@ -0,0 +1 @@ +This example uses the ability to load images as a Picture.t in Claudius to recreate the old [Flying Windows Screensaver](https://microsoft.fandom.com/wiki/Flying_Windows). \ No newline at end of file diff --git a/flying_camels/bin/dune b/flying_camels/bin/dune new file mode 100644 index 0000000..05b29f1 --- /dev/null +++ b/flying_camels/bin/dune @@ -0,0 +1,4 @@ +(executable + (public_name flying_camels) + (name main) + (libraries claudius)) diff --git a/flying_camels/bin/main.ml b/flying_camels/bin/main.ml new file mode 100644 index 0000000..c8c53ad --- /dev/null +++ b/flying_camels/bin/main.ml @@ -0,0 +1,56 @@ +open Claudius + +type point = { x : float; y : float } + +let generate_points dimensions = + let width, height = dimensions in + let f_width, f_height = (float_of_int width, float_of_int height) in + Random.init 42; + List.init 42 (fun _i -> + let x = Random.float f_width -. (f_width /. 2.) + and y = Random.float f_height -. (f_height /. 2.) in + { x; y }) + +let move_points t points = + let ft = float_of_int t in + List.map + (fun p -> + let distance = Float.sqrt ((p.x *. p.x) +. (p.y *. p.y)) in + let angle = Float.atan2 p.y p.x in + let new_distance = distance +. ft in + let i_dist = int_of_float new_distance in + let wrapped_dist = i_dist mod 300 in + let f_wrapped_dist = float_of_int wrapped_dist in + let f_wrapped_dist = f_wrapped_dist *. f_wrapped_dist /. 100. in + let x = f_wrapped_dist *. Float.cos angle + and y = f_wrapped_dist *. Float.sin angle in + { x; y }) + points + +let tick t s _f _e = + let fb = Framebuffer.init (Screen.dimensions s) (fun _ _ -> 0) in + let img = (Screen.pictures s).(0) in + let w, h = Screen.dimensions s in + let img_w = Picture.original_width img + and img_h = Picture.original_height img in + + let points = generate_points (Screen.dimensions s) |> move_points t in + + List.iter + (fun p -> + let x, y = (int_of_float p.x, int_of_float p.y) in + let distance_from_origin = Float.sqrt ((p.x *. p.x) +. (p.y *. p.y)) in + let scale = distance_from_origin /. 200. in + Framebuffer.draw_picture img ~scale + (x - (img_w / 2) + (w / 2)) + (y - (img_h / 2) + (h / 2)) + fb) + points; + + fb + +let () = + let image_filenames = [ "flying_camels/images/logo48.png" ] in + Palette.generate_classic_vga_palette () + |> Screen.create ~image_filenames 640 480 1 + |> Base.run "Flying camels" None tick diff --git a/flying_camels/images/logo48.png b/flying_camels/images/logo48.png new file mode 100644 index 0000000..d5414e4 Binary files /dev/null and b/flying_camels/images/logo48.png differ