04.03 - Pixel Manipulation

Started by
47 comments, last by Teej 22 years, 4 months ago
Here''s one with a moving solid circle that bounces off of the screen edges and changes colors.

void Game_Main()
{
DDSURFACEDESC2 ddsd;
WORD *buffer;
long lPitch;

static int circRad = 25;
static int color = 0;
static int dY = 10;
static int dX = 10;

// start with entire circle on screen
static POINT p = {circRad+1,circRad+1};

// prepare ddsurfacedesc2 structure for locking
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);

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

// get surface pointer and memory pitch
buffer = (WORD *)ddsd.lpSurface;
lPitch = ddsd.lPitch / 2;

// change the direction and color when hitting edge of screen
p.x = p.x + dX;
p.y = p.y + dY;
if (p.x + circRad >= SCREEN_WIDTH || p.x - circRad <= 0)
{
dX = - dX;
color = RGB16(rand()%32, rand()%64, rand()%32);
}
if (p.y + circRad >= SCREEN_HEIGHT || p.y - circRad <= 0)
{
dY = - dY;
color = RGB16(rand()%32, rand()%64, rand()%32);
}

// draw on the display
int x,y;
int yDiff, xDiff;
for (y = 0; y < SCREEN_HEIGHT; y++)
{
for (x = 0; x < SCREEN_WIDTH; x++)
{
xDiff = abs(x - p.x);
yDiff = abs(y - p.y);
if (xDiff * xDiff + yDiff * yDiff < circRad * circRad)
// use color if current point is within the circle
buffer[y * lPitch + x] = color;
else
// black backgound
buffer[y * lPitch + x] = RGB16(0,0,0);
}
}

// unlock surface
G.lpDDSBack->Unlock(NULL);

// flip surfaces
G.lpDDSPrimary->Flip(NULL,0);
}
Advertisement
Nice code russ, here''s a bit of a re-write, this time with 3 lights moving around the screen.

  void Game_Main(){	DDSURFACEDESC2 ddsd;	WORD *buffer;	long lPitch;	static int circRad = 25;	static int color[3] = { RGB16(255,0,0), RGB16(0,255,0), RGB16(0,0,255) };	static int dY[3] = { 3, 3, 3 };	static int dX[3] = { 1, 2, 3 };	// start with entire circle on screen	static POINT p[3] = { {SCREEN_WIDTH >> 1,SCREEN_HEIGHT >> 1}, {SCREEN_WIDTH >> 1,SCREEN_HEIGHT >> 1}, {SCREEN_WIDTH >> 1,SCREEN_HEIGHT >> 1} }; 	// prepare ddsurfacedesc2 structure for locking	ZeroMemory(&ddsd,sizeof(ddsd));	ddsd.dwSize = sizeof(ddsd);	EraseBackground();	// lock backbuffer surface	G.lpDDSBack->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);	// get surface pointer and memory pitch	buffer = (WORD *)ddsd.lpSurface;	lPitch = ddsd.lPitch / 2;	int i;	for( i = 0; i < 3; i ++ )	{		// change the direction and color when hitting edge of screen		p[i].x = p[i].x + dX[i];		p[i].y = p[i].y + dY[i]; 		if (p[i].x + circRad + 5 >= SCREEN_WIDTH || p[i].x - circRad <= 5)		{			dX[i] = - dX[i];//			color = RGB16(rand()%32, rand()%64, rand()%32);<br></font><br>		}<br>		<font color="blue">if</font> (p[<font color="purple">i</font>].y + circRad + 5 &gt;= SCREEN_HEIGHT || p[<font color="purple">i</font>].y - circRad &lt;= 5)<br>		{ <br>			dY[<font color="purple">i</font>] = - dY[<font color="purple">i</font>];<br><font color="gray">//			color = RGB16(rand()%32, rand()%64, rand()%32);<br></font><br>		}<br><br>		<font color="gray">// draw on the display<br></font><br>		<font color="blue">int</font> x,y;<br>		<font color="blue">for</font> (y = -circRad; y &lt; circRad; y++)<br>		{<br>			<font color="blue">for</font> (x = -circRad; x &lt; circRad; x++)<br>			{ <br>				<font color="blue">if</font> (x * x + y * y &lt; circRad * circRad)<br>				<font color="gray">// use color if current point is within the circle<br></font><br>					buffer[<font color="purple">( y + p[i</font>].y ) * lPitch + x + p[<font color="purple">i</font>].x] = buffer[<font color="purple">( y + p[i</font>].y ) * lPitch + x + p[<font color="purple">i</font>].x] | color[<font color="purple">i</font>];<br><font color="gray">//				else <br></font><br>				<font color="gray">// black backgound<br></font><br><font color="gray">//					buffer[( y + p.y ) * lPitch + x + p.x] = RGB16(0,0,0);<br></font><br>			}<br>		}<br>	}<br><br>	<font color="gray">// unlock surface<br></font><br>	G.lpDDSBack-&gt;Unlock(NULL);<br><br>	<font color="gray">// flip surfaces<br></font><br>	G.lpDDSPrimary-&gt;Flip(NULL,0);<br>}<br>  </pre></font></td></tr></table></center><!–ENDSCRIPT–><br><br>Teej, nice going, this is better than the last forum, keep up the good work.  Oh and I take it we will not get to the actual game writing until chapter 5 or 6. good <img src="smile.gif" width=15 height=15 align=middle>    <br><br>When I find my code in tons of trouble,<br>Friends and colleages come to me,<br>Speaking words of wisdom:<br>"Write in C."    
When I find my code in tons of trouble,Friends and colleages come to me,Speaking words of wisdom:"Write in C."My Web Site
I''m sure there''s a more efficient algorithm for this (isn''t there always ), but here''s a radar-screen type thing that I messed around with for a few hours. By the way, I love this forum Teej...thanks for all your time and effort!

  void Game_Main(){	    DDSURFACEDESC2 ddsd;    	WORD *buffer;    	long lPitch;     		// Prepare a DDSURFACEDESC2 structure for Lock()    	ZeroMemory(&ddsd, sizeof(ddsd));    	ddsd.dwSize = sizeof(ddsd);     		// 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;   // (bytes / 2 = WORDs)     		// Draw onto the display    	int x, y;                     // the cartesian coordinates (x,y)	int cX = 320;                 // the horixontal centerpoint	int cY = 240;                 // the vertical centerpoint	int radius = 130;             // radius of the radar screen	double pi = 3.1415926535;     // PI	static double degree = 0;     // the number of degrees in radians that 	                              // the search arm is currently at	double angle;                 // the angle of (x,y) with respect to the  								  // center of the circle	// clear the back buffer by painting it totally black	for (y = 0; y < SCREEN_HEIGHT; y++)    	{        		for (x = 0; x < SCREEN_WIDTH; x++)        		{            			buffer[y * lPitch + x] = RGB16(0, 0, 0);        		}    	}		//every time the search arm finishes one rotation, it is reset	if (degree > 2*pi)	{		degree = 0;	}	// Draw the radar screen	for (y = -radius; y <= radius; y++)	{		for (x = -radius; x <= radius; x++)		{			//draw a vertical line through the circle			if (y == 0)				buffer[(cY) * lPitch + (cX+x)] = RGB16(0, 32, 0);			//draw a horizontal live through the circle			if (x == 0)				buffer[(cY+y) * lPitch + (cX)] = RGB16(0, 32, 0);			//draw the circle			if (((x*x + y*y) < (radius+1)*(radius+1))&&				((x*x + y*y) > (radius-1)*(radius-1)))			{				buffer[(cY+y) * lPitch + (cX+x)] = RGB16(0, 63, 0);			}			//find the angle for the x and y for this loop			angle = atan(double(y)/double(x));			//adjust for the quadrant (x,y) is in			//*********************************			if (y>0 && x>0)  //first quadrant			{					//do nothing			}			if (y>0 && x<0)  //second quadrant			{				angle = -angle;				angle = pi/2 - angle;				angle += pi/2;			}			if (y<0 && x<0)  //third quadrant			{				angle += pi;			}			if (y<0 && x>0)  //fourth quadrant			{				angle = -angle;				angle = pi/2 - angle;				angle += (3*pi)/2;			}			//*********************************			// draw the rotating search arm			if (degree < angle &&				angle < (degree+.01) &&				(x*x + y*y) < (radius-1)*(radius-1))			{				buffer[(cY-y) * lPitch + (cX+x)] = RGB16(0, 63, 0);			}			//draw the trail left by the search arm			int color = 58;			for (int i=1; i<=10; i++)			{				if ((degree-(double)(i*.01)) < angle &&					angle < (degree-(double)((i*.01)-.01)) &&					(x*x + y*y) < (radius-1)*(radius-1))				{					buffer[(cY-y) * lPitch + (cX+x)] = RGB16(0, color, 0);				}				color -= 5;  //make the green increasingly darker			}		}	}	// Increment degree	degree = degree + pi/64;			// Unlock the surface    	G.lpDDSBack->Unlock(NULL);     		// Flip the surfaces    	G.lpDDSPrimary->Flip(NULL, 0);}  
===================================Josh Ebersol"I'm not afraid of computers taking over the world. They're just sitting there. I can hit them with a two by four." -Thom York
Heey you guy''s a have a problem when i run my project i get 3 errors. here are the 3 errors i hope somebody can help my.

--------------------Configuration: Test Project - Win32 Debug--------------------
Compiling...
Game_main.cpp
Linking...
Game_main.obj : error LNK2001: unresolved external symbol "struct __unnamed G" (?G@@3U__unnamed@@A)
LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16
Debug/Test Project.exe : fatal error LNK1120: 2 unresolved externals
Error executing link.exe.

Test Project.exe - 3 error(s), 0 warning(s)

greetings Twan
Teej, this tutorial is awesome. I''ve been learning how to program for the last couple of years in school and now I finally get a chance to put some of that to GOOD USE!!!

It''s not much, but I have learned so much from this tutorial, I wanted to contribute something while it is still relevant.

So...for anyone who is interested in a scrolling starfield, here it is.

void Game_Main()
{
DDSURFACEDESC2 ddsd;
WORD *buffer;

long lPitch;
const int noOfStars = 100;
static POINT p[noOfStars];
static int once = 1;
static WORD color = RGB16 (0, 0, 0);

// Initialize the star locations
if (once == 1)
{
for (int i = 0; i < noOfStars; i++)
{
p.x = rand() % SCREEN_WIDTH;
p.y = rand() % SCREEN_HEIGHT;<br> }<br> once ++;<br> }<br><br> // Color the surface black<br> DDBLTFX ddbltfx;<br> ZeroMemory (&ddbltfx, sizeof (ddbltfx));<br> ddbltfx.dwSize = sizeof (ddbltfx);<br> ddbltfx.dwFillColor = 0;<br> G.lpDDSBack->Blt (NULL,NULL,NULL,<br> DDBLT_COLORFILL | DDBLT_WAIT,<br> &ddbltfx);<br> <br> // Prepare a DDSURFACEDESC2 structure for Lock()<br> ZeroMemory (&ddsd, sizeof (ddsd));<br> ddsd.dwSize = sizeof (ddsd);<br><br> // Lock the backbuffer surface<br> G.lpDDSBack->Lock (NULL, &ddsd,<br> DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);<br><br> // Get the surface memory and surface pitch (in WORDs)<br> buffer = (WORD *) ddsd.lpSurface;<br> lPitch = ddsd.lPitch >> 1;<br><br> // Scroll the stars downward or generate new ones<br> for (int i = 0; i < noOfStars; i++)<br> {<br> if (p.y >= SCREEN_HEIGHT)<br> {<br> p.x = rand() % SCREEN_WIDTH;<br> p.y = 0;<br> }<br> else<br> {<br> p.y = p.y + 1;<br> }<br> }<br><br> // Draw the stars onto the display<br> for (i = 0; i < noOfStars; i++)<br> {<br> buffer[p.y * lPitch + p.x] = RGB16 (31, 63, 31);<br> }<br><br> // Unlock the backbuffer surface<br> G.lpDDSBack->Unlock (NULL);<br> <br> // Flip the backbuffer surface to the screen<br> G.lpDDSPrimary->Flip (NULL, 0);<br> }<br><br>I can''t wait to see the next tutorial.<br><br>Thanks again,<br><br>Analogkid </i>
Hey, the anon person with the square sample program was me. I forgot to login. Now you know.

btw, thanks for reviewing my little program.
taking analogkid''s stars into another dimension (namely the third).

void Game_Main()
{
DDSURFACEDESC2 ddsd;
WORD *buffer;

long lPitch;
const int noOfStars = 160;
struct star{
int sx;
int sy;
int sz;
};

static star Stars[noOfStars];
static POINT p[noOfStars];
static int once = 1;
static WORD color = RGB16 (0, 0, 0);
int halfwidth=SCREEN_WIDTH/2;
int halfheight=SCREEN_HEIGHT/2;

// Initialize the star locations
if (once == 1)
{
for (int i = 0; i < noOfStars; i++)
{
Stars.sx = (rand()%SCREEN_WIDTH)-halfwidth;
Stars.sy = (rand()%SCREEN_HEIGHT)-halfheight;<br>Stars.sz = i+1;<br>}<br>once ++;<br>}<br><br><br>// Color the surface black<br>DDBLTFX ddbltfx;<br>ZeroMemory (&ddbltfx, sizeof (ddbltfx));<br>ddbltfx.dwSize = sizeof (ddbltfx);<br>ddbltfx.dwFillColor = 0;<br>G.lpDDSBack->Blt (NULL,NULL,NULL,<br>DDBLT_COLORFILL | DDBLT_WAIT,<br>&ddbltfx);<br><br>// Prepare a DDSURFACEDESC2 structure for Lock()<br>ZeroMemory (&ddsd, sizeof (ddsd));<br>ddsd.dwSize = sizeof (ddsd);<br><br>// Lock the backbuffer surface<br>G.lpDDSBack->Lock (NULL, &ddsd,<br>DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);<br><br>// Get the surface memory and surface pitch (in WORDs)<br>buffer = (WORD *) ddsd.lpSurface;<br>lPitch = ddsd.lPitch >> 1;<br><br><br>//Turn 3d points into 2d equiv. (basically just divide by x and y by z.<br>for (int j = 0; j < noOfStars; j++){<br> p[j].x=((Stars[j].sx*60)/Stars[j].sz)+halfwidth;<br> p[j].y=((Stars[j].sy*60)/Stars[j].sz)+halfheight;<br>}<br><br><br>// Draw the stars onto the display<br>for (int i = 0; i < noOfStars; i++)<br>{<br> if (p.x>0 && p.x<SCREEN_WIDTH && p.y>0 && p.y<SCREEN_HEIGHT){<br> //this bit sets different colours, depending on the distance (z)<br> if (Stars.sz>150) buffer[p.y * lPitch + p.x] = RGB16 (0, 0, 5);<br> else if (Stars.sz>120) buffer[p.y * lPitch + p.x] = RGB16 (5, 10, 5);<br> else if (Stars.sz>90) buffer[p.y * lPitch + p.x] = RGB16 (10, 20, 10);<br> else if (Stars.sz>50) buffer[p.y * lPitch + p.x] = RGB16 (20, 40, 20);<br> else buffer[p.y * lPitch + p.x] = RGB16 (31, 63, 31);<br> }<br>}<br><br>// Unlock the backbuffer surface<br>G.lpDDSBack->Unlock (NULL);<br><br>// Flip the backbuffer surface to the screen<br>G.lpDDSPrimary->Flip (NULL, 0);<br><br><br>//move the stars for the next iteration.<br>for (j=0; j < noOfStars; j++){<br> Stars[j].sz=Stars[j].sz-1;<br> if (Stars[j].sz<1){<br> Stars[j].sz=(Stars[j].sz+noOfStars);<br> }<br>}<br><br>} </i>
Sorry, something went wrong on the original post, and some bits got cut off. How do you post code into a listbox? And how do you copy that code into VC++ without it all being on one line?

Anyway, I didn''t check it all but in the part labeled:
// Draw the stars onto the display
and under the "for" loop it reads:

"if (p.x>0 && p.x0 && p.y //this bit sets different colours, depending on the distance (z)"<br><br>but it should read:<br><br>"if (p.x>0 && p.x<SCREEN_WIDTH && p.y>0 && p.y<SCREEN_HEIGHT){<br>//this bit sets different colours, depending on the distance (z)"<br><br>I don''t know what happened, but hey, I hope this works because I deleted my version!<br><br><br> </i>
ok, I guess if a line is too long it gets truncated or something, so I'll try one more time!

the "if" statement should be:

if (p.x"greaterthan"0 && p.x"lessthan"SCREEN_WIDTH<br> && p.y"greaterthan"0 && p.y"lessthan"SCREEN_HEIGHT){<br></i><br>incase this doesnt work - it says if p.x is greater than zero and less than screen width and p.y is greater than zero and less than screen height (ie - if its on the screen) then do the next bit!<br></i><br>ok, I figured out the post problem - i was making html tags by using the greater than and less than symbols! duh! substitute the symbols, and all will be startrekish.<br></i><br>Also, for some reason, it says "Stars.sx=" but should read "Stars.sx="<br></i><br>I trully hope this is it!<br><br>Edited by - nmoog on May 16, 2001 11:44:02 PM </i> <br><br>Edited by - nmoog on May 16, 2001 11:46:46 PM
Very cool nmoog! It took me a while to figure out what was going on with that code (still not 100% sure), but I like it.

Thanks for the dimensional upgrade!

~kid

This topic is closed to new replies.

Advertisement