Thread: Trying to make Tetris

  1. #1
    Registered User
    Join Date
    Jun 2004
    Posts
    5

    Question Trying to make Tetris



    Ok what I am trying to do is make a simple tetris game yet I do not know how to come about doing this. What I would like to know is how exactly do you get the tiles to be able to drop from the sky and and how do i make the row disappear when its full.








  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Showing you everything won't help you. But I'll give some pointers:

    The board
    Let's think of the board as an array. In fact I'll even think of it as a 2D array here.
    Elements where a block is will be set to 1 and empty blocks will be 0 in the array.

    So.....

    If you have 20 blocks total that can fit widthwise on your board at any one time and you only use 1's and 0's perhaps the number 20 is significant.

    Even farther perhaps the total number of blocks that can fit widthwise in any size tetris board is significant in determining when a row is full.

    Definitely not the fastest way....but probably the easiest.


    Falling blocks

    If we are at Y and we want to move down 1 block we need to know two things.

    1. How far is 1 block in pixels?
    2. Is that block empty?

    If the block is empty we move down 1 row (which equates to blockheight number of pixels on screen).

    If the block is not empty, moving down would be a bad idea.

    Drawing the board

    Look at the first explanation of the 2D array and you should be able to figure it out.
    A challenge would be to find a way to use colored blocks, but still only 1's and 0's in the array, since putting the color in the array would screw up your row full detection scheme....or at least the one I gave you.


    If you need more help...show some code and the areas you are having problems with and I'll help you.

    Detecting multiple full rows

    There is an extremely fast way to do this.
    It has to do with each block's neighbor block.
    Last edited by VirtualAce; 06-17-2004 at 08:10 AM.

  3. #3
    Registered User
    Join Date
    Jun 2004
    Posts
    5
    o ya and how exactly to u set key commands to be able to turn the blocks and move it from side to side

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    No more help till I see some effort.

    I'm not being an azz here. I know how to program the whole game but it won't help you at all if I code it for you.

  5. #5
    Registered User
    Join Date
    Jun 2004
    Posts
    5
    Ok this is what I have so far and I get an error that im still looking for so can u look over it and see what you think

    Code:
    #include <WINDOWS.H>
    #include <STDLIB.H>
    #include <STDIO.H>
    
    struct BOARD
    {
    	CHAR umBoard[ 14 ][ 21 ];
    	CHAR uLines;
    };
    
    struct BLOCK
    {
    	CHAR umBlock[ 4 ][ 4 ];
    	CHAR uX;
    	CHAR uY;
    };
    
    const CHAR  g_mmBlockI[ 4 ][ 4 ] = { { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, };
    const CHAR  g_mmBlockJ[ 4 ][ 4 ] = { { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, };
    const CHAR  g_mmBlockL[ 4 ][ 4 ] = { { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, };
    const CHAR  g_mmBlockO[ 4 ][ 4 ] = { { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, };
    const CHAR  g_mmBlockS[ 4 ][ 4 ] = { { 0, 1, 1, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, };
    const CHAR  g_mmBlockT[ 4 ][ 4 ] = { { 1, 1, 1, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, };
    const CHAR  g_mmBlockZ[ 4 ][ 4 ] = { { 1, 1, 0, 0 }, { 0, 1, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, };
    
    double		g_fLastTime			 = 0.0;
    HBRUSH		g_hbrBlock			 = CreateSolidBrush( RGB( 100, 100, 120 ) );
    HBRUSH		g_hbrSpace			 = CreateSolidBrush( RGB( 0, 0, 0 ) );
    BOARD		g_Board				 = { 0 };
    BLOCK		g_Block				 = { 0 };
    BOOL		g_bDoUpdate			 = FALSE;
    
    //-----------------------------------------------------------------------------
    
    //	Reset the game board
    
    //
    
    VOID ResetGameBoard( )
    {	
    	for ( int i = 0; i < 21; ++i )
    		for ( int j = 0; j < 14; ++j )
    			if ( i == 20 || j == 0 || j == 13 )
    				g_Board.umBoard[ j ][ i ] = 1;
    			else
    				g_Board.umBoard[ j ][ i ] = 0;
    	
    	g_Board.uLines = 0;
    }
    
    //-----------------------------------------------------------------------------
    
    //	Generate a new random figure
    
    //
    
    VOID GenerateRandomBlock( )
    {
    	CHAR uBlock = ( rand( ) % 7 ) + 1;
    	
    	switch ( uBlock )
    	{
    	case 1: memcpy( g_Block.umBlock, g_mmBlockI, 16 ); break;
    	case 2: memcpy( g_Block.umBlock, g_mmBlockJ, 16 ); break;
    	case 3: memcpy( g_Block.umBlock, g_mmBlockL, 16 ); break;
    	case 4: memcpy( g_Block.umBlock, g_mmBlockO, 16 ); break;
    	case 5: memcpy( g_Block.umBlock, g_mmBlockS, 16 ); break;
    	case 6: memcpy( g_Block.umBlock, g_mmBlockT, 16 ); break;
    	case 7: memcpy( g_Block.umBlock, g_mmBlockZ, 16 ); break;
    	}
    	
    	g_Block.uX = 6;
    	g_Block.uY = 0;
    }
    
    //-----------------------------------------------------------------------------
    
    //	Check for a collision on the board
    
    //
    
    BOOL CheckCollision
    	(
    	CHAR umBlock[ 4 ][ 4 ]
    	)
    {
    	for ( int i = 0; i < 4; ++i )
    		for ( int j = 0; j < 4; ++j )
    			if ( umBlock[ j ][ i ] == 0 )
    				break;
    			else
    			if ( g_Board.umBoard[ j + g_Block.uX ][ i + g_Block.uY ] + umBlock[ j ][ i ] != umBlock[ j ][ i ] )
    				return TRUE;
    
    	return FALSE;
    }
    
    //-----------------------------------------------------------------------------
    
    //	Move a block
    
    //
    
    BOOL MoveBlock( int nDX, int nDY )
    {
    	int nTempX, nTempY;
    
    	nTempX = g_Block.uX;
    	nTempY = g_Block.uY;
    
    	g_Block.uX += nDX;
    	g_Block.uY += nDY;
    	
    	if ( TRUE == CheckCollision( g_Block.umBlock ) )
    	{
    		g_Block.uX = nTempX;
    		g_Block.uY = nTempY;
    
    		return TRUE;
    	}
    	
    	return FALSE;
    }
    
    //-----------------------------------------------------------------------------
    
    //	Rotate a block 90 degrees
    
    //
    
    VOID RotateBlock( )
    {
    	CHAR i, j, umFig[ 4 ][ 4 ];
    	
    	for ( i = 0; i < 4; ++i )
    		for ( j = 0; j < 4; ++j )
    			umFig[ j ][ i ] = g_Block.umBlock[ 4 - i ][ j ];
    
    	if ( TRUE == CheckCollision( umFig ) )
    		return;
    
    	for ( i = 0; i < 4; ++i )
    		for ( j = 0; j < 4; ++j )
    			umFig[ j ][ i ] = g_Block.umBlock[ j ][ i ];
    }
    
    //-----------------------------------------------------------------------------
    
    //	Insert a block
    
    //
    
    VOID InsertBlock( )
    {
    	for ( int i = 0; i < 4; ++i )
    		for ( int j = 0; j < 4; ++j )
    			if ( g_Block.umBlock[ j ][ i ] != 0 )
    				g_Board.umBoard[ g_Block.uX + j ][  g_Block.uY + i ] = g_Block.umBlock[ j ][ i ];
    }
    
    //-----------------------------------------------------------------------------
    
    //	Remove completed lines
    
    //
    
    VOID RemoveLine( UINT uIndex )
    {
    	for ( int i = uIndex; i > 0; --i )
    		for ( int j = 1; j < 13; ++j )
    			g_Board.umBoard[ j ][ i ] = g_Board.umBoard[ j ][ i - 1 ];
    }
    
    //-----------------------------------------------------------------------------
    
    //	Search for completed lines
    
    //
    
    VOID SearchLines( )
    {
    	CHAR uNumBlocks = 0;
    
    	for ( int i = 0; i < 21; ++i )
    		for ( int j = 1; j < 13; ++j )
    			if ( g_Board.umBoard[ j ][ i ] == 0 )
    			{
    				uNumBlocks = 0;
    				break;
    			}
    			else
    			{
    				++uNumBlocks;
    
    				if ( uNumBlocks >= 12 )
    				{
    					RemoveLine( i );
    
    					++g_Board.uLines;
    					--i;
    				}
    			}
    }
    
    //-----------------------------------------------------------------------------
    
    //	Paint the scene
    
    //
    
    VOID PaintScene( HWND hWnd )
    {
    	CHAR		cvBuffer[ 80 ];
    	RECT		rcBlock;
    	HDC			hDC;
    	int			i, j;
    	
    	hDC = GetDC( hWnd );
    	
    	for ( i = 0; i < 20; ++i )
    		for ( j = 1; j < 13; ++j )
    		{
    			rcBlock.top		= ( i * 16 ) + 4;
    			rcBlock.left	= ( j * 16 ) + 4;
    			rcBlock.bottom	= rcBlock.top  + 16;
    			rcBlock.right	= rcBlock.left + 16;
    		
    			if ( g_Board.umBoard[ j ][ i ] == 0 )
    				FillRect( hDC, &rcBlock, g_hbrSpace );
    			else
    				FillRect( hDC, &rcBlock, g_hbrBlock );
    		}	
    
    	for ( i = 0; i < 4; ++i )
    		for ( j = 0; j < 4; ++j )
    			if ( g_Block.umBlock[ j ][ i ] == 0 )
    				break;
    			else
    			{
    				rcBlock.top		= ( ( g_Block.uY + i ) * 16 ) + 4;
    				rcBlock.left	= ( ( g_Block.uX + j ) * 16 ) + 4;
    				rcBlock.bottom	= rcBlock.top  + 16;
    				rcBlock.right   = rcBlock.left + 16;
    
    				if ( g_Block.umBlock[ j ][ i ] != 0 )
    					FillRect( hDC, &rcBlock, g_hbrBlock );
    			}
    
    	SetBkColor( hDC, RGB( 100, 120, 100 ) );
    	SetTextColor( hDC, RGB( 255, 240, 50 ) );
    
    	sprintf( cvBuffer, "Level: %i", ( g_Board.uLines / 15 ) );
    	TextOut( hDC, 210, 100, cvBuffer, ( int )strlen( cvBuffer ) );
    
    	sprintf( cvBuffer, "Lines: %i", g_Board.uLines );
    	TextOut( hDC, 210, 135, cvBuffer, ( int )strlen( cvBuffer ) );
    
    	ReleaseDC( hWnd, hDC );
    }
    
    //-----------------------------------------------------------------------------
    
    //	Process Win32 application messages
    
    //
    
    LRESULT CALLBACK WindowProc
    	( 
    	HWND		hWnd, 
    	UINT		uMessage, 
    	WPARAM		wParam, 
    	LPARAM		lParam 
    	)
    {
    	switch ( uMessage )
    	{
    	case WM_LBUTTONDOWN:
    		 SendMessage( hWnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam );
    		 return 0L;
    	case WM_KEYDOWN:
    		 switch ( LOWORD( wParam ) )
    		 {
    		 case VK_ESCAPE:
    			  PostQuitMessage( 0 );
    			  break;
    		 case VK_LEFT:
    			  MoveBlock( -1, 0 );
    			  g_bDoUpdate = TRUE;
    			  break;
    		 case VK_RIGHT:
    			  MoveBlock( 1, 0 );
    			  g_bDoUpdate = TRUE;
    			  break;
    		 case VK_DOWN:
    			  MoveBlock( 0, 1 );
    			  g_bDoUpdate = TRUE;
    			  break;		  
    		 case VK_SPACE:
    			  RotateBlock( );
    			  g_bDoUpdate = TRUE;
    			  break;
    		 }
    		 return 0L;
    	case WM_DESTROY:
    		 PostQuitMessage( 0 );
    		 return 0L;
    	}
    
    	return DefWindowProc( hWnd, uMessage, wParam, lParam );
    }
    
    //-----------------------------------------------------------------------------
    
    //	Application entry point
    
    //
    
    int WINAPI WinMain
    	( 
    	HINSTANCE	hInstance,
    	HINSTANCE	hPrevInstance,
    	LPSTR		lpCmdLine,
    	int			nShowCmd
    	)
    {
    	WNDCLASS			sWC;
    	HWND				hWnd;
    	MSG					sMsg;
    
    	memset( &sWC, 0, sizeof( WNDCLASS ) );
    	sWC.hbrBackground	= CreateSolidBrush( RGB( 100, 120, 100 ) );
    	sWC.hCursor			= LoadCursor( NULL, IDC_ARROW );
    	sWC.hIcon			= LoadIcon( NULL, IDI_WINLOGO );
    	sWC.hInstance		= hInstance;
    	sWC.lpfnWndProc		= WindowProc;
    	sWC.lpszClassName	= "DEMO";
    
    	RegisterClass( &sWC );
    	
    	hWnd = CreateWindow( "DEMO", "Demo", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 
    	WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 270, 400, NULL, NULL, hInstance, NULL );
    
    	ResetGameBoard( );
    	GenerateRandomBlock( );
    
    	PeekMessage( &sMsg, NULL, 0U, 0U, PM_NOREMOVE );
    
    	while ( WM_QUIT != sMsg.message )
    		if ( PeekMessage( &sMsg, NULL, 0U, 0U, PM_REMOVE ) )
    		{
    			TranslateMessage( &sMsg );
    			DispatchMessage( &sMsg );
    		}
    		else
    		{
    			double fTime = GetTickCount( ) * 0.001;
    			
    			if ( fTime - g_fLastTime > ( 1.0 - ( ( g_Board.uLines / 15 ) * 0.1 ) ) )
    			{
    				g_fLastTime = fTime;
    			
    				if ( MoveBlock( 0, 1 ) )
    				{
    					InsertBlock( );
    					SearchLines( );
    					GenerateRandomBlock( );
    				}
    				
    				g_bDoUpdate = TRUE;
    			}
    			
    			if ( TRUE == g_bDoUpdate )
    			{
    				PaintScene( hWnd );
    				g_bDoUpdate = FALSE;
    			}
    		}
    
    	return ( int )sMsg.wParam;
    }
    Last edited by Salem; 06-17-2004 at 11:07 AM. Reason: tagging

  6. #6
    Registered User
    Join Date
    Jun 2004
    Posts
    5
    o ya and bubba how did u get so good at programming

  7. #7
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    By reading books, learning from internet tutorials and by being determined.

  8. #8
    Registered User
    Join Date
    Jun 2004
    Posts
    5

    Exclamation Game programming Using Dev C++ and Direct X 8.1

    Just a little FYI there is a good tutorial on compiling games using Bloodshed's DEV C++ and direct X8.1.If anyone is interested.
    http://www.imagethis.org/

  9. #9
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Who said I was good at programming?

    I'm still at a hobbyist stage IMO.

    But if you want to be good...then yes, Shakti hit the nail right on the head.

    Books, books, and more books.

    Amazon has a great selection and www.gamedev.net has great suggestions on what to get. I lost the link to the books when I upgraded to XP. You can navigate the sight at the top of the main page.

    Before the books I read a lot of internet books (e-books) PDFs, read me's, txt files, etc, etc., etc. Googled till I couldn't google anymore. As of late I've not done this as much because I've found that paying 20 or 30 for a book that has all of the info I'd find on the net....both saves time and frustration for me.

    But if you are short on cash then google is your friend. www.gamedev.net is an excellent resource. Spend some time browsing their game articles, tutorials, etc. www.programmersheaven.com is another as well as www.gamasutra.com. Gamasutra is very good but very advanced.

    Main thing is don't let the stuff attack you and scare you. You won't understand it right off and you'll be scratching your head sometimes and feeling like you are in over your head. But with persistence and patience....you will be well on your way.

    Also I want to complement your effort at the code. I will definitely read over it later. Great job man.

    BTW I really like your attitude and your willingness to try this code on your own. It shows a lot about you to me. I would like to get you on my teamspeak server so that I can talk to you. You will need a microphone and speakers in order to use teamspeak. You can get the client at www.teamspeak.org. If you are interested either PM me or Shakti for more info. I have created a game development room on there just for all of us to chat and share code/game ideas. It has been invaluable to Shakti and I.

  10. #10
    mov.w #$1337,D0 Jeremy G's Avatar
    Join Date
    Nov 2001
    Posts
    704
    There are several of us who have released some kind of tetris source code here in the game dev section. Run a source and your can slurp from the source yourself. I released a very simplified version for dos called DosTris. Search for that, I'm pretty sure I uploaded the source code for it. It may help you on collision detection. I'm sure the other members source codes would be helpful as well. Search is your friend, be not afriad to use it :0
    c++->visualc++->directx->opengl->c++;
    (it should be realized my posts are all in a light hearted manner. And should not be taken offense to.)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Establishing 'make clean' with GNU make
    By Jesdisciple in forum C Programming
    Replies: 9
    Last Post: 04-11-2009, 09:10 AM
  2. How to make a Packet sniffer/filter?
    By shown in forum C++ Programming
    Replies: 2
    Last Post: 02-22-2009, 09:51 PM
  3. HELP!wanting to make full screen game windowed
    By rented in forum Game Programming
    Replies: 3
    Last Post: 06-11-2004, 04:19 AM
  4. make all rule
    By duffy in forum C Programming
    Replies: 9
    Last Post: 09-11-2003, 01:05 PM
  5. Replies: 6
    Last Post: 04-20-2002, 06:35 PM