• Create Account

### #ActualServant of the Lord

Posted 04 November 2012 - 12:15 PM

Okay so

return pixels[offset + x];
how does return of pixels[offset + x]; work exactly?

'pixels' is a pointer to PixelColor types (which is just a typedef of unsigned int). So pixels point to a block of memory it is treating as one or more unsigned ints - in this case, the unsigned ints represent the colors of each pixel on a surface. A surface is just SDL's term for an image in memory.
Using the [] operator let's us pretend pixels is an array (which it basically is - it's a block of memory holding a bunch of unsigned ints). pixels[0] returns the first unsigned int of the pixels in the surface, pixels[1] returns the second, and so on.

However, an image is two-dimensional, and we want to access pixels by an x and a y, not just a single number. So we treat the block of memory like a 2D array, by converting our x and y into an index. The math normally is: index = (y * width) + x;, and we could then go pixels[index].
I explain this more indepth in another thread, with visual aids.

Except that we're multiplying by surface->pitch / sizeof(unsigned int) instead of by width, because SDL surfaces may (to support certain video cards when running in hardware accelerated mode) make the surfaces larger than is actually required. surface->pitch is the real width of the image, including the extra padding. You can read more about this at Sol's SDL tutorials.

Why are you locking surfaces to access pixels to stop tearing or something?

I'm not really sure - the SDL documentation says not to access pixels except between locking and unlocking unless the surface doesn't need to be locked. I bet the most important reason for it is that if the surface is hardware accelerated, it'd be stored in Video Card memory, and locking the surface would probably bring it back into RAM for the program to safely work on - but that's speculation.

this function below makes a rect filling it with a user defined color yes?

void DrawRectangle(SDL_Surface *destination, const SDL_Color &color, SDL_Rect *rect = NULL)
{SDL_FillRect(destination, rect, SDL_MapRGB(destination->format, color.r, color.g, color.b));}


It doesn't "make" a rect. It draws a bunch of pixels in the same of a rectangle onto a surface that already exists.
The 'rect' here is just a concept, not a actual thing in memory.
SDL_MapRGB converts a color to the proper color the surface needs, taking into account the surface's format.
'rect' describes the shape of the rectangle to draw, and draws it onto the surface 'destination'. If 'rect' is NULL, the entire surface is filled with the color.

this code is fairly hard to grasp the technical concepts



if(!newSurface) {std::cerr << "CreateEmptySurface() - Something went wrong creating a " << width << "x" << height << " surface.\n" << "  Error: " << SDL_GetError() << std::endl;}	   //Let's start off filling it with a solid color, like solid white.	  DrawRectangle(newSurface, SDL_Color(255, 255, 255));	return newSurface;}


That is a bit confusing, yes. SDL_CreateRGBSurface() creates a new empty surface of size 'width' and 'height', and needs to know the number of bits per pixel, and the different masking formats, for the new surface. We just copy it from a different surface to make sure we get it right - preferably we copy it from the screen, so the screen and the new surface have the same format when drawing (so no conversions need to happen, and the drawing is sped up).
I typo'd it - in the call to SDL_CreateRGBSurface() it should say 'width' and 'height', not 'int width' and 'int height'.

We check to make sure the function didn't return null (which is an error if it does), and since the surface just has random memory junk where its pixels are, we make sure to fill it with the color white.

The entire function just wraps all that for convenience.

What does this do from a technical point of view

SDL_Surface *waterImage = CreateEmptySurface(50, 50, screen);

We're calling the function just previously described to create an empty surface of width '50' and height '50', using the same format as 'screen'.

This code below is oddly written what does that all mean ?

void MakeWaterSurface(SDL_Surface *surface, unsigned int frame){		//We only have 20 frames, so keep within range. frame %= 20;	int offset = frame;	 if(offset >= 10)		{			   //0 1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1			  offset = (10 - (offset - 10));  }	   SDL_Color colors[] = {SDL_Color(100, 150, 190),SDL_Color(100, 160, 180),SDL_Color(100, 170, 170),SDL_Color(100, 180, 160),SDL_Color(100, 190, 150),											   SDL_Color(100, 190, 170),SDL_Color(100, 190, 190),SDL_Color(100, 190, 210),SDL_Color(100, 190, 230),SDL_Color(100, 220, 250)};		for(int y = 0; y < surface->height; y++)		{			   for(int x = 0; x < surface->height; x++)				{					   //I'm coding blind without a compiler, so I have completely no idea if this will work or not.				   int waveDepth = ((y + offset) % 10);									int waveHorizontalOffset = ((x + (offset/3)) % 20);					 int waveVerticalOffset = ((x + waveHorizontalOffset) + offset);								 unsigned colorIndex = (waveDepth + waveVerticalOffset) % 10;									WritePixel(x, y, colors[colorIndex], surface);		  }	   }}

That function is weird, yes. Of all the code I posted, that's the bit I'm most iffy about - not being able to compile it (since I don't have SDL on my computer), I don't know for sure if it does what I wanted it to.

It's *supposed to* make a semi-gradiented bands of color, and offset them vertically and horizontally, to sort-of look like waves of water. Whether it works or not, I don't know - which is embarrassing, since I wrote it.

### #1Servant of the Lord

Posted 04 November 2012 - 12:15 PM

Okay so

return pixels[offset + x];
how does return of pixels[offset + x]; work exactly?

'pixels' is a pointer to PixelColor types (which is just a typedef of unsigned int). So pixels point to a block of memory it is treating as one or more unsigned ints - in this case, the unsigned ints represent the colors of each pixel on a surface. A surface is just SDL's term for an image in memory.
Using the [] operator let's us pretend pixels is an array (which it basically is - it's a block of memory holding a bunch of unsigned ints). pixels[0] returns the first unsigned int of the pixels in the surface, pixels[1] returns the second, and so on.

However, an image is two-dimensional, and we want to access pixels by an x and a y, not just a single number. So we treat the block of memory like a 2D array, by converting our x and y into an index. The math normally is: index = (y * width) + x;, and we could then go pixels[index].
I explain this more indepth in another thread, with visual aids.

Except that we're multiplying by surface->pitch / sizeof(unsigned int) instead of by width, because SDL surfaces may (to support certain video cards when running in hardware accelerated mode) make the surfaces larger than is actually required. surface->pitch is the real width of the image, including the extra padding. You can read more about this at Sol's SDL tutorials.

Why are you locking surfaces to access pixels to stop tearing or something?

I'm not really sure - the SDL documentation says not to access pixels except between locking and unlocking unless the surface doesn't need to be locked. I bet the most important reason for it is that if the surface is hardware accelerated, it'd be stored in Video Card memory, and locking the surface would probably bring it back into RAM for the program to safely work on - but that's speculation.

this function below makes a rect filling it with a user defined color yes?

void DrawRectangle(SDL_Surface *destination, const SDL_Color &color, SDL_Rect *rect = NULL)
{SDL_FillRect(destination, rect, SDL_MapRGB(destination->format, color.r, color.g, color.b));}


It doesn't "make" a rect. It draws a bunch of pixels in the same of a rectangle onto a surface that already exists.
The 'rect' here is just a concept, not a actual thing in memory.
SDL_MapRGB converts a color to the proper color the surface needs, taking into account the surface's format.
'rect' describes the shape of the rectangle to draw, and draws it onto the surface 'destination'. If 'rect' is NULL, the entire surface is filled with the color.

this code is fairly hard to grasp the technical concepts



if(!newSurface) {std::cerr << "CreateEmptySurface() - Something went wrong creating a " << width << "x" << height << " surface.\n" << "  Error: " << SDL_GetError() << std::endl;}	   //Let's start off filling it with a solid color, like solid white.	  DrawRectangle(newSurface, SDL_Color(255, 255, 255));	return newSurface;}


That is a bit confusing, yes. SDL_CreateRGBSurface() creates a new empty surface of size 'width' and 'height', and needs to know the number of bits per pixel, and the different masking formats, for the new surface. We just copy it from a different surface to make sure we get it right - preferably we copy it from the screen, so the screen and the new surface have the same format when drawing (so no conversions need to happen, and the drawing is sped up).
I typo'd it - in the call to SDL_CreateRGBSurface() it should say 'width' and 'height', not 'int width' and 'int height'.

We check to make sure the function didn't return null (which is an error if it does), and since the surface just has random memory junk where its pixels are, we make sure to fill it with the color white.

The entire function just wraps all that for convenience.

What does this do from a technical point of view

SDL_Surface *waterImage = CreateEmptySurface(50, 50, screen);

We're calling the function just previously described to create an empty surface of width '50' and height '50', using the same format as 'screen'.

This code below is oddly written what does that all mean ?

void MakeWaterSurface(SDL_Surface *surface, unsigned int frame){		//We only have 20 frames, so keep within range. frame %= 20;	int offset = frame;	 if(offset >= 10)		{			   //0 1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1			  offset = (10 - (offset - 10));  }	   SDL_Color colors[] = {SDL_Color(100, 150, 190),SDL_Color(100, 160, 180),SDL_Color(100, 170, 170),SDL_Color(100, 180, 160),SDL_Color(100, 190, 150),											   SDL_Color(100, 190, 170),SDL_Color(100, 190, 190),SDL_Color(100, 190, 210),SDL_Color(100, 190, 230),SDL_Color(100, 220, 250)};		for(int y = 0; y < surface->height; y++)		{			   for(int x = 0; x < surface->height; x++)				{					   //I'm coding blind without a compiler, so I have completely no idea if this will work or not.				   int waveDepth = ((y + offset) % 10);									int waveHorizontalOffset = ((x + (offset/3)) % 20);					 int waveVerticalOffset = ((x + waveHorizontalOffset) + offset);								 unsigned colorIndex = (waveDepth + waveVerticalOffset) % 10;									WritePixel(x, y, colors[colorIndex], surface);		  }	   }}

That function is weird, yes. Of all the code I posted, that's the bit I'm most iffy about - not being able to compile it (since I don't have SDL on my computer), I don't know for sure if it does what I wanted it to.

It's *supposed to* make a semi-gradiented bands of color, and offset them vertically and horizontally, to sort-of look like waves of water. Whether it works or not, I don't know - which is embarrassing, since I wrote it.

PARTNERS