#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.x = pTempBlock.x; // Update Positions
pBlock.y = pTempBlock.y;
pBlock.z = pTempBlock.z;
}
UpdateSpaceArray(pBlock, SAMEBLOCK); // Update the SpaceArray with the new Block positions
delete [] pTempBlock; // Deallocate memory
return true; // Rotation Successful, return true;
}
An ANNOYING Bug in my Tetris 3D game?
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.
[Edited by - Waaayoff on February 25, 2010 1:37:52 PM]
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!!
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!!
Quote:Original post by Waaayoff
#define PI 3.14159265358979323846
That's a little overkill, double only has 16 decimal digits of precision.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement