{ Updated EGAVGA.SWG on May 26, 1995 } { From: Scott Stone Ok, here's that 3-D starfield code that I promised. (it works) } Program Starfield_3D; Uses dos,crt; Const NumStars=100; StarSpeed=20; {change these to change the # of stars/speed, then recompile} Type Starrec=record x : integer; y : integer; z : integer end; Var a,b,c : integer; ch : char; stars : array [1..numstars] of starrec; p2,p3 : pointer; {Pointers to "virtual" VGA screens} Procedure InitVGA; Begin asm mov ax,13h int 10h end; end; {Moves the 320x200x256 mode identifier, 13 hexadecimal, into the AX system register then calls interrupt 10 hex, which handles the video card. Basically, it sets up the video mode} Procedure Restoretext; begin asm mov ax,03h int 10h end; end; {restores textmode - text mode is mode 03 hex} Procedure AllocatePages; Begin getmem(p2,64000); getmem(p3,64000); End; {gets 64k for each of the 2 pointer variables, p2 and p3} {These pointers represent "imaginary" vga pages, for swapping} Procedure ClearPage3; var i : longint; Begin for i:=0 to 63999 do begin mem[seg(p3^):i]:=0; end; end; Procedure Deallocatepages; begin freemem(p2,64000); freemem(p3,64000); End; {frees system memory so you don't get a heap overflow later} Procedure SwapPages; Begin move(mem[seg(p2^):0],mem[$A000:0],64000); move(mem[seg(p3^):0],mem[seg(p2^):0],64000); End; {Moves the data from the imaginary "page 2" to the visible page #1,} {Then moves the blank page 3 over to page 2, to start over. this} {is how you do smooth animation.} Procedure PutPixel(x,y : integer; c : integer); Begin mem[$A000:((320*y)+x)]:=c; End; {A000 Hex is the VGA segment address - the thing after the colon is the offset - imagine a 320x200 array, that's how you'd find the "linear" address in the array. After finding the right byte, it simply sets it equal to c, the color of the pixel you want} Procedure PP2(x,y : integer; c: integer); begin mem[seg(p2^):((320*y)+x)]:=c; End; {Same as putpixel, but puts it on the imaginary page #2 instead of the visual page} Procedure CalculateStars; Begin for a:=1 to numstars do begin stars[a].x:=(random(2000)-1000); {this produces a range from -1000 to +1000} stars[a].y:=(random(2000)-1000); stars[a].z:=(random(400)+1); {don't want Z to ever be negative -you'll see} end; end; {Basically, we've calculated the stars' initial positions} Procedure DisplayStars; Const expf=75; {local constant} {play with this value for some interesting FX} Var sx,sy : integer; {these are variables defined only for THIS procedure} tempcolor : integer; okshow : boolean; Begin for a:=1 to numstars do begin okshow:=true; {remember - positive Z is AWAY from you} if (stars[a].z<200) then tempcolor:=7; {light gray} if (stars[a].z<100) then tempcolor:=15; {white} if (stars[a].z>=200) then tempcolor:=8; {dark gray} if (stars[a].z>0) then {have to do this or get div by 0 error} begin sx:=round((stars[a].x*expf)/stars[a].z); sy:=round((stars[a].y*expf)/stars[a].z); sx:=sx+160; sy:=sy+100; {put the origin at the center, not upper-left} if (sx<0) then okshow:=false; if (sx>319) then okshow:=false; if (sy<0) then okshow:=false; if (sy>199) then okshow:=false; if (okshow=true) then pp2(sx,sy,tempcolor); end; end; end; {Displays one frame of the starfield, basically} Procedure MoveStars; Begin for a:=1 to numstars do begin stars[a].z:=(stars[a].z-starspeed); if (stars[a].z<=0) then stars[a].z:=400; {can't have 0 or negative value} end; End; {Updates the position of the stars} Begin {main program execution begins here} initvga; {first, setup the screen - we have lots of predef procedures now!} allocatepages; {get the virtual pages set up} clearpage3; {make sure page 3 is blank} calculatestars; {setup initial positions} repeat displaystars; {display one frame} swappages; {copy frame to visual page and erase working page} movestars; {update star data} until keypressed; {repeats the loop until you hit a key} restoretext; {put the video card back in 80x25 text mode} deallocatepages; {free up the system RAM we used} End. {end the program execution}