Weird glitch in my tetris game

Started by
10 comments, last by ISDCaptain01 9 years, 11 months ago

Im having a problem with the collision in my tetris game. When the blocks collide, the block wont stop moving until it exits the entire screen. That leads to another problem: The blocks keep falling well below the screen and than collide. What could be causing this? I have a video to demonstrate this glitch:

Also here is some source code:

This is my main loop where the controls are:


int main()
{
	//Initialize Allegro and all subsystems
	initAllegro();
	initColors();
	initBitMaps();

	//Screen height
	int mScreenHeight = HEIGHT-78;

	//Pieces
	Pieces mPieces;

	//Board
	Board mBoard(&mPieces, mScreenHeight);
	

	//Game
	Game mGame(&mBoard, &mPieces, mScreenHeight);

	//Set the state
	state = -1;
	ChangeState(state, title);

	//Hide the windows OS mouse cursor
	//al_hide_mouse_cursor(display);

	//Start the main timer
	al_start_timer(timer);

	//Game Loop
	while(!done)
	{
		//start the event queue
		al_wait_for_event(event_queue, &events);

		//Poll the keyboard
		al_get_keyboard_state(&keyState);

		//Check for specific key presses
		if(events.type == ALLEGRO_EVENT_KEY_DOWN)
		{
			//Quit the game
			if(events.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
				done = true;

			//Move the piece right
			if(events.keyboard.keycode == ALLEGRO_KEY_RIGHT)
			{
				if(mBoard.IsPossibleMovement(mGame.mPosX+1, mGame.mPosY,
					mGame.mPiece, mGame.mRotation) == true)
				{
					mGame.mPosX++;
				}
			}
				

			//Move the piece left
			if(events.keyboard.keycode == ALLEGRO_KEY_LEFT)
			{
				if(mBoard.IsPossibleMovement(mGame.mPosX-1, mGame.mPosY,
					mGame.mPiece, mGame.mRotation) == true)
				{
					mGame.mPosX--;
				}

			}

			//Move the piece down
			if(events.keyboard.keycode == ALLEGRO_KEY_DOWN)
			{
				if(mBoard.IsPossibleMovement(mGame.mPosX, mGame.mPosY+1,
					mGame.mPiece, mGame.mRotation) == true)
				{
					mGame.mPosY++;
				}	
			}

			//Make the piece fall down
			if(events.keyboard.keycode == ALLEGRO_KEY_X)
			{
				while(mBoard.IsPossibleMovement(mGame.mPosX, mGame.mPosY,
					                            mGame.mPiece, mGame.mRotation))
				{
					mGame.mPosY++;
				}

				//Store the piece in the board
				mBoard.StorePiece(mGame.mPosX, mGame.mPosY-1, mGame.mPiece, mGame.mRotation);

				//Check if a row of blocks has formed in the board, if so delete
				mBoard.DeletePossibleLines();

				//IF the top row is filled, than gameover
				if(mBoard.IsGameOver())
				{
					ChangeState(state, ending);
				}
				TrackStatistics(mGame.mPiece);

				//IF not, than continue the game by creating a new piece
				mGame.CreateNewPiece();

			}

			//Rotate the piece
			if(events.keyboard.keycode == ALLEGRO_KEY_Z)
			{
				if(mBoard.IsPossibleMovement(mGame.mPosX, mGame.mPosY, mGame.mPiece,
					                         (mGame.mRotation+1)%4))
				{
					mGame.mRotation = (mGame.mRotation+1)%4;
					al_play_sample_instance(rotationInstance);
				}
				
			}

			//Switch from the title screen to the playing screen
			if(events.keyboard.keycode == ALLEGRO_KEY_ENTER)
			{
				if(state == title)
					ChangeState(state, playing);
			}
			//Switch from the playing screen to the ending
			if(events.keyboard.keycode == ALLEGRO_KEY_S)
			{
				if(state == playing)
					ChangeState(state, ending);
			}
		}
		
			
		//Check if user closes the window
		if(events.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
		{
			done = true;
		}


		///////////////////////////////////////////////////////////////
		///                                                         ///
		///         Updating starts here                            ///
		///                                                         ///
		///////////////////////////////////////////////////////////////
		if(events.type == ALLEGRO_EVENT_TIMER)
		{
			if(state == title)
			{
			}
			else if(state == playing)
			{
				if(events.timer.source == dropTimer)
				{
					if(mBoard.IsPossibleMovement(mGame.mPosX, mGame.mPosY+1,
													mGame.mPiece, mGame.mRotation))
						mGame.mPosY++;
					else
					{
						mBoard.StorePiece(mGame.mPosX, mGame.mPosY, mGame.mPiece, mGame.mRotation);
						mBoard.DeletePossibleLines();
				
						if(mBoard.IsGameOver())
						{
							ChangeState(state, ending);
						}
						mGame.CreateNewPiece();
					}
				}
			}
			else if(state == ending)
			{
			}
			//draw = true;
		}

		///////////////////////////////////////////////////////////////
		///                                                         ///
		///         Rendering starts here                           ///
		///                                                         ///
		///////////////////////////////////////////////////////////////
		if(!done)
		{
			if(state == title)
			{
				al_draw_bitmap(titleScreen, 0, 0, NULL);
			}
			else if(state == playing)
			{
				al_draw_bitmap(guiScreen, 0, 0, NULL);
				DrawStatistics();

				//Draw the statistics screen pieces
				mGame.DrawPiece(-15, -9, 0, 0);
				mGame.DrawPiece(-15, -6, 1, 0);
				mGame.DrawPiece(-15, -4, 2, 1);
				mGame.DrawPiece(-15, -1, 3, 3);
				mGame.DrawPiece(-15, 2, 4, 1);
				mGame.DrawPiece(-15, 5, 5, 1);
				mGame.DrawPiece(-15, 8, 6, 1);
				mGame.DrawScene();
			}
			else if(state == ending)
			{
				al_draw_bitmap(endingScreen, 0, 0, NULL);
			}

			al_flip_display();
			al_clear_to_color(al_map_rgb(0,0,0));
			//draw = false;
		}
	}

	return 0;
}

And this is my collision code and pixel location code:


/Check if the piece can be stored at this position without any collision
//Returns true if the movement is  possible, false if its not possible
bool Board::IsPossibleMovement (int pX, int pY, int pPiece, int pRotation)
{
	// Checks collision with pieces already stored in the board or the board limits
	// This is just to check the 5x5 blocks of a piece with the appropiate area in the board
	for (int i1 = pX, i2 = 0; i1 < pX + PIECE_BLOCKS; i1++, i2++)
	{
		for (int j1 = pY, j2 = 0; j1 < pY + PIECE_BLOCKS; j1++, j2++)
		{	
			// Check if the piece is outside the limits of the board
			if (i1 < 0 			|| i1 > BOARD_WIDTH  - 1	||
				j1 > BOARD_HEIGHT - 1)
			{
				//If an actual block if the piece is outside the board,
				//than movement is not possible
				if (mPieces->GetBlockType (pPiece, pRotation, j2, i2) != 0)
					return false;		
			}

			// Check if the piece have collisioned with a block already stored in the map
			if (j1 >= 0)	
			{
				if ((mPieces->GetBlockType (pPiece, pRotation, j2, i2) != 0) &&
					(!IsFreeBlock (i1, j1))	)
					return false;
			}
		}
	}

	// No collision
	return true;
}

//Store a piece in the board by filling the block
void Board::StorePiece (int pX, int pY, int pPiece, int pRotation)
{
	// Store each block of the piece into the board
	for (int i1 = pX, i2 = 0; i1 < pX + PIECE_BLOCKS; i1++, i2++)
	{
		for (int j1 = pY, j2 = 0; j1 < pY + PIECE_BLOCKS; j1++, j2++)
		{	
			// Store only the blocks of the piece that are not empty
			if (mPieces->GetBlockType (pPiece, pRotation, j2, i2) != 0)	
			{
				mBoard[i1][j1] = POS_FILLED;
				al_play_sample_instance(collideInstance);
			}

		}
	}
}

//Returns the horizontal position (in pixels) of the block given like parameter
int Board::GetXPosInPixels(int pPos)
{
	return( (BOARD_POSITION - (BLOCK_SIZE * (BOARD_WIDTH / 2))) + (pPos * BLOCK_SIZE));
}

//Returns the vertical position (in pixels) of the block given like parameter
int Board::GetYPosInPixels(int pPos)
{
	return( (mScreenHeight - (BLOCK_SIZE *(BOARD_HEIGHT / 2))) + (pPos * BLOCK_SIZE));
}
Advertisement

I've scanned through it a dozen times, but can't seem to find much. It's probably nothing but I did notice an inconsistency with with your GetBlockType


if (mPieces->GetBlockType (pPiece, pRotation, j2, i2) != 0)

that you seem to be passing in your Y value j2 before your X value i2. Is it meant to be like this or have you accidentally switched the order in which you pass them into the function? Just strange that everything else addresses the x values first.

Your authority is not recognized in Fort Kick-ass http://www.newvoxel.com

I've scanned through it a dozen times, but can't seem to find much. It's probably nothing but I did notice an inconsistency with with your GetBlockType


if (mPieces->GetBlockType (pPiece, pRotation, j2, i2) != 0)

that you seem to be passing in your Y value j2 before your X value i2. Is it meant to be like this or have you accidentally switched the order in which you pass them into the function? Just strange that everything else addresses the x values first.

Its accessing a 4x4 array (yuck I know). I cant find the bug either. Im gonna look more tommorow

Can you still move the piece around while it glitches?

Have you tried using a debugger? I'd debug the IsPossibleMovement and GetBlockType functions first. I can't do that since it appears to be missing code.

Check what values are passed as pY in IsPossibleMovement for a single piece since it appears on the top and it collides at the bottom, it should be incremental by 1 position up to a number between BOARD_HEIGHT - 1 and BOARD_HEIGHT - 5 I guess.

Also, where do you reset mGame.mPosX and mPosY for new pieces? What's that reset value?

And related to that... is the piece supposed to appear fully visible or above the board? Maybe you're drawing the pieces some "blocks" lower than you should.

I can't really tell from your code, but it looks like your program does properly check for collisions and stores where those collisions are. My intuition tells me that your program doesn't break after a collision is detected and skip to the next piece.

If you have any logic that is supposed to do that in your code I'd put a breakpoint there and see if it is ever reached. If not it should be pretty straightforward to implement happy.png

http://javilop.com/gamedev/tetris-tutorial-in-c-platform-independent-focused-in-game-logic-for-beginners/

That's the tutorial im following. I try resetting everything back to default position and still occurs. Im still looking

I checked out his .exe and he doesn't seem to have this problem

Have you compared your code to his downloadable code? Could be that you are forgetting something that he hadn't covered.

Are you using a debug tool? Everything we told you to check have correct values?

Try reducing the board to something like 10 blocks tall and draw it as close as you can from the top of the screen (or add more height to the window), I still think that you're drawing the pieces in the wrong place and the collision is happening when the piece is too far down.

DiegoSLTS, on 13 Jun 2014 - 12:22 PM, said:

Are you using a debug tool? Everything we told you to check have correct values?

Try reducing the board to something like 10 blocks tall and draw it as close as you can from the top of the screen (or add more height to the window), I still think that you're drawing the pieces in the wrong place and the collision is happening when the piece is too far down.

You are correct, I counted how many cells the block falls and it is exactly what the macro defines but for some reason it is not synced with the board. I just don't know hwta s causing it

This topic is closed to new replies.

Advertisement