Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// Solar System Simulation by oliver @pixelchipcode
- /// This simulation creates a pseudo-3D solar system with planets orbiting around a sun.
- /// The user can rotate, tilt, and zoom the camera to explore the system, while planets
- /// are rendered with proper depth sorting for occlusion effects, meaning planets in
- /// front of the sun are drawn on top, and those behind are occluded.
- ///
- /// Key Features:
- /// - **Pseudo-3D Camera**: Camera movement allows for dynamic rotation, tilt, and zoom.
- /// - **Planet Occlusion**: Planets are depth sorted to render behind or in front of the sun.
- /// - **Interactive System**: Planets and the sun are clickable, displaying relevant data like
- /// orbit radius, size, and orbital period.
- /// - **Dynamic Orbits**: Orbits can be toggled on or off via spacebar, adjusting planet speeds.
- /// - **Text Display**: When clicking on a planet or the sun, text information is displayed
- /// dynamically, fading out after a few seconds.
- /// - **Ease-based Motion**: Smooth transitions in camera angles, zoom, and planet orbits.
- ///
- /// Key Constants:
- /// - **NUM_PLANETS**: Total number of planets in the simulation.
- /// - **SUN_SIZE**: Size of the central star (sun).
- /// - **SUN_COLOR**: Color of the sun.
- /// - **ORBIT_COLOR**: Color for drawing the orbital paths.
- ///
- /// This system demonstrates occlusion rendering, interactive celestial bodies, and smooth
- /// pseudo-3D camera controls, making it an excellent example of dynamic 3D-like simulations
- /// in a 2D environment.
- /// Create Event
- // Constants and configuration
- #macro NUM_PLANETS 10
- #macro SUN_SIZE 30
- #macro SUN_COLOR make_color_rgb(255, 208, 21)
- #macro BACKGROUND_COLOR make_color_rgb(37, 38, 42)
- #macro FONT_COLOR make_color_rgb(192, 191, 193)
- #macro ORBIT_COLOR make_color_rgb(96, 99, 101)
- // Arrays for names and colors
- star_names = ["Proxima Centauri", "Sirius", "Vega", "Altair", "Deneb"];
- planet_names = ["Kepler-22b", "Proxima Centauri b", "TRAPPIST-1d", "Gliese 581c", "HD 209458b"];
- planet_colors = [
- make_color_rgb(239, 52, 36), // Red
- make_color_rgb(254, 254, 194), // Light Yellow
- make_color_rgb(109, 72, 205), // Purple
- make_color_rgb(252, 145, 65) // Orange
- ];
- // Camera and simulation control
- view_angle = 0;
- target_view_angle = 0;
- tilt_angle = 0;
- target_tilt_angle = 0;
- zoom = 1;
- target_zoom = 1;
- orbits_active = false;
- // Text display variables
- text_to_display = "";
- text_index = 0;
- is_displaying_text = false;
- text_display_timer = 0;
- // Sun properties
- sun_name = star_names[irandom(array_length(star_names) - 1)];
- // Initialize planets array
- planets = array_create(NUM_PLANETS);
- // Function to initialize planets
- function initialize_planets() {
- var previous_orbit_radius = 0;
- for (var i = 0; i < NUM_PLANETS; i++) {
- var planet_name = planet_names[irandom(array_length(planet_names) - 1)];
- var orbital_period = irandom_range(200, 1000);
- var planet_size = random_range(5, 10);
- var planet_orbit_radius = (i == 0)
- ? random_range(50, 100)
- : previous_orbit_radius + planets[i - 1].size + planet_size + random_range(20, 40);
- previous_orbit_radius = planet_orbit_radius;
- planets[i] = {
- name: planet_name,
- orbit_radius: planet_orbit_radius,
- orbit_speed: random_range(0.5, 1.5),
- angle: random(360),
- color: planet_colors[i % array_length(planet_colors)],
- size: planet_size,
- current_speed: 0,
- target_speed: 0,
- orbital_period: orbital_period
- };
- }
- }
- // Function to determine if a point is in front of the sun
- function is_point_in_front(dist, angle, _tilt_angle) {
- var cy = room_height / 2;
- return (cy + lengthdir_y(dist, angle) * dcos(_tilt_angle) > cy);
- }
- // Function to sort planets by depth
- function sort_planets_by_depth() {
- array_sort(planets, function(a, b) {
- var cy = room_height / 2;
- var y1 = cy + lengthdir_y(a.orbit_radius * zoom, a.angle + view_angle) * dcos(tilt_angle);
- var y2 = cy + lengthdir_y(b.orbit_radius * zoom, b.angle + view_angle) * dcos(tilt_angle);
- return sign(y1 - y2);
- });
- }
- // Function to get clicked object
- function get_clicked_object(mx, my) {
- var cx = room_width / 2;
- var cy = room_height / 2;
- // Sort planets by depth before checking clicks
- sort_planets_by_depth();
- // Check planets from front to back
- for (var i = NUM_PLANETS - 1; i >= 0; i--) {
- var planet = planets[i];
- var dist = planet.orbit_radius * zoom;
- var angle = planet.angle + view_angle;
- var x_rot = cx + lengthdir_x(dist, angle);
- var y_rot = cy + lengthdir_y(dist, angle);
- var ny = cy + (y_rot - cy) * dcos(tilt_angle);
- if (point_distance(mx, my, x_rot, ny) <= planet.size * zoom) {
- return {
- type: "planet",
- name: planet.name,
- orbit_radius: planet.orbit_radius,
- orbital_period: planet.orbital_period,
- size: planet.size
- };
- }
- }
- // Check if sun was clicked (only if no planet was clicked)
- if (point_distance(mx, my, cx, cy) <= SUN_SIZE * zoom) {
- return {
- type: "sun",
- name: sun_name,
- size: SUN_SIZE
- };
- }
- return noone;
- }
- // Function to display object info
- function display_object_info(obj) {
- if (obj == noone) return;
- if (obj.type == "sun") {
- text_to_display = obj.name + "\nSun Size: " + string(obj.size);
- } else if (obj.type == "planet") {
- text_to_display = obj.name + "\n" +
- "Orbit Radius: " + string(obj.orbit_radius) + "\n" +
- "Orbital Period: " + string(obj.orbital_period) + " days\n" +
- "Size: " + string(obj.size);
- }
- text_index = 1;
- is_displaying_text = true;
- text_display_timer = room_speed * 3;
- }
- // Initialize planets
- initialize_planets();
- /// Step Event
- var ease_factor = 0.05;
- // Toggle orbits
- if (keyboard_check_pressed(vk_space)) {
- orbits_active = !orbits_active;
- for (var i = 0; i < NUM_PLANETS; i++) {
- planets[i].target_speed = orbits_active ? planets[i].orbit_speed : 0;
- }
- }
- // Update planet speeds and positions
- for (var i = 0; i < NUM_PLANETS; i++) {
- var planet = planets[i];
- planet.current_speed = lerp(planet.current_speed, planet.target_speed, ease_factor);
- planet.angle += planet.current_speed;
- }
- // Camera controls
- var rotate_speed = 1;
- var tilt_speed = 1;
- var zoom_speed = 0.05;
- if (keyboard_check(vk_left)) target_view_angle -= rotate_speed;
- if (keyboard_check(vk_right)) target_view_angle += rotate_speed;
- if (keyboard_check(vk_up)) target_tilt_angle = min(target_tilt_angle + tilt_speed, 89);
- if (keyboard_check(vk_down)) target_tilt_angle = max(target_tilt_angle - tilt_speed, -89);
- if (keyboard_check(vk_pageup)) target_zoom = min(target_zoom + zoom_speed, 2);
- if (keyboard_check(vk_pagedown)) target_zoom = max(target_zoom - zoom_speed, 0.2);
- view_angle = lerp(view_angle, target_view_angle, ease_factor);
- tilt_angle = lerp(tilt_angle, target_tilt_angle, ease_factor);
- zoom = lerp(zoom, target_zoom, ease_factor);
- // Text display logic
- if (is_displaying_text) {
- if (text_index < string_length(text_to_display)) {
- text_index++;
- } else if (text_display_timer > 0) {
- text_display_timer--;
- } else {
- is_displaying_text = false;
- }
- }
- /// Draw Event
- draw_clear(BACKGROUND_COLOR);
- var cx = room_width / 2;
- var cy = room_height / 2;
- // Draw text
- if (is_displaying_text) {
- draw_set_color(FONT_COLOR);
- draw_text(20, 20, string_copy(text_to_display, 1, text_index));
- }
- // Draw orbits behind the sun
- draw_set_color(ORBIT_COLOR);
- for (var i = 0; i < NUM_PLANETS; i++) {
- var planet = planets[i];
- var dist = planet.orbit_radius * zoom;
- for (var angle = 0; angle < 360; angle += 5) {
- var angle_current = angle + view_angle;
- var angle_next = angle_current + 5;
- if (!is_point_in_front(dist, angle_current, tilt_angle)) {
- var x1 = cx + lengthdir_x(dist, angle_current);
- var y1 = cy + lengthdir_y(dist, angle_current) * dcos(tilt_angle);
- var x2 = cx + lengthdir_x(dist, angle_next);
- var y2 = cy + lengthdir_y(dist, angle_next) * dcos(tilt_angle);
- draw_line(x1, y1, x2, y2);
- }
- }
- }
- // Draw planets behind the sun
- sort_planets_by_depth();
- for (var i = 0; i < NUM_PLANETS; i++) {
- var planet = planets[i];
- var dist = planet.orbit_radius * zoom;
- var angle = planet.angle + view_angle;
- var x_rot = cx + lengthdir_x(dist, angle);
- var y_rot = cy + lengthdir_y(dist, angle);
- var ny = cy + (y_rot - cy) * dcos(tilt_angle);
- if (!is_point_in_front(dist, angle, tilt_angle)) {
- draw_set_color(planet.color);
- draw_circle(x_rot, ny, planet.size * zoom, false);
- }
- }
- // Draw the sun
- draw_set_color(SUN_COLOR);
- draw_circle(cx, cy, SUN_SIZE * zoom, false);
- // Draw orbits in front of the sun
- draw_set_color(ORBIT_COLOR);
- for (var i = 0; i < NUM_PLANETS; i++) {
- var planet = planets[i];
- var dist = planet.orbit_radius * zoom;
- for (var angle = 0; angle < 360; angle += 5) {
- var angle_current = angle + view_angle;
- var angle_next = angle_current + 5;
- if (is_point_in_front(dist, angle_current, tilt_angle)) {
- var x1 = cx + lengthdir_x(dist, angle_current);
- var y1 = cy + lengthdir_y(dist, angle_current) * dcos(tilt_angle);
- var x2 = cx + lengthdir_x(dist, angle_next);
- var y2 = cy + lengthdir_y(dist, angle_next) * dcos(tilt_angle);
- draw_line(x1, y1, x2, y2);
- }
- }
- }
- // Draw planets in front of the sun
- for (var i = 0; i < NUM_PLANETS; i++) {
- var planet = planets[i];
- var dist = planet.orbit_radius * zoom;
- var angle = planet.angle + view_angle;
- var x_rot = cx + lengthdir_x(dist, angle);
- var y_rot = cy + lengthdir_y(dist, angle);
- var ny = cy + (y_rot - cy) * dcos(tilt_angle);
- if (is_point_in_front(dist, angle, tilt_angle)) {
- draw_set_color(planet.color);
- draw_circle(x_rot, ny, planet.size * zoom, false);
- }
- }
- // Handle clicks
- if (mouse_check_button_pressed(mb_left)) {
- var clicked_object = get_clicked_object(mouse_x, mouse_y);
- if (clicked_object != noone) {
- display_object_info(clicked_object);
- }
- }
Add Comment
Please, Sign In to add comment