/* * ORXONOX - the hottest 3D action shooter ever to exist * > www.orxonox.net < * * * License notice: * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Author: * ... * Co-authors: * ... * */ /** @file TetrisBrick.cc @brief Implementation of the TetrisBrick class. */ #include "TetrisBrick.h" #include "core/CoreIncludes.h" #include "core/XMLPort.h" #include "TetrisCenterpoint.h" #include "TetrisStone.h" #include "Tetris.h" #include "util/Math.h" namespace orxonox { RegisterClass(TetrisBrick); /** @brief Constructor. Registers and initializes the object. @ingroup Tetris */ TetrisBrick::TetrisBrick(Context* context): ControllableEntity(context) { RegisterObject(TetrisBrick); this->shapeIndex_ = 1 + static_cast(rnd(6.0f)); //stonesPerBrick_ = 4; //delay_ = false; this->delayTimer_.setTimer(0.2f, false, createExecutor(createFunctor(&TetrisBrick::enableMovement, this))); this->lockRotation_ = false; this->tetris_ = this->getTetris(); this->size_ = 10.0f; //TODO: fix this via this->tetris_->center_->getStoneSize(); this->rotationCount_ = 0; this->createBrick(); //shapeIndex_ == 0) this->stonesPerBrick_ = 1; for (unsigned int i = 0; i < this->stonesPerBrick_; i++) { // Create a new stone and add it to the brick. TetrisStone* stone = new TetrisStone(this->getContext()); this->brickStones_.push_back(stone); this->attach(stone); this->formBrick(stone, i); if(this->tetris_ != nullptr) { stone->setGame(this->tetris_); if(this->tetris_->getCenterpoint() != nullptr) stone->addTemplate(this->tetris_->getCenterpoint()->getStoneTemplate()); else orxout()<< "tetris_->getCenterpoint == nullptr in TetrisBrick.cc"<< endl; } else orxout()<< "tetris_ == nullptr in TetrisBrick.cc"<< endl; } } /** @brief This function creates the shape of a TetrisBrick. ! Spaghetti-Code ! @param i The stone's number. @param stone The TetrisStone that is placed relative to the brick's position. */ void TetrisBrick::formBrick(TetrisStone* stone, unsigned int i) { if(i == 0) //setting the first stone as { stone->setPosition(0.0f, 0.0f, 0.0f); } else if(i == 1) { stone->setPosition(0.0f, size_, 0.0f); } else if(i == 2) { if(this->shapeIndex_ == 1 || this->shapeIndex_ == 6 || this->shapeIndex_ == 7) { stone->setPosition(0.0f, 2*size_, 0.0f); } else if(this->shapeIndex_ == 3 || this->shapeIndex_ == 4|| this->shapeIndex_ == 5) { stone->setPosition(size_, 0, 0.0f); } else if(this->shapeIndex_ == 2) { stone->setPosition(-size_, 0, 0.0f); } } else if(i == 3) { if(this->shapeIndex_ == 2 || this->shapeIndex_ == 5) { stone->setPosition(size_, size_, 0.0f); } else if(this->shapeIndex_ == 1) { stone->setPosition(0, 3*size_, 0.0f); } else if(this->shapeIndex_ == 3 || this->shapeIndex_ == 7) { stone->setPosition(-size_, 0, 0.0f); } else if(this->shapeIndex_ == 4) { stone->setPosition(-size_, size_, 0.0f); } else if(this->shapeIndex_ == 6) { stone->setPosition(size_, 0, 0.0f); } } } bool TetrisBrick::isValidMove(const Vector3& position, bool isRotation = false) { return this->tetris_->isValidMove(this,position, isRotation); } TetrisStone* TetrisBrick::getStone(unsigned int i) { if(i < this->brickStones_.size()) return this->brickStones_[i]; else return nullptr; } Tetris* TetrisBrick::getTetris() { if (this->getGametype() != nullptr && this->getGametype()->isA(Class(Tetris))) { Tetris* tetrisGametype = orxonox_cast(this->getGametype()); return tetrisGametype; } return nullptr; } /** @brief Overloaded the function to rotate the Brick. @param value A vector whose first component is the angle by which to rotate. */ void TetrisBrick::moveFrontBack(const Vector2& value) { if(value.x < 0) //speedup on key down { Vector3 v_new = this->getVelocity()*1.2; if (v_new.y < -400.0f) //limiting the speed to prevent break throughs. v_new.y = -400.0f; this->setVelocity(v_new); } else if(!this->lockRotation_) //rotate when key up is pressed { if(!isValidMove(this->getPosition(), true)) //catch illegal rotations return; this->lockRotation_ = true; // multiple calls of this function have to be filtered out. this->rotationTimer_.setTimer(0.1f, false, createExecutor(createFunctor(&TetrisBrick::unlockRotation, this))); Quaternion q(Degree(90), Vector3::UNIT_Z); this->setOrientation(this->getOrientation()*q); //rotation: roll 90° this->rotationCount_ = (this->rotationCount_ + 1) % 4; } } /** @brief Overloaded the function to steer the Brick right and left @param value A vector whose first component is the direction in which we want to steer the Brick. */ void TetrisBrick::moveRightLeft(const Vector2& value) { if(!this->delay_) { const Vector3& position = this->getPosition(); Vector3 newPos = Vector3(position.x+value.x/abs(value.x)*this->size_, position.y, position.z); if(!this->isValidMove(newPos)) return; this->setPosition(newPos); this->delay_ = true; this->delayTimer_.startTimer(); } } /** @brief Is called when the player changed. */ void TetrisBrick::changedPlayer() { this->setVelocity(0.0f, 0.0f, 0.0f); } /** @brief Attaches stones to the Centerpoint. */ void TetrisBrick::releaseStones(TetrisCenterpoint* center) { assert(this->tetris_); for(auto & elem : this->brickStones_) { elem->detachFromParent(); elem->attachToParent(center); elem->setPosition(this->getPosition()+this->tetris_->rotateVector(elem->getPosition(),this->rotationCount_ )); } this->brickStones_.clear(); } }