#include <allegro.h>
#include <time.h>
unsigned char controlTicks = 0; // Used for the player input timer.
unsigned char downTicks = 0; // Used for the blocks scrolling down timer.
void init(); // Initialize allegro functions first.
void controlTimer(); // Timer function (could use more work)
void downTimer(); // Timer function (could use more work)
void gameSetup(); // Setting up the background and start of game.
void moveBlock(); // Moving the Blocks and collision detection.
void draw(); // Used to draw on to the screen.
void controlBlock(); // Player manipulation of blocks as they descend.
void resetBlock(); // Reloads the Block array with the default block positions.
void removeBlock(); // Clears full row of blocks
void rotateBlock(int rotateNum); // Rotates block
void whatsNext(); // Used to determine the next block.
void youWin(); // Under construction
/*---Global variables---------------------------------------------------| x is used to determine which block form in the block[][] array to use.|
| tempX is used to store the flip value plus plus x value. |
| nextBlock is used in determining what block is next in whatsNext(); |
| hasRun is used to determine if the what's next function has run yet |
\----------------------------------------------------------------------*/
int x = 0, tempX = 0, flip = 0, nextBlock = 0;
bool hasRun = false;
// Global constants
const int WIDTH = 10;
const int HEIGHT = 14;
/* gameBoard[][] is used to store the location of the blocks. \ The value '1' is a block and '0' is the absense of a block. */
int gameBoard[HEIGHT][WIDTH] = {{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,1,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,1,1,0}};
/* Used to display what the next block will be. */
int tempBlock[4][4] = {{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}};
/* This holds the 7 original block configurations. */
int block[7][4];
/* Declare containers for images. */
BITMAP *buffer;
BITMAP *background;
BITMAP *gBlock;
int main()
{
init();
gameSetup();
/* Main game loop */
while(!key[KEY_ESC])
{
controlBlock();
draw();
youWin();
}
destroy_bitmap(buffer);
destroy_bitmap(background);
destroy_bitmap(gBlock);
return 0;
}
END_OF_MAIN();
void init ()
{
allegro_init();
install_keyboard();
install_timer();
LOCK_VARIABLE(downTicks);
LOCK_FUNCTION(downTimer);
install_int_ex(&downTimer, SECS_TO_TIMER(1));
LOCK_VARIABLE(controlTicks);
LOCK_FUNCTION(controlTimer);
install_int_ex(&controlTimer, MSEC_TO_TIMER(100));
set_color_depth(16);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 1024,768, 0, 0);
}
void controlTimer()
{
controlTicks++;
}
END_OF_FUNCTION(controlTimer);
void downTimer()
{
downTicks++;
}
END_OF_FUNCTION(downTimer);
void gameSetup()
{
background = load_bitmap("background.bmp", NULL);
buffer = create_bitmap(1024, 768);
gBlock = load_bitmap("gBlock.bmp", NULL);
srand ( (unsigned)time ( 0) );
whatsNext();
resetBlock();
for(int r = 0; r <= 13; r++)
{
for(int c = 0; c <= 9; c++)
{
if(gameBoard[r][c] == 1)blit(gBlock, buffer, 0, 0, (50*c)+175, (50*r), 50, 50);
}
}
}
void moveBlock()
{
while(downTicks > 0)
{
/* Initialize variables */
int r = 0, c = 0;
/* Allowing block to move again. */
bool move = true;
/* Clear the original block location */
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH);
c = (block[x] % WIDTH);
if(r > 0) gameBoard[r-1][c] = 0;
}
/* Collision Detection (can the block move any further). */
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH);
c = (block[x] % WIDTH);
/* If the block form encounters another block, stop moving. */
if(gameBoard[r][c] == 1 || r >= HEIGHT)
{
move = false;
break;
}
}
/* If the block is unable to move. */
if(!move)
{
/* Set permanent location of block. */
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH);
c = (block[x] % WIDTH);
if(r >0)gameBoard[r-1][c] = 1;
}
removeBlock(); // check for any completed rows, remove them, move the grid down,
resetBlock(); // and then reset the block array to default.
flip = 0;
return;
}
/* Continually move the block form currently stored in block[][]. */
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH);
c = (block[x] % WIDTH);
gameBoard[r][c] = 1;
r ++;
block[x] = (r * WIDTH + c);
}
downTicks--;
}
}
/* Player control of the block. */
void controlBlock()
{
while(controlTicks > 0)
{
/* Initalize and reset variables */
int r = 0, c = 0;
bool kUp = false, kRight = false, kLeft = false, kDown = false;
bool cUp = true, cRight=true, cLeft = true, cDown=true;
/* Each direction also does a little bit of collision detecion \ to insure that a block is not in the way before it can move. */
if(key[KEY_RIGHT]) kRight = true;
if(kRight)
{
/* Clear block first. */
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
if(r >=0)gameBoard[r][c] = 0;
}
/* Check for collision. */
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
if(gameBoard[r][c+1] == 1 || c >= WIDTH-1 || r <=0 ) cRight = false;
}
/* If nothing collides move peice. */
if(cRight)
{
for(int i = 0; i <= 3; i++)
{
block[x]++;
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
gameBoard[r][c] = 1;
}
}
}
if(key[KEY_LEFT]) kLeft = true;
if(kLeft)
{
/* Clear block first. */
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
if(r >=0)gameBoard[r][c] = 0;
}
/* Check for collision. */
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
if(gameBoard[r][c-1] == 1 || c <= 0 ) cLeft = false;
}
/* If nothing collides move peice. */
if(cLeft)
{
for(int i = 0; i <= 3; i++)
{
block[x]--;
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
if(r >= 0)gameBoard[r][c] = 1;
}
}
}
/* If the UP key is pressed, activate rotate. */
if(key[KEY_UP]) kUp = true;
if(kUp)
{
/* Clear block first. */
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
if(r >=0)gameBoard[r][c] = 0;
}
/* Check for collision. */
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
if(gameBoard[r+1][c] == 1 || c <= 0 && i == 1 || c >= WIDTH-1 && i == 1)
{
cUp = false;
}
if( x == 6 && c >= WIDTH-2 && i == 2 && flip < 6) cUp = false;
}
/* If nothing collides move peice. */
if(cUp)
{
rotateBlock(tempX);
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
if(r >=0)gameBoard[r][c] = 1;
}
}
}
/* If the down key is pressed, move down faster. */
if(key[KEY_DOWN]) kDown = true;
if(kDown)
{
// Clear block first.
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
if(r >=0)gameBoard[r][c] = 0;
}
// Check for collision.
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
if(gameBoard[r+1][c] == 1 || r >= HEIGHT-1) cDown = false;
}
// If nothing collides move peice.
if(cDown)
{
for(int i = 0; i <= 3; i++)
{
block[x] += 10;
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
gameBoard[r][c] = 1;
}
}
}
if(!cRight || !cLeft || !cDown || !cUp )
{
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
if(r >=0)gameBoard[r][c] = 1;
}
}
/* If the block can not move in either direction, make sure it's drawn. */
tempX = x + flip; //tempX is sent to rotate funtion for flip number.
controlTicks--;
}
moveBlock(); // After player input check is finished move the block
}
// Clears row or rows when full.
void removeBlock()
{
/* Initialize variables */
int nRow = 0, rRow[4], i=0;
bool shift=false;
for(i = 0; i <= 4; i++)
{
rRow = 0;
}
i=0;
/* Find all gameBoard rows that have 10 blocks and | save the row number to an array. Then allow |
\ shift condition if any row has 10 blocks. */
for(int r = 0; r <= HEIGHT-1; r++)
{
for(int c = 0; c <= WIDTH-1; c++)
{
nRow += gameBoard[r][c];
if(nRow >= 10)
{
rRow = r;
nRow = 0;
if(i < 3) i++;
shift = true;
}
}
/* Reset the number in the row to 0 if it's \ not a complete line. */
if(nRow < 10) nRow = 0;
}
/* If any row has ten blocks take the value you in \ that row and move all of the above block down. */
if(shift)
{
for(int i = 0; i <= 3; i++)
{
for(int r = rRow; r >0; r--)
{
for(int c = 0; c <= WIDTH-1; c++)
{
if(r > 0)gameBoard[r][c] = gameBoard[r-1][c];
}
}
}
}
}
/* Resets block shape positions for use again and picks a new block. */
void resetBlock()
{
//if(!hasRun) x = rand()%7;
//else
x = nextBlock;
/* {4, 5, 6, 15}, // T-Block
{4, 5, 13, 14}, // S-Block
{4, 14, 24, 25}, // L-Block
{4, 5, 14, 15}, // Sq-Block
{4, 14, 24, 34}};*/ // Li-Block
// T-Block
block[0][0] = 13;
block[0][1] = 14;
block[0][2] = 15;
block[0][3] = 4;
// S-Block
block[1][0] = 5;
block[1][1] = 4;
block[1][2] = 14;
block[1][3] = 13;
// Z-Block
block[2][0] = 3;
block[2][1] = 4;
block[2][2] = 14;
block[2][3] = 15;
// L-Block
block[3][0] = 4;
block[3][1] = 14;
block[3][2] = 24;
block[3][3] = 25;
// 7-Block
block[4][0] = 4;
block[4][1] = 14;
block[4][2] = 24;
block[4][3] = 23;
// Sq-Block
block[5][0] = 4;
block[5][1] = 5;
block[5][2] = 14;
block[5][3] = 15;
// Li-Block
block[6][0] = 4;
block[6][1] = 14;
block[6][2] = 24;
block[6][3] = 34;
whatsNext();
}
void rotateBlock( int rotateNum)
{
int r = 0, c = 0;
// Clear block first.
for(int i = 0; i <= 3; i++)
{
r = (block[x] / WIDTH)-1;
c = (block[x] % WIDTH);
if(r >=0)gameBoard[r][c] = 0;
}
switch(rotateNum)
{
case 0:
// T-Block (First Right)
block[0][0] -= 9;
block[0][1] += 0;
block[0][2] += 9;
block[0][3] += 11;
flip += 7;
break;
case 1:
// S-Block{5, 4, 14, 13},
block[1][0] -= 11;
block[1][1] += 0;
block[1][2] -= 9;
block[1][3] += 2;
flip += 9;
break;
case 2:
// Z-Block{3, 4, 14, 15},
block[2][0] -= 9;
block[2][1] -= 0;
block[2][2] -= 1;
block[2][3] -= 12;
flip += 9;
break;
case 3:
// L-Block {4, 14, 24, 25},
block[3][0] += 11;
block[3][1] -= 0;
block[3][2] -= 11;
block[3][3] -= 2;
flip += 9;
break;
case 4:
// 7-Block
block[4][0] += 11;
block[4][1] += 0;
block[4][2] -= 11;
block[4][3] -= 20;
flip += 11;
break;
case 5:
// Sq-Block
flip = 0;
break;
case 6:
// Li-Block (Horizonal)
block[6][0] += 9;
block[6][1] -= 0;
block[6][2] -= 9;
block[6][3] -= 18;
flip += 12;
break;
case 7:
// T-Block (Second Right)
block[0][0] += 11;
block[0][1] += 0;
block[0][2] -= 11;
block[0][3] += 9;
flip += 1;
break;
case 8:
// T-Block
block[0][0] += 9;
block[0][1] += 0;
block[0][2] -= 9;
block[0][3] -= 11;
flip += 1;
break;
case 9:
// T-Block
block[0][0] -= 11;
block[0][1] += 0;
block[0][2] += 11;
block[0][3] -= 9;
flip -= 9;
break;
case 10:
// S-Block
block[1][0] += 11;
block[1][1] += 0;
block[1][2] += 9;
block[1][3] -= 2;
flip -= 9;
break;
case 11:
// Z-Block{3, 4, 14, 15},
block[2][0] += 9;
block[2][1] += 0;
block[2][2] += 1;
block[2][3] += 12;
flip -= 9;
break;
case 12:
// L-Block {4, 14, 24, 25},
block[3][0] += 9;
block[3][1] -= 0;
block[3][2] -= 9;
block[3][3] -= 20;
flip += 1;
break;
case 13:
// L-Block {4, 14, 24, 25},
block[3][0] -= 11;
block[3][1] -= 0;
block[3][2] += 11;
block[3][3] += 2;
flip += 1;
break;
case 14:
// L-Block {4, 14, 24, 25},
block[3][0] -= 9;
block[3][1] -= 0;
block[3][2] += 9;
block[3][3] += 20;
flip -= 11;
break;
case 15:
// 7-Block
block[4][0] += 9;
block[4][1] += 0;
block[4][2] -= 9;
block[4][3] += 2;
flip += 1;
break;
case 16:
// 7-Block
block[4][0] -= 9;
block[4][1] += 0;
block[4][2] += 9;
block[4][3] += 20;
flip += 1;
break;
case 17:
// 7-Block
block[4][0] -= 11;
block[4][1] += 0;
block[4][2] += 11;
block[4][3] -= 2;
flip -= 13;
break;
case 18:
// Li-Block (Vertical)
block[6][0] -= 9;
block[6][1] += 0;
block[6][2] += 9;
block[6][3] += 18;
flip -= 12;
break;
}
}
void whatsNext()
{
int r=0, c=0;
bool hasRun = true;
for(r = 0; r <= 3; r++)
{
for(c = 0; c <= 3; c++)
{
tempBlock[r][c] = 0;
}
}
nextBlock = rand()%7;
for(int i = 0; i <= 3; i++)
{
r = (block[nextBlock] / WIDTH)+1;
c = (block[nextBlock] % WIDTH)-6;
tempBlock[r][c] = 1;
}
}
void youWin()
{
int value = 0;
bool val = false;
for(int c = 0; c <= WIDTH-1; c++)
{
for(int r = 0; r <= HEIGHT-1; r++)
{
if(gameBoard[r][c] == 1)value++;
if(value >= HEIGHT) val = true;
}
value = 0;
}
if(val)
{
for(int r = 0; r <= HEIGHT-1; r++)
{
for(int c = 0; c <= WIDTH-1; c++)
{
gameBoard[r][c] = 0;
}
textout_ex(buffer, font, "You Lose!", 10, 10, makecol(0, 0, 255), -1);
}
rest(5000);
}
}
void draw()
{
blit(background, buffer, 0, 0, 0, 0, 1024, 768);
for(int r = 0; r <= HEIGHT-1; r++)
{
for(int c = 0; c <= WIDTH-1; c++)
{
if(gameBoard[r][c] == 1) blit(gBlock, buffer, 0, 0, (50*c)+175, r*50, 50, 50);
}
}
for(int r = 0; r <= 3; r++)
{
for(int c = 0; c <= 3; c++)
{
if(tempBlock[r][c] == 1) blit(gBlock, buffer, 0, 0, (50*c)+700, (r*50)+225, 50, 50);
}
}
blit(buffer, screen, 0, 0, 0, 0, 1024, 768);
}
Download: http://defessler.jeremycrapsey.com/ontheblocks/ontheblocks.rar