Code:
#include <time.h>
#include <allegro.h>
#include <stdio.h>
volatile int dropdelay = 0;
int counter;
int board[20][10];
int boardx = 220, boardy = 40;
short blockx = 3;
short blocky = 0;
short current_rotation = 0;
short (*current_piece)[4][4];
short (*next_piece)[4][4];
short Iblock[4][4][4] = {
{
{0, 0, 1, 0},
{0, 0, 1, 0},
{0, 0, 1, 0},
{0, 0, 1, 0}
},
{
{0, 0, 0, 0},
{0, 0, 0, 0},
{1, 1, 1, 1},
{0, 0, 0, 0}
},
{
{0, 0, 1, 0},
{0, 0, 1, 0},
{0, 0, 1, 0},
{0, 0, 1, 0}
},
{
{0, 0, 0, 0},
{0, 0, 0, 0},
{1, 1, 1, 1},
{0, 0, 0, 0}
}
};
short Jblock[4][4][4] = {
{
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 0, 0}
},
{
{0, 0, 0, 0},
{0, 1, 1, 1},
{0, 1, 0, 0},
{0, 0, 0, 0}
},
{
{0, 0, 0, 0},
{0, 1, 1, 0},
{0, 0, 1, 0},
{0, 0, 1, 0}
},
{
{0, 0, 0, 0},
{0, 0, 1, 0},
{1, 1, 1, 0},
{0, 0, 0, 0}
}
};
short Lblock[4][4][4] = {
{
{0, 0, 0, 0},
{0, 1, 1, 0},
{0, 1, 0, 0},
{0, 1, 0, 0}
},
{
{0, 0, 0, 0},
{1, 1, 1, 0},
{0, 0, 1, 0},
{0, 0, 0, 0}
},
{
{0, 0, 1, 0},
{0, 0, 1, 0},
{0, 1, 1, 0},
{0, 0, 0, 0}
},
{
{0, 0, 0, 0},
{0, 1, 0, 0},
{0, 1, 1, 1},
{0, 0, 0, 0}
}
};
short Oblock[4][4][4] = {
{
{0, 0, 0, 0},
{0, 1, 1, 0},
{0, 1, 1, 0},
{0, 0, 0, 0}
},
{
{0, 0, 0, 0},
{0, 1, 1, 0},
{0, 1, 1, 0},
{0, 0, 0, 0}
},
{
{0, 0, 0, 0},
{0, 1, 1, 0},
{0, 1, 1, 0},
{0, 0, 0, 0}
},
{
{0, 0, 0, 0},
{0, 1, 1, 0},
{0, 1, 1, 0},
{0, 0, 0, 0}
}
};
short Tblock[4][4][4] = {
{
{0, 1, 0, 0},
{0, 1, 1, 0},
{0, 1, 0, 0},
{0, 0, 0, 0}
},
{
{0, 0, 0, 0},
{1, 1, 1, 0},
{0, 1, 0, 0},
{0, 0, 0, 0}
},
{
{0, 1, 0, 0},
{1, 1, 0, 0},
{0, 1, 0, 0},
{0, 0, 0, 0}
},
{
{0, 1, 0, 0},
{1, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
}
};
short Sblock[4][4][4] = {
{
{0, 0, 0, 0},
{0, 0, 1, 0},
{0, 1, 1, 0},
{0, 1, 0, 0}
},
{
{0, 0, 0, 0},
{1, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 0, 0}
},
{
{0, 0, 0, 0},
{0, 0, 1, 0},
{0, 1, 1, 0},
{0, 1, 0, 0}
},
{
{0, 0, 0, 0},
{1, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 0, 0}
}
};
short Zblock[4][4][4] = {
{
{0, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 1, 0},
{0, 0, 0, 0}
},
{
{0, 0, 0, 0},
{0, 1, 1, 0},
{1, 1, 0, 0},
{0, 0, 0, 0}
},
{
{0, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 1, 0},
{0, 0, 0, 0}
},
{
{0, 0, 0, 0},
{0, 1, 1, 0},
{1, 1, 0, 0},
{0, 0, 0, 0}
}
};
BITMAP *buffer;
BITMAP *block;
BITMAP *block_change;
BITMAP *back;
BITMAP *bg;
void setup();
void load_bitmaps();
void update_counter()
{
counter++;
}END_OF_FUNCTION(update_counter);
void rotate_c( short blocks[4][4][4] )
{
int next_rotation = current_rotation - 1;
if ( next_rotation == -1 )
next_rotation = 3;
for ( int x = 0; x < 4; x++ )
for ( int y = 0; y < 4; y++ )
if ( blocks[current_rotation][x][y] )
if ( blockx + x - 1 < 0 )
{
if(( blockx + x < 0) || (blockx + x > 9) || (blocky + y > 19))
return;
if( board[x + blockx][y + blocky] )
return;
}
current_rotation = next_rotation;
}
void rotate_cc( short blocks[4][4][4] )
{
int next_rotation = current_rotation + 1;
if ( next_rotation == 4 )
next_rotation = 0;
for ( int x = 0; x < 4; x++ )
for ( int y = 0; y < 4; y++ )
if ( blocks[current_rotation][x][y] )
if ( blockx + x - 1 < 0 )
{
if(( blockx + x < 0) || (blockx + x > 9) || (blocky + y > 19))
return;
if( board[x + blockx][y + blocky] )
return;
}
current_rotation = next_rotation;
}
void move_L( short blocks[4][4][4] )
{
for( int y = 0; y < 4; y++ )
{
if ( y + blocky < 0 )
continue;
for( int x = 0; x < 4; x++ )
if ( blocks[current_rotation][x][y] )
if ( blockx + x - 1 < 0 )
return;
else if ( board[x + blockx - 1][y + blocky] )
return;
}
blockx--;
}
void move_R( short blocks[4][4][4] )
{
for( int y = 0; y < 4; y++ )
{
if ( y + blocky < 0 )
continue;
for( int x = 0; x < 4; x++ )
if ( blocks[current_rotation][x][y] )
if ( blockx + x + 1 > 9 )
return;
else if ( board[x + blockx + 1][y + blocky] )
return;
}
blockx++;
}
void draw_to_board( short blocks[4][4][4], int xend, int yend )
{
xend = boardx + ( blockx * 20 );
yend = boardy + ( blocky * 20 );
for ( int x = 0; x < 4; x++ )
for ( int y = 0; y < 4; y++ )
if ( blocks[current_rotation][x][y] && ( y + blocky >= 0 ) )
blit ( block, buffer, 0, 0, xend + ( 20 * x ), yend + ( 20 * y), 20, 20 );
}
void draw( short blocks[4][4][4], int xend, int yend )
{
for ( int x = 0; x < 4; x++ )
for ( int y = 0; y < 4; y++ )
if ( blocks[0][x][y] && (y + blocky >= 0) )
blit ( block, buffer, 0, 0, xend + ( 20 * x ), yend + ( 20 * y ), 20, 20 );
}
bool fall( short blocks[4][4][4] )
{
for(int y = 0; y < 4; y++)
{
if(y + blocky < 0)
continue;
for(int x = 0; x< 4; x++)
if(blocks[current_rotation][x][y])
if( blocky + y + 1 > 19 )
return 0;
else if( board[x + blockx][y + blocky + 1] )
return 0;
}
blocky++;
return 1;
}
bool game_over( short blocks[4][4][4] )
{
for ( int x = 0; x < 4; x++ )
for ( int y = 0; y < 4; y++ )
if ( blocks[current_rotation][x][y] )
if ( board[x + blockx][y + blocky] )
return 1;
return 0;
}
////////////////////////////////////MAIN////////////////////////////////////////
int main()
{
setup();
load_bitmaps();
short lineclear[10][20];
short clearline[20];
int level = 0;
int dropd = 0;
int score = 0;
int linenum = 0;
bool quit = 0;
short moveleft = 0;
short moveright = 0;
short rotate_c_ = 0;
short rotate_cc_ = 0;
short drop = 0;
switch ( rand() % 7 )
{
case 0: current_piece = Oblock; break;
case 1: current_piece = Iblock; break;
case 2: current_piece = Lblock; break;
case 3: current_piece = Jblock; break;
case 4: current_piece = Sblock; break;
case 5: current_piece = Zblock; break;
case 6: current_piece = Tblock; break;
}
switch ( rand() % 7 )
{
case 0: next_piece = Oblock; break;
case 1: next_piece = Iblock; break;
case 2: next_piece = Lblock; break;
case 3: next_piece = Jblock; break;
case 4: next_piece = Sblock; break;
case 5: next_piece = Zblock; break;
case 6: next_piece = Tblock; break;
}
int speed[10] = { 30, 25, 20, 15, 10, 6, 5, 4, 3, 1 };
for ( int y = 0; y < 20; y++ )
for ( int x = 0; x < 10; x++ )
board[x][y] = lineclear[x][y] = 0;
while ( !quit )
{
clear(buffer);
draw_sprite ( buffer, bg, 210, 30 );
for ( int y = 0; y < 20; y++ )
for ( int x = 0; x< 10; x++ )
if ( board[x][y] )
blit( back, buffer, 0, 0, boardx + 20 * x, boardy + 20 * y, 20, 20);
draw_to_board ( current_piece, boardx, boardy );
draw ( next_piece, 500, 100 );
textprintf ( buffer, font, 5, 10, makecol16(255,255,255), "Score = %d", score);
textprintf ( buffer, font, 5, 20, makecol16(255,255,255), "Lines Cleared = %d", linenum);
textprintf ( buffer, font, 5, 30, makecol16(255,255,255), "Level = %d", level);
textprintf ( buffer, font, 5, 50, makecol16(255,255,255), "Drop Distance = %d", dropd);
blit(buffer, screen, 0, 0, 0, 0, 640, 480);
while ( counter > 0 )
{
if ( key[KEY_LEFT] && ( !moveleft || moveleft == 15 ) )
{
move_L ( current_piece );
if ( !moveleft ) moveleft = 1;
}
else if(key[KEY_LEFT])
moveleft++;
else if(!key[KEY_LEFT])
moveleft = 0;
if ( key[KEY_RIGHT] && ( !moveright || moveright == 15 ) )
{
move_R ( current_piece );
if ( !moveright ) moveright = 1;
}
else if(key[KEY_RIGHT])
moveright++;
else if(!key[KEY_RIGHT])
moveright = 0;
if ( key[KEY_Z] && !rotate_cc_ )
{
rotate_cc ( current_piece );
rotate_cc_ = 1;
}
else if ( !key[KEY_Z] )
rotate_cc_ = 0;
if ( key[KEY_X] && !rotate_c_ )
{
rotate_c ( current_piece );
rotate_c_ = 1;
}
else if ( !key[KEY_X] )
rotate_c_ = 0;
if(key[KEY_DOWN] && !drop)
{
dropd++;
dropdelay = 200;
}
else if(!key[KEY_DOWN])
dropd = drop = 0;
if ( key[KEY_ESC] ) quit = 1;
if ( dropdelay > speed[level] )
{
if ( !fall( current_piece ) )
{
for ( int y = 0; y < 4; y++ )
for ( int x = 0; x< 4; x++ )
if ( current_piece[current_rotation][x][y] )
board[x + blockx][y + blocky] = current_piece[current_rotation][x][y];
current_piece = next_piece;
switch ( rand() % 7 )
{
case 0: next_piece = Oblock; break;
case 1: next_piece = Iblock; break;
case 2: next_piece = Lblock; break;
case 3: next_piece = Jblock; break;
case 4: next_piece = Sblock; break;
case 5: next_piece = Zblock; break;
case 6: next_piece = Tblock; break;
}
blockx = 3;
blocky = 0;
current_rotation = 0;
if ( game_over( current_piece ) )
{
clear(buffer);
draw_sprite ( buffer, bg, 210, 30 );
for ( int y = 0; y < 20; y++ )
for ( int x = 0; x < 10; x++ )
if ( board[x][y] )
blit( back, buffer, 0, 0, boardx + 20 * x, boardy + 20 * y, 20, 20);
draw_to_board ( current_piece, boardx, boardy);
draw (next_piece, 500, 100);
blit( buffer, screen, 0, 0, 0, 0, 640, 480 );
quit = 1;
}
int count = 0;
int linescleared = 0;
for ( int y = 0; y < 20; y++ )
{
count = 0;
clearline[y] = 0;
for ( int x = 0; x < 10; x++ )
if ( board[x][y] )
count++;
if ( count == 10 )
{
clearline[y] = 1;
linenum++;
}
}
for(int y = 0; y < 20; y++)
for(int x = 0; x < 10; x++)
lineclear[x][y] = 0;
for( int y = 19, count = 19; y >= 0; y-- )
{
for(int x = 0; x < 10; x++)
lineclear[x][count] = board[x][y];
if(!clearline[y])
count--;
}
for(int y = 0; y < 20; y++)
for(int x = 0; x < 10; x++)
board[x][y] = lineclear[x][y];
}
}
}
}
destroy_bitmap(block);
destroy_bitmap(buffer);
destroy_bitmap(block_change);
allegro_exit();
return 0;
}
END_OF_MAIN();
///////////////////////////////////////////////////////////////////////////////
void setup()
{
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0);
LOCK_VARIABLE(counter);
LOCK_FUNCTION(update_counter);
install_int_ex( update_counter, BPS_TO_TIMER(60));
text_mode ( -1 );
srand(time(NULL));
}
void load_bitmaps()
{
block = load_bitmap( "block.bmp", NULL );
block_change = load_bitmap( "block2.bmp", NULL );
buffer = create_bitmap( 640, 480 );
bg = load_bitmap( "bg.bmp", NULL );
back = load_bitmap( "backing.bmp", NULL );
}