Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Aug 30, 2012, 11:08:17 PM (12 years ago)
Author:
landauf
Message:

merged branch presentation2012merge back to trunk

Location:
code/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/modules/tetris/Tetris.cc

    r8858 r9348  
    2323 *      ...
    2424 *   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
    2733 */
    2834
     
    4248#include "TetrisCenterpoint.h"
    4349#include "TetrisStone.h"
     50#include "TetrisBrick.h"
    4451#include "infos/PlayerInfo.h"
    4552
     
    5259    @brief
    5360        Constructor. Registers and initializes the object.
     61    @ingroup Tetris
    5462    */
    5563    Tetris::Tetris(BaseObject* creator) : Deathmatch(creator)
     
    5765        RegisterObject(Tetris);
    5866
    59         this->activeStone_ = NULL;
     67        this->activeBrick_ = 0;
    6068
    6169        // Pre-set the timer, but don't start it yet.
    62         this->starttimer_.setTimer(1.0, false, createExecutor(createFunctor(&Tetris::startStone, this)));
     70        this->starttimer_.setTimer(1.0, false, createExecutor(createFunctor(&Tetris::startBrick, this)));
    6371        this->starttimer_.stopTimer();
    6472
    6573        this->player_ = NULL;
     74        this->setHUDTemplate("TetrisHUD");
     75        this->futureBrick_ = 0;
    6676    }
    6777
     
    8292    void Tetris::cleanup()
    8393    {
    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();
    85108    }
    86109
     
    89112        SUPER(Tetris, tick, dt);
    90113
    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();
    98124            }
    99125        }
     
    109135            return false;
    110136
    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        {
    116139            const Vector3& currentStonePosition = (*it)->getPosition(); //!< Saves the position of the currentStone
    117140
     
    123146    }
    124147
     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
    125185    bool Tetris::isValidStonePosition(TetrisStone* stone, const Vector3& position)
    126186    {
    127187        assert(stone);
    128188
    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)
    133198                continue;
    134 
    135             const Vector3& currentStonePosition = (*it)->getPosition(); //!< Saves the position of the currentStone
    136 
    137199            if((position.x == currentStonePosition.x) && (position.y < currentStonePosition.y + this->center_->getStoneSize()))
    138200            {
    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));
    140205                return false;
    141206            }// This case applies if the stones overlap partially vertically
     
    145210        if(position.y < this->center_->getStoneSize()/2.0f) //!< If the stone has reached the bottom of the level
    146211        {
    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));
    148216            return false;
    149217        }
     
    151219        return true;
    152220    }
     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    }
    153261
    154262    /**
     
    160268        if (this->center_ != NULL) // There needs to be a TetrisCenterpoint, i.e. the area the game takes place.
    161269        {
    162             // Create the first stone.
    163             this->createStone();
     270            // Create the first brick.
     271            this->createBrick();
    164272        }
    165273        else // If no centerpoint was specified, an error is thrown and the level is exited.
     
    190298    void Tetris::end()
    191299    {
     300        this->activeBrick_->setVelocity(Vector3::ZERO);
     301        if(this->activeBrick_ != NULL)
     302        {
     303            this->player_->stopControl();
     304        }
     305
    192306        this->cleanup();
    193307
     
    225339    }
    226340
    227     /**
    228     @brief
    229         Starts the first stone.
    230     */
    231     void Tetris::startStone(void)
     341
     342
     343    void Tetris::startBrick(void)
    232344    {
    233345        if(this->player_ == NULL)
     
    235347
    236348        unsigned int cameraIndex = 0;
    237         if(this->activeStone_ != NULL)
     349        if(this->activeBrick_ != NULL)
    238350        {
    239351            // Get camera settings
    240             cameraIndex = this->activeStone_->getCurrentCameraIndex();
     352            cameraIndex = this->activeBrick_->getCurrentCameraIndex();
    241353            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_);
    267364        float xPos = (this->center_->getWidth()/2 + ((this->center_->getWidth() % 2)*2-1)/2.0f)*this->center_->getStoneSize();
    268365        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
    272395
    273396    /**
     
    282405    }
    283406
     407    /*TetrisCenterpoint* Tetris::getCenterpoint(void) const
     408    {
     409        return this->center_;
     410    }*/
     411
    284412    /**
    285413    @brief Set the TetrisCenterpoint (the playing field).
     
    291419    }
    292420
     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
    293474}
Note: See TracChangeset for help on using the changeset viewer.