// Includes #include // Include for PA_Lib #include #include //int x,y,angl; typedef struct { float x, y; // 2D coordinates, a float so we can store fractional values } POINT; typedef struct { int NumPoints; POINT Point[ 20 ]; // Three is enough for now but will have to make } SHAPE; // this more flexible later. typedef struct { POINT Loc; // Location on the screen int ViewAngle; // Angle at which the object is facing POINT Direction; // Direction which the object is moving, in pixels SHAPE Shape; // The shape of the object SHAPE Screen; // Actual points it occupies on the screen } OBJECT; struct { OBJECT Ship; // The players spaceship } g; typedef struct { POINT Loc; int ViewAngle; POINT Direction; SHAPE Shape; SHAPE Screen; int Frames; } PARTICLE; struct { PARTICLE Fire[10]; } fire; //Exhaust particles void TranslatePoint( POINT *Dest, POINT *Src, int Angle ) { double Radians; Radians = Angle * 0.01745; Dest->x = Src->x * cos( Radians ) - Src->y * sin( Radians ); Dest->y = Src->x * sin( Radians ) + Src->y * cos( Radians ); } void TranslateParticle( PARTICLE *Particle ){ int i; for( i = 0; i < Particle->Shape.NumPoints; i++ ) TranslatePoint(&Particle->Screen.Point[i],&Particle->Shape.Point[i],Particle->ViewAngle); Particle->Screen.Point[i].x += Particle->Loc.x; Particle->Screen.Point[i].y += Particle->Loc.y; } void TranslateObject( OBJECT *Object ) { int i; for( i = 0; i < Object->Shape.NumPoints; i++ ) { // First, account for rotation TranslatePoint( &Object->Screen.Point[ i ], &Object->Shape.Point[ i ], Object->ViewAngle ); // Now make it relative to the screen location Object->Screen.Point[ i ].x += Object->Loc.x; Object->Screen.Point[ i ].y += Object->Loc.y; } } void DrawParticle(PARTICLE *Particle){ if(Particle->Frames>0){ int i; for( i = 1; i < Particle->Shape.NumPoints; i++ ) PA_Draw8bitLineEx(0, Particle->Screen.Point[ i - 1 ].x,Particle->Screen.Point[ i - 1 ].y,Particle->Screen.Point[ i ].x, Particle->Screen.Point[ i ].y,1,1); } } void MoveParticle(PARTICLE *Particle){ if(Particle->Frames<50 && Particle->Frames>0){ if(Particle->Frames==1){ Particle->Shape.NumPoints = 2; Particle->Shape.Point[1].x = 3; Particle->Shape.Point[1].y = 5; Particle->Shape.Point[2].x = 12; Particle->Shape.Point[2].y = 0; // Particle->Loc.x = g.Ship.Loc.x; // Particle->Loc.y = g.Ship.Loc.y; Particle->Loc.x =50; Particle->Loc.y = 50; } Particle->Loc.x += Particle->Direction.x; Particle->Loc.y += Particle->Direction.y; Particle->Frames++; } else Particle->Frames=0; } void DrawObject( OBJECT *Object ) { int i; for( i = 1; i < Object->Shape.NumPoints; i++ ) { PA_Draw8bitLineEx(0, Object->Screen.Point[ i - 1 ].x,Object->Screen.Point[ i - 1 ].y,Object->Screen.Point[ i ].x, Object->Screen.Point[ i ].y,1,1); } PA_Draw8bitLineEx(0, Object->Screen.Point[ i - 1 ].x,Object->Screen.Point[ i - 1 ].y,Object->Screen.Point[ 0 ].x, Object->Screen.Point[ 0 ].y,1,1); } void MoveObject( OBJECT *Object ) { Object->Loc.x += Object->Direction.x; Object->Loc.y += Object->Direction.y; // Handle screen wrap-around if( Object->Loc.x < 0 ) Object->Loc.x = Object->Loc.x + 255; if( Object->Loc.x > 255 ) Object->Loc.x = Object->Loc.x - 255; if( Object->Loc.y < 0 ) Object->Loc.y = Object->Loc.y + 191; if( Object->Loc.y > 191 ) Object->Loc.y = Object->Loc.y - 191; } // This routine just waits until the display is // in a vertical retrace cycle. This is useful // for two things: to perform drawing during retrace // when it can't be seen and (more importantly) // to provide a method of synchronizing the animation // with the game play so that it runs at a constant // speed on virtually every machine. void SyncToVerticalRetrace( void ) { // If we happen to be in the middle of a vertical retrace // period wait until its over. PA_WaitForVBL(); Cleanup(); } #define N 10 #define ROTATE_STEP 3 // Number of degrees to rotate #define SPEED 0.08 // Speed control #define FRICTION 0.996 // Speed reduction per frame void Supervisor( void ) { // unsigned short KeyboardStatus; int c,i = 0; while( c != 'q' && c != 'Q' ) { for(i=0;i<=10;i++){ TranslateParticle(&fire.Fire[i]); DrawParticle(&fire.Fire[i]); MoveParticle(&fire.Fire[i]); } // Get the keyboard status bits from the BIOS data area //KeyboardStatus = *(unsigned short far *)MK_FP( 0x40, 0x17 ); TranslateObject( &g.Ship ); DrawObject( &g.Ship ); // Draw the ship MoveObject( &g.Ship ); // Simulate friction. g.Ship.Direction.x *= FRICTION; g.Ship.Direction.y *= FRICTION; // If a real keystroke is waiting get it if(Pad.Held.Left) // left shift, rotate left { g.Ship.ViewAngle -= ROTATE_STEP; if( g.Ship.ViewAngle < 0 ) g.Ship.ViewAngle = 360 - ROTATE_STEP; } if(Pad.Held.Right) // right shift, rotate right { g.Ship.ViewAngle += ROTATE_STEP; if( g.Ship.ViewAngle > 359 ) g.Ship.ViewAngle = 0 + ROTATE_STEP; } if(Pad.Held.B) // shift-lock, fire { // Not supported yet. } if(Pad.Held.A) // alt, thrust { double Radians,Radp; int randm; randm = (int) N * rand() / (RAND_MAX + 1.0)+1; Radians = g.Ship.ViewAngle * 0.01745; Radp = g.Ship.ViewAngle+(randm*3) -15* 0.01745; //if (fire.Fire[randm].Frames==0 || fire.Fire[randm].Frames==NULL){ fire.Fire[randm].ViewAngle=g.Ship.ViewAngle+(randm*3)-15; fire.Fire[randm].Frames=1; fire.Fire[randm].Loc.x = g.Ship.Loc.x; fire.Fire[randm].Loc.y = g.Ship.Loc.y; fire.Fire[randm].Direction.x+=sin(Radp); fire.Fire[randm].Direction.y+=cos(Radp); //} g.Ship.Direction.x += sin( Radians ) * SPEED; g.Ship.Direction.y -= cos( Radians ) * SPEED; // fire.Fire.Direction.x } SyncToVerticalRetrace(); // Pause until vertical retrace // if( EraseFlag ) DrawObject( &g.Ship ); // Erase the ship // // if( c == 'c' || c == 'C' ) // Change color // { // Color ^= (WHITE ^ LIGHTGREEN); // setcolor( Color ); // c = 0; // } } } // Initialization code. void Init( void ) { // int GraphicsDriver = VGA; // assume VGA graphics card // int GraphicsMode = VGAHI; // use VGA 640x480 16 color mode // // initgraph( &GraphicsDriver, &GraphicsMode, NULL ); // setwritemode( XOR_PUT ); PA_Init(); // Initializes PA_Lib PA_InitVBL(); // Initializes a standard VBL PA_Init8bitBg(0,0); PA_SetBgPalCol(0, 1, PA_RGB(31, 31, 31)); PA_SetBgPalCol(0, 2, PA_RGB(31, 0, 0)); PA_SetBgPalCol(0, 3, PA_RGB(0, 0, 31)); PA_SetBgPalCol(0, 4, PA_RGB(0, 31, 0)); PA_SetBgPalCol(1, 1, PA_RGB(31, 31, 31)); PA_SetBgPalCol(1, 2, PA_RGB(31, 0, 0)); PA_SetBgPalCol(1, 3, PA_RGB(0, 0, 31)); PA_SetBgPalCol(1, 4, PA_RGB(0, 31, 0)); g.Ship.Shape.NumPoints = 16; g.Ship.Shape.Point[ 0 ].x = 0; g.Ship.Shape.Point[ 0 ].y = -5; g.Ship.Shape.Point[ 1 ].x = 4; g.Ship.Shape.Point[ 1 ].y = -3; g.Ship.Shape.Point[ 2 ].x = 3; g.Ship.Shape.Point[ 2 ].y = -1; g.Ship.Shape.Point[ 3 ].x = 3; g.Ship.Shape.Point[ 3 ].y = 0; g.Ship.Shape.Point[ 4 ].x = 4; g.Ship.Shape.Point[ 4 ].y = 4; g.Ship.Shape.Point[ 5 ].x = 0; g.Ship.Shape.Point[ 5 ].y = 3; g.Ship.Shape.Point[ 6 ].x = -4; g.Ship.Shape.Point[ 6 ].y = 4; g.Ship.Shape.Point[ 7 ].x = -3; g.Ship.Shape.Point[ 7 ].y = 0; g.Ship.Shape.Point[ 8 ].x = -3; g.Ship.Shape.Point[ 8 ].y = -1; g.Ship.Shape.Point[ 9 ].x = 0; g.Ship.Shape.Point[ 9 ].y = -2; g.Ship.Shape.Point[ 10 ].x = 3; g.Ship.Shape.Point[ 10 ].y = -1; g.Ship.Shape.Point[ 11 ].x = 3; g.Ship.Shape.Point[ 11 ].y = 0; g.Ship.Shape.Point[ 12 ].x = 0; g.Ship.Shape.Point[ 12 ].y = -1; g.Ship.Shape.Point[ 13 ].x = -3; g.Ship.Shape.Point[ 13 ].y = 0; g.Ship.Shape.Point[ 14 ].x = -3; g.Ship.Shape.Point[ 14 ].y = -1; g.Ship.Shape.Point[ 15 ].x = -4; g.Ship.Shape.Point[ 15 ].y = -3; g.Ship.ViewAngle = 0; g.Ship.Loc.x = 56; g.Ship.Loc.y = 45; g.Ship.Direction.x = 0; g.Ship.Direction.y = 0; } void Cleanup( void ) { PA_Clear8bitBg(0); } int main( int Argc, char *Argv[] ) { // puts( "\n\n" ); // puts( "Asteroids. October 1994, \"What's the Code?\"\n" ); // puts( "Left shift: Rotate left" ); // puts( "Right shift: Rotate right" ); // puts( "Alt: Thrust" ); // puts( "E: Toggle 'erase' mode" ); // puts( "C: Toggle color between white and green" ); // puts( "Q: Quit\n" ); // // puts( "Press any key to begin..." ); // // getch(); Init(); Supervisor(); // Cleanup(); return 0; } /* // Function: main() int main(int argc, char ** argv) { // Infinite loop to keep the program running while (1) { PA_Clear8bitBg(0); // PA_Draw8bitLineEx(0,35,35,89,98,1,2); DrawObject( &g.Ship ); // Draw the ship } } // End of main()*/