Changeset 9348 for code/trunk/src/modules/tetris/Tetris.cc
- Timestamp:
- Aug 30, 2012, 11:08:17 PM (12 years ago)
- Location:
- code/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
- Property svn:ignore
-
old new 1 .project 1 2 build 2 3 codeblocks 4 dependencies 3 5 vs 4 dependencies
-
- Property svn:mergeinfo changed
- Property svn:ignore
-
code/trunk/src/modules/tetris/Tetris.cc
r8858 r9348 23 23 * ... 24 24 * Co-authors: 25 * ... 26 * 25 * Johannes Ritz 26 * 27 * 28 * 29 * 30 *TASK c) end the game in a nicer way 31 *TASK d) save the highscore 32 *TASK e) eye candy 27 33 */ 28 34 … … 42 48 #include "TetrisCenterpoint.h" 43 49 #include "TetrisStone.h" 50 #include "TetrisBrick.h" 44 51 #include "infos/PlayerInfo.h" 45 52 … … 52 59 @brief 53 60 Constructor. Registers and initializes the object. 61 @ingroup Tetris 54 62 */ 55 63 Tetris::Tetris(BaseObject* creator) : Deathmatch(creator) … … 57 65 RegisterObject(Tetris); 58 66 59 this->active Stone_ = NULL;67 this->activeBrick_ = 0; 60 68 61 69 // Pre-set the timer, but don't start it yet. 62 this->starttimer_.setTimer(1.0, false, createExecutor(createFunctor(&Tetris::start Stone, this)));70 this->starttimer_.setTimer(1.0, false, createExecutor(createFunctor(&Tetris::startBrick, this))); 63 71 this->starttimer_.stopTimer(); 64 72 65 73 this->player_ = NULL; 74 this->setHUDTemplate("TetrisHUD"); 75 this->futureBrick_ = 0; 66 76 } 67 77 … … 82 92 void Tetris::cleanup() 83 93 { 84 94 if (this->activeBrick_) 95 { 96 this->activeBrick_->destroy(); 97 this->activeBrick_ = 0; 98 } 99 if (this->futureBrick_) 100 { 101 this->futureBrick_->destroy(); 102 this->futureBrick_ = 0; 103 } 104 105 for (std::list<SmartPtr<TetrisStone> >::iterator it = this->stones_.begin(); it != this->stones_.end(); ++it) 106 (*it)->destroy(); 107 this->stones_.clear(); 85 108 } 86 109 … … 89 112 SUPER(Tetris, tick, dt); 90 113 91 if(this->activeStone_ != NULL) 92 { 93 if(!this->isValidStonePosition(this->activeStone_, this->activeStone_->getPosition())) 94 { 95 this->activeStone_->setVelocity(Vector3::ZERO); 96 this->createStone(); 97 this->startStone(); 114 if((this->activeBrick_ != NULL)&&(!this->hasEnded())) 115 { 116 if(!this->isValidBrickPosition(this->activeBrick_)) 117 { 118 for (unsigned int i = 0; i < this->activeBrick_->getNumberOfStones(); i++) 119 this->stones_.push_back(this->activeBrick_->getStone(i)); 120 this->activeBrick_->setVelocity(Vector3::ZERO); 121 this->activeBrick_->releaseStones(this->center_); 122 this->findFullRows(); 123 this->startBrick(); 98 124 } 99 125 } … … 109 135 return false; 110 136 111 for(std::vector<TetrisStone*>::const_iterator it = this->stones_.begin(); it != this->stones_.end(); ++it) 112 { 113 if(stone == *it) 114 continue; 115 137 for(std::list<SmartPtr<TetrisStone> >::const_iterator it = this->stones_.begin(); it != this->stones_.end(); ++it) 138 { 116 139 const Vector3& currentStonePosition = (*it)->getPosition(); //!< Saves the position of the currentStone 117 140 … … 123 146 } 124 147 148 /** 149 @brief 150 Check for each stone in a brick if it is moved the right way. 151 */ 152 bool Tetris::isValidMove(TetrisBrick* brick, const Vector3& position, bool isRotation = false) 153 { 154 assert(brick); 155 156 for (unsigned int i = 0; i < brick->getNumberOfStones(); i++ ) 157 { 158 TetrisStone* stone = brick->getStone(i); 159 Vector3 stonePosition; //the current stone's offset to position 160 if(isRotation) 161 stonePosition = rotateVector(stone->getPosition(), brick->getRotationCount()+1); 162 else 163 stonePosition = rotateVector(stone->getPosition(), brick->getRotationCount()); 164 165 if(! this->isValidMove(stone, position + stonePosition )) 166 { 167 return false; 168 } 169 170 //catch illegal rotation (such that collisions with ground are not permitted) 171 if(isRotation) 172 { 173 if((position + stonePosition).y < this->center_->getStoneSize()/2.0f) //!< If the stone has reached the bottom of the level 174 { 175 return false; 176 } 177 } 178 } 179 return true; 180 181 } 182 183 184 125 185 bool Tetris::isValidStonePosition(TetrisStone* stone, const Vector3& position) 126 186 { 127 187 assert(stone); 128 188 129 // we use a reverse iterator because we have to check for collisions with the topmost stones first 130 for(std::vector<TetrisStone*>::const_reverse_iterator it = this->stones_.rbegin(); it != this->stones_.rend(); ++it) 131 { 132 if(stone == *it) 189 // check for collisions with all stones 190 for(std::list<SmartPtr<TetrisStone> >::const_iterator it = this->stones_.begin(); it != this->stones_.end(); ++it) 191 { 192 //Vector3 currentStonePosition = rotateVector((*it)->getPosition(), this->activeBrick_->getRotationCount()); 193 const Vector3& currentStonePosition = (*it)->getPosition(); //!< Saves the position of the currentStone 194 //!< Saves the position of the currentStone 195 196 //filter out cases where the falling stone is already below a steady stone 197 if(position.y < currentStonePosition.y - this->center_->getStoneSize()/2.0f) 133 198 continue; 134 135 const Vector3& currentStonePosition = (*it)->getPosition(); //!< Saves the position of the currentStone136 137 199 if((position.x == currentStonePosition.x) && (position.y < currentStonePosition.y + this->center_->getStoneSize())) 138 200 { 139 this->activeStone_->setPosition(Vector3(this->activeStone_->getPosition().x, currentStonePosition.y+this->center_->getStoneSize(), this->activeStone_->getPosition().z)); 201 float y_offset = static_cast<int>((this->activeBrick_->getPosition().y-currentStonePosition.y+10)/10)*10 + currentStonePosition.y; 202 if(y_offset < 0) //filter out extreme cases (very rare bug) 203 y_offset = 0; 204 this->activeBrick_->setPosition(Vector3(this->activeBrick_->getPosition().x, y_offset, this->activeBrick_->getPosition().z)); 140 205 return false; 141 206 }// This case applies if the stones overlap partially vertically … … 145 210 if(position.y < this->center_->getStoneSize()/2.0f) //!< If the stone has reached the bottom of the level 146 211 { 147 stone->setPosition(Vector3(stone->getPosition().x, this->center_->getStoneSize()/2.0f, stone->getPosition().z)); 212 float yOffset = stone->getPosition().y + this->center_->getStoneSize()/2.0f;//calculate offset 213 if(yOffset < 0) //catch brake-throughs 214 yOffset = 0; 215 this->activeBrick_->setPosition(Vector3(this->activeBrick_->getPosition().x, yOffset, this->activeBrick_->getPosition().z)); 148 216 return false; 149 217 } … … 151 219 return true; 152 220 } 221 /** 222 * @brief This function determines wether a brick touches another brick or the ground. 223 * 224 */ 225 bool Tetris::isValidBrickPosition(TetrisBrick* brick) 226 { 227 assert(brick); 228 229 const Vector3& brickPosition = this->activeBrick_->getPosition(); 230 231 // check all stones in the brick 232 for (unsigned int i = 0; i < brick->getNumberOfStones(); i++ ) 233 { 234 TetrisStone* stone = brick->getStone(i); 235 const Vector3& stonePosition = rotateVector(stone->getPosition(), brick->getRotationCount()); 236 if(! this->isValidStonePosition(stone, brickPosition + stonePosition) ) 237 { 238 // recurse because all stones have to checked again after the brick was re-positioned 239 this->isValidBrickPosition(brick); 240 return false; 241 } 242 } 243 return true; 244 } 245 246 /** 247 @brief 248 A Vector3 is rolled 90 * degrees * amount (anticlockwise rotation) 249 */ 250 Vector3 Tetris::rotateVector(Vector3 position, unsigned int amount) 251 { 252 float temp = 0; 253 for(unsigned int i = 0; i < amount; i++) 254 { 255 temp = position.x; 256 position.x = -position.y; 257 position.y = temp; 258 } 259 return position; 260 } 153 261 154 262 /** … … 160 268 if (this->center_ != NULL) // There needs to be a TetrisCenterpoint, i.e. the area the game takes place. 161 269 { 162 // Create the first stone.163 this->create Stone();270 // Create the first brick. 271 this->createBrick(); 164 272 } 165 273 else // If no centerpoint was specified, an error is thrown and the level is exited. … … 190 298 void Tetris::end() 191 299 { 300 this->activeBrick_->setVelocity(Vector3::ZERO); 301 if(this->activeBrick_ != NULL) 302 { 303 this->player_->stopControl(); 304 } 305 192 306 this->cleanup(); 193 307 … … 225 339 } 226 340 227 /** 228 @brief 229 Starts the first stone. 230 */ 231 void Tetris::startStone(void) 341 342 343 void Tetris::startBrick(void) 232 344 { 233 345 if(this->player_ == NULL) … … 235 347 236 348 unsigned int cameraIndex = 0; 237 if(this->active Stone_ != NULL)349 if(this->activeBrick_ != NULL) 238 350 { 239 351 // Get camera settings 240 cameraIndex = this->active Stone_->getCurrentCameraIndex();352 cameraIndex = this->activeBrick_->getCurrentCameraIndex(); 241 353 this->player_->stopControl(); 242 } 243 244 // Make the last stone to be created the active stone. 245 this->activeStone_ = this->stones_.back(); 246 247 this->player_->startControl(this->activeStone_); 248 this->activeStone_->setVelocity(0.0f, -this->center_->getStoneSpeed(), 0.0f); 249 this->activeStone_->setCameraPosition(cameraIndex); 250 } 251 252 /** 253 @brief 254 Creates a new stone. 255 */ 256 void Tetris::createStone(void) 257 { 258 // Create a new stone and add it to the list of stones. 259 TetrisStone* stone = new TetrisStone(this->center_); 260 this->stones_.push_back(stone); 261 262 // Apply the stone template to the stone. 263 stone->addTemplate(this->center_->getStoneTemplate()); 264 265 // Attach the stone to the Centerpoint and set the position of the stone to be at the top middle. 266 this->center_->attach(stone); 354 // destroy old active brick 355 this->activeBrick_->destroy(); 356 } 357 358 // Make the last brick to be created the active brick. 359 this->activeBrick_ = this->futureBrick_; 360 this->futureBrick_ = 0; 361 362 // set its position 363 this->player_->startControl(this->activeBrick_); 267 364 float xPos = (this->center_->getWidth()/2 + ((this->center_->getWidth() % 2)*2-1)/2.0f)*this->center_->getStoneSize(); 268 365 float yPos = (this->center_->getHeight()-0.5f)*this->center_->getStoneSize(); 269 stone->setPosition(xPos, yPos, 0.0f); 270 stone->setGame(this); 271 } 366 this->activeBrick_->setPosition(xPos, yPos, 0.0f); 367 this->activeBrick_->setVelocity(0.0f, -this->center_->getStoneSpeed(), 0.0f); 368 this->activeBrick_->setCameraPosition(cameraIndex); 369 370 // create a new future brick 371 this->createBrick(); 372 373 // check if the new brick is in a valid position, otherwise end the game 374 if (!this->isValidBrickPosition(this->activeBrick_)) 375 this->end(); 376 } 377 378 void Tetris::createBrick(void) //TODO: random rotation offset between 0 and 3 (times 90°) 379 { 380 // create new futureBrick_ 381 this->futureBrick_ = new TetrisBrick(this->center_); 382 383 384 // Apply the stone template to the stone. 385 this->futureBrick_->addTemplate(this->center_->getBrickTemplate()); 386 387 // Attach the brick to the Centerpoint and set the position of the brick to be at the left side. 388 this->center_->attach(this->futureBrick_); 389 float xPos = (this->center_->getWidth()*1.6f + ((this->center_->getWidth() % 2)*2-1)/2.0f)*this->center_->getStoneSize(); 390 float yPos = (this->center_->getHeight()-5.1f)*this->center_->getStoneSize(); 391 this->futureBrick_->setPosition(xPos, yPos, 0.0f); 392 this->futureBrick_->setGame(this); 393 } 394 272 395 273 396 /** … … 282 405 } 283 406 407 /*TetrisCenterpoint* Tetris::getCenterpoint(void) const 408 { 409 return this->center_; 410 }*/ 411 284 412 /** 285 413 @brief Set the TetrisCenterpoint (the playing field). … … 291 419 } 292 420 421 /** 422 @brief Check each row if it is full. Removes all full rows. Update 423 @brief Manages score. 424 */ 425 void Tetris::findFullRows() 426 { 427 unsigned int correctPosition = 0; 428 unsigned int stonesPerRow = 0; 429 for (unsigned int row = 0; row < this->center_->getHeight(); row++) 430 { 431 stonesPerRow = 0; 432 for(std::list<SmartPtr<TetrisStone> >::iterator it = this->stones_.begin(); it != this->stones_.end(); ) 433 { 434 std::list<SmartPtr<TetrisStone> >::iterator it_temp = it++; 435 correctPosition = static_cast<unsigned int>(((*it_temp)->getPosition().y - 5)/this->center_->getStoneSize()); 436 if(correctPosition == row) 437 { 438 stonesPerRow++; 439 if(stonesPerRow == this->center_->getWidth()) 440 { 441 clearRow(row); 442 row--; //the row counter has to be decreased in order to detect multiple rows! 443 this->playerScored(this->player_);// add points 444 //increase the stone's speed 445 this->center_->setStoneSpeed(this->center_->getStoneSpeed()+1.0f); 446 } 447 } 448 } 449 } 450 } 451 452 void Tetris::clearRow(unsigned int row) 453 {// clear the full row 454 for(std::list<SmartPtr<TetrisStone> >::iterator it = this->stones_.begin(); it != this->stones_.end(); ) 455 { 456 if(static_cast<unsigned int>(((*it)->getPosition().y - 5)/this->center_->getStoneSize()) == row) 457 { 458 (*it)->destroy(); 459 this->stones_.erase(it++); 460 } 461 else 462 ++it; 463 } 464 // adjust height of stones above the deleted row //TODO: check if this could be a source of a bug. 465 for(std::list<SmartPtr<TetrisStone> >::iterator it = this->stones_.begin(); it != this->stones_.end(); ++it) 466 { 467 if(static_cast<unsigned int>(((*it)->getPosition().y - 5)/this->center_->getStoneSize()) > row) 468 (*it)->setPosition((*it)->getPosition()-Vector3(0,10,0)); 469 } 470 471 } 472 473 293 474 }
Note: See TracChangeset
for help on using the changeset viewer.