Search Tips Advanced Search |
| Delphi Graphics and Game Programming Exposed with DirectX 7.0 by John Ayres Wordware Publishing, Inc. ISBN: 1556226373 Pub Date: 12/01/99
Search this book:
Previous | Table of Contents | Next
Listing 11-7: A 3-D star field
    const

       .

       .

       .

      {the total number of stars on the screen at once}

      NUMSTARS = 1000;

      {the viewing distance}

      VIEWDISTANCE = 350;

       .

       .

       .

    type

      {tracks single point within our 3D world}

      TStar = record

        X, Y, Z: Single;

      end;

       .

       .

       .

    var

       .

       .

       .

      {the palette interface}

      FPalette: IDirectDrawPalette;

    implementation

       .

       .

       .

    procedure TfrmDXAppMain.FormActivate(Sender: TObject);

    var

       .

       .

       .

      {holds palette colors}

      PalColors: TColorTable;

      iCount: Integer;

    begin

       .

       .

       .

      {define the colors for the palette. this produces a ranged palette,

       fading from black to white in the lower half, and all white in

       the upper half. this is used to make the stars appear to fade in as

       they move closer to the user}

      for iCount := 0 to 127 do

      begin

        PalColors[iCount].R := 255;

        PalColors[iCount].G := 255;

        PalColors[iCount].B := 255;

        PalColors[iCount].A := 0;

      end;

      for iCount := 128 to 255 do

      begin

        PalColors[iCount].R := 255-(2*(iCount-128));

        PalColors[iCount].G := 255-(2*(iCount-128));

        PalColors[iCount].B := 255-(2*(iCount-128));

        PalColors[iCount].A := 0;

      end;

      {create the actual palette}

      FDirectDraw.CreatePalette(DDPCAPS_8BIT or DDPCAPS_ALLOW256,

                                @PalColors, FPalette, nil);

      {attach the palette to the primary surface}

      FPrimarySurface.SetPalette(FPalette);

      {finally, initialize all of the stars}

      for iCount := 0 to NUMSTARS do

        InitStar(iCount);

       .

       .

       .

    end;

       .

       .

       .

    procedure TfrmDXAppMain.DrawSurfaces;

    var

      SrfcDesc: TDDSurfaceDesc2;

      BytePtr: PByte;

      iCount: Integer;

      XPos, YPos: Integer;

    begin

      {clear the back buffer}

      ColorFill(FBackBuffer, 255, nil);

      {lock the back buffer. all animation will take place on this surface}

      FillChar(SrfcDesc, SizeOf(TDDSurfaceDesc2), 0);

      SrfcDesc.dwSize := SizeOf(TDDSurfaceDesc2);

      FBackBuffer.Lock(nil, SrfcDesc, DDLOCK_WAIT, 0);

      BytePtr := SrfcDesc.lpSurface;

      {move and draw all of the stars}

      for iCount := 0 to NUMSTARS do

      begin

        {a negative value here moves the stars closer to the screen. a positive

         value would move them away, giving the sensation of moving backwards}

        Stars[iCount].Z := Stars[iCount].Z - 15;

        {if the star’s Z value is greater than zero...}

        if Stars[iCount].Z > 0 then

        begin

          {project the star onto our 2D computer screen in a perspectively

           correct manner.  note that since the origin of the computer

           screen is in the upper left-hand corner, we’re moving the stars

           into the center of the screen to produce a more desirable effect.

           note that we’re also reversing the sign of the Y coordinate so

           that it accurately reflects the movement in a Cartesian coordinate

           system}

          XPos := Round((DXWIDTH div 2)+

                        (Stars[iCount].X/Stars[iCount].Z*VIEWDISTANCE));

          YPos := Round((DXHEIGHT div 2)-

                        (Stars[iCount].Y/Stars[iCount].Z*VIEWDISTANCE));

          {if our stars are off of the screen...}

          if (XPos<0) or (XPos>DXWIDTH) or (YPos<0) or (YPos>DXHEIGHT) then

            {...re-create it}

            InitStar(iCount)

          else

            {otherwise, draw it at the correct position, using a color

             proportional to its Z axis position, making it appear to fade in

             from black}

            PByte(Longint(BytePtr)+XPos+(YPos*SrfcDesc.lPitch))^ :=

                  Trunc(255*(Stars[iCount].Z/1000));

        end

        else

          {...otherwise, reinitialize the star}

          InitStar(iCount);

      end;

      {finally, unlock the buffer}

      FBackBuffer.Unlock(nil);

    end;

       .

       .

       .

    procedure TfrmDXAppMain.InitStar(Index: Integer);

    begin

      {place the star at a random position}

      Stars[Index].X := random(2000)-1000;

      Stars[Index].Y:=random(2000)-1000;

      {start the star as far back as necessary}

      Stars[Index].Z:=1000;

    end;

    end.
Alternatives/Enhancements Allowing the user to specify the velocity of the stars through some sort of throttle control would create the perception of speed. By modifying the starting position of the stars, it would even be possible to create the sensation of turning. Coupled with a fast bitmap scaling algorithm, this effect could be used to create a pretty cool arcade-type space shooter.
| Tip: While this animation is pretty fast in its current implementation, there’s really no need to use a three-dimensional coordinate system with perspective projection unless we’re going to be creating a full 3-D game. This same effect can be reproduced using only x and y velocities and integer math, which could dramatically speed up the effect and leave more CPU time for more critical tasks. Remember, graphical effects do not have to be totally accurate; as long as it looks right, it is right.
Alternatively, if this was going to be used simply as a static animation or a transition from scene to scene, it may be faster just to create an actual animation using bitmaps drawn by an artist. However, the method by which stars are implemented could be considered a primitive particle system. By starting several “stars” at the exact same coordinate but giving each one a different heading and velocity and implementing a lifespan counter for each one so it disappears after a certain amount of time, a very realistic particle explosion system could be created. Adding gravity effects to the particles could produce an even more remarkable effect.
Previous | Table of Contents | Next

Products | Contact Us | About Us | Privacy | Ad Info | Home Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.