home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: Science
/
Science.zip
/
SPACE.ZIP
/
SPACE.C
< prev
next >
Wrap
Text File
|
1991-02-24
|
16KB
|
540 lines
//------------------------------------------
// 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 );
}