Pragt.info
Partner site van: www.heinpragt.com
(c) Hein Pragt
logo pragt.info
Zoeken op deze site!
 
 

Starfield programma's en broncode in C
© 2010 Hein Pragt

starfield Een klassiek stukje grafische code is een starfield demo. Het wekt de suggestie dat u door de ruimte vliegt en de sterren op u afkomen en u aan alle zijden passeren. Sterren die ver weg zijn zullen kleiner zijn en ze moeten groter worden als ze de camera (onze kijk positie) naderen. Voor de helderheid geldt hetzelfde, sterren die verder van ons vandaan zijn hebben een minder heldere kleur dan sterren die dichtbij zijn. Dit wekt de indruk dat de sterren echt op ons afkomen.

Voor de sterren gebruiken we een structure waarin we de eigenschappen van de ster opslaan. Dat zijn de x, y en z positie als float, een 3d coordinaat in de wiskunde, waarmee we de positie horizontaal, verticaal en in de diepte opslaan. Een groter z positie betekend dus dat het voorwerp ver van ons verwijderd is (in dit wiskundig model) en de grootte en helderheid kunnen we dan ook berekenen uit de (z) afstand. Verder slaan we deze vector (x,y,z) ook op als int waarbij ze omgerekend zijn naar een punt op het beeldscherm. Dit is eenvoudig te doen als we toch aan het rekenen zijn en scheelt weer tijd als we de punten willen schrijven in het venster.

Omdat het om vrij universele code gaat heb ik de Windows Win32 interface zo minimaal mogelijk gemaakt, dit is trouwens altijd mijn voorkeur om programma’s zo portable mogelijk te maken en niet te afhankelijk te zijn van het besturingssysteem.


// ------------------------------------
// Win32 Demo  Starfield
// (c) 2010 Hein Pragt
// ------------------------------------

#include <windows.h>
#include <windowsx.h>
#include <stdlib.h>

// Interface to windows
void PlotPixel(int x, int y, int r, int g, int b);

// -------------------------------------------------------------
// This is our starfield code
// -------------------------------------------------------------

struct t_stars {
  float x;
  float y;
  float z;
  int   sx;
  int   sy;
  int   sz;
} stars[300];

int   sWidth, sHeight; 
DWORD nStartTime; 

void DeleteStars(void); 
void DrawStar(int x, int y, int z, int color); 
void InitStars(int WinWidth, int WinHeight);
void GameLoop(void);
void MoveStars(void); 
void PlotStars(void); 

// ---------------------------------------
// Call this before at init of the app
// ---------------------------------------

void InitStars(int WinWidth, int WinHeight) 
{ 
int a; 

  sWidth = WinWidth;
  sHeight = WinHeight;
  nStartTime = GetTickCount(); 
  srand(GetTickCount());  // Random seed
  for (a=0; a<300; a++) { 
    stars[a].x = (float)(rand()%70 - 35); 
    stars[a].y = (float)(rand()%70 - 35); 
    stars[a].z = (float)(rand()%100 + 1); 
  } 
} 

// ---------------------------------------
// Call this to keep the engine running
// ---------------------------------------

void GameLoop()
{
  if ((GetTickCount() - nStartTime) < 33) {
    Sleep(1);
    return; // Wait for next frame
  }
  nStartTime = GetTickCount(); 
  DeleteStars(); 
  MoveStars(); 
  PlotStars(); 
}

// ---------------------------------------
// Delete alle stars from screen
// ---------------------------------------

void DeleteStars(void) 
{ 
int a; 

for (a=0; a<300; a++) 
  DrawStar(stars[a].sx, stars[a].sy, stars[a].sz, 0); 
} 

// ---------------------------------------
// Plot alle stars on screen
// ---------------------------------------

void PlotStars(void) 
{ 
int a, col; 

  for (a=0; a<300; a++) { 
    col = 255 - (int)(stars[a].sz * 2); 
    DrawStar(stars[a].sx, stars[a].sy, stars[a].sz, col); 
  } 
} 

// ---------------------------------------
// Plot single star on screen
// ---------------------------------------

void DrawStar(int x, int y, int z, int color) 
{ 
int a, b, max; 

  max = 3 - (int)(z/33);     // size based on distance from camera 
  for (a=0; a<max; a++) 
    for (b=0; b<max; b++) 
      PlotPixel(x+a, y+b, color, color, color);
} 

// ---------------------------------------
// Calculate new position of starts
// ---------------------------------------

void MoveStars(void) 
{ 
int a; 

  for (a=0; a<300; a++) { 
    stars[a].z -= 3; 
    if (stars[a].z <= 0) { 
      // re-initialize if too close 
      stars[a].x = (float)(rand()%70 - 35); 
      stars[a].y = (float)(rand()%70 - 35); 
      stars[a].z += 100; 
    } 
    // Simple perspective transformation from 3D to 2D: 
    // x2D = x3D / z3D * (screen width) + (half of screen width) 
    // y2D = y3D / z3D * (screen height) + (half of screen height) 
    stars[a].sx = (stars[a].x / stars[a].z) * sWidth + (sWidth >> 1); 
    stars[a].sy = (stars[a].y / stars[a].z) * sHeight + (sHeight >> 1);
    stars[a].sz = (int) stars[a].z; 
  } 
} 



// ---------------------------------------------
// The minimal Window interface code
// ---------------------------------------------

#define WIN_CLASS_NAME "MyGraphClass" 

HDC hMainDC; 
HINSTANCE hInstance; 
HWND hWnd; 

int WinWidth = 500;
int WinHeight = 500; 

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); 


int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) 
{ 
WNDCLASSEX winclass;
HWND hwnd;
MSG msg;

  winclass.cbSize = sizeof(WNDCLASSEX); 
  winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; 
  winclass.lpfnWndProc = WindowProc; 
  winclass.cbClsExtra = 0; 
  winclass.cbWndExtra = 0; 
  winclass.hInstance = hinstance;  
  winclass.hIcon = LoadIcon(NULL, IDI_WINLOGO); 
  winclass.hCursor = LoadCursor(NULL, IDC_ARROW); 
  winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 
  winclass.lpszMenuName = NULL; // no menu 
  winclass.lpszClassName = (LPCWSTR) WIN_CLASS_NAME; 
  winclass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); 

  if (!RegisterClassEx(&winclass)) 
    return(0); 

  if (!(hwnd = CreateWindowEx(NULL,  
    WIN_CLASS_NAME, // class identifier 
    TEXT("Demo"), // window title 
    WS_OVERLAPPEDWINDOW | WS_VISIBLE, // parameters 
    CW_USEDEFAULT, CW_USEDEFAULT, // initial position 
    WinWidth, WinHeight, // Window size 
    NULL, // handle to parent
    NULL, // handle to menu 
    hinstance, // app handle 
    NULL)))
    return(0); 

  // Copy to globals 
  hWnd = hwnd; 
  hInstance = hinstance; 
  hMainDC = GetDC(hWnd); 

  InitStars(WinWidth, WinHeight); 

  while(TRUE) { 
    if (PeekMessage(&msg,0,0,0,PM_REMOVE)) { 
      if (msg.message == WM_QUIT) // exit loop on quit 
        break; 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
    } 
    GameLoop(); // keep animation running
  } 
  ReleaseDC(hWnd, hMainDC); 
  return(msg.wParam); 
} 

// ---------------------------------------------
// The minimal Window message handler
// ---------------------------------------------

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg,WPARAM wparam, LPARAM lparam) 
{ 
  switch(msg) { 
  case WM_DESTROY: 
    PostQuitMessage(0); 
    return(0); 
    break; 
  case WM_CLOSE: 
    break; 
  } 
  return(DefWindowProc(hwnd, msg, wparam, lparam)); 
} 

// ---------------------------------------------
// The plot pixel function
// ---------------------------------------------

void PlotPixel(int x, int y, int r, int g, int b)
{
  SetPixel(hMainDC, x, y, RGB(r, g, b));
}




Last update: 06-04-2010
 

Disclaimer.

Hoewel de heer Hein Pragt de informatie beschikbaar op deze pagina met grote zorg samenstelt, sluit de heer Pragt alle aansprakelijkheid uit met betrekking tot de informatie die, in welke vorm dan ook, via deze site wordt aangeboden. Het opnemen van een afbeelding of verwijzing is uitsluitend bedoeld als een mogelijke bron van informatie voor de bezoeker en mag op generlei wijze als instemming, goedkeuring of afkeuring worden uitgelegd, noch kunnen daaraan rechten worden ontleend.
Op de artikelen van de heer Pragt op deze Internet Site rust auteursrecht. Overname van informatie (tekst en afbeeldingen) is uitsluitend toegestaan na voorafgaande schriftelijke toestemming van de rechthebbende. Voor vragen over copyright en het gebruik van de informatie op deze site kunt u contact opnemen met: (email: copyright@heinpragt.com)

Webdedesign: © Hein Pragt
Fotografie: © Hein Pragt
Auteur: © Hein Pragt

Privacy beleid
Wij maken gebruik van externe advertentiebedrijven om advertenties weer te geven wanneer u onze website bezoekt. Deze bedrijven gebruiken mogelijk informatie (niet uw naam, adres, e-mailadres of telefoonnummer) over uw bezoek aan deze of aan andere websites om advertenties weer te geven over goederen en services waarin u wellicht geďnteresseerd bent. Als u hierover meer informatie wenst of als u wilt voorkomen dat deze bedrijven deze informatie gebruiken, klikt u op deze link.