-
Notifications
You must be signed in to change notification settings - Fork 3
/
TetrisGameState.pde
137 lines (105 loc) · 3.29 KB
/
TetrisGameState.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
static final int MoveLeft = -1;
static final int MoveRight = 1;
boolean isBlockStuck(Game game)
{
Block block = game.fallingBlock;
if (block == null)
return false;
boolean[][] blocks = game.blocks;
BlockPart[] parts = block.parts;
boolean stuck = false;
for (int i = 0; (i < BlockPartsCount) && (!stuck); i++) {
if (parts[i].xPos >= 0 && parts[i].yPos >= 0)
stuck = stuck
|| parts[i].yPos + 1 >= game.wellHeight
|| blocks[parts[i].xPos][parts[i].yPos + 1];
}
return stuck;
}
void fixateBlock(Game game) {
Block block = game.fallingBlock;
if (block == null)
return;
BlockPart[] parts = block.parts;
for (int i = 0; i < BlockPartsCount; i++) {
if (parts[i].yPos >= 0)
game.blocks[parts[i].xPos][parts[i].yPos] = true;
}
game.fallingBlock = null;
}
void eraseFilledLines(Game game) {
for (int y = game.wellHeight - 1; y >= 0;) {
boolean erasable = true;
for (int x = 0; x < game.wellWidth; x++)
erasable = erasable && game.blocks[x][y];
if (erasable) {
// Move blocks down
for (int y2 = y - 1; y2 >= 0; y2--)
for (int x = 0; x < game.wellWidth; x++)
game.blocks[x][y2 + 1] = game.blocks[x][y2];
// Top level needs to be cleared.
for (int x = 0; x < game.wellWidth; x++)
game.blocks[x][0] = false;
} else {
y--;
}
}
game.erasingNeeded = false;
}
void enableErasing(Game game) {
game.erasingNeeded = true;
}
void generateRandomBlock(Game game) {
int blockType = int(random(0, BlocksCount));
int blockDirection = int(random(0, DirectionsCount));
int xPos = int(random(0, game.wellWidth));
game.fallingBlock = createBlock(blockType, blockDirection, xPos, -1, game.wellWidth);
}
boolean isBlockMovingPossible(Game game, int moveDirection) {
Block block = game.fallingBlock;
if (block == null)
return false;
boolean possible = true;
for (int i = 0; i < BlockPartsCount; i++) {
int desiredXPos = block.parts[i].xPos + moveDirection;
int desiredYPos = block.parts[i].yPos;
possible = possible
&& (moveDirection == MoveLeft ? desiredXPos >= 0 : desiredXPos < game.wellWidth);
if ((desiredYPos >= 0) && (desiredYPos < game.wellHeight))
possible = possible && !(game.blocks[desiredXPos][desiredYPos]);
}
return possible;
}
void moveBlock(Game game, int moveDirection) {
if (isBlockMovingPossible(game, moveDirection))
moveBlockHorizontal(game.fallingBlock, moveDirection);
}
void makeBlockFall(Game game) {
if (isBlockStuck(game)) {
fixateBlock(game);
enableErasing(game);
generateRandomBlock(game);
} else {
makeBlockFall(game.fallingBlock);
}
}
void rotateBlock(Game game) {
Block block = game.fallingBlock;
Block rotated = createBlock(block.type, rotateDirection(block.direction), block.xPos, block.yPos, game.wellWidth);
game.fallingBlock = rotated;
}
Game updateGameState(Game game) {
Game currentGame = game;
if (currentGame.erasingNeeded) {
eraseFilledLines(currentGame);
} else if (currentGame.fallingBlock != null) {
makeBlockFall(currentGame);
}
return currentGame;
}
boolean isGameOver(Game game) {
for (int i = 0; i < game.wellWidth; i++)
if (game.blocks[i][0])
return true;
return false;
}