Nuppiz

SOLAR.C

Jan 9th, 2022 (edited)
418
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.61 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <dos.h>
  5. #include <math.h>
  6.  
  7. #define VIDEO_INT           0x10      /* the BIOS video interrupt. */
  8. #define SET_MODE            0x00      /* BIOS func to set the video mode. */
  9. #define VGA_256_COLOR_MODE  0x13      /* use to set 256-color mode. */
  10. #define TEXT_MODE           0x03      /* use to set 80x25 text mode. */
  11.  
  12. #define SCREEN_WIDTH        320       /* width in pixels of mode 0x13 */
  13. #define SCREEN_HEIGHT       200       /* height in pixels of mode 0x13 */
  14. #define SCREEN_SIZE         64000
  15. #define NUM_COLORS          256       /* number of colors in mode 0x13 */
  16.  
  17. #define SET_PIXEL(x,y,color)      screen_buf[(y)*SCREEN_WIDTH + (x)] = color
  18.  
  19. //#define M_PI                3.14159265358979323846264338327950288
  20. #define degToRad(degree)    (degree * (M_PI / 180.0))
  21.  
  22. #define SP_MER              degToRad(41.49)
  23. #define SP_VEN              degToRad(16.26)
  24. #define SP_EAR              degToRad(10.0)
  25. #define SP_MOO              degToRad(133.6)
  26. #define SP_PRO              degToRad(60.0)
  27. #define SP_MAR              degToRad(5.32)
  28.  
  29. typedef struct
  30. {
  31.     int x, y;
  32. } Vec2;
  33.  
  34. typedef struct
  35. {
  36.     Vec2 pos; // offset from orbit center
  37.     float angle; // which way the body itself is facing
  38.     float angular_vel; // rotation speed
  39.     uint8_t radius;
  40.     uint8_t color;
  41.    
  42.     Vec2* orbit_center; // pointer to the "parent body's" position; set to NULL for sun
  43.     float orbital_angle; // angle on the orbit
  44.     float orbital_ang_vel; // rotation speed around whatever it orbits
  45.     uint16_t orbit_radius; // distance to the "parent body"
  46.     uint8_t orbit_color;
  47. } CelestialBody;
  48.  
  49. enum CelestialBodies
  50. {
  51.     Sun,
  52.     Mercury,
  53.     Venus,
  54.     Earth,
  55.     Moon,
  56.     MoonProbe,
  57.     Mars,
  58.     MarsProbe,
  59.     Num_CelBodies
  60. };
  61.  
  62. CelestialBody celbodies[Num_CelBodies] = { /*
  63.   pos     angle    angvel  radius  color   orb. center           orb.ang orb.angvel   orb.radius, orb.color*/
  64. {{0, 0},  0.0,     0.0,    10,     44,     NULL,                 0.0,    0.0,         0,          0},  // Sun
  65. {{15, 0}, 0.0,     10.0,   5,      66,     &celbodies[Sun].pos,  0.0,    SP_MER,      20,         1}, // Mercury
  66. {{30, 0}, 0.0,     10.0,   6,      68,     &celbodies[Sun].pos,  0.0,    SP_VEN,      40,         1}, // Venus
  67. {{45, 0}, 0.0,     10.0,   6,      54,     &celbodies[Sun].pos,  0.0,    SP_EAR,      65,         1}, // Earth
  68. {{5, 0},  0.0,     10.0,   4,      7,      &celbodies[Earth].pos,0.0,    SP_MOO,      11,         8}, // Moon
  69. {{3, 0},  0.0,     10.0,   2,      92,     &celbodies[Moon].pos, 0.0,    SP_PRO,      4,          19}, // Moon probe
  70. {{60, 0}, 0.0,     10.0,   6,      41,     &celbodies[Sun].pos,  0.0,    SP_MAR,      92,         1}, // Mars
  71. {{3, 0},  0.0,     10.0,   2,      92,     &celbodies[Mars].pos, 0.0,    SP_PRO,      7,          19}  // Mars probe
  72. };
  73.  
  74. uint8_t far *VGA=(uint8_t *)0xA0000000L;        /* this points to video memory. */
  75. uint8_t far screen_buf [64000]; // double buffer
  76.  
  77. float angle_scale = 0.01;
  78.  
  79. void set_mode(uint8_t mode)
  80. {
  81.     union REGS regs;
  82.  
  83.     regs.h.ah = SET_MODE;
  84.     regs.h.al = mode;
  85.     int86(VIDEO_INT, &regs, &regs);
  86. }
  87.  
  88. void draw_orbit(Vec2* orbit_center, uint16_t radius, uint8_t color)
  89. {
  90.     int rad_x;
  91.     int rad_y;
  92.  
  93.     int center_x = orbit_center->x;
  94.     int center_y = orbit_center->y;
  95.  
  96.     rad_y = 0;
  97.     do
  98.     {
  99.         rad_x = sqrt((float)radius*radius - (float)rad_y*rad_y);
  100.         SET_PIXEL(center_x + rad_x, center_y + rad_y, color); // lower right octant
  101.         SET_PIXEL(center_x - rad_x, center_y + rad_y, color); // lower left octant
  102.         SET_PIXEL(center_x + rad_x, center_y - rad_y, color); // upper right octant
  103.         SET_PIXEL(center_x - rad_x, center_y - rad_y, color); // upper left octant
  104.         SET_PIXEL(center_x + rad_y, center_y + rad_x, color); // bottom right octant
  105.         SET_PIXEL(center_x - rad_y, center_y + rad_x, color); // bottom left octant
  106.         SET_PIXEL(center_x + rad_y, center_y - rad_x, color); // top right octant
  107.         SET_PIXEL(center_x - rad_y, center_y - rad_x, color); // top left octant
  108.  
  109.         rad_y++;
  110.     }
  111.     while (rad_y < rad_x);
  112. }
  113.  
  114. void draw_celbody(Vec2 pos, uint16_t radius, uint8_t color)
  115. {
  116.     int rad_x;
  117.     int rad_y;
  118.  
  119.     int fill_x = 0;
  120.     int fill_y = 0;
  121.  
  122.     int x = pos.x;
  123.     int y = pos.y;
  124.  
  125.     rad_y = 0;
  126.    
  127.     while (rad_y < rad_x)
  128.     {
  129.         rad_x = sqrt((float)radius*radius - (float)rad_y*rad_y);
  130.         while (fill_y < rad_y)
  131.         {
  132.             while (fill_x < rad_x)
  133.             {
  134.                 SET_PIXEL(x + fill_x, y + fill_y, color); // lower right octant
  135.                 SET_PIXEL(x - fill_x, y + fill_y, color); // lower left octant
  136.                 SET_PIXEL(x + fill_x, y - fill_y, color); // upper right octant
  137.                 SET_PIXEL(x - fill_x, y - fill_y, color); // upper left octant
  138.                 SET_PIXEL(x + fill_y, y + fill_x, color); // bottom right octant
  139.                 SET_PIXEL(x - fill_y, y + fill_x, color); // bottom left octant
  140.                 SET_PIXEL(x + fill_y, y - fill_x, color); // top right octant
  141.                 SET_PIXEL(x - fill_y, y - fill_x, color); // top left octant
  142.                 fill_x++;
  143.             }
  144.             fill_x = 0;
  145.             fill_y++;
  146.         }
  147.         rad_y++;
  148.     }
  149. }
  150.  
  151. void draw_celbodies()
  152. {
  153.     int i = 0;
  154.    
  155.     while (i < Num_CelBodies)
  156.     {
  157.         draw_celbody(celbodies[i].pos, celbodies[i].radius, celbodies[i].color);
  158.         i++;
  159.     }
  160. }
  161.  
  162. void draw_orbits()
  163. {
  164.     int i = 0;
  165.    
  166.     while (i < Num_CelBodies)
  167.     {
  168.         if (celbodies[i].orbit_center == NULL) // don't draw an orbit for the Sun
  169.             i++;
  170.         else
  171.         {
  172.             draw_orbit(celbodies[i].orbit_center, celbodies[i].orbit_radius, celbodies[i].orbit_color);
  173.             i++;
  174.         }
  175.     }
  176. }
  177.        
  178. void updateCelBody(CelestialBody* CelBody)
  179. {
  180.     float radians = CelBody->orbital_angle + CelBody->orbital_ang_vel * angle_scale;
  181.  
  182.     if (radians < 0 || radians > 2*M_PI)
  183.         CelBody->orbital_angle = 0.0;
  184.  
  185.     CelBody->pos.x = CelBody->orbit_center->x + ((cos(radians))*CelBody->orbit_radius);
  186.     CelBody->pos.y = CelBody->orbit_center->y + ((sin(radians))*CelBody->orbit_radius);
  187.  
  188.     CelBody->orbital_angle = radians;
  189. }
  190.  
  191. void move_celbodies()
  192. {
  193.     int i = 0;
  194.  
  195.     CelestialBody* CelBody;
  196.    
  197.     while (i < Num_CelBodies)
  198.     {
  199.         if (celbodies[i].orbit_center == NULL) // the Sun doesn't move
  200.             i++;
  201.         else
  202.         {
  203.             CelBody = &celbodies[i];
  204.             updateCelBody(CelBody);
  205.             i++;
  206.         }
  207.     }
  208. }
  209.  
  210. void set_celestial_pos()
  211. {
  212.     celbodies[Sun].pos.x = SCREEN_WIDTH / 2;
  213.     celbodies[Sun].pos.y = SCREEN_HEIGHT / 2;
  214.  
  215.     celbodies[Mercury].pos.x = celbodies[Mercury].orbit_center->x + celbodies[Mercury].orbit_radius;
  216.     celbodies[Mercury].pos.y = celbodies[Mercury].orbit_center->y;
  217.    
  218.     celbodies[Venus].pos.x = celbodies[Venus].orbit_center->x + celbodies[Venus].orbit_radius;
  219.     celbodies[Venus].pos.y = celbodies[Venus].orbit_center->y;
  220.  
  221.     celbodies[Earth].pos.x = celbodies[Earth].orbit_center->x + celbodies[Earth].orbit_radius;
  222.     celbodies[Earth].pos.y = celbodies[Earth].orbit_center->y;
  223.  
  224.     celbodies[Moon].pos.x = celbodies[Moon].orbit_center->x + celbodies[Moon].orbit_radius;
  225.     celbodies[Moon].pos.y = celbodies[Moon].orbit_center->y;
  226.  
  227.     celbodies[MoonProbe].pos.x = celbodies[MoonProbe].orbit_center->x + celbodies[MoonProbe].orbit_radius;
  228.     celbodies[MoonProbe].pos.y = celbodies[MoonProbe].orbit_center->y;
  229.  
  230.     celbodies[Mars].pos.x = celbodies[Mars].orbit_center->x + celbodies[Mars].orbit_radius;
  231.     celbodies[Mars].pos.y = celbodies[Mars].orbit_center->y;
  232.  
  233.     celbodies[MarsProbe].pos.x = celbodies[MarsProbe].orbit_center->x + celbodies[MarsProbe].orbit_radius;
  234.     celbodies[MarsProbe].pos.y = celbodies[MarsProbe].orbit_center->y;
  235. }
  236.  
  237. int main()
  238. {  
  239.     int ticks = 0;
  240.     float speed = 0.0;
  241.  
  242.     printf("Enter the speed at which you want to run the simulation.\n");
  243.     printf("Enter a negative value for a reverse simulation.\n");
  244.     scanf("%f", &speed);
  245.  
  246.     angle_scale = angle_scale * speed;
  247.  
  248.     set_celestial_pos();
  249.     set_mode(VGA_256_COLOR_MODE);
  250.    
  251.     _fmemset(screen_buf, 0, SCREEN_SIZE);
  252.  
  253.     draw_orbits();
  254.     draw_celbodies();
  255.     memcpy(VGA,screen_buf,SCREEN_SIZE);
  256.  
  257.     while (ticks < 16385)
  258.     {
  259.         _fmemset(screen_buf, 0, SCREEN_SIZE);
  260.         move_celbodies();
  261.         draw_orbits();
  262.         draw_celbodies();
  263.         memcpy(VGA,screen_buf,SCREEN_SIZE);
  264.         ticks++;
  265.         delay(10);
  266.     }
  267.     return 0;
  268. }
Add Comment
Please, Sign In to add comment