'---------------------------------------------------------------------------
'| Star Field 1.1 |
'| A first-person view of flying in space. |
'| |
'| October 1996 |
'| by |
'| William Travis Jones / wtjones@cswnet.com |
'| |
'| |
'| Keyboard layout: None, just press a key to quit. |
'| Several things are customizable. |
'| Tab Stops: 3 |
'---------------------------------------------------------------------------
' As I got more and more hooked on QBASIC, I always wondered how to make
'one of those zooming star animations like the Windows screen savers:
'"Flying Windows" and "Flying Through Space". I could study it all
'I wanted, but the fact was I didn't understand how they got the
'values for each of the stars as they moved. I knew that each time through
'the loop, I could: alter the x value, the y value, or both. The screen saver
'went against my current (at the time) knowledge of not just BASIC, but
'programming in general.
' From looking at the screen savers closely, you can easily tell that
'each star(or logo) has a focal point and then moves in a straight line
'outward in each loop.
'The QBASIC LINE statement does the same thing, but wont let you get the
'value of each pixel, which is what I needed.
' I figured the way Microsoft did the screen savers was probably from a
'simple calculation, and that most if not all programs that did similar point
'movement used the same formula. I just needed to find it.
' I posted on comp.sys.lang.basic a request of how to make a point
'rotate around another. Soon after, someone emailed me a small program that
'made a small circle rotate around in another in the center. Thanks Brennen
'Bearnes!
' The source was very easy to understand, except for the
'fact that it uses sine and cosine. I really didn't understand
'what that mean't, and I still don't know to tell you the truth. So
'far I can tell that the program uses sine and cosine to
'emulate the radius of a circle. All I do can pass it: the angle ,x and y
'of the center point(not nesessarily the center of the screen), and the
'radius to get the x and y coordinites of whatever point I need. The
'points in this program are of course the stars. I should stop babbling and
'start with the code...
'---------------------------------------------------------------------------
' Update... 1.1 is MUCH faster! It loads the sine and cosine tables into
'memory for a huge speed boost of about 80% or maybe more. I can now make
'all variable integers except I use single precision floating-point
'variables for the tables. I will give Brent P. Newhall credit for the
'table creation code. This version runs uncompiled almost as fast as M/K's
'StarWarp 1.2 in compiled form! (Not trying to be competitive, being theirs
'is in 640*480 and has the stars seem to come from a more distant
'starting point for realism.)
' Each star is reset at or near the middle after reaching a certian radius.
'the downside is that sometimes stars are getting caculated and drawn even
'if they are offscreen. I am working on a version that checks if the stars
'are out of the 320*200 area and then resets them. There are a few problems
'with it, but I will figure it out.
DEFINT A
-Z
'now n is not the only integer variable
PRINT "Creating tables..."
cosine
(n
) = COS(n
* 3.14159 / 180)
sine
(n
) = SIN(n
* 3.14159 / 180)
TYPE star
'data type for a star
CONST tou
= 250 'total number of stars on the outer part
CONST tin
= 50 'total number of stars in the inner part
CONST centx
= 160, centy
= 100
CONST clrdgry
= 8, clrlgry
= 7, clrwht
= 15 'color constants
CONST activepage
= 1, visualpage
= 0, blankpage
= 2
'these two loops give all the stars starting positions
outer
(n
).radius
= INT(RND * 180) + 30 'at least 30 pixels from center
outer
(n
).angle
= INT(RND * 360)
outer(n).speed = 1
inner
(n
).radius
= INT(RND * 200) 'these can start anywhere
inner
(n
).angle
= INT(RND * 360)
inner(n).speed = 1
'320*200 @ 16 colors - I only use: black, white, and 2 shades of gray
SCREEN 7, , workpage
, visiblepage
'show one page, but draw on another
'******************** {MAIN LOOP} ********************
'calculate the stars with a pi generator
PCOPY blankpage
, activepage
'blank out the active page
'draw the stars
'LOCATE 12, 16: PRINT "Star Field": LOCATE 22, 17: PRINT "1996 WTJ"
PCOPY activepage
, visualpage
'copy the active page to the visual page
SCREEN 7, , activepage
, visualpage
'flip it
'******************** {END MAIN LOOP} ********************
'******************** {END PROGRAM} **********************
updateouter:
IF outer
(n
).radius
> 75 THEN 'the closer the brighter
PSET (outer
(n
).x
, outer
(n
).y
), clrlgry
PSET (outer
(n
).x
, outer
(n
).y
), clrdgry
updateinner:
IF inner
(n
).radius
> 80 THEN 'the closer the bigger
LINE (inner
(n
).x
, inner
(n
).y
)-(inner
(n
).x
+ 1, inner
(n
).y
+ 1), clrwht
, B
PSET (inner
(n
).x
, inner
(n
).y
), clrwht
doouter:
IF outer
(n
).radius
> 150 THEN 'put back in center
outer
(n
).radius
= INT(RND * 150) + 30
outer
(n
).angle
= INT(RND * 360)
outer(n).speed = 1
IF outer
(n
).radius
> 35 THEN outer
(n
).speed
= 2
IF outer
(n
).radius
> 45 THEN outer
(n
).speed
= 4
IF outer
(n
).radius
> 75 THEN outer
(n
).speed
= 6
outer(n).radius = outer(n).radius + outer(n).speed
outer(n).x = centx + outer(n).radius * (cosine(outer(n).angle))
outer(n).y = centy - outer(n).radius * (sine(outer(n).angle))
doinner:
IF inner
(n
).radius
> 150 THEN 'put back in center
inner
(n
).radius
= INT(RND * 40)
inner
(n
).angle
= INT(RND * 360)
inner(n).speed = 3
IF inner
(n
).radius
> 15 THEN inner
(n
).speed
= 4
IF inner
(n
).radius
> 45 THEN inner
(n
).speed
= 8
IF inner
(n
).radius
> 75 THEN inner
(n
).speed
= 10
inner(n).radius = inner(n).radius + inner(n).speed
inner(n).x = centx + inner(n).radius * (cosine(inner(n).angle))
inner(n).y = centy - inner(n).radius * (sine(inner(n).angle))