'Tetris' source code

Forum Archive - from http://theuniversal.net
Locked
User avatar
Mit
Staff
Staff
Posts: 3551
Joined: Sun Sep 21, 2003 10:14 pm
Location: Unknown

'Tetris' source code

Post by Mit »

Heres a simple tetris game i knocked out recently .. It isnt complete (no scores, no game over, only one piece) and has a few lil bugs in it, but some of ya might find it interesting/useful to look thru.. I'll finish it up properly and include it in the arcade.dll sometime soon.

(Total coding time : 22 minutes. I actually timed it :) ) (And amazingly some ppl on the web actually charge for the source code!! )

Code: Select all


// 'Tetris' Arcade game.code by Mit

#include <Windows.h>

extern "C"
{

#include <StandardDef.h>
#include "Interface.h"
#include "Tetris.h"
}

#define		TETRIS_PIECE_ROWS		3
#define		TETRIS_PIECE_COLS		3

#define		TETRIS_BOX_HEIGHT		210
#define		TETRIS_BOX_ROWS			15
#define		TETRIS_BLOCK_HEIGHT		(TETRIS_BOX_HEIGHT/TETRIS_BOX_ROWS)

#define		TETRIS_BOX_WIDTH		200
#define		TETRIS_BOX_COLS			8
#define		TETRIS_BLOCK_WIDTH		(TETRIS_BOX_WIDTH/TETRIS_BOX_COLS)

#define		TETRIS_BLOCK_SPOTS		(TETRIS_BOX_COLS*TETRIS_BOX_ROWS)

int		mnBlocksBoxX = 100;			// Top left screen coord of the playing region
int		mnBlocksBoxY = 20;

BYTE	mabTetrisSpots[TETRIS_BOX_ROWS][ TETRIS_BOX_COLS ];

BYTE	mabCurrentBlockShape[TETRIS_PIECE_ROWS][TETRIS_PIECE_COLS];

int		mnCurrentBlockPosX = 4;
int		mnCurrentBlockPosY = 1;
ulong	mulNextMovePieceTime = 0;
ulong	mulMoveDelayTime = 1000;
ulong	mulNormalMoveDelayTime = 1000;


//-------------------------------------------------
// Function : TetrisCanMoveTo
//   Checks that a position is valid for the current piece
//-------------------------------------------------
BOOL TetrisCanMoveTo( int nMoveToX, int nMoveToY )
{
int		nX, nY;
int		nPieceX, nPieceY;

	nX = nMoveToX - 1;
	nY = nMoveToY - 1;
	
	for ( nPieceY = 0; nPieceY < 3; nPieceY++ )
	{
		for ( nPieceX = 0; nPieceX < 3; nPieceX++ )
		{
			if ( mabCurrentBlockShape[ nPieceY ][ nPieceX ] )
			{
				if ( ( (nY + nPieceY) >= TETRIS_BOX_ROWS ) ||
					 ( (nX + nPieceX) >= TETRIS_BOX_COLS ) ||
					 ( (nX + nPieceX) < 0 ) ||
					 ( (nY + nPieceY) < 0 ) )
				{
					return( FALSE );
				}
				if ( mabTetrisSpots[ nY + nPieceY ][ nX + nPieceX ] != 0 )
				{
					return( FALSE );
				}
			}
		}
	}
	return( TRUE );
}

//-------------------------------------------------
// Function : TetrisRotatePiece
//   Rotates the current piece
//-------------------------------------------------
void TetrisRotatePiece( void )
{
BYTE	mabCopyShape[TETRIS_PIECE_ROWS][TETRIS_PIECE_COLS];

	memcpy( &mabCopyShape[0][0], &mabCurrentBlockShape[0][0], TETRIS_PIECE_ROWS*TETRIS_PIECE_COLS*sizeof(BYTE) );
	// Fun fun.. manually change the position of the blockparts to rotate it
	mabCurrentBlockShape[0][0] = mabCopyShape[2][0];
	mabCurrentBlockShape[0][1] = mabCopyShape[1][0];
	mabCurrentBlockShape[0][2] = mabCopyShape[0][0];
	mabCurrentBlockShape[1][0] = mabCopyShape[2][1];
	mabCurrentBlockShape[1][1] = mabCopyShape[1][1];
	mabCurrentBlockShape[1][2] = mabCopyShape[0][1];
	mabCurrentBlockShape[2][0] = mabCopyShape[2][2];
	mabCurrentBlockShape[2][1] = mabCopyShape[1][2];
	mabCurrentBlockShape[2][2] = mabCopyShape[0][2];

	// Check the rotated piece is in a valid position. If not, restore the original rotation
	if ( TetrisCanMoveTo( mnCurrentBlockPosX, mnCurrentBlockPosY ) == FALSE )
	{
		memcpy( &mabCurrentBlockShape[0][0], &mabCopyShape[0][0], TETRIS_PIECE_ROWS*TETRIS_PIECE_COLS*sizeof(BYTE) );
	}
}

//-------------------------------------------------
// Function : TetrisDrawBlock
//   Draws a single block on the playing area
//-------------------------------------------------
void TetrisDrawBlock( int nLayer, int nX, int nY,ulong ulCol )
{
	nX *= TETRIS_BLOCK_WIDTH;
	nY *= TETRIS_BLOCK_HEIGHT;

	nX += mnBlocksBoxX;
	nY += mnBlocksBoxY;

	InterfaceRect( 1, nX, nY, TETRIS_BLOCK_WIDTH, TETRIS_BLOCK_HEIGHT, ulCol );
	InterfaceRect( 2, nX, nY, 2, TETRIS_BLOCK_HEIGHT, 0x80D0D0D0 );
	InterfaceRect( 2, nX, nY, TETRIS_BLOCK_WIDTH, 2, 0x80D0D0D0 );
	InterfaceRect( 2, nX + TETRIS_BLOCK_WIDTH - 2, nY, 2, TETRIS_BLOCK_HEIGHT, 0x80101010 );
	InterfaceRect( 2, nX,  nY + TETRIS_BLOCK_HEIGHT - 2, TETRIS_BLOCK_WIDTH, 2, 0x80101010 );
}

//-------------------------------------------------
// Function : TetrisCheckRowComplete
//  Returns TRUE if the specified row is full of blocks
//-------------------------------------------------
BOOL TetrisCheckRowComplete( int nY )
{
int	nX;

	for ( nX = 0; nX < TETRIS_BOX_COLS; nX++ )
	{
		// If any of the blocks in the row are not filled, the line is not complete
		if ( mabTetrisSpots[ nY ][ nX ] == 0 )
		{
			return( FALSE );
		}
	}
	return( TRUE );
}

//-------------------------------------------------
// Function : TetrisRemoveRow
//  Removes the specified row and moves the other rows down
//-------------------------------------------------
void TetrisRemoveRow( int nY )
{
int		nLoop;
int		nX;

	for ( nLoop = nY; nLoop > 0; nLoop-- )
	{
		for ( nX = 0; nX < TETRIS_BOX_COLS; nX++ )
		{
			mabTetrisSpots[ nLoop ][ nX ] =  mabTetrisSpots[ nLoop-1 ][ nX ];
		}	
	}
}



//-------------------------------------------------
// Function : TetrisStorePiece
//  Puts the current piece into the background blocks
//-------------------------------------------------
void TetrisStorePiece( void )
{
int		nX;
int		nY;
int		nPieceX;
int		nPieceY;

	nX = mnCurrentBlockPosX - 1;
	nY = mnCurrentBlockPosY - 1;
	for ( nPieceY = 0; nPieceY < TETRIS_PIECE_ROWS; nPieceY++ )
	{
		for ( nPieceX = 0; nPieceX < TETRIS_PIECE_COLS; nPieceX++ )
		{
			if ( mabCurrentBlockShape[ nPieceY ][ nPieceX ] != 0 )
			{
				mabTetrisSpots[ nY + nPieceY ][ nX + nPieceX ] = mabCurrentBlockShape[ nPieceY ][ nPieceX ];
			}
		}
	}
	// Now check for any complete rows and remove em
	for ( nY = TETRIS_BOX_ROWS-1; nY > 0; nY-- )
	{
		if ( TetrisCheckRowComplete( nY ) == TRUE )
		{
			TetrisRemoveRow( nY );
			nY++;
		}
	}
}

//-------------------------------------------------
// Function : TetrisUpdate
//  Main update function called every frame. Draws the game and moves the current piece if neccessary
//-------------------------------------------------
void TetrisUpdate( void )
{
int		nX;
int		nY;
int		nBlockX;
int		nBlockY;
ulong	ulTick = GetTickCount();

	InterfaceRect( 1, mnBlocksBoxX, mnBlocksBoxY, TETRIS_BOX_WIDTH, TETRIS_BOX_HEIGHT, 0xFF000060 );

	// Draw all the blocks in place
	for ( nY = 0; nY < TETRIS_BOX_ROWS; nY++ )
	{
		for ( nX = 0; nX < TETRIS_BOX_COLS; nX++ )
		{
  			switch( mabTetrisSpots[ nY ][ nX ] )
			{
			case 1:
				TetrisDrawBlock( 2,nX, nY, 0xFFD03010 );
				break;
			default:
				break;
			}
		}
	}

	// Draw the current block
	for ( nY = 0; nY < 3; nY++ )
	{
		for ( nX = 0; nX < 3; nX++ )
		{
			nBlockX = (mnCurrentBlockPosX - 1 + nX);
			nBlockY = (mnCurrentBlockPosY - 1 + nY);
			switch( mabCurrentBlockShape[ nY ][ nX ] )
			{
			case 1:
				TetrisDrawBlock( 2, nBlockX, nBlockY, 0xFFD03010 );
				break;
			}
		}
	}

	// Update the current blocks position if the time has run out.
	if ( mulNextMovePieceTime < ulTick )
	{
		mulNextMovePieceTime = ulTick + mulMoveDelayTime;
		if ( TetrisCanMoveTo( mnCurrentBlockPosX, mnCurrentBlockPosY + 1 ) == TRUE )
		{
			mnCurrentBlockPosY++;
		}
		else
		{
			if ( mnCurrentBlockPosY == 1 )
			{
				// Game Over!!!
			}
			else
			{		// Spawn a new piece
				// First copy the existing
				TetrisStorePiece();
				mnCurrentBlockPosY = 1;
				mnCurrentBlockPosX = 4;
				mulMoveDelayTime = mulNormalMoveDelayTime;
			}	
		}
	}
}


//-------------------------------------------------
// Function : TetrisInitGraphics
//  Initialisation function for the game
//-------------------------------------------------
void TetrisInitGraphics( void )
{
	ZeroMemory( mabTetrisSpots, sizeof( BYTE ) * TETRIS_BLOCK_SPOTS );
	mabTetrisSpots[ TETRIS_BOX_ROWS-1][0] = 1;

	ZeroMemory( mabCurrentBlockShape, sizeof( BYTE ) * TETRIS_PIECE_ROWS * TETRIS_PIECE_COLS );
	mabCurrentBlockShape[ 1 ][ 0 ] = 1;
	mabCurrentBlockShape[ 1 ][ 1 ] = 1;
	mabCurrentBlockShape[ 1 ][ 2 ] = 1;
	mabCurrentBlockShape[ 2 ][ 2 ] = 1;
}


//-------------------------------------------------
// Function : TetrisFreeGraphics
//  DeInitialisation function for the game
//-------------------------------------------------
void TetrisFreeGraphics( void )
{
}


//-------------------------------------------------
// Function : TetrisKeydown
//   Called when a key is pressed
//-------------------------------------------------
BOOL TetrisKeyDown( short key )
{
	if ( key == VK_LEFT )
	{
		if ( TetrisCanMoveTo( mnCurrentBlockPosX - 1, mnCurrentBlockPosY ) == TRUE )
		{
			mnCurrentBlockPosX--;
		}
	}
	if ( key == VK_UP )
	{
		TetrisRotatePiece();
	}

	if ( key == VK_DOWN )
	{
		mulMoveDelayTime = 50;
		mulNextMovePieceTime = 0;
	}

	if ( key == VK_RIGHT )
	{
		if ( TetrisCanMoveTo( mnCurrentBlockPosX + 1, mnCurrentBlockPosY ) == TRUE )
		{
			mnCurrentBlockPosX++;
		}
	}
	return( FALSE );
}


BOOL TetrisKeyUp( short key )
{
	return( FALSE );
}
User avatar
Fudrake
Posts: 244
Joined: Sat Oct 04, 2003 6:18 am
Location: UK, Europe, Northern Hemisphere, Earth, Solar System, Milky Way, the only universe we know of ;)

:/

Post by Fudrake »

public class Speech {
public static void main(String[] args){
byte thing=1;
short thing1=1;
int thing2=1;
long thing3=1;
float thing4=1;
double thing5 = 1.0;
System.out.println("Sometimes, I laugh at myself, why try to learn C++, then take a big U-turn then learn Java? It's nice to know proper C coding is quite similar to that of Java, but I just had to leave it for the great advantages (and the disadvantages) of Java. Persuaded by my brother I was, and now I can do not much other than to declare classes, like this class \"Speech\", print things out, do simple loops, prove to the world that 1+0.2+0.2+0.2 doesn't equal 1.6.....it equals a random floating point number like " + (thing5+0.2+0.2+0.2)+"...... and I like to do stupid programs that repeats words over and over again ");

for(int c=0;;){
System.out.print("and again");
}
}
}
User avatar
Mattizme
Posts: 615
Joined: Sat Oct 04, 2003 6:23 pm
Location: At work/school/home
Contact:

Post by Mattizme »

Darn you Mit - you've made me sit down and make my own now :P
User avatar
Kaezon
Posts: 8
Joined: Sun Feb 08, 2004 2:31 am
Location: East Coast, MD

Post by Kaezon »

ONLY 22 minutes?!? Jeeze, doing php i cant crank out that much unless it's a good day :P
User avatar
Mattizme
Posts: 615
Joined: Sat Oct 04, 2003 6:23 pm
Location: At work/school/home
Contact:

Post by Mattizme »

Kaezon, he does it for a living. he has allt he time int he world to do that :P
User avatar
Kaezon
Posts: 8
Joined: Sun Feb 08, 2004 2:31 am
Location: East Coast, MD

Post by Kaezon »

lol, cool, that's what I plan to do in the future :D siting at a comp screen all day typing code.
User avatar
Knoxjoey
Posts: 98
Joined: Tue Sep 30, 2003 8:52 pm
Location: Canada
Contact:

Post by Knoxjoey »

yep i want too do it too :)
User avatar
Fudrake
Posts: 244
Joined: Sat Oct 04, 2003 6:18 am
Location: UK, Europe, Northern Hemisphere, Earth, Solar System, Milky Way, the only universe we know of ;)

Post by Fudrake »

Me too probs. But probably with Java, or some other language if I get to learn it.......

Java's portable :)
Java's object oriented :)
Java's simple :)
Java's Garbage Collection :)
Java's Garbage Collection is too automatic :(
Java's slooooooooooooooooooow :(
Java's still coooooooooool :)
User avatar
hedgehog
Staff
Staff
Posts: 1057
Joined: Tue Sep 30, 2003 2:57 am
Location: ann arbor, michigan
Contact:

Post by hedgehog »

it's no entire works of shakespeare, but i s'pose it'll have to do ;)
Locked