Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation/src/modules/tetris/Tetris.cc @ 8661

Last change on this file since 8661 was 8661, checked in by landauf, 13 years ago

fixed two possible causes which stacked multiple tetris stones at the same position (happens if a stone moves so fast that it "tunnels" the topmost stone. before the collisions were checked from lower to upper, now its the other way round, which fixes the issue)

  • Property svn:eol-style set to native
File size: 8.3 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      ...
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file Tetris.cc
31    @brief Implementation of the Tetris class.
32*/
33
34#include "Tetris.h"
35
36#include "core/CoreIncludes.h"
37#include "core/EventIncludes.h"
38#include "core/command/Executor.h"
39
40#include "gamestates/GSLevel.h"
41
42#include "TetrisCenterpoint.h"
43#include "TetrisStone.h"
44#include "infos/PlayerInfo.h"
45
46namespace orxonox
47{
48
49    CreateUnloadableFactory(Tetris);
50
51    /**
52    @brief
53        Constructor. Registers and initializes the object.
54    */
55    Tetris::Tetris(BaseObject* creator) : Deathmatch(creator)
56    {
57        RegisterObject(Tetris);
58
59        this->activeStone_ = NULL;
60
61        // Pre-set the timer, but don't start it yet.
62        this->starttimer_.setTimer(1.0, false, createExecutor(createFunctor(&Tetris::startStone, this)));
63        this->starttimer_.stopTimer();
64
65        this->player_ = NULL;
66    }
67
68    /**
69    @brief
70        Destructor. Cleans up, if initialized.
71    */
72    Tetris::~Tetris()
73    {
74        if (this->isInitialized())
75            this->cleanup();
76    }
77
78    /**
79    @brief
80        Cleans up the Gametype.
81    */
82    void Tetris::cleanup()
83    {
84
85    }
86
87    void Tetris::tick(float dt)
88    {
89        SUPER(Tetris, tick, dt);
90
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();
98            }
99        }
100    }
101
102    bool Tetris::isValidMove(TetrisStone* stone, const Vector3& position)
103    {
104        assert(stone);
105
106        if(position.x < this->center_->getStoneSize()/2.0)  //!< If the stone touches the left edge of the level
107            return false;
108        else if(position.x > (this->center_->getWidth()-0.5)*this->center_->getStoneSize()) //!< If the stone touches the right edge of the level
109            return false;
110
111        for(std::vector<TetrisStone*>::const_iterator it = this->stones_.begin(); it != this->stones_.end(); ++it)
112        {
113            if(stone == *it)
114                continue;
115
116            const Vector3& currentStonePosition = (*it)->getPosition(); //!< Saves the position of the currentStone
117
118            if((position.x == currentStonePosition.x) && abs(position.y-currentStonePosition.y) < this->center_->getStoneSize())
119                return false;
120        }
121
122        return true;
123    }
124
125    bool Tetris::isValidStonePosition(TetrisStone* stone, const Vector3& position)
126    {
127        assert(stone);
128
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)
133                continue;
134
135            const Vector3& currentStonePosition = (*it)->getPosition(); //!< Saves the position of the currentStone
136
137            if((position.x == currentStonePosition.x) && (position.y < currentStonePosition.y + this->center_->getStoneSize()))
138            {
139                this->activeStone_->setPosition(Vector3(this->activeStone_->getPosition().x, currentStonePosition.y+this->center_->getStoneSize(), this->activeStone_->getPosition().z));
140                return false;
141            }// This case applies if the stones overlap partially vertically
142        }
143
144        // after we checked for collision with all stones, we also check for collision with the bottom
145        if(position.y < this->center_->getStoneSize()/2.0f) //!< If the stone has reached the bottom of the level
146        {
147            stone->setPosition(Vector3(stone->getPosition().x, this->center_->getStoneSize()/2.0f, stone->getPosition().z));
148            return false;
149        }
150
151        return true;
152    }
153
154    /**
155    @brief
156        Starts the Tetris minigame.
157    */
158    void Tetris::start()
159    {
160        if (this->center_ != NULL) // There needs to be a TetrisCenterpoint, i.e. the area the game takes place.
161        {
162            // Create the first stone.
163            this->createStone();
164        }
165        else // If no centerpoint was specified, an error is thrown and the level is exited.
166        {
167            COUT(1) << "Error: No Centerpoint specified." << std::endl;
168            GSLevel::startMainMenu();
169            return;
170        }
171
172        // Start the timer. After it has expired the stone is started.
173        this->starttimer_.startTimer();
174
175        // Set variable to temporarily force the player to spawn.
176        bool temp = this->bForceSpawn_;
177        this->bForceSpawn_ = true;
178
179        // Call start for the parent class.
180        Deathmatch::start();
181
182        // Reset the variable.
183        this->bForceSpawn_ = temp;
184    }
185
186    /**
187    @brief
188        Ends the Tetris minigame.
189    */
190    void Tetris::end()
191    {
192        this->cleanup();
193
194        // Call end for the parent class.
195        Deathmatch::end();
196    }
197
198    /**
199    @brief
200        Spawns player.
201    */
202    void Tetris::spawnPlayersIfRequested()
203    {
204        // Spawn a human player.
205        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
206            if (it->first->isHumanPlayer() && (it->first->isReadyToSpawn() || this->bForceSpawn_))
207                this->spawnPlayer(it->first);
208    }
209
210    /**
211    @brief
212        Spawns the input player.
213    @param player
214        The player to be spawned.
215    */
216    void Tetris::spawnPlayer(PlayerInfo* player)
217    {
218        assert(player);
219
220        if(this->player_ == NULL)
221        {
222            this->player_ = player;
223            this->players_[player].state_ = PlayerState::Alive;
224        }
225    }
226
227    /**
228    @brief
229        Starts the first stone.
230    */
231    void Tetris::startStone(void)
232    {
233        if(this->player_ == NULL)
234            return;
235       
236        if(this->activeStone_ != NULL)
237            this->player_->stopControl();
238       
239        // Make the last stone to be created the active stone.
240        this->activeStone_ = this->stones_.back();
241       
242        this->player_->startControl(this->activeStone_);
243        this->activeStone_->setVelocity(0.0f, -this->center_->getStoneSpeed(), 0.0f);
244    }
245
246    /**
247    @brief
248        Creates a new stone.
249    */
250    void Tetris::createStone(void)
251    {
252        // Create a new stone and add it to the list of stones.
253        TetrisStone* stone = new TetrisStone(this->center_);
254        this->stones_.push_back(stone);
255       
256        // Apply the stone template to the stone.
257        stone->addTemplate(this->center_->getStoneTemplate());
258       
259        // Attach the stone to the Centerpoint and set the position of the stone to be at the top middle.
260        this->center_->attach(stone);
261        float xPos = (this->center_->getWidth()/2 + ((this->center_->getWidth() % 2)*2-1)/2.0f)*this->center_->getStoneSize();
262        float yPos = (this->center_->getHeight()-0.5f)*this->center_->getStoneSize();
263        stone->setPosition(xPos, yPos, 0.0f);
264        stone->setGame(this);
265    }
266
267    /**
268    @brief
269        Get the player.
270    @return
271        Returns a pointer to the player. If there is no player, NULL is returned.
272    */
273    PlayerInfo* Tetris::getPlayer(void) const
274    {
275        return this->player_;
276    }
277
278    /**
279    @brief Set the TetrisCenterpoint (the playing field).
280    @param center A pointer to the TetrisCenterpoint to be set.
281    */
282    void Tetris::setCenterpoint(TetrisCenterpoint* center)
283    {
284        this->center_ = center;
285    }
286
287}
Note: See TracBrowser for help on using the repository browser.