-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTetrisLogic.cpp
176 lines (166 loc) · 5.82 KB
/
TetrisLogic.cpp
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/**
* TetrisLogic.cpp
*
* $Revision$
* $Id$
*
* @see TetrisLogic.h
*
*/
#include "TetrisLogic.h"
#include "Ticker.h"
#include <iostream>
CTetrisLogic::CTetrisLogic() {
settings = &SConfig::getInstance();
m_previewBoardSize = settings->getValueAsInt("preview size");
//m_previewBoardHeight = settings->getValueAsInt("preview height");
m_previewBoardWidth = settings->getValueAsInt("preview width");
m_gameBoard = new CTetrisBoard(settings->getValueAsInt("board width"), settings->getValueAsInt("board height"));
initialize();
}
/**
* @deprecated didn't work well with configuration file and was never used anyway
*/
/*CTetrisLogic::CTetrisLogic(const int gameboardWidth, const int gameboardHeight) {
settings = &SConfig::getInstance();
m_gameBoard = new CTetrisBoard(gameboardWidth, gameboardHeight);
initialize();
}*/
void CTetrisLogic::initialize() {
// luodaan factory
m_factory = new CTetrominoFactory();
m_previewSpacingY = 5;
m_previewBoard = new CTetrisBoard(m_previewBoardWidth, m_previewSpacingY*m_previewBoardSize);
// luodaan nykyinen tetrominoe ja liitetään se gameBoardiin
m_currentTetromino = m_factory->createRandom();
m_currentTetromino->attach(m_gameBoard);
m_currentTetromino->setGhost(settings->getValueAsBool("ghost"));
m_stats = new CTetrisStats();
// luodaan previewTetrominoet ja liitetään ne previewBoardiin
for(int i=0; i<m_previewBoardSize; i++) {
m_previewTetrominoes[i] = m_factory->createRandom();
m_previewTetrominoes[i]->attach(m_previewBoard, m_previewSpacingY * i * -1 - m_previewSpacingY/2);
}
m_previewCount = 0;
m_gameOver = false;
m_moveLock = false;
m_running = false;
myTickTask = STicker::getInstance().registerListener(dynamic_cast<VTickListener*>(this), m_stats->getDropDelay());
}
CTetrisLogic::~CTetrisLogic() {
for(int i=0; i<m_previewBoardSize; i++) {
delete m_previewTetrominoes[i];
}
delete m_currentTetromino;
delete m_factory;
delete m_stats;
delete m_gameBoard;
delete m_previewBoard;
}
bool CTetrisLogic::start(void) {
if(!m_gameOver) {
m_running = true;
notifyGameState(VGameStateListener::RESUME);
return true;
}
return false;
}
void CTetrisLogic::handleCommand(VCommandListener::COMMAND cmd) {
/*if(m_gameOver) {
STicker::getInstance().stop();
return;
}*/
if(!m_running)
start();
if(m_running && !m_gameOver) {
switch(cmd) {
case GAME_COMMAND_LEFT:
m_currentTetromino->moveLeft();
break;
case GAME_COMMAND_RIGHT:
m_currentTetromino->moveRight();
break;
case GAME_COMMAND_ROTATE_CW:
m_currentTetromino->rotateRight();
break;
case GAME_COMMAND_ROTATE_CCW:
m_currentTetromino->rotateLeft();
break;
case GAME_COMMAND_SOFTDROP:
m_currentTetromino->moveDown();
// TODO: reset tick
break;
case GAME_COMMAND_HARDDROP:
m_currentTetromino->drop();
myTickTask->resetTick();
// TODO: reset tick
break;
case GAME_COMMAND_PAUSE:
m_running = false; // TODO: parempi pause. tämä on vaan tilapäinen
notifyGameState(VGameStateListener::PAUSE);
break;
case GAME_COMMAND_QUIT:
// TODO: pysäytä timer
m_gameOver = true;
notifyGameState(VGameStateListener::GAMEOVER); // abort running game
break;
default:
break;
}
} else if(m_gameOver && cmd == GAME_COMMAND_QUIT) {
notifyGameState(VGameStateListener::EXIT); // game already over - exit from game
}
}
int CTetrisLogic::handleTick() {
if(m_gameOver) {
myTickTask = 0;
return -1;
}
// testataan onko nykyinen palikka jos laskeutunut
if(!m_running)
return 10;
if(m_currentTetromino->hasLanded()) {
// käsketään lautaa tyhjäämään täydet rivit
int lines = m_gameBoard->clearFullLines();
m_stats->linesRemoved(lines);
// pyöräytetään palikoita
rotateTetrominoes();
} else {
// tiputetaan nykyistä palikkaa
m_currentTetromino->moveDown();
}
return m_stats->getDropDelay();
}
void CTetrisLogic::rotateTetrominoes() {
if(!m_gameOver) {
m_stats->tetrominoAdded();
// Tuhoaa nykyisen pelipalikan (currentTetromino)
delete m_currentTetromino;
// Irrottaa seuraavaksi vuorossa olevan preview-palikan previewBoardista
m_previewTetrominoes[0]->detach(true);
// Ottaa previewTetromino-taulukosta seuraavaksi vuorossa olevan nykyiseksi.
m_currentTetromino = m_previewTetrominoes[0];
// Nostaa jäljelle jääneiden preview-palikoiden vuoronumeroa yhdellä.
for(int i=0; i<m_previewBoardSize-1; i++) {
m_previewTetrominoes[i] = m_previewTetrominoes[i+1];
// Nostaa jäljelle jääneiden preview-palikoiden sijaintia previewBoardissa
m_previewTetrominoes[i]->moveUp(m_previewSpacingY);
}
// Luo preview-taulun loppuun uuden palikan.
m_previewTetrominoes[m_previewBoardSize-1] = m_factory->createRandom();
// Kiinnittää preview-taulun loppuun luodun palikan previewBoardiin omalle paikalleen
m_previewTetrominoes[m_previewBoardSize-1]->attach(m_previewBoard, m_previewSpacingY * m_previewBoardSize * -1 + m_previewSpacingY/2);
// Yrittää kiinnittää uuden nykyisen palikan gameBoardiin. Jos ei onnistu, peli loppuu
if(!m_currentTetromino->attach(m_gameBoard)) {
m_gameOver = true;
notifyGameState(VGameStateListener::GAMEOVER);
} else {
// asetetaan ghost päälle gameboardissa olevalle palikalle
m_currentTetromino->setGhost(settings->getValueAsBool("ghost"));
}
}
}
void CTetrisLogic::notifyGameState(VGameStateListener::GAMESTATE state) {
for(int i=0; i<m_listenerCount; i++)
listeners[i]->handleGameState(state);
}