I'm writing a little Tetris clone in C++ with SDL and I've run into a few flaws which I would like help with.
Problem 1:
Let me define a few things in my program.
Objects:
Tile: A single square in a Tetris game. A tile holds its coordinates and its SDL Surface.
Block: the 4 piece Tetris block that falls down. A block contains 4 tile objects.
Play_Area: This object contains an array of of Tile pointers. If a Tile pointer == NULL then the that space is considered empty.
So here's the problem. When a block falls down and collides with the bottom of the play_area I have to transfer the 4 tiles contained in the block object to the play_area. This is how I've implemented that(its in a for loop to get all 4 tiles):
d_area[y][x] = new Tile();
memcpy(d_area[y][x], &block->getTiles(i), sizeof(Tile));
Then I delete the old block and create a new one. This creates a bit of a problem. The destructor of the block object calls the destructors of all 4 tiles. Each tile destructor tells SDL to free its SDL Surface. Now the tile copies I made in play_area have SDL_Surface pointers pointing to nothing.
I could copy the tile and then create a new SDL Surface for it, blitting the original tile onto the copy's surface. I'm sure there's a better way to handle this problem.
Problem 2:
This is more of a coding issue. I'm having trouble handling different pixel formats. As a result I have code that looks like this in two places.
void Tile::rotateLeft()
{
int bytes_per_pixel;
Uint32* pixels = 0;
Uint8* pixels_copy = 0;
int x2, y2;
if(d_tile == NULL)
convertStat2Dyn();
bytes_per_pixel = d_tile->format->BytesPerPixel;
pixels = (Uint32 *)d_tile->pixels;
pixels_copy = (Uint8 *)calloc(d_tile->w*d_tile->h, bytes_per_pixel);
memcpy(pixels_copy, pixels, bytes_per_pixel*d_tile->w*d_tile->h);
switch(bytes_per_pixel){
case 1: // 8 bpp
for(int x1 = 0; x1 < d_tile->w; x1++)
for(int y1 = 0; y1 < d_tile->h; y1++){
x2 = y1;
y2 = d_tile->h-1-x1;
putPixel8(d_tile, x2, y2, &pixels_copy[(y1*d_tile->pitch)+x1*3]);
}
break;
case 2: // 16 bpp
for(int x1 = 0; x1 < d_tile->w; x1++)
for(int y1 = 0; y1 < d_tile->h; y1++){
x2 = y1;
y2 = d_tile->h-1-x1;
putPixel16(d_tile, x2, y2, (Uint16 *)pixels_copy[(y1*d_tile->pitch/2)+x1]);
}
break;
case 3: // 24 bpp
for(int x1 = 0; x1 < d_tile->w; x1++)
for(int y1 = 0; y1 < d_tile->h; y1++){
x2 = y1;
y2 = d_tile->h-1-x1;
putPixel24(d_tile, x2, y2, &pixels_copy[(y1*d_tile->pitch)+x1*3]);
}
break;
case 4: // 32 bpp
for(int x1 = 0; x1 < d_tile->w; x1++)
for(int y1 = 0; y1 < d_tile->h; y1++){
x2 = y1;
y2 = d_tile->h-1-x1;
putPixel32(d_tile, x2, y2, (Uint32 *)pixels_copy[(y1*d_tile->pitch)+x1]);
}
break;
}
free(pixels_copy);
}
Its pretty painful to look at. I'd like to simplify this function considerably. Maybe throw it in a template of some sort. I'm not really sure how.