| |
| Starfield programma's en broncode in C |
© 2010 Hein Pragt
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 programmas 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
|
Wilt u deze site steunen dan kunt u dit doen door VIA deze site iets te bestellen op:

Programmeren
|