home *** CD-ROM | disk | FTP | other *** search
- //------------------------------------------
- // Space.C
- //------------------------------------------
-
- #define INCL_WIN
- #define INCL_GPI
- #define INCL_DOSPROCESS
- #define INCL_DOS
- #define INCL_GPIERRORS
- #define INCL_SHLERRORS
- #define INCL_WINERRORS
- #include <os2.h>
- #include <stdlib.h>
- #include <process.h>
- #include <stddef.h>
- #include <math.h>
- #include <stdio.h>
- #include <malloc.h>
- #include <ctype.h>
- #include "space.h"
-
- #define M_PI 3.14159265358979323846
-
-
- //**** Global variables ****
- typedef struct
- {
- double x_pos;
- double y_pos;
- double x_vel;
- double y_vel;
- double x_temp;
- double y_temp;
- double mass;
- } star_type;
-
- star_type *star;
- int number_stars = 0;
- long x_shift = 0;
- long y_shift = 0;
- double Time = 1.0;
- double G_constant = 1.0;
- double magnification = 1.0;
-
- typedef struct
- {
- HPS hps;
- SHORT width;
- SHORT height;
- ULONG thread_unterminated;
- BOOL run;
- BOOL repaint;
- BOOL load;
- BOOL center;
- BOOL magnification;
- BOOL terminate;
- BOOL trace;
- } win_data;
-
- HAB hab;
- win_data Win;
-
-
- //**** Prototypes ****
- void load_star( void );
- double get_constant( FILE *star_file );
- void thread( void *dummy );
- void set_magnification( void );
- void show_stars( long color );
- void center_stars( void );
- void move_star( int body );
- void line( win_data *Win, SHORT x1, SHORT y1, SHORT x2, SHORT y2, LONG color );
- void line_to( win_data *Win, SHORT xx, SHORT yy, LONG color );
- void pset( win_data *Win, SHORT xx, SHORT yy, LONG color );
- void move( win_data *Win, SHORT xx, SHORT yy );
-
- //**** Window prototypes ****
- MRESULT EXPENTRY ClientWndProc( HWND, USHORT, MPARAM, MPARAM );
- MRESULT EXPENTRY AboutDlgProc ( HWND, USHORT, MPARAM, MPARAM );
-
-
- //---------------------------------------------------------------------------
- // Main process
- //---------------------------------------------------------------------------
- int main( void )
- {
- static CHAR szClientClass [] = "Space";
- static ULONG flFrameFlags = FCF_TITLEBAR | FCF_SYSMENU |
- FCF_SIZEBORDER | FCF_MINMAX |
- FCF_SHELLPOSITION | FCF_TASKLIST |
- FCF_MENU | FCF_ICON;
- HMQ hmq;
- HWND hwndFrame, hwndClient;
- QMSG qmsg;
-
- load_star();
-
- hab = WinInitialize( 0 );
- hmq = WinCreateMsgQueue( hab, 0 );
-
- WinRegisterClass( hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0 );
-
- hwndFrame = WinCreateStdWindow( HWND_DESKTOP, WS_VISIBLE,
- &flFrameFlags, szClientClass, NULL,
- 0L, 0, ID_RESOURCE, &hwndClient );
-
- while(WinGetMsg( hab, &qmsg, NULL, 0, 0 ) )
- WinDispatchMsg( hab, &qmsg );
-
- free( star );
- WinDestroyWindow( hwndFrame );
- WinDestroyMsgQueue( hmq );
- WinTerminate( hab );
- return 0;
- }
-
-
- //---------------------------------------------------------------------------
- // Load star information
- //---------------------------------------------------------------------------
- void load_star()
- {
- FILE *star_file;
- int count;
- double velocity, angle;
-
- if ( (star_file = fopen( "STARFILE.TXT", "r" )) == NULL )
- {
- exit( 0 );
- }
-
- number_stars = (int)get_constant( star_file );
- G_constant = get_constant( star_file );
- Time = get_constant( star_file );
- star = malloc( number_stars * sizeof( star_type ) );
-
- for (count=0; count<number_stars; ++count)
- {
- star[count].x_pos = get_constant( star_file );
- star[count].y_pos = get_constant( star_file );
- star[count].mass = get_constant( star_file );
- angle = get_constant( star_file );
- velocity = get_constant( star_file );
- star[count].x_vel = velocity * cos( angle );
- star[count].y_vel = velocity * sin( angle );
- }
-
- fclose( star_file );
- return;
- }
-
-
- //---------------------------------------------------------------------------
- // get constant from file
- //---------------------------------------------------------------------------
- double get_constant( FILE *star_file )
- {
- static char buffer[200] = {0};
- static pos = 0;
- char chr;
- double answer;
-
- do {
- chr = buffer[ pos++ ];
- while (chr == 0 || chr == ';')
- {
- fgets( buffer, 200, star_file );
- if (buffer == NULL)
- exit(0);
- pos = 0;
- chr = buffer[ pos++ ];
- }
- }
- while( !isdigit(chr) && chr != '+' && chr != '-' && chr != '.' );
- --pos;
- sscanf( &buffer[pos], "%lf", &answer );
-
- while( isdigit(chr) || chr == '+' || chr == '-' || chr == '.' || chr == 'e' || chr == 'E' )
- chr = buffer[ pos++ ];
- --pos;
-
- return answer;
- }
-
-
- //---------------------------------------------------------------------------
- // Window message reciever
- //---------------------------------------------------------------------------
- MRESULT EXPENTRY ClientWndProc( HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2 )
- {
- HDC hdc;
- SIZEL sizl;
-
- switch( msg )
- {
- case WM_COMMAND:
- switch( COMMANDMSG(&msg)->cmd )
- {
- case IDM_RELOAD:
- Win.load = TRUE;
- return 0;
-
- case IDM_RECENTER:
- Win.center = TRUE;
- return 0;
-
- case IDM_ZOOM_IN:
- magnification *= 2.0;
- Win.center = TRUE;
- return 0;
-
- case IDM_ZOOM_OUT:
- magnification /= 2.0;
- Win.center = TRUE;
- return 0;
-
- case IDM_TRACE:
- Win.trace = (Win.trace)? FALSE: TRUE;
- return 0;
-
- case IDM_ABOUT:
- WinDlgBox( HWND_DESKTOP, hwnd, AboutDlgProc,
- 0, IDD_ABOUT, NULL );
- return 0;
- }
- break;
-
- case WM_CREATE:
- hdc = WinOpenWindowDC( hwnd );
- sizl.cx = 0;
- sizl.cy = 0;
- Win.hps = GpiCreatePS( hab, hdc, &sizl,
- PU_PELS | GPIF_DEFAULT |
- GPIT_MICRO | GPIA_ASSOC );
- Win.terminate = FALSE;
- Win.run = FALSE;
- Win.load = FALSE;
- Win.magnification = TRUE;
- Win.center = TRUE;
- Win.trace = FALSE;
- _beginthread( thread, NULL, 5000, NULL );
- return 0;
-
- case WM_SIZE:
- Win.width = SHORT1FROMMP( mp2 );
- Win.height = SHORT2FROMMP( mp2 );
- Win.center = TRUE;
- return 0;
-
- case WM_PAINT:
- WinInvalidateRect( hwnd, NULL, FALSE );
- WinBeginPaint( hwnd, Win.hps, NULL );
- WinEndPaint( Win.hps );
-
- Win.repaint = TRUE;
- Win.run = TRUE;
- return 0;
-
- case WM_DESTROY:
- Win.terminate = TRUE;
- DosSemWait( &Win.thread_unterminated, SEM_INDEFINITE_WAIT );
- GpiDestroyPS( Win.hps );
- return 0;
- }
- return WinDefWindowProc( hwnd, msg, mp1, mp2 );
- }
-
-
- //---------------------------------------------------------------------------
- // About dialogue box.
- //---------------------------------------------------------------------------
- MRESULT EXPENTRY AboutDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
- {
- switch (msg)
- {
- case WM_COMMAND:
- switch ( COMMANDMSG(&msg)->cmd )
- {
- case DID_OK:
- case DID_CANCEL:
- WinDismissDlg( hwnd, TRUE );
- return 0;
- }
- break;
- }
- return WinDefDlgProc (hwnd, msg, mp1, mp2);
- }
-
-
- //---------------------------------------------------------------------------
- // Second thread
- //---------------------------------------------------------------------------
- void thread( void *dummy )
- {
- HAB hab;
- RECTL crl;
- int ii;
-
- DosSemSet( &Win.thread_unterminated );
- DosSetPrty( PRTYS_PROCESS, PRTYC_IDLETIME, 0, 0 );
- hab = WinInitialize( 0 );
-
- while( !Win.terminate )
- {
- DosSleep( 0L );
- if ( Win.load )
- {
- Win.load = FALSE;
- load_star();
- Win.center = TRUE;
- }
- if ( Win.run )
- {
- if ( Win.magnification )
- set_magnification();
- if ( Win.center )
- {
- Win.center = FALSE;
- center_stars();
- }
- if ( Win.repaint )
- {
- Win.repaint = FALSE;
- crl.xLeft = 0;
- crl.yBottom = 0;
- crl.xRight = Win.width;
- crl.yTop = Win.height;
- WinFillRect( Win.hps, &crl, CLR_BLACK );
- }
-
- for (ii=0; ii<number_stars; ++ii)
- move_star( ii );
- // Erase stars.
- if ( Win.trace )
- show_stars( CLR_BLUE );
- else
- show_stars( CLR_BLACK );
- // Draw stars.
- for (ii=0; ii<number_stars; ++ii)
- {
- star[ii].x_pos = star[ii].x_temp;
- star[ii].y_pos = star[ii].y_temp;
- }
- show_stars( CLR_WHITE );
- }
- }
-
- // Close hab and terminate thread.
- WinTerminate( hab );
- DosSemClear( &Win.thread_unterminated );
- _endthread();
- }
-
-
- //---------------------------------------------------------------------------
- // Set magnification
- //---------------------------------------------------------------------------
- void set_magnification()
- {
- double x_min, x_max, y_min, y_max, x_diff, y_diff, x_mag, y_mag;
- int ii;
-
- Win.magnification = FALSE;
- x_min = 1e30; x_max = -1e30;
- y_min = 1e30; y_max = -1e30;
- for (ii=0; ii<number_stars; ++ii)
- {
- if (x_min > star[ii].x_pos)
- x_min = star[ii].x_pos;
- if (x_max < star[ii].x_pos)
- x_max = star[ii].x_pos;
- if (y_min > star[ii].y_pos)
- y_min = star[ii].y_pos;
- if (y_max < star[ii].y_pos)
- y_max = star[ii].y_pos;
- }
- x_diff = x_max - x_min;
- y_diff = y_max - y_min;
- x_mag = 1e30;
- y_mag = 1e30;
- if (x_diff != 0)
- x_mag = Win.width / x_diff;
- if (y_diff != 0)
- y_mag = Win.height / y_diff;
- magnification = (x_mag > y_mag)? y_mag: x_mag;
- return;
- }
-
-
- //---------------------------------------------------------------------------
- // Show stars on screen
- //---------------------------------------------------------------------------
- void show_stars( long color )
- {
- int ii;
- long xx, yy;
-
- for (ii=0; ii<number_stars; ++ii)
- {
- xx = (long)(star[ii].x_pos * magnification) + x_shift;
- if (labs( xx ) > 32000)
- return;
- yy = (long)(star[ii].y_pos * magnification) + y_shift;
- if (labs( yy ) > 32000)
- return;
- pset( &Win, (int)xx, (int)yy, color );
- }
- return;
- }
-
-
- //---------------------------------------------------------------------------
- // Center stars
- //---------------------------------------------------------------------------
- void center_stars()
- {
- int ii;
- double x_center, y_center;
-
- // Find center position of stars.
- x_center = 0;
- y_center = 0;
- for (ii=0; ii<number_stars; ++ii)
- {
- x_center += star[ii].x_pos * magnification;
- y_center += star[ii].y_pos * magnification;
- }
- x_center /= number_stars;
- y_center /= number_stars;
-
- // Shift stars position to center of window.
- x_shift = (long)(Win.width / 2 - x_center);
- y_shift = (long)(Win.height / 2 - y_center);
-
- Win.repaint = TRUE;
- return;
- }
-
-
- //---------------------------------------------------------------------------
- // calculate next position of star
- //---------------------------------------------------------------------------
- void move_star( int body )
- {
- double distance, x_dist, y_dist;
- double force, x_force, y_force;
- double star_x_dist, star_y_dist;
- double angle;
- int ii;
-
- // Calculate star's x, y force toward other stars.
- x_force = 0;
- y_force = 0;
- for (ii=0; ii<number_stars; ++ii)
- {
- if (ii == body)
- continue;
- x_dist = star[ii].x_pos - star[body].x_pos;
- y_dist = star[ii].y_pos - star[body].y_pos;
- distance = x_dist * x_dist + y_dist * y_dist;
- force = G_constant * star[body].mass * star[ii].mass / distance;
- angle = atan2( y_dist, x_dist );
- x_force += force * cos( angle );
- y_force += force * sin( angle );
- DosSleep( 0L );
- }
-
- // Add to star's x, y velocity the addition velocity from current force.
- star[body].x_vel += Time * x_force / star[body].mass;
- star[body].y_vel += Time * y_force / star[body].mass;
-
- // Calculate star's displacement durring Time.
- star_x_dist = Time * star[body].x_vel;
- star_y_dist = Time * star[body].y_vel;
-
- // Add star's displacement to star's current position.
- star[body].x_temp = star[body].x_pos + star_x_dist;
- star[body].y_temp = star[body].y_pos + star_y_dist;
-
- return;
- }
-
-
- //---------------------------------------------------------------------------
- // Line routine
- //---------------------------------------------------------------------------
- void line( win_data *Win, SHORT x1, SHORT y1, SHORT x2, SHORT y2, LONG color )
- {
- POINTL ptl;
-
- GpiSetColor( Win->hps, color );
- ptl.x = x1;
- ptl.y = y1;
- GpiMove( Win->hps, &ptl );
- ptl.x = x2;
- ptl.y = y2;
- GpiLine( Win->hps, &ptl );
- }
-
-
- //---------------------------------------------------------------------------
- // Line routine
- //---------------------------------------------------------------------------
- void line_to( win_data *Win, SHORT xx, SHORT yy, LONG color )
- {
- POINTL ptl;
-
- GpiSetColor( Win->hps, (long)color );
- ptl.x = xx;
- ptl.y = yy;
- GpiLine( Win->hps, &ptl );
- }
-
-
- //---------------------------------------------------------------------------
- // Pset routine
- //---------------------------------------------------------------------------
- void pset( win_data *Win, SHORT xx, SHORT yy, LONG color )
- {
- POINTL ptl;
-
- GpiSetColor( Win->hps, color );
- ptl.x = xx;
- ptl.y = yy;
- GpiSetPel( Win->hps, &ptl );
- GpiMove( Win->hps, &ptl );
- }
-
-
- //---------------------------------------------------------------------------
- // Move Gpi pel routine
- //---------------------------------------------------------------------------
- void move( win_data *Win, SHORT xx, SHORT yy )
- {
- POINTL ptl;
-
- ptl.x = xx;
- ptl.y = yy;
- GpiMove( Win->hps, &ptl );
- }