' =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
'									3D Starfield
'
'									The Flipside
'
' =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Declare Sub GenerateStar(index As Integer)

Const MAX_STARS = 500
Const SCRN_WIDTH = 320
Const SCRN_HEIGHT = 200
Const SPEED = 0.015      ' Adjust for different speed

Type Point3D
	x As Integer
	y As Integer
	z As Integer
End Type

Type Point2D
	x As Integer
	y As Integer
End Type

Dim shared Star(0 To (MAX_STARS - 1)) As Point3D
Dim p2d(0 To (MAX_STARS - 1)) As Point2D

Dim i As Integer
Dim Scale As Integer
Dim OldTime As double
Dim TimeDummy As double

' Initialize starfield and variables 
Randomize Timer					' Random seed
For i = 0 To (MAX_STARS - 1)
	GenerateStar(i)				' Create stars!!!
Next

Scale = 256					    ' Perspective

' =-=-=-=-=-= Main Loop =-=-=-=-=-=
Screen 13 ' Screen mode 13, change if you like but don't forget the constants!

Do While Inkey <> Chr(27) ' Loop until esc is pressed
	
	For i = 0 To (MAX_STARS - 1)
		' Delete old star
		PSet (p2d(i).x, p2d(i).y), 0 ' draw a black pixel on old position
		
		' Transformation from 3D to 2D
		' Origin lies in the middle of the screen
		p2d(i).x = star(i).x * Scale / star(i).z + (SCRN_WIDTH / 2)
		p2d(i).y = star(i).y * Scale / star(i).z + (SCRN_HEIGHT / 2)
		
		' Draw star
		PSet (p2d(i).x, p2d(i).y), 15
		
		' reduce z and check if z > 0 (no division by zero)
		star(i).z = star(i).z - 1
	
		If Star(i).z <= 0 Then ' star has passed us, lets create a new one
			GenerateStar(i)
		EndIf 	
			
	Next		
	
	' Some timing code to reduce the speed of the starfield
	' Waiting time = SPEED seconds
	OldTime = Timer
	Do
		TimeDummy = Timer
        SLEEP 1
		' Does nothing but wait. (Old QB way of timing im always using)
		' I know there are better ways, but this works
	Loop Until (TimeDummy - OldTime) >= SPEED 
	
Loop 


Sub GenerateStar(index As Integer)

	' The origin of the screen lies at the middle of the screen.
	' So in case of screen 13 the possible screen coordinates are:
	' -160 to 160, -100 to 100
	' This procedure divides the stars array in four and assign every
	' screen quadrant with it. Sounds complicated?
	' Look at it this way: 
	' The first IF puts one fourth of MAX_STARS in the box constaining
	' the coordinates (0, 0), (100, 160)
	' Then the ElseIf puts stars in the box containing the coordinates
	' (0, 0), (-160, 100)
	' And so on! Get it already???
	' If not change the signs before the (SCRN_WIDTH / 2) or (SCRN_HEIGTH / 2)
	' and see what happens!  
	
	If index < (MAX_STARS / 4) THEN
		Star(index).x = Rnd(1) * (SCRN_WIDTH / 2) + 1
		Star(index).y = Rnd(1) * (SCRN_HEIGHT / 2) + 1 
	ElseIf (index > (MAX_STARS / 4)) And (index < (MAX_STARS / 2)) Then
		Star(index).x = Rnd(1) * -(SCRN_WIDTH / 2) + 1
		Star(index).y = Rnd(1) * (SCRN_HEIGHT / 2) + 1
	ElseIf (index > (MAX_STARS / 2)) And (index < (3 * MAX_STARS / 4)) Then
		Star(index).x = Rnd(1) * (SCRN_WIDTH / 2) + 1
		Star(index).y = Rnd(1) * -(SCRN_HEIGHT / 2) + 1
	ElseIf (index > (3 * MAX_STARS / 4)) And (index < MAX_STARS) Then
		Star(index).x = Rnd(1) * -(SCRN_WIDTH / 2) + 1
		Star(index).y = Rnd(1) * -(SCRN_HEIGHT / 2) + 1
	EndIf			
	Star(index).z = Rnd(1) * 256
		
End Sub


