> I know I am starting to look for optimization in places where there are almost nothing to be gained, but how expensive is assignment?
That's about the simplest thing there is.
What you really need to do is get hold of a profiler to actually tell you where the problem areas are, rather than guessing. Also, you need to look at your algorithms, not micro-optimisations which the compiler will manage perfectly well to do itself.
I am not really sure what I can do to improve my algorithm. I have looked online at other blitting functions, and they are almost the same. A few are a bit faster, but they are using evil assembly hacks which I dont understand.
In fact, if you get too "clever" about it, you might just make it worse rather than better, as the compiler will no longer be able to figure out what you're really trying to do.
The compiler contains the distilled wisdom of programmers with a combined total of hundreds, if not thousands of years of programming experience. If there's a trick, you can be pretty sure they know about it, and hence the compiler probably does as well, if you make your intent clear enough to being with.
I have seen that a few times. Makes me feel bad, when the compiler better knows what I want to do then I know myself.
> It optimized several of my functions away (Hey, who needs input functions in a game?)
In a correct program, optimisation should not change the functionality of the program. If the functionality changed, then I'd suspect bugs in your code. Many "problems" such as using uninitialised variables or minor buffer overruns are easy to gloss over in debug mode, but are then exposed when in release mode. Similarly, people sometimes complain it works in release mode but not debug mode for pretty much the same reasons.
I was expecting it to be my fault, I just found it amusing at the time.
> int offset = (( SCREENWIDTH * y) + x) * 4;
If you're calling this for incrementing x and y values all through the 2D array, then you can definitely improve things by moving this outside the function. Making it static and inline may give the compiler enough of a clue to achieve the kind of code motion which would reduce this to just adding 4 each time around the loop.
The function is just for drawing more random like things, say a star field.
I know(or I have read in the game programming book) that if you have a special case happening over and over again, you should make a special blitting function for that case. I am not really sure how to do this, but maybe someone can point me in the right direction?
My player and enemy sprites are always 32x32 and always have alpha channel. Almost all of the center of the sprite if fully coloured(no alpha) while the edges have alpha. Is there any way I can use that to make a faster blitter?
> So it will not work to good if I try to use that to draw a sprite of a car or something onto something else?
Well you could, if you create more "layers" in your palette, but the number of colours goes down in response. A background, and non-overlapping foreground characters is about the limit of the technique.
If I have to use more then one logic operator, it is better to use an if, as one if statement take about the same time as two logic operators.
What you really need to do is get hold of a profiler to actually tell you where the problem areas are, rather than guessing.
I have tried to use one, but I could not really get it to work very well. Can anyone recommend a free one that work on Vista? (I am using Visual studio)
Here is the blitting function for alpha, it is probably not perfect, but it is as good as I can get it without any help
Code:
void Sprite::drawAlphaSprite(BYTE *screenData, Rectangle2D &screenRec, int xPos, int yPos)
{
// Figure out which part of the texture to draw
Rectangle2D newTextureRec = calculateClipping(screenRec, textureRec, xPos, yPos);
// A pointer to the memory we want to copy to
BYTE *screenDataPnt = screenData + (xPos + yPos * screenRec.getWidth()) * 4;
// A pointer to the memory we want to copy from
BYTE *textureDataPnt = spriteData + (newTextureRec.left + newTextureRec.top * textureRec.right) * 4;
// Calculate the offset after each line
int endScreenOffset = (screenRec.getWidth() - newTextureRec.getWidth()) * 4;
int endTextureOffset = (textureRec.getWidth() - newTextureRec.getWidth()) * 4;
// Do the drawing
for (int y = 0; y < newTextureRec.getHeight(); y++)
{
for (int x = 0; x < newTextureRec.getWidth(); x++)
{
BYTE blue = textureDataPnt[0];
BYTE green = textureDataPnt[1];
BYTE red = textureDataPnt[2];
BYTE alpha = textureDataPnt[3];
// Calculate how much the alpha value is going to effect the pixel
float alphaMod = alpha / 255.0;
if(alphaMod != 0)
{
// Assign the correct colour to the current pixel, the fast way
screenDataPnt[0] = screenDataPnt[0] + (( alpha * (blue - screenDataPnt[0] )) >> 8);
screenDataPnt[1] = screenDataPnt[1] + (( alpha * (green - screenDataPnt[1] )) >> 8);
screenDataPnt[2] = screenDataPnt[2] + (( alpha * (red - screenDataPnt[2] )) >> 8);
}
// Move to the next pixel on the screen
screenDataPnt += 4;
// Move to the next pixel on the sprite
textureDataPnt += 4;
}
// Move to the next line on the screen and the next line of the sprite
screenDataPnt += endScreenOffset;
textureDataPnt += endTextureOffset;
}
}
And I use this one when there is no alpha. This one is a lot faster
Code:
void Sprite::drawNoAlphaSprite(BYTE *screenData, Rectangle2D &screenRec,int xPos, int yPos)
{
// Figure out which part of the texture to draw
Rectangle2D newTextureRec = calculateClipping(screenRec, textureRec, xPos, yPos);
// Pointer to the memory we want to copy to
BYTE *screenDataPnt = screenData + (xPos + yPos * screenRec.getWidth()) * 4;
// Pointer to the memory we want to copy from
BYTE *textureDataPnt = spriteData + (newTextureRec.left + newTextureRec.top * textureRec.getWidth()) * 4;
// Copy one line of the sprite to the screen for each loop
for (int y = newTextureRec.top; y < newTextureRec.bottom; y++)
{
// Copy the line
memcpy(screenDataPnt,textureDataPnt, newTextureRec.getWidth() * 4);
// Move to the next line of the texture
textureDataPnt += textureRec.getWidth() * 4;
// Move to the next line of the screen
screenDataPnt += screenRec.getWidth() * 4;
}
}