[Back to GRAPHICS SWAG index]  [Back to Main SWAG index]  [Original]


{$G+}
{   Simulador de Campo de Estrellas.        Starfield Simulator
  -------------------------------------|----------------------------
                 Tomas Laurenzo - tlaure@lsa.lsa.com.uy
                            Montevideo - Uruguay
 
  DISCLAIMER: Same as usual, use it at your own risk.
 
  COPYRIGHT: Use it freely, just remember _I_ coded it, BTW the '*' (Big
             Bang Flower) routine will be in a demo i'm coding, and it's
             dedicated to a girl nicknamed Kash, so if you use it, name
             us in the credits, thanks. :)
 
 
  DESCRIPTION:
  This is a simple starfield simulator, with two or three simple routines
  in it, press '?' for help (if you can actually read it >;) ), or just try
  '4','5','0','+','-','*'.. i think that's all, check the code anyway.
  I do use some routines that i've collected for quite awhile.
  I think most of'em are from the SWAG files, and from the Asphyxia VGA
  Trainer by Denthor... which helped me a lot, time ago.
  Sorry, it's not fully optimized, but there are some routines that I do
  not wont to make public yet ;)
 
  Oh, the Big Bang flower in radar mode has a bug... some boxes appear where
  they shouldn't.. help.
  The 'speed < -2' bug is easily fixeable, but I like the 'good bye mon TV'
  effect, and if fixed, the '*' routine would disappear :)
 
  Any comments, suggestions, whatever, _please_ mail.
 
  Sal£,
    Tom.
 
 
  P.S. Sorry again, it's not very commented, the procedural names are self
       descriptive, but most of them are in spanish.
       Anyway I think the code should be easy to understand. O:)
       And please oversee my tarzan-style english ;)
 
^`§:;,.,;:§'^`§:;,.,;:§'^`§:;,.,;:§'^`§:;,.,;:§'^`§:;,.,;:§'^`§:;,.,;:§'^`§:;,.
}
 
 
 
PROGRAM Startrek;                         { Yeah, God save the enterprise! }
 
 USES Crt;
 
 CONST CantStars = 1000;   { # of stars }
 
 TYPE
   Observador = RECORD
                   X : Word;
                   Y : Word;
                   Z : Word;
                END;
 
   Colores  = (Blanco, Amarillo, Celeste, Violeta);
 
   Estrella = RECORD
                 X,Y,Z : Word;
              END;
 
   Stars = ARRAY [0..CantStars] OF Estrella;
 
 
 CONST
       VGA = $A000;
       Obs : Observador = (
                          X : 0;
                          Y : 0;
                          Z : 60
                          );
 
 VAR
   CosTable  : ARRAY [0..1024] of Integer;
   Color : Colores;
   AnguloZ : Integer;
   Vel   : ShortInt;
   I     : Byte;
   Campo : Stars;
   Tecla : Char;
   RotoZ,
   Termina,
   Borro : Boolean;
   Cola  : ARRAY [0..CantStars] OF RECORD
                                    X1,Y1,
                                    X2,Y2 : Integer;
                                   END;
 
{............................................................................}
 
 FUNCTION Coseno (Angulo : Integer): Integer; Assembler;
   ASM
    mov  ax,Seg CosTable
    mov  es,ax
    mov  di,Offset CosTable
    mov  dx,Angulo
    shl  dx,1
    add  di,dx
    mov  ax,es:[di]
  END;
 
{............................................................................}
 
  PROCEDURE Proyecta (X, Y, Z :Integer;
                      VAR Xscr, Yscr : Word;
                          XCentro, YCentro : Integer);
 
   BEGIN
    IF Z >= Obs.Z THEN BEGIN
        Xscr := 319;
        Yscr := 200;
    END
    ELSE BEGIN
     Xscr := XCentro + ((Obs.X * Z - X * Obs.Z) div (Z - Obs.Z));
     Yscr := YCentro + ((Obs.Y * Z - Y * Obs.Z) div (Z - Obs.Z));
   END;
  END;
 
{............................................................................}
 
 PROCEDURE MakeCosTable;
 
  VAR
    CntVal : Word;
    CntAng : Real;
    IncDeg : Real;
 
  BEGIN
    IncDeg := 2*PI/1024;
    CntAng := IncDeg;
    CntVal := 0;
    REPEAT
      CosTable [CntVal] := Round(255*cos(CntAng));
      CntAng := CntAng+IncDeg;
      Inc (CntVal);
    UNTIL CntVal > 1024;
 END;
 
{...........................................................................}
 
 FUNCTION Seno (Angulo : Integer): Integer; Assembler;
   ASM
    mov  ax,Seg CosTable
    mov  es,ax
    mov  di,Offset CosTable
    mov  dx,Angulo
    mov  bx,1024
    add  dx,256
    cmp  dx,bx
    jle  @@Ok
    sub  dx,1024
  @@Ok:
    shl  dx,1
    add  di,dx
    mov  ax,es:[di]
  END;
 
{............................................................................}
 
 
  PROCEDURE Modo13h; Assembler;
   ASM
    MOV AX, 13h
    INT 10h
 
{    MOV ah,0fh     Si se quiere que el procedimiento devuelva un errcode
     INT 10h        se le agrega esto, se cambia el proc a func : word
     XOR ah,ah      y si no devuelve 13h ($13) es que no tiene VGA }
 
   END;
 
{............................................................................}
 
  PROCEDURE ModoTexto; Assembler;
   ASM
    MOV ax,03h
    INT 10h
   END;
 
{...........................................................................-}
 
 PROCEDURE Retraso; Assembler;
  ASM
      mov   dx,3DAh
  @@1:
      in    al,dx
      and   al,08h
      jnz   @@1
  @@2:
      in    al,dx
      and   al,08h
      jz    @@2
  END;
{
 BEGIN
  WHILE (PORT[$3da] AND 8)<>0 DO;
  WHILE (PORT[$3da] AND 8)=0 DO;   { sta es la implementaci¢n pascal   }
{ END;}
 
{............................................................................}
 
  PROCEDURE Cls (Col : Byte; Where:word); assembler;
   ASM
    push    es
    mov     cx, 32000;
    mov     es,[where]
    xor     di,di
    mov     al,[col]
    mov     ah,al
    rep     stosw
    pop     es
   END;
 
{............................................................................}
 
 PROCEDURE PutDot (X,Y : Integer; Color : Byte; SegDes:word); Assembler;
  ASM
   cmp  X,0
   jl   @@END
   cmp  Y,0
   jl   @@END
   cmp  X,319
   jg   @@END
   cmp  Y,199
   jg   @@END
   mov  ax,SegDes
   mov  es,ax
   mov  al,Color
   mov  di,Y
   mov  bx,X
   mov  dx,di
   xchg dh,dl
   shl  di,6
   add  di,dx
   add  di,bx
   mov  es:[di],al
 @@END:
 END;
 
{............................................................................}
 
 PROCEDURE SeteaColor (Col,R,G,B : Byte); assembler;
  ASM
    mov    dx,3c8h
    mov    al,[col]
    out    dx,al
    inc    dx
    mov    al,[r]
    out    dx,al
    mov    al,[g]
    out    dx,al
    mov    al,[b]
    out    dx,al
  END;
 
{--------------------------------------------------------------------------}
 
 PROCEDURE  GeneroPaleta (Tipo : Colores);
  VAR I : Byte;
  BEGIN
   SeteaColor (0,0,0,0);
   CASE Tipo OF
     Blanco   : FOR I := 1 TO 255 DO SeteaColor (I,I,I,I);
     Celeste  : FOR I := 1 TO 255 DO SeteaColor (I,64,I,I);
     Violeta  : FOR I := 1 TO 255 DO SeteaColor (I,I,64,I);
     Amarillo : FOR I := 1 TO 255 DO SeteaColor (I,I,I,64);
  END;
 END;
 
{--------------------------------------------------------------------------}
 
 PROCEDURE GeneroEstrellas;
  VAR  J,
       I : Integer;
  BEGIN
    FOR I := 0 TO CantStars DIV 6 DO BEGIN
       Campo [I].X := Random (320)-160;
       Campo [I].Y := Random (200)-100;
       Campo [I].Z := 0;
       Cola  [I].X1 := Campo [I]. X;
       Cola  [I].Y1 := Campo [I]. Y;
    END;
 
    FOR I := 1 TO 5 DO
      FOR J := (I * CantStars DIV 6) TO (CantStars DIV 6) * (I+1) -1
      DO BEGIN
       Campo [J].X := Random (320)-160;
       Campo [J].Y := Random (200)-100;
       Campo [J].Z := I * 10;
       Cola  [I].X1 := Campo [I]. X;
       Cola  [I].Y1 := Campo [I]. Y;
 
      END;
  END;
 
{--------------------------------------------------------------------------}
 
 PROCEDURE EscriboEstrellas ;
  VAR I : Integer;
      X,Y : Word;
      X1,Y1,Z1,
      X2,Y2,Z2,
      Xr,Yr,Zr : Integer;
 
  BEGIN
   CASE RotoZ OF
    True  : BEGIN
              FOR I := 0 to CantStars DO BEGIN
                X := Campo[I].X;
                Y := Campo[I].Y;
 
                Xr := (Coseno (AnguloZ) * X) div 256
                                  -
                      (Seno (AnguloZ) * Y) div 256;
 
                Yr := (Seno (AnguloZ) * X) div 256
                                  +
                      (Coseno (AnguloZ) * Y) div 256;
 
 
{                Campo [I].X := Xr;
                Campo [I].Y := Yr;}
 
 
                Proyecta (Xr,
                          Yr,
                          Campo[I].Z,
                          X, Y,
                          160,100);
                PutDot (X,Y,Campo[I].Z,VGA);
                Cola [I].X1 := X;
                Cola [I].Y1 := Y;
              END;
              IF AnguloZ > 1024 THEN AnguloZ := AnguloZ - 1024
                                ELSE Inc (AnguloZ,5);
            END;
    False : BEGIN
              FOR I := 0 to CantStars DO BEGIN
 
                Proyecta (Campo[I].X,
                          Campo[I].Y,
                          Campo[I].Z,
                          X, Y,
                          160,100);
                PutDot (X,Y,Campo[I].Z,VGA);
                Cola [I].X1 := X;
                Cola [I].Y1 := Y;
              END;
            END;
    END;
  END;
 
{--------------------------------------------------------------------------}
 
 PROCEDURE BorroEstrellas;
  VAR I : Integer;
 
  BEGIN
    IF Borro THEN BEGIN
     FOR I := 0 to CantStars DO BEGIN
       PutDot (Cola [I].X1, Cola [I].Y1, 0, VGA);
       PutDot (Cola [I].X2, Cola [I].Y2, 0, VGA);
     END;
     Borro := FALSE
     END ELSE Borro := True;
 
  END;
 
{--------------------------------------------------------------------------}
 
 PROCEDURE MuevoEstrellas (Creo : Boolean);
  VAR I : Integer;
  BEGIN
    FOR I := 0 TO CantStars DO BEGIN
 
      Cola [I].X2 := Cola [I].X1;
      Cola [I].Y2 := Cola [I].Y1;
 
 
{}IF Vel > 0 THEN BEGIN
      IF (Cola [I].X1 > 0) and (Cola [I].Y1 > 0) and
         (Cola [I].X1 < 320) and (Cola [I].Y1 < 200) and
         (Campo [I].Z < Obs.Z) THEN Inc (Campo[I].Z,Vel)
      ELSE BEGIN
        IF Creo THEN BEGIN
          Campo [I].X := Random (320)-160;
          Campo [I].Y := Random (200)-100
        END
        ELSE BEGIN
          Campo [I].X := 3000;
          Campo [I].Y := 3000
        END;
        Campo [I].Z := 0;
      END
{}END
  ELSE BEGIN
      IF Campo [I].Z > 0 THEN Inc (Campo[I].Z,Vel)
      ELSE BEGIN
        IF Creo THEN BEGIN
          Campo [I].X := Random (320)-160;
          Campo [I].Y := Random (200)-100
        END
        ELSE BEGIN
          Campo [I].X := 3000;
          Campo [I].Y := 3000
        END;
        Campo [I].Z := Obs.Z + 1
      END
{}END
 
    END
  END;
 
{--------------------------------------------------------------------------}
 
 PROCEDURE Bouncing; { Not really, it's the Big Bang Flower }
  Var VT : ShortInt;
      I  : Byte;
      J  : Integer;
  BEGIN
   VT := Vel;
   Vel := -1;
   FOR I := 1 to 20 do BEGIN
    FOR J := 0 to CantStars DO BEGIN
      Campo [J].Z := Campo[J].Z -1 ;
    END;
    EscriboEstrellas;
   END;
   Vel := VT;
  END;
 
{--------------------------------------------------------------------------}
 
 PROCEDURE Lluvia;  { Rain }
  VAR  J, I : Integer;
       Pant : ARRAY [0..CantStars] OF RECORD X,Y,Z : Word; END;
 
   FUNCTION HayPant : BOOLEAN;
    VAR I : Integer; Hay : Boolean;
    BEGIN
      Hay := False;
      FOR I := 0 to CantStars DO IF Pant[I].Y < 200 THEN Hay := True;
      HayPant := Hay;
    END;
 
    PROCEDURE EscriboPant;
     VAR I : Integer;
      BEGIN FOR I := 0 to CantStars do PutDot (Pant[I].X,
                                               Pant[I].Y,
                                               Pant[I].Z,
                                               VGA);
      END;
 
     PROCEDURE MuevoPant;
      VAR I : Integer;
      BEGIN FOR I := 0 to CantStars DO
           IF Pant[I].Z > 10 THEN Pant[I].Y := Pant[I].Y + Pant[I].Z div 8
                             ELSE Pant[I].Y := Pant[I].Y +1 ;
      END;
 
    PROCEDURE BorroPant (Inc : ShortInt);
     VAR I : Integer;
     BEGIN FOR I := 0 to CantStars do PutDot (Pant[I].X,
                                              Pant[I].Y+Inc,
                                              0,
                                              VGA);
     END;
 
  BEGIN
   Cls (0,VGA);
   FOR I := 0 to CantStars DO BEGIN
        Proyecta (Campo[I].X,
                  Campo[I].Y,
                  Campo[I].Z,
                  Pant[I].X,
                  Pant[I].Y,
                  160,100);
         Pant[I].Z := Campo[I].Z;
 
   END;
   WHILE HayPant DO BEGIN
     EscriboPant;
     Retraso;
     BorroPant (0);
     MuevoPant;
   END;
  END;
 
{--------------------------------------------------------------------------}
 
 PROCEDURE Help;
 
  PROCEDURE Escribo (S : String; Salto : Boolean);
   VAR I : Byte;
 
   BEGIN
     GotoXY (40 - Length (S) DIV 2, WhereY);
     FOR I := 1 TO Length (S) DO BEGIN
       TextColor (Random (15)+1);
       Write (S[I]);
     END;
     IF Salto THEN WriteLn;
   END;
 
  PROCEDURE Apagacursor; Assembler;  { Sets the cursor off }
   ASM
     MOV AH, 02h
     MOV BH, 0
     MOV DH, 80
     MOV DL, 25
     INT 10h
   END;
 
 
 BEGIN
   ModoTexto;
   REPEAT
    ClrScr;
    Escribo ('Simulador de Campo de Estrellas',True);
    Escribo ('(Starfield Simulator)',True);
    Escribo ('---------------------------------',True);
    Escribo ('1996 ú Tomas Laurenzo ú tlaure@lsa.lsa.com.uy',True);
    WriteLn;
    Escribo ('Teclas (keys):',True);
    WriteLn;
    Escribo (' ? : Esta pantalla          ú This screen     ',True);
    Escribo (' + : Aumenta la velocidad   ú Increases speed ',True);
    Escribo (' - : Disminuye la velocidad ú Decreases speed ',True);
    Escribo (' 0 : Rota los colores       ú Rotate colors   ',True);
    Escribo (' 1 : Lluvia                 ú Rain            ',True);
    Escribo (' 5 : Modo radar             ú Radar mode      ',True);
    Escribo (' 4 : Modo normal            ú Normal mode     ',True);
    Escribo ('  spc : Rebote                 ú Bounce             ',True);
    Escribo (' * : Flor de Big Bang ;)   ú Big Bang Flower',True);
    WriteLn;
    Escribo ('Archivos (files):',True);
    Escribo ('CAMPO.EXE | CAMPO.TXT',True);
    WriteLn;
    Escribo ('Tomas Laurenzo ú tlaure@lsa.lsa.com.uy ú Montevideo - Uruguay',True);
    WriteLn;   Escribo (' IF Speed < -1 THEN Quite_A_Bug (ON)  a.k.a.  Good Bye mon T.V.',True);
    WriteLn;
    Escribo ('^`§:;,.,;:§''^`§:;,.,;:§''^`§:;,.,;:§''^`§:;,.,;:§''^`§:;,.,;:§''^`§:;,.,;:§''^`§:;,.',False);
    ApagaCursor;
    Delay (500);
   UNTIL keypressed;
   ReadKey;
   Modo13h;
   GeneroPaleta (Color);
  END;
 
 
 
{--------------------------------------------------------------------------
                               Principal
 --------------------------------------------------------------------------}
                                {main}
 BEGIN
   Randomize;
   MakeCosTable;
   GeneroEstrellas;
   AnguloZ := 0;
   Modo13h;
   GeneroPaleta (Blanco);
   Cls (0,VGA);
   Borro := False;
   Vel := 1;
   Termina := False;
 
   REPEAT
    EscriboEstrellas;
    Retraso;
    BorroEstrellas;
    MuevoEstrellas(True);
 
    IF KeyPressed THEN BEGIN
      Tecla := ReadKey;
      CASE Tecla OF
      '?' : Help;
      '+' : Inc (Vel);
      '-' : Dec (Vel);
      '0' : BEGIN
              IF Color = Violeta THEN Color := Blanco
                                 ELSE Inc (Color);
              GeneroPaleta (Color)
            END;
      '1' : Lluvia;
      '5' : RotoZ := True;
      '4' : RotoZ := False;
      ' ' : Vel := - Vel;
      '*' : BEGIN
              WHILE NOT KEYPRESSED DO Bouncing;
              CLS (0, VGA);
              ReadKey;
            END;
 
 
      ELSE Termina := True;
      END;
    END;
 
   UNTIL Termina;
 
   IF Vel <> 0 THEN
    FOR I := 0 TO 50 div Abs(Vel) DO BEGIN
     EscriboEstrellas;
     Retraso;
     BorroEstrellas;
     MuevoEstrellas(False);
    END;
   ModoTexto;
 END.


[Back to GRAPHICS SWAG index]  [Back to Main SWAG index]  [Original]