Now that you made a starfield you probably noticed the stars (pixels) are more or less invisible when flying fast. That's because they skip a large distance depending on the speed value.
If you ever played a space game you surely know what the solution is: lines instead of single pixels. But does this work with our concept? Well, yes it does! We're going to use the API again to draw lines and the rest is fairly easy.
Ludicrous speed I say!
Similar to SetPixel the Win32 API also provides a LineTo function. Unfortunately it comes without a color parameter and the only way to set the line color is creating a pen and brush. I don't know why Microsoft made this a pain in the ass but here's a little wrapper function that does the work for you. You can use it to draw lines without worrying about the API stuff behind it.
Here's the neccessary API declares:
'Types Public Type tPoint x as Long y as Long End Type 'Functions Public Declare Function LineTo Lib "gdi32" ( ByVal iDC as Long, ByVal x as Long, ByVal y as Long ) as Long Public Declare Function MoveToEx Lib "gdi32" ( ByVal iDC as Long, ByVal x as Long, ByVal y as Long, _ iPoint as tPoint ) as Long Public Declare Function DeleteObject Lib "gdi32" ( ByVal iObject as Long ) as Long Public Declare Function SelectObject Lib "gdi32" ( ByVal iDC as Long, ByVal iObject as Long ) as Long Public Declare Function CreateSolidBrush Lib "gdi32" ( ByVal iColor as Long ) as Long Public Declare Function CreatePen Lib "gdi32" ( ByVal iStyle as Long, ByVal iWidth as Long, _ ByVal iColor as Long ) as Long
And here's the function:
Public Function DrawLine( DC as Long, x1 as Long, y1 as Long, x2 as Long, y2 as Long, iColor as Long ) Dim Pen as Long Dim Brush as Long Dim OldPen as Long Dim OldBrush as Long Dim TempPos as tPoint 'Create pen Pen = CreatePen( 0, 1, iColor ) OldPen = SelectObject( DC, Pen ) 'Create brush Brush = CreateSolidBrush( iColor ) OldBrush = SelectObject( DC, Brush ) 'Draw line MoveToEx DC, x1, y1, TempPos LineTo DC, x2, y2 'Restore brush SelectObject DC, OldBrush DeleteObject Brush 'Restore pen SelectObject DC, OldPen DeleteObject Pen End Function
If you had a look at the 3rd example from the last page you'll surely remember the function - in fact it's the same except we have no size property but a second pair of coordinates instead. That's because this time we truly want to draw lines and not just bigger points.
Yet we just calculated the current point's position from .x / .z and .y / .z but now we need 2 points to draw the lines. Well let's think about what happens between two frames; the MoveStars function is called and it subtracts Speed from each z-value. So basically we can just add Speed again to get the position of a point in the last frame. And that's exactly what we're going to do now:
Public Sub DrawStars( DC as Long ) Dim A as Long Dim FromPos as tPoint Dim ToPos as tPoint Dim Brightness as Single For A = 0 To StarCount With Star( A ) 'Get start point FromPos.x = ( .x / .z ) + OffsetX FromPos.y = ( .y / .z ) + OffsetY 'Get end point (adding speed to the .z value) ToPos.x = ( .x / ( .z + Speed ) ) + OffsetX ToPos.y = ( .y / ( .z + Speed ) ) + OffsetY 'Get brightness from distance (here ^2 just smooths the fading of darker stars) Brightness = ( 1 - ( .z / SpreadZ ) ) ^ 2 * 255 'Draw the line DrawLine DC, FromPos.x, FromPos.y, ToPos.x, ToPos.y, RGB( Brightness * 1, Brightness * 0.8, Brightness * 0.4 ) End With Next End Sub
As you can see this is nothing too fancy. To make the code clear I used the FromPos and ToPos variables to store the positions of both points. For a minor speed gain you can put those 4 formulas directly into the DrawLine call.
If you're coming straight from the first starfield tutorial you'll notice two new things here: The ^2 statement in the Brightness calculation and the multipliers within the RGB() function. Both are easy to explain: Since the Brightness is calculated as a value between 0 and 1 we can use any exponent to tween the results. Try using ^3 or higher to clearly see the effect; the higher the value is the longer the stars stay dark. This makes them appear more smoothly but on the other hand you'll need more stars to fill up the screen. Talking about speed vs. quality here; as always in graphics programming.
The second thing is nothing more than a tint value, I used some kind of yellow in the example. If you prefer white stars you can leave it out, if you want blue stars use 0 / 0 / 1 as the multipliers.
Hard to believe but we're done already. Now the starfield shows up more clearly because the stars are stretched to lines depending on the Speed value. The higher the speed is, the bigger the skipping distance between two frames is and thus the longer the lines are. As on the last page the second download is a little advanced, showing how to combine the lines with a background picture. Nothing that'd need further explanation though.