12

Parallax Starfield

Almost a year earlier I had downloaded someone else's starfield code, and here I convert it from BGI to direct memory manipulation. Nothing exciting, but it seems I was getting more comfortable with these different approaches and how to translate between them.

Parallax by modulo

Three depth layers, and the depth is done with if q mod x = 0 - a star in the far layer only moves every second or third frame. No per-star velocity, no fixed point, just a counter and a remainder. It is the cheapest possible parallax and it reads correctly.

The .BAK is the earlier draft, still on BGI at 640×480, and it carries an erase-offset hack (+((3-Field) div 2)) compensating for something the rewrite makes unnecessary.

ASMSTARS.PAS

1996-01-25 07:00 · 1,188 bytes · Mode 13h, direct DAC writes, the FUN4 machinery.

Uses Crt;Type StarField=Array[1..3,1..2,1..5]of Integer;T=Array[1..3]of
Integer;Var Colors:T;Stars:StarField;x,y,q:integer;

Procedure Plot(a,b,c:integer);Begin Mem[$a000:b*320+a]:=c;end;

Procedure VidMode(Mode:Byte);Begin
Asm Mov AH,00;Mov AL,Mode;Int 16;End;End;

Procedure PlotStar(Var Stars:StarField;Field,Specific,PlotColor:Integer);
begin plot(Stars[Field,1,Specific],Stars[Field,2,Specific],PlotColor);End;

Procedure ChangeStars(Var Stars:StarField;Var Colors:T);Var Color:Integer;
Begin Repeat inc(q);For x:=1to 3do If(q mod x=0)then Begin
delay(2);For y:=1to 5do
Begin Plotstar(Stars,x,y,0);Stars[x,1,y]:=Stars[x,1,y]-1;If(Stars[x,1,y]<-1)
then Begin Stars[x,1,y]:=319;Stars[x,2,y]:=Random(200);End else
PlotStar(Stars,x,y,Colors[x]);End;End;Until Keypressed;End;

Begin vidmode(19);Port[$3C8]:=7;Port[$3C9]:=60;Port[$3C9]:=60;Port[$3C9]:=60;
Port[$3C8]:=8;Port[$3C9]:=40;Port[$3C9]:=40;Port[$3C9]:=40;Port[$3C8]:=9;
Port[$3C9]:=20;Port[$3C9]:=20;Port[$3C9]:=20;
Colors[1]:=7;Colors[2]:=8;Colors[3]:=9;q:=1;
Randomize;For x:=1to 3do For y:=1to 5do Begin
Stars[x,1,y]:=Random(319);Stars[x,2,y]:=Random(200);End;
ChangeStars(Stars,Colors);vidmode(3);End.
ASMSTARS.BAK

1996-01-25 06:48 · 1,053 bytes · Byte-identical to pas/JSTARS.PAS.

Uses Crt, Graph, BGIDriv;
Type StarField=Array[1..3,1..2,1..5]of Integer;T=Array[1..3]of Integer;
Var Colors:T;Stars:StarField;d,m,x,y,q:integer;

Procedure PlotStar(Var Stars:StarField;Field,Specific,PlotColor:Integer);
Begin If(PlotColor=0)then
PutPixel(Stars[Field,1,Specific]+((3-Field)div 2),Stars[Field,2,Specific],0)else
PutPixel(Stars[Field,1,Specific],Stars[Field,2,Specific],PlotColor);End;

Procedure ChangeStars(Var Stars:StarField;Var Colors:T);Var Color:Integer;
Begin Repeat inc(q);For x:=1to 3do If(q mod x=0)then Begin For y:=1to 5do
Begin PlotStar(Stars,x,y,0);Stars[x,1,y]:=Stars[x,1,y]-1;If(Stars[x,1,y]<-1)
then Begin Stars[x,1,y]:=639;Stars[x,2,y]:=Random(480);End else
PlotStar(Stars,x,y,Colors[x]);End;End;Until Keypressed;End;

Begin if RegisterBGIDriver(@EGAVGADriverProc)<0then halt(1);
Colors[1]:=63;Colors[2]:=7;Colors[3]:=56;q:=1;d:=detect;Initgraph(d,m,'');
Randomize;For x:=1to 3do For y:=1to 5do Begin
Stars[x,1,y]:=Random(639);Stars[x,2,y]:=Random(480);End;
ChangeStars (Stars,Colors);Closegraph;End.
STARS.PAS

1995-03-22 08:36 · 5,670 bytes · The collected original, as downloaded.

Uses
   Crt, Graph, BGIDriv;

Type
   StarField = Array [1..5,1..2,1..100] of Integer;
   Timing = Array [1..5] of Integer;

Var
   Delays, Master, Limit, Colors : Timing;
   Stars : StarField;
   Choice : Integer;
   d,m:integer;



Procedure ShowLimits (Limit : Timing);
Var Count : Integer;
Begin
Clrscr;
For Count := 1 to 5 do begin
    GotoXY (5,Count+2);  TextColor (9);
    Write ('Number of Stars in Vicinity #',count,': ');
    If (Limit[Count]=0) then Writeln ('None')
    else Writeln (Limit[Count]); end;
End;


Procedure SetLimits (Var Limit : Timing);

Var
   StarCount, Loop : Integer;
   MasterDone, Done : Boolean;
   Keys : Char;

Begin
   MasterDone := False;
   
   While Not(MasterDone) do
   Begin
      For Loop :=1 to 5 do Limit[loop]:=0;
      For Loop := 1 to 5 do
      Begin
            ShowLimits (Limit);
            GotoXY (1,1);  TextColor (15);
            Write ('Please Enter A Star Count For');
            Write (' Vicinity #',loop,' (1-100): ');
            TextColor (10);  Readln (StarCount);
            If (StarCount<101) and (StarCount>0) then
            Limit[Loop] := StarCount;
            End;
            Showlimits(Limit);
      GotoXY (1,1);  TextColor (15);
      Writeln ('Star Count Entered for All Vicinities.');
      GotoXY (1,9);  TextColor (15);
      Writeln ('Are These Figures Okay With You? (Y/N)');
      GotoXY (1,11);  TextColor (0);  Write (' ');  GotoXY (1,11);
      Done := False;
      While Not(Done) do
      Begin
         Keys := readkey;
         If (Keys='Y') or (Keys='y') then
         Begin
            MasterDone := True;
            Done := True;
         End;
         If (Keys='N') or (Keys='n') then Done := True;
      End;
   End;
End;

Procedure SetSets (Var Colors : Timing;  Select : Integer);

Begin
  Case Select of

    1 :  Begin
            Colors [1] := EGAWhite;
            Colors [2] := EGALightGray;
            Colors [3] := EGALightGray;
            Colors [4] := EGALightGray;
            Colors [5] := EGADarkGray;
         End;

    2 : Begin
           Colors [1] := EGALightCyan;
           Colors [2] := EGALightBlue;
           Colors [3] := EGALightBlue;
           Colors [4] := EGALightBlue;
           Colors [5] := EGABlue;
        End;

    3 : Begin
           Colors [1] := EGAWhite;
           Colors [2] := EGAYellow;
           Colors [3] := EGALightRed;
           Colors [4] := EGALightRed;
           Colors [5] := EGARed;
        End;

    4 : Begin
           Colors [1] := EGALightMagenta;
           Colors [2] := EGAMagenta;
           Colors [3] := EGAMagenta;
           Colors [4] := EGAMagenta;
           Colors [5] := EGABlue;
        End;
   End;
End;


Procedure InitStars (Var Stars : StarField;  Var Delays, Master,
                     Limit : Timing);

Var
   Loop, LoopB : Integer;

Begin
   Randomize;
   Master [1] := 1;  Master [2] := 2;
   Delays [1] := 1;  Delays [2] := 2;

   Master [3] := 3;  Master [4] := 4;
   Delays [3] := 3;  Delays [4] := 4;

   Master [5] := 5;  Delays [5] := 5;

   For Loop := 1 to 5 do
   For LoopB := 1 to Limit[Loop] do
   Begin
      Stars [Loop,1,LoopB] := Random (639);
      Stars [Loop,2,LoopB] := Random (480);
   End;
End;


Procedure PlotStar (Var Stars : StarField;  Field, Specific, PlotColor : Integer);

Begin
   If (PlotColor=0) then
   PutPixel (Stars[Field,1,Specific]+((5-Field)div 2),Stars[Field,2,Specific],0) else
   PutPixel (Stars[Field,1,Specific],Stars[Field,2,Specific],PlotColor);
End;


Procedure ChangeStars (Var Stars : StarField;  Var Delays, Master,
                       Limit : Timing;  Colors : Timing);

Var
   Loop, LoopB, LoopC, Color : Integer;
   Blinkies : Timing;
   Done : Boolean;
   Keys : Char;

Begin
   Done := False;  For Loop := 1 to 5 do Blinkies [Loop] := 1;
   While Not(Done) do
   Begin
      For Loop := 1 to 5 do
      Begin
         Delays [Loop] := Delays [Loop]-1;
         If (Delays[Loop]=0) then
         Begin
            Delays [Loop] := Master [Loop];
            For LoopB := 1 to Limit[Loop] do
            Begin
               PlotStar (Stars,Loop,LoopB,0);
               Stars [Loop,1,LoopB] := Stars [Loop,1,LoopB]-1;
               If (Stars[Loop,1,LoopB]=-Master[Loop]-2) then
               Begin
                  PutPixel (Stars[Loop,1,LoopB],Stars[Loop,2,LoopB],0);
                  Stars[Loop,1,LoopB] := 639;
                  Stars[Loop,2,LoopB] := Random (480);
               End else
               If (Blinkies[Loop]=1) then
               PlotStar (Stars,Loop,LoopB,Colors[Loop]) else
               PlotStar (Stars,Loop,LoopB,Colors[Random(5)]);
            End;
         End;
      End;
      If (Keypressed) then
      Begin
         Keys := ReadKey;
         Case (Keys) of

           '6', '7',
           '8', '9' : Begin
                         Val (Keys,Color,Color);
                         SetSets (Colors,Color-5);
                      End;

           '1', '2',
           '3', '4',
           '5'      : Begin
                         Val (Keys,Color,Color);
                         Blinkies [Color] := Blinkies [Color]*(-1);
                      End;


           Else Done := True;
         End;
      End;
   End;
End;


Begin
   if RegisterBGIDriver(@EGAVGADriverProc) < 0 then halt(1);
   SetLimits (Limit);  SetSets (Colors,1);
   d:=detect;Initgraph (d,m,'');  InitStars (Stars,Delays,Master,Limit);
   ChangeStars (Stars,Delays,Master,Limit,Colors);
   Closegraph;
End.