Code from Le Paint Petite (1993)
In most programs we've seen aimed at kids, any old "throw some random white pixels on a black window and call it done" algorithm is used. The result looks like a bunch of random dots on black. But it doesn't look like a night sky, and kids know this.
When coding Le Paint Petite, we knew that stars don't appear purely at random in the sky. There's a hint of pattern. We live somewhere on a spiral arm, and when we see the sky, we can look at the center of the galaxy. We see bands of stars, including the Milky Way. Heavier concentrations of stars appear depending on where you look. There is some order, and we can see it.
The algorithm below paints stars in the sky and concentrates these somewhat in bands. Sometimes the bands are narrow and very populated. Sometimes they are sparse. And they look realistic. They don't look like a bunch of random dots on a black window. They look like stars at night. When creating games or other programs that are supposed to simulate something natural, pure randomness conveys an artificial feel. Adding some amount of order creates a more natural look. Using this code as a starting point, you can easily add the effects of clouds and weather via coding to come up with scenery that looks and feels "right." But the background star pattern has to be right first.
The Star Drawing Algorithm
// Draw a black sky in hwnd and put in a starfield of white stars.
void StarryNite(HWND hwnd, HPALETTE currentpal, COLORREF white,
COLORREF black, int hmax, int vmax)
{
HDC hdc;
HPALETTE oldpal;
HPEN hPen, oldpen;
HBRUSH hBrush, oldbrush;
int i, j, k, wherex, wherey, spiralx, spiraly,
spiralpoints, numarms, numstars;
#define STARMAX 1000
hdc = GetDC(hwnd);
oldpal = SelectPalette(hdc, currentpal, FALSE);
RealizePalette(hdc);
// Paint a black sky.
// If you want to simulate ground light pollution, add some
// blues near the horizon and dither into black.
hBrush = CreateSolidBrush(black);
oldbrush = SelectObject(hdc,hBrush);
hPen = CreatePen(PS_SOLID,1,black);
oldpen = SelectObject(hdc,hPen);
Rectangle(hdc,0,0,hmax,vmax);
// restore the drawing objects used
SelectObject(hdc,oldpen);
SelectObject(hdc,oldbrush);
// Draw some background stars. These are our nearest neighbours.
numstars = random(STARMAX) + (STARMAX / 2);
for(i = 0; i < numstars; i++)
SetPixel(hdc,random(hmax),random(vmax),white | 0x2000000L);
// Now draw some spiral arms...
numarms = random(10) + 1;
for(k = 0; k < numarms; k++){
spiralx = random(50) + 30; // x distance
spiralpoints = random(20) + 10; // number of points in the spiral
spiraly = random(60) + 3; // y deviation
if((spiraly % 2) == 0) spiraly *= -1; // randomly make pos or neg
wherex = 0; // start x point
wherey = random(vmax); // start y point
for(i = 0; i < spiralpoints; i++){ // for every point on the spiral
numstars = random(70);
for(j = 0; j < numstars; j++) // draw NUMSTARS random points
SetPixel(hdc,wherex + random(200),
wherey + random(200),
white | 0x2000000L);
wherex += spiralx;
wherey += spiraly;
if(spiraly >= 0) spiraly -= (spiraly / 3);
}
} // k (number of spiral arms)
// Now create a few bright suns, because some stars are nearer
// and/or brighter.
numarms = random(numarms * 5);
for(i = 0; i < numarms; i++){
spiralx = random(hmax);
spiraly = random(vmax);
SetPixel(hdc, spiralx, spiraly, white | 0x2000000L);
SetPixel(hdc, spiralx + 1, spiraly, white | 0x2000000L);
SetPixel(hdc, spiralx, spiraly + 1, white | 0x2000000L);
SetPixel(hdc, spiralx + 1, spiraly + 1, white | 0x2000000L);
}
// clean up and exit
SelectPalette(hdc, oldpal, TRUE);
ReleaseDC(hwnd,hdc);
DeleteObject(hBrush);
DeleteObject(hPen);
}