Sign in to follow this  

An ANNOYING Bug in my Tetris 3D game?

This topic is 2849 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

EDIT: Could it possibly be due to PI not being accurate enough? I sincerely doubt it... Anyway i define PI like this: #define PI 3.14159265358979323846 Whenever i try to rotate the blocks, this bug occurs where sometimes bricks disappear or the block becomes rearranged in a different way. I'm desperate. I've been trying to find out what's wrong for 2 days!! (The game is not complete yet, but i'll post the related code) Here's the ENTIRE Logic File. (Last Function is the one that deals with rotation, it's called by the first function.
#include "stdafx.h"
#include <ctime>
#include "Global.h"

extern INPUTDATA Input;
int SpaceArray[7][15][7];
const int NumBricks = 4;
int Shape;
int FallTime = FALLSPEED;
int MoveTime = 150;
int RotateTime = 150;
bool NewBlock(true);

void InitializeGame()
{
	for (int x=0; x<7; x++)
	{
		for (int y=0; y<15; y++)
		{
			for (int z=0; z<7; z++)
				SpaceArray[x][y][z] = EMPTY;
		}
	}
}

void Logic(OBJECT* pBlock)
{
	static int Time, StartTime = GetTickCount();			// Figure out how much time has passed since last frame
	Time = GetTickCount() - StartTime;
	StartTime = GetTickCount();

	for (int ms = 0; ms < Time; ms++)						// For every millisecond
	{
		--FallTime;											// Reduce time needed to MOVE the block DOWN BY 1 UNIT
		--MoveTime;											// Reduce time needed to MOVE the block by the PLAYER
		--RotateTime;										// Reduce time needed to ROTATE the block by the PLAYER

		if (FallTime < 0)
		{
			MoveBlockDown(pBlock);							// Move the Block down by 1 unit
			FallTime = FALLSPEED;							// Reset FallTime
		}
	}

	if (MoveTime < 0)										// If Block can be moved ( 150 millisecond movement cooldown)
	{
		if (ApplyMovement(pBlock))							// If a move OCCURED and was SUCCESSFUL
			MoveTime = 150;									// Reset Cooldown to 150 milliseconds
	}

	if (RotateTime < 0 && (Input.Keyboard.RotateX == true || Input.Keyboard.RotateY == true || Input.Keyboard.RotateZ == true))										// If Block can be rotated ( 150 millisecond movement cooldown)
	{
		if (ApplyRotation(pBlock))							// If a rotation OCCURED and was SUCCESSFUL
			RotateTime = 150;									// Reset Cooldown to 150 milliseconds
	}
}

OBJECT* CreateNewObject()
{
	time_t t;
	time(&t);
	srand(t);

	OBJECT* pBlock = new OBJECT[NumBricks];			// Allocate Memory To Hold 4 Bricks per Block

	Shape = rand()% 70;				// Generate A Random Shape
	if (Shape < 10) Shape = OSHAPE;
	if (Shape >= 10 && Shape < 20) Shape = ISHAPE;
	if (Shape >= 20 && Shape < 30) Shape = TSHAPE;
	if (Shape >= 30 && Shape < 40) Shape = SSHAPE;
	if (Shape >= 40 && Shape < 50) Shape = ZSHAPE;
	if (Shape >= 50 && Shape < 60) Shape = LSHAPE;
	if (Shape >= 60 && Shape < 70) Shape = JSHAPE;
	
	switch(Shape)									// Building The Shapes
	{
	case OSHAPE:									// OSHAPE
		{
			pBlock[0].x = rand() % 6;				// Create The Brick which acts as a Pivot For Rotation (Always Brick 0)
			pBlock[0].z = rand() % 6;
			pBlock[0].y = 2;						// Place At the top (2): 0 and 1 are reserved to store unrendered bricks

			pBlock[1].x = pBlock[0].x + 1;
			pBlock[2].x = pBlock[1].x;
			pBlock[3].x = pBlock[0].x;

			pBlock[1].z = pBlock[0].z;
			pBlock[2].z = pBlock[3].z = pBlock[0].z + 1;

			pBlock[1].y = pBlock[2].y = pBlock[3].y = pBlock[0].y;
		} break;

	case ISHAPE:
		{
			pBlock[0].x = rand() % 7;
			pBlock[0].z = rand() % 4 + 1;
			pBlock[0].y = 2;

			pBlock[1].x = pBlock[2].x = pBlock[3].x = pBlock[0].x;
			pBlock[1].z = pBlock[0].z - 1;
			pBlock[2].z = pBlock[0].z + 1;
			pBlock[3].z = pBlock[2].z + 1;

			pBlock[1].y = pBlock[2].y = pBlock[3].y = pBlock[0].y;
		} break;

	case TSHAPE:
		{
			pBlock[0].x = rand() % 5 + 1;
			pBlock[0].z = rand()% 7;
			pBlock[0].y = 2;

			pBlock[1].x = pBlock[0].x - 1;
			pBlock[2].x = pBlock[0].x + 1;
			pBlock[3].x = pBlock[0].x;

			pBlock[1].z = pBlock[2].z = pBlock[3].z = pBlock[0].z;
			
			pBlock[1].y = pBlock[2].y = pBlock[0].y;
			pBlock[3].y = pBlock[0].y - 1;
		} break;

	case SSHAPE:
		{
			pBlock[0].x = rand() % 5 + 1;
			pBlock[0].z = rand() % 7;
			pBlock[0].y = 2;

			pBlock[1].x = pBlock[0].x - 1;
			pBlock[2].x = pBlock[0].x;
			pBlock[3].x = pBlock[2].x + 1;

			pBlock[1].z = pBlock[2].z = pBlock[3].z = pBlock[0].z;

			pBlock[1].y = pBlock[0].y;
			pBlock[2].y = pBlock[3].y = pBlock[0].y - 1;
		} break;

	case ZSHAPE:
		{
			pBlock[0].x = rand() % 5 + 1;
			pBlock[0].z = rand() % 7;
			pBlock[0].y = 2;

			pBlock[1].x = pBlock[0].x + 1;
			pBlock[2].x = pBlock[0].x;
			pBlock[3].x = pBlock[2].x - 1;

			pBlock[1].z = pBlock[2].z = pBlock[3].z = pBlock[0].z;

			pBlock[1].y = pBlock[0].y;
			pBlock[2].y = pBlock[3].y = pBlock[0].y - 1;
		} break;

	case LSHAPE:
		{
			pBlock[0].x = rand() % 7;
			pBlock[0].z = rand() % 6;
			pBlock[0].y = 1;

			pBlock[1].x = pBlock[2].x = pBlock[3].x = pBlock[0].x;

			pBlock[3].z = pBlock[0].z + 1;
			pBlock[1].z = pBlock[2].z = pBlock[0].z;

			pBlock[3].y = pBlock[2].y = pBlock[0].y + 1;
			pBlock[1].y = pBlock[0].y - 1;
		} break;

	case JSHAPE:
		{
			pBlock[0].x = rand() % 7;
			pBlock[0].z = rand() % 6 + 1;
			pBlock[0].y = 1;

			pBlock[1].x = pBlock[2].x = pBlock[3].x = pBlock[0].x;

			pBlock[3].z = pBlock[0].z - 1;
			pBlock[1].z = pBlock[2].z = pBlock[0].z;

			pBlock[3].y = pBlock[2].y = pBlock[0].y + 1;
			pBlock[1].y = pBlock[0].y - 1;
		} break;
	}
	
	UpdateSpaceArray(pBlock, SAMEBLOCK);

	return pBlock;
}

void UpdateSpaceArray(OBJECT* pBlock, int Type)
{	
	for (int Num=0; Num<NumBricks; Num++)
		SpaceArray[pBlock[Num].x][pBlock[Num].y][pBlock[Num].z] = Type;	
}

int MoveBlockDown(OBJECT* pBlock)
{
	if (CheckForCollision(pBlock) && WithinWalls(pBlock, 0, 1, 0))
	{
		UpdateSpaceArray(pBlock, EMPTY);

		for (int Num=0;Num<NumBricks;Num++)
			++pBlock[Num].y;
	
		UpdateSpaceArray(pBlock, SAMEBLOCK);
	}

	else
	{
		for (int Num=0;Num<NumBricks;Num++)
			SpaceArray[pBlock[Num].x][pBlock[Num].y][pBlock[Num].z] = FULL;
		NewBlock = true;
	}

	return 0;
}

bool CheckForCollision(OBJECT* pBlock)
{
	for (int Num=0;Num<NumBricks;Num++)
	{
		if (SpaceArray[pBlock[Num].x][pBlock[Num].y + 1][pBlock[Num].z] == FULL)
			return false;
	}
	return true;
}

bool WithinWalls(OBJECT* pBlock, int x, int y, int z)
{	
	for (int Num=0;Num<NumBricks;Num++)
	{
		if ((pBlock[Num].x + x > 6) || (pBlock[Num].x + x < 0) ||
			(pBlock[Num].y + y > 14) ||
			(pBlock[Num].z + z > 6) || (pBlock[Num].z + z < 0))
			return false;
	}
	return true;
}

bool ApplyMovement(OBJECT* pBlock)
{
	if (Input.Keyboard.MoveForward == true)						// If the Block is being moved FORWARDS
	{
		for (int Num=0;Num<NumBricks;Num++)						// For every brick
		{
			if (SpaceArray[pBlock[Num].x][pBlock[Num].y][pBlock[Num].z - 1] == FULL)	// If the moved block intersects
				return false;															// another block, return false
		}
		if (!WithinWalls(pBlock, 0, 0, -1))						// If the Moved Block is NOT inside the walls, return false
			return false;

		UpdateSpaceArray(pBlock, EMPTY);						// Move is Valid. Empty Original Block position
		for (int Num=0; Num<NumBricks; Num++)					// For every brick in the block
				pBlock[Num].z -= 1;								// Move the brick
		UpdateSpaceArray(pBlock, SAMEBLOCK);					// Fill New Block position
		return true;											// Move successful
	}

	if (Input.Keyboard.MoveBackward == true)						// If the Block is being moved BACKWARDS
	{
		for (int Num=0;Num<NumBricks;Num++)						// For every brick
		{
			if (SpaceArray[pBlock[Num].x][pBlock[Num].y][pBlock[Num].z + 1] == FULL)	// If the moved block intersects
				return false;															// another block, return false
		}
		if (!WithinWalls(pBlock, 0, 0, 1))						// If the Moved Block is NOT inside the walls, return false
			return false;

		UpdateSpaceArray(pBlock, EMPTY);						// Move is Valid. Empty Original Block position
		for (int Num=0; Num<NumBricks; Num++)					// For every brick in the block
				pBlock[Num].z += 1;								// Move the brick
		UpdateSpaceArray(pBlock, SAMEBLOCK);					// Fill New Block position
		return true;											// Move successful
	}

	if (Input.Keyboard.MoveRight == true)						// If the Block is being moved TO THE RIGHT
	{
		for (int Num=0;Num<NumBricks;Num++)						// For every brick
		{
			if (SpaceArray[pBlock[Num].x + 1][pBlock[Num].y][pBlock[Num].z] == FULL)	// If the moved block intersects
				return false;															// another block, return false
		}
		if (!WithinWalls(pBlock, 1, 0, 0))						// If the Moved Block is NOT inside the walls, return false
			return false;

		UpdateSpaceArray(pBlock, EMPTY);						// Move is Valid. Empty Original Block position
		for (int Num=0; Num<NumBricks; Num++)					// For every brick in the block
				pBlock[Num].x += 1;								// Move the brick
		UpdateSpaceArray(pBlock, SAMEBLOCK);					// Fill New Block position
		return true;											// Move successful
	}

	if (Input.Keyboard.MoveLeft == true)						// If the Block is being moved TO THE LEFT
	{
		for (int Num=0;Num<NumBricks;Num++)						// For every brick
		{
			if (SpaceArray[pBlock[Num].x - 1][pBlock[Num].y][pBlock[Num].z] == FULL)	// If the moved block intersects
				return false;															// another block, return false
		}
		if (!WithinWalls(pBlock, -1, 0, 0))						// If the Moved Block is NOT inside the walls, return false
			return false;

		UpdateSpaceArray(pBlock, EMPTY);						// Move is Valid. Empty Original Block position
		for (int Num=0; Num<NumBricks; Num++)					// For every brick in the block
				pBlock[Num].x -= 1;								// Move the brick
		UpdateSpaceArray(pBlock, SAMEBLOCK);					// Fill New Block position
		return true;											// Move successful
	}
}

bool ApplyRotation(OBJECT* pBlock)
{
	OBJECT* pTempBlock = new OBJECT[4];

	int rMatrix[3] = {0,0,0};
	int FinalMatrix[3] = {0,0,0};

	int RotateArX[3][3] = { 1, 0, 0,
							0, cos(Input.Keyboard.Angle), -sin(Input.Keyboard.Angle),
							0, sin(Input.Keyboard.Angle), cos(Input.Keyboard.Angle), };
	
	int RotateArY[3][3] = { cos(Input.Keyboard.Angle), 0, sin(Input.Keyboard.Angle),
							0,1,0,
							-sin(Input.Keyboard.Angle),0, cos(Input.Keyboard.Angle), };
	
	float RotateArZ[3][3] = { cos(Input.Keyboard.Angle), -sin(Input.Keyboard.Angle), 0,
							sin(Input.Keyboard.Angle), cos(Input.Keyboard.Angle), 0,
							0,0,1,};

	for (int Num=0;Num<NumBricks;Num++)					// For every Brick in the Block
	{
		rMatrix[0] = pBlock[Num].x - pBlock[0].x;		// Fill rMatrix with x,y,z values relative to the pivot Block (0)
		rMatrix[1] = pBlock[Num].y - pBlock[0].y;
		rMatrix[2] = pBlock[Num].z - pBlock[0].z;

		if (Input.Keyboard.RotateX)							// If the Player rotated the Block around X
		{
			for (int j=0;j<3;j++)
				FinalMatrix[j] = rMatrix[0] * RotateArX[j][0] + rMatrix[1] * RotateArX[j][1]
								+ rMatrix[2] * RotateArX[j][2];
		}

		if (Input.Keyboard.RotateY)							// If the Player rotated the Block around Y
		{
			for (int j=0;j<3;j++)
				FinalMatrix[j] = rMatrix[0] * RotateArY[j][0] + rMatrix[1] * RotateArY[j][1]
								+ rMatrix[2] * RotateArY[j][2];
		}

		if (Input.Keyboard.RotateZ)							// If the Player rotated the Block around Z
		{
			for (int j=0;j<3;j++)
				FinalMatrix[j] = rMatrix[0] * RotateArZ[j][0] + rMatrix[1] * RotateArZ[j][1]
								+ rMatrix[2] * RotateArZ[j][2];
		}

		pTempBlock[Num].x = pBlock[0].x + FinalMatrix[0];		// Fill pTempBlock with the new rotated block location
		pTempBlock[Num].y = pBlock[0].y + FinalMatrix[1];
		pTempBlock[Num].z = pBlock[0].z + FinalMatrix[2];
	}

	if (!WithinWalls(pTempBlock,0,0,0))						// If the rotated Block is not inside the Grid Box walls,
	{														// deallocate the temporary Block and return false
		delete [] pTempBlock;
		return false;
	}

	if (!CheckForCollision(pTempBlock))						// If the rotated Block collides with other Bricks,
	{														// deallocate the temporary Block and return false
		delete [] pTempBlock;
		return false;
	}

	UpdateSpaceArray(pBlock, EMPTY);						// If everything clears, Clear the old Block positions
	for (int i=0;i<NumBricks;i++)							// For every Brick
	{
		pBlock[i].x = pTempBlock[i].x;						// Update Positions
		pBlock[i].y = pTempBlock[i].y;
		pBlock[i].z = pTempBlock[i].z;
	}
	UpdateSpaceArray(pBlock, SAMEBLOCK);					// Update the SpaceArray with the new Block positions

	delete [] pTempBlock;									// Deallocate memory
	return true;											// Rotation Successful, return true;
}




[Edited by - Waaayoff on February 25, 2010 1:37:52 PM]

Share this post


Link to post
Share on other sites
SOLVED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

The Z rotation matrix was a float! not an int! so i was getting results like 0.00000004 instead of 0 due to the percision of PI like i predicted!!




W0000000000000000000000000000000000000000000000000T I'M SO HAPPY!!

Share this post


Link to post
Share on other sites

This topic is 2849 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this