04.03 - Pixel Manipulation

Started by
47 comments, last by Teej 22 years, 4 months ago
Got a bit carried away with this one, but once I started, I couldn't stop! Far too many angles and radii to keep track of...

Thanks for the tutorial, Teej, this is by far the best on the net. THANKS!

      void Game_Main(){    WORD *buffer;    long lPitch;    DDBLTFX ddbltfx;    ZeroMemory(&ddbltfx, sizeof(ddbltfx));    ddbltfx.dwSize = sizeof(ddbltfx);    // fill with black      ddbltfx.dwFillColor = 0;      G.lpDDSBack->Blt(NULL,NULL,NULL,                     DDBLT_COLORFILL | DDBLT_WAIT,                     &ddbltfx);        DDSURFACEDESC2 ddsd;    ZeroMemory(&ddsd, sizeof(ddsd));    ddsd.dwSize = sizeof(ddsd);    	// lock surface    G.lpDDSBack->Lock(NULL, &ddsd,                          DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,                          NULL);    buffer = (WORD *)ddsd.lpSurface;    lPitch = ddsd.lPitch/2;    	double theta,angle;	static double firsttheta=0,bigtheta=0;	int x,y,r;	static int radius=1;	// radius of coloured circles	double xcentre;		// centre coords of each coloured  	double ycentre;		// circle	WORD colour;	double tempblue, tempred;	int green, red, blue;	static int flag=0;		// draw three circles 120 degrees apart	for (angle=bigtheta; angle<360+bigtheta; angle=angle+120)	{		// calculate centre coords of each circle 		xcentre=(100*cos(angle*(3.141/180)))+(SCREEN_WIDTH/2);		ycentre=(100*sin(angle*(3.141/180)))+(SCREEN_HEIGHT/2);		green=63;		tempblue=tempred=31;		// draw green section of each coloured circle		for (theta=firsttheta+60; theta>firsttheta-1; theta--)		{			colour=RGB16(0, green, 0);				for (r=-radius; r<radius+1; r++)				{				x=(int) ((r*cos((3.141/180)*theta)) + xcentre);				y=(int) ((r*sin((3.141/180)*theta)) + ycentre);				buffer[y*lPitch + x]=colour;				}			// darken green by 1 step every degree			green=green-1;		}		// draw red section of each coloured circle		for (theta=firsttheta+180; theta>(firsttheta+120)-1; theta--)		{			colour=RGB16(red, 0, 0);				for (r=-radius; r<radius+1; r++)				{				x=(int) ((r*cos((3.141/180)*theta)) + xcentre);				y=(int) ((r*sin((3.141/180)*theta)) + ycentre);				buffer[y*lPitch + x]=colour;			}			// darken red by 1 step every 2 degrees			tempred=tempred-0.5;			red=(int)tempred;		}		// draw blue section of each coloured circle		for (theta=firsttheta+300; theta>(firsttheta+240)-1; theta--)		{			colour=RGB16(0, 0, blue);				for (r=-radius; r<radius+1; r++)				{				x=(int) ((r*cos((3.141/180)*theta)) + xcentre);				y=(int) ((r*sin((3.141/180)*theta)) + ycentre);				buffer[y*lPitch + x]=colour;				}            // darken blue by 1 step every 2 degrees			tempblue=tempblue-0.5;			blue=int(tempblue);		}	}			firsttheta++;   // rotate circles clockwise	bigtheta--;     // rotate entire thing anti-clockwise	if (radius>50) flag=1; // maximum radius for each circle, set flag to begin			       // radius decrease		if (flag==0)	radius++;	else	radius--;	if (radius<1)          // minimum radius for each circle, set radius to 1 and	{		       // set flag to begin radius increase		radius=1;		flag=0;	}		// unlock the surface again    G.lpDDSBack->Unlock(NULL);     // flip backbuffer to primary    G.lpDDSPrimary->Flip(NULL, 0);}    


Edited by - mirrorman on June 14, 2001 4:19:28 PM

Edited by - mirrorman on June 14, 2001 4:24:26 PM
Advertisement
More fractal fun: this time with the Mandelbrot set.

NOTE: This code requires a SCREEN_BITDEPTH of 8,
and it only looks good if you load a palette that is
like a gradient.

   #define OUTER_BOUND (double)1000.0 void Game_Main(){	static int xLoc = 0;	static int yLoc = 0;	static double cx = -2.5;	static double cy = 1.5;	double zx = 0.0;	double zy = 0.0;	// so it doesn't try to keep calculating	if(yLoc > SCREEN_HEIGHT) return;	for(int i = 0; i < 256; i++)	{		double oldZX = zx;		zx = (zx*zx) - (zy*zy) + cx;		zy = (2*oldZX*zy) + cy;		if( (sqrt( zx*zx + zy*zy )) > OUTER_BOUND)			break;	}	DDSURFACEDESC2 ddsd;	UCHAR *buffer; 	long lPitch;  	// Prepare a DDSURFACEDESC2 structure for Lock() 	ZeroMemory(&ddsd, sizeof(ddsd));	ddsd.dwSize = sizeof(ddsd);	// Lock the backbuffer surface	G.lpDDSPrimary->Lock(NULL, &ddsd,				 DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);  	// Get the surface pointer and the memory pitch (in WORDs)	buffer = (UCHAR *)ddsd.lpSurface;	lPitch = ddsd.lPitch;	// Draw onto the display 	buffer[yLoc*lPitch + xLoc] = i;		  	// Unlock the surface 	G.lpDDSPrimary->Unlock(NULL);		xLoc++;	if(xLoc > SCREEN_WIDTH)	{		xLoc = 0;		cx = -2.5;		yLoc++;		cy -= (double)3/SCREEN_HEIGHT;	}	else	{		cx += (double)4/SCREEN_WIDTH;	}}    




Edited by - FragLegs on June 19, 2001 2:09:56 PM
Hey- well I also got this working using directx3 on win nt.... was more difficult this time- had to use directdrawsurface2- because the lock funtion isnt in the first- that was easy enough- but I had to do a query interface- which I have no idea why

hRet = G.lpDD->CreateSurface(&ddsd, &G.lpDDSPrimary1, NULL);
hRet = G.lpDDSPrimary1->QueryInterface(IID_IDirectDrawSurface2, (LPVOID *)&G.lpDDSPrimary);


why is this??? why can''t i just use the 2nd implementiation directly????
Hey All

Well here''s my assignment, hehe (how far behind the class am I haha????). Its inspired by the "Symphony of Lights" going on here right now- its an annual international fireworks contest held ever summer in Engish Bay Vancouver. It has noise, diagonal lines, a breast stroke thingee going from (0,0) to (640,480), waves and pulsating bursts (well-not really the last thing). LOL,it all looks kindof weird and the pyrotechnicians would laugh but I''m still proud of it!! And also- please- don''t laugh at my programming hehe.

2 things bugging me:
1)Diagonal lines- how to get rid of the dashed effect at certian angles?????? Is this a result of converting to an integer grid???
2)Random Noise: I ended up having to get both a random x pixel and a random y pixel. Why doesn''t
rpStars=(rand()%100)*tp/100;
buffer[rpStars] = RGB16(31,63,31)
work??????? Can''t figure it out.

Id be curious to know how this runs on a faster computer than mine... no timers in the program.

Thanx and if you look at it, get ready for a good laugh hahaha!!


************************************************************

void Game_Main(){

DDSURFACEDESC ddsd;
WORD *buffer;
long lPitch;

// Prepare a DDSURFACEDESC structure for Lock()
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
G.lpDDSBack->Lock(NULL, &ddsd,DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
// Get the surface pointer and the memory pitch (in WORDs) (bytes / 2 = WORDs)
buffer = (WORD *)ddsd.lpSurface;
lPitch = ddsd.lPitch / 2;


const long int tp=lPitch*SCREEN_HEIGHT + SCREEN_WIDTH;
const long int cp=tp/2;
static WORD color, color2;
int x, y,z;
const double mypi=3.14159265358;


// basic background
const WORD color_background=RGB16(0,0,0);
for (y = 0; y < SCREEN_HEIGHT; y++){
for (x = 0; x < SCREEN_WIDTH; x++){
buffer[y * lPitch + x] = color_background;
}}


//bug************************************************************
const int lBug=50, hBug=5, dyBug=40, sBug=15;
int xBug,yBug;
static int phaseBug=1, countBug;
const WORD color_bug=RGB16(20,20,20);
const WORD color_bug2=RGB16(31,63,31);
static long int pixelBug=dyBug*lPitch+lBug;
static int yPrevious, yCurrent;
countBug++;
if (countBug>15){
countBug=0;
phaseBug=!phaseBug;
}
pixelBug +=sBug;
yCurrent=pixelBug/lPitch;
if (yCurrent>yPrevious) {
yCurrent +=dyBug;
pixelBug=pixelBug+dyBug*lPitch;
}
yPrevious=yCurrent;
if ((pixelBug+2*hBug*lPitch+2*lBug)>=tp) {
pixelBug=dyBug*lPitch+lBug;
yCurrent=0;
}
for (xBug=-lBug*phaseBug/2;xBug<(lBug+lBug*phaseBug/2);xBug++){
if (yCurrent==(pixelBug+xBug)/lPitch){
for (yBug=-hBug;yBug buffer[pixelBug+xBug+ yBug*lPitch] = color_bug;
}
}
}
if (phaseBug==0){
for (xBug=0;xBug if (yCurrent==(pixelBug+xBug)/lPitch){
for (yBug=-2*hBug;yBug<-hBug;yBug++){
buffer[pixelBug+xBug+ yBug*lPitch] = color_bug;
}
for (yBug=2*hBug;yBug buffer[pixelBug+xBug+ yBug*lPitch] = color_bug;
}
}
}
}


//diagonals*******************************************************
const WORD cTrail=RGB16(31,63,31);
const WORD cTip=RGB16(31,0,0);
const int szTip=4;
static int rDiagonal;
rDiagonal +=4;
int wTip, hTip;
double rad, theta0=0,fDiag;
const double dtheta=3.14159265358/6.0;
double ymax, xmax;
int rCurrent;

for (fDiag=1.0;fDiag>0.01; fDiag -=0.33){

rCurrent=(int)(fDiag*rDiagonal);
for (rad=theta0;rad<=theta0+3.14159265358;rad +=dtheta){
ymax=rCurrent*sin(rad);
xmax=rCurrent*cos(rad);
for (y=0;y<(long int)ymax;y++){
x=(long int)xmax*y/(long int)ymax;
buffer[cp+y * lPitch + x ] = cTrail;
buffer[cp-y * lPitch + x ] = cTrail;
}
if (y!=0){
for (hTip=-szTip;hTip<=szTip; hTip++){
for (wTip=-szTip;wTip<=szTip; wTip++){
buffer[cp+(y+hTip)* lPitch + x+wTip ] = cTip;
buffer[cp-(y+hTip)* lPitch + x+wTip ] = cTip;
}}
}
}
for (x=-rCurrent;x<=rCurrent;x++){
buffer[cp+ x ] = cTrail;
}
for (hTip=-szTip;hTip<=szTip; hTip++){
for (wTip=-szTip;wTip<=szTip; wTip++){
buffer[cp+(hTip*lPitch)+rCurrent+wTip ] = cTip;
buffer[cp-(hTip*lPitch)-rCurrent+wTip ] = cTip;
}}

theta0 +=0.314159265358;

}
if (rDiagonal>SCREEN_HEIGHT/2-10) rDiagonal=0;




//Noise*******************************************************
long int iPixel;
const long int nPixels=tp/100;
srand( (unsigned)timeGetTime() );
for (iPixel=0;iPixel<=nPixels;iPixel++){
x=rand()%SCREEN_WIDTH;
y=rand()%SCREEN_HEIGHT;
buffer[y*lPitch+x] = RGB16(31,63,31);
//I don''t know why, but the foloowing produced constant diagonal lines:
//I''d prefer to use it: needs only one rand() call versus 2
//rpStars=(rand()%100)*tp/100;
//buffer[rpStars] = RGB16(31,63,31);
}


//random circle*****************************************************
int rCircle, ymaxCircle;
long int pixelCircle;
static int rp1, kCircle;
static WORD color_circle;
const int kCircleMax=50;
kCircle +=2;
if (kCircle==2) rp1=tp*(rand()%100)/100;
for (rCircle = 0; rCircle <=kCircle; rCircle++) {
for (x = -rCircle; x <=rCircle; x++) {
ymaxCircle=(long int)sqrt(rCircle*rCircle-x*x);
for (y = -ymaxCircle; y <=ymaxCircle; y++) {
if ( rand()%kCircleMax> 0.95*kCircle){
pixelCircle=rp1+ y* lPitch + x;
if ( (tp>pixelCircle) && (pixelCircle>0) ) {
buffer[pixelCircle] = color_circle;
}
}
}
}
}
if (kCircle>kCircleMax) {
kCircle=0;
color_circle=RGB16(rand()%32, rand()%64, rand()%32);
}




//waves******************************************************
const WORD color_water=RGB16(0,0,31);
const WORD color_boat=RGB16(31,63,0);
const int amp=20, szShip=10;
const int y0wave=SCREEN_HEIGHT-50;
const int waveSpeed=2;
static int x0wave;
int dxShip, dyShip;

y=y0wave+(long int)(amp*cos(x0wave*20*mypi/SCREEN_WIDTH));
for (dyShip=-3*szShip;dyShip<=szShip;dyShip++){
for (dxShip=-szShip;dxShip<=szShip;dxShip++){
buffer[(y+dyShip) * lPitch + x0wave+dxShip]=color_boat;
}}
for (x = x0wave; x <=SCREEN_WIDTH+x0wave; x++) {
y=y0wave+(long int)(amp*cos(x*10*mypi/SCREEN_WIDTH));
buffer[y * lPitch + (x-x0wave)]=color_water;
for (z=y;z buffer[z * lPitch + (x-x0wave)]=color_water;
}
}
x0wave=x0wave+waveSpeed;
if (x0wave>SCREEN_WIDTH) x0wave=0;




// Unlock the surface
G.lpDDSBack->Unlock(NULL);
// Flip the surfaces
G.lpDDSPrimary->Flip(NULL, 0);
}


// GameMain.cpp - End of file

Hi, can someone tell me how to plot pixels? I don''t know if the function is already in directx or if we have to make it ourselves. If we do have to make it ourselves, can someone give me a short example on how?
Thanks

SEZ
-darkcoder8
Teej, thanks a lot. "You rock my world dude."
I have some ''work'' to post, so here is another snow falling ''animation''. On this ''animation'' when the snow hits the ground it stays there, and accumulates until hitting the top screen line, I hope you like it. Also, it has three (3) diferent falling speeds, trying to give an idea of depth.

Put these defines on top of GameMain.cpp file
#define SNOW_FLAKES 250
#define MAX_SPEED 3
#define START_SNOW_HEIGHT 2


Replace your Game_Main() function with these one
void Game_Main()
{
DDSURFACEDESC2 ddsd;
WORD *buffer;
long lPitch;

struct SnowFlake
{
int pos_x;
int pos_y;
int fall_speed;
};

// Prepare a DDSURFACEDESC2 structure for Lock()
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);

EraseBackground();

// Lock the backbuffer surface
G.lpDDSBack->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);

// Get the surface pointer and the memory pitch (in WORDs)
buffer = (WORD *)ddsd.lpSurface;
lPitch = ddsd.lPitch / 2;

static SnowFlake falling_snow[SNOW_FLAKES];
static int ground_snow[SCREEN_WIDTH];
static bool first = true;

//run only once, for initializing the variables
if(first)
{
// Init the array of flakes with their current position and falling speed
for(int i = 0; i < SNOW_FLAKES ; i++)
{
falling_snow.pos_x = rand()%SCREEN_WIDTH;
falling_snow.pos_y = rand()%SCREEN_HEIGHT;<br> falling_snow.fall_speed = 1 + rand()%MAX_SPEED;<br> }<br> // Init the array that keeps track of the height of the snow on the floor<br> for(int j = 0 ; j < SCREEN_WIDTH ; j++)<br> ground_snow[j] = SCREEN_HEIGHT - START_SNOW_HEIGHT;<br> <br> first = false;<br> }<br> <br> // paints falling snow flakes and updates their positions.<br> for(int i = 0 ; i < SNOW_FLAKES ; i++)<br> {<br> buffer[falling_snow.pos_y * lPitch + falling_snow.pos_x] = RGB16(31,63,31);<br> <br> falling_snow.pos_y += falling_snow.fall_speed;<br> <br> // creates new snow flake if one hit the ground<br> if(falling_snow.pos_y > ground_snow[falling_snow.pos_x])<br> {<br> ground_snow[falling_snow.pos_x]–;<br><br> if(ground_snow[falling_snow.pos_x] < 0)<br> ground_snow[falling_snow.pos_x] = 0;<br> <br> falling_snow.pos_y = 0;<br> falling_snow.pos_x = rand()%SCREEN_WIDTH;<br> falling_snow.fall_speed = 1 + rand()%MAX_SPEED;<br> }<br> }<br> <br> // paints snow on the ground<br> for(int k = 0 ; k < SCREEN_WIDTH ; k++)<br> for(int l = ground_snow[k] ; l < SCREEN_HEIGHT ; l++)<br> buffer[l * lPitch + k] = RGB16(31,63,31);<br><br> // Unlock the surface<br> G.lpDDSBack->Unlock(NULL);<br> <br> // Flip the surfaces<br> G.lpDDSPrimary->Flip(NULL, 0);<br>}<br><br>That''s if I wish you have no problem compiling that, I''m been having not much luck compiling others work <img src="sad.gif" width=15 height=15 align=middle> some starnge compile errors, and somewhat strange for statements incomplete (!?!?!?), I just hope you don''t find nothing like that here.<br><br><br><br><br>I was almost forgetting… How can I draw the sin function? I''ve tried the following code<br><br>for(int i = 0; i < SCREEN_WIDTH ; i++)<br>{<br>// trying to paint the sin function on the center of the screen with an amplitude of 30 pixels<br>buffer[(int)(sin(i) * 30 + SCREEN_HEIGHT/2)* lPitch + i] = RGB16(31,63,31);<br>}<br><br>but it apparently it''s draw around 4 sin functions at the same time(!?!?!?). What am I doing wrong? (I''ve included math.h, of course)<br><br>Thanks in advance,<br>TomaHawK<br> </i>
Do I really need one? :)
TomaHawk:

Try this for your sin function:

for(int i = 0; i < SCREEN_WIDTH ; i++)
{
// trying to paint the sin function on the center of the screen with an amplitude of 30 pixels
buffer[(int)(sin((2*3.1415)(i/SCREEN_WIDTH)) * 30 + SCREEN_HEIGHT/2)* lPitch + i] = RGB16(31,63,31);
}

I hope that helps. I haven''t tested it, though, so who knows?

FragLegs


I managed to find how sin function works, but thanks anyway FragLegs. sin() takes as parameter radians ans I was giving degrees that''s why it was not working, I should pass it something like this : angle * 2 * PI / 360 (converts angle from degrees to radians)

So... with the sin function working, I did another version of the snow falling... Snow now moves with as the sin function.

Anyone interested click HERE to download the GameMain.cpp

Thanks,
TomaHawK

P.S. Now with the sin there are some bugs when snow hitting the ground
Do I really need one? :)
hi there, i have a mystic problem with the pixel manipulation. i just paste in the code of teej in the game_main, the result is a white picture (yeah) but my computer freeze (so hang up). it''s the same with the examples made by the others. they go for 1-3 seconds and then system freeze. i have winxp/directx8 and a geforce3 ti500.
where is the fault?! is the geforce3 ti500 (5,6,5)? somebody else the problem?
hopefull mrxst

This topic is closed to new replies.

Advertisement