Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/pCuts/src/modules/tetris/Tetris.cc @ 9085

Last change on this file since 9085 was 9085, checked in by jo, 13 years ago

backup checkin - still the same bugs experiencable

  • Property svn:eol-style set to native
File size: 12.0 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 "TetrisBrick.h"
45#include "infos/PlayerInfo.h"
46
47namespace orxonox
48{
49
50    CreateUnloadableFactory(Tetris);
51
52    /**
53    @brief
54        Constructor. Registers and initializes the object.
55    */
56    Tetris::Tetris(BaseObject* creator) : Deathmatch(creator)
57    {
58        RegisterObject(Tetris);
59
60        this->activeBrick_ = NULL;
61
62        // Pre-set the timer, but don't start it yet.
63        this->starttimer_.setTimer(1.0, false, createExecutor(createFunctor(&Tetris::startBrick, this)));
64        this->starttimer_.stopTimer();
65
66        this->player_ = NULL;
67    }
68
69    /**
70    @brief
71        Destructor. Cleans up, if initialized.
72    */
73    Tetris::~Tetris()
74    {
75        if (this->isInitialized())
76            this->cleanup();
77    }
78
79    /**
80    @brief
81        Cleans up the Gametype.
82    */
83    void Tetris::cleanup()
84    {
85        /*for(int i = 0;i < this->stones_.size(); i++) //TODO: Why isn't there any code like this
86        {                                              // compensating the 'new' statement?
87            delete this->stones_[i];
88        }//*/
89
90    }
91
92    void Tetris::tick(float dt)
93    {
94        SUPER(Tetris, tick, dt);
95
96        if(this->activeBrick_ != NULL)
97        {
98            if(!this->isValidBrickPosition(this->activeBrick_, this->activeBrick_->getPosition()))
99            {
100                this->activeBrick_->setVelocity(Vector3::ZERO);
101                this->activeBrick_->releaseStones(this->center_);
102                //delete this->activeBrick_; //releasing the memory
103                this->createBrick();
104                this->startBrick();
105            }
106        }
107    }
108
109    bool Tetris::isValidMove(TetrisStone* stone, const Vector3& position)
110    {
111        assert(stone);
112
113        if(position.x < this->center_->getStoneSize()/2.0)  //!< If the stone touches the left edge of the level
114            return false;
115        else if(position.x > (this->center_->getWidth()-0.5)*this->center_->getStoneSize()) //!< If the stone touches the right edge of the level
116            return false;
117
118        for(std::vector<TetrisStone*>::const_iterator it = this->stones_.begin(); it != this->stones_.end(); ++it)
119        {
120            if(stone == *it)
121                continue;
122
123            const Vector3& currentStonePosition = (*it)->getPosition(); //!< Saves the position of the currentStone
124            orxout()<< "position.x: " << position.x << endl;
125            orxout()<< "currentStonePosition.x: " << currentStonePosition.x << endl;
126            if(position.x == currentStonePosition.x)
127                orxout()<< "NON Valid Move Candidate" <<endl;
128
129            if((position.x == currentStonePosition.x) && abs(position.y-currentStonePosition.y) < this->center_->getStoneSize())
130                return false;
131        }
132
133        return true;
134    }
135
136    /**
137    @brief
138        Check for each stone in a brick if it is moved the right way.
139    */
140    bool Tetris::isValidMove(TetrisBrick* brick, const Vector3& position, bool isRotation = false)
141    {
142        assert(brick);
143
144        for (unsigned int i = 0; i < brick->getNumberOfStones(); i++ )
145        {
146            TetrisStone* stone = brick->getStone(i);
147            Vector3 stonePosition;
148            if(isRotation)
149                stonePosition = rotateVector(stone->getPosition(), brick->getRotationCount()+1);
150            else
151                stonePosition = rotateVector(stone->getPosition(), brick->getRotationCount());
152
153            if(! this->isValidMove(stone, position + stonePosition )) // wrong position??
154            {
155                return false;
156            }
157        }
158        return true;
159
160    }
161
162
163
164    bool Tetris::isValidStonePosition(TetrisStone* stone, const Vector3& position)
165    {
166        assert(stone);
167
168        // we use a reverse iterator because we have to check for collisions with the topmost stones first
169        for(std::vector<TetrisStone*>::const_reverse_iterator it = this->stones_.rbegin(); it != this->stones_.rend(); ++it)
170        {
171            if(this->activeBrick_->contains(*it))
172                continue;
173            //Vector3 currentStonePosition = rotateVector((*it)->getPosition(), this->activeBrick_->getRotationCount());
174            const Vector3& currentStonePosition = (*it)->getPosition(); //!< Saves the position of the currentStone
175            //!< Saves the position of the currentStone
176            if(position.x == currentStonePosition.x)
177            {
178                orxout()<< "candidate found" << endl;
179                orxout()<< "position.y: "<< position.y << endl;
180                orxout()<< "urrentStonePosition.y: " << currentStonePosition.y << endl;
181            }
182
183            if((position.x == currentStonePosition.x) && (position.y < currentStonePosition.y + this->center_->getStoneSize()))
184            {//TODO: Why are such events not detected ??
185             // Because currentStonePosition.x isn't calculated globally, but locally
186                orxout()<< "YEAY !!"<<endl;
187                this->activeBrick_->setPosition(Vector3(this->activeBrick_->getPosition().x, currentStonePosition.y+this->center_->getStoneSize(), this->activeBrick_->getPosition().z));
188                return false;
189            }// This case applies if the stones overlap partially vertically
190        }
191
192        // after we checked for collision with all stones, we also check for collision with the bottom
193        if(position.y < this->center_->getStoneSize()/2.0f) //!< If the stone has reached the bottom of the level
194        {
195                int yOffset = stone->getPosition().y;//calculate offset
196                this->activeBrick_->setPosition(Vector3(this->activeBrick_->getPosition().x, this->center_->getStoneSize()/2.0f+yOffset, this->activeBrick_->getPosition().z));
197            return false;
198        }
199
200        return true;
201    }
202
203    bool Tetris::isValidBrickPosition(TetrisBrick* brick, const Vector3& position)
204    {
205        assert(brick);
206
207        for (unsigned int i = 0; i < brick->getNumberOfStones(); i++ )
208        {
209            TetrisStone* stone = brick->getStone(i);
210            Vector3 stonePosition = rotateVector(stone->getPosition(), brick->getRotationCount());
211            if(! this->isValidStonePosition(stone, position + stonePosition) )
212                return false;
213        }
214        return true;
215    }
216
217    /**
218    @brief
219        A Vector3 is rolled 90 * degrees * amount (anticlockwise rotation)
220    */
221    Vector3 Tetris::rotateVector(Vector3 position, unsigned int amount)
222    {
223        int temp = 0;
224        for(unsigned int i = 0; i < amount; i++)
225        {
226            temp = position.x;
227            position.x = -position.y;
228            position.y = temp;
229        }
230        return position;
231    }
232
233    /**
234    @brief
235        Starts the Tetris minigame.
236    */
237    void Tetris::start()
238    {
239        if (this->center_ != NULL) // There needs to be a TetrisCenterpoint, i.e. the area the game takes place.
240        {
241            // Create the first brick.
242            this->createBrick();
243        }
244        else // If no centerpoint was specified, an error is thrown and the level is exited.
245        {
246            orxout(internal_error) << "Tetris: No Centerpoint specified." << endl;
247            GSLevel::startMainMenu();
248            return;
249        }
250
251        // Start the timer. After it has expired the stone is started.
252        this->starttimer_.startTimer();
253
254        // Set variable to temporarily force the player to spawn.
255        bool temp = this->bForceSpawn_;
256        this->bForceSpawn_ = true;
257
258        // Call start for the parent class.
259        Deathmatch::start();
260
261        // Reset the variable.
262        this->bForceSpawn_ = temp;
263    }
264
265    /**
266    @brief
267        Ends the Tetris minigame.
268    */
269    void Tetris::end()
270    {
271        this->cleanup();
272
273        // Call end for the parent class.
274        Deathmatch::end();
275    }
276
277    /**
278    @brief
279        Spawns player.
280    */
281    void Tetris::spawnPlayersIfRequested()
282    {
283        // Spawn a human player.
284        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
285            if (it->first->isHumanPlayer() && (it->first->isReadyToSpawn() || this->bForceSpawn_))
286                this->spawnPlayer(it->first);
287    }
288
289    /**
290    @brief
291        Spawns the input player.
292    @param player
293        The player to be spawned.
294    */
295    void Tetris::spawnPlayer(PlayerInfo* player)
296    {
297        assert(player);
298
299        if(this->player_ == NULL)
300        {
301            this->player_ = player;
302            this->players_[player].state_ = PlayerState::Alive;
303        }
304    }
305
306
307
308    void Tetris::startBrick(void)
309    {
310        if(this->player_ == NULL)
311            return;
312
313        unsigned int cameraIndex = 0;
314        if(this->activeBrick_ != NULL)
315        {
316            // Get camera settings
317            cameraIndex = this->activeBrick_->getCurrentCameraIndex();
318            orxout() << "cameraIndex: " << this->activeBrick_->getCurrentCameraIndex() << endl;
319            this->player_->stopControl();
320        }
321
322        // Make the last brick to be created the active brick.
323        this->activeBrick_ = this->bricks_.back();
324
325        this->player_->startControl(this->activeBrick_);
326        this->activeBrick_->setVelocity(0.0f, -this->center_->getStoneSpeed(), 0.0f);
327        orxout() << "velocity: " << this->center_->getStoneSpeed() << endl;
328        this->activeBrick_->setCameraPosition(cameraIndex);
329    }
330
331    void Tetris::createBrick(void)             //TODO: random rotation offset between 0 and 3 (times 90°)
332    {
333        // Create a new brick and add it to the list of bricks && to the list of stones.
334        TetrisBrick* brick = new TetrisBrick(this->center_);
335        this->bricks_.push_back(brick);
336        for (unsigned int i = 0; i < brick->getNumberOfStones(); i++)
337        {
338            this->stones_.push_back(brick->getStone(i));
339        }
340
341        // Apply the stone template to the stone.
342        brick->addTemplate(this->center_->getStoneTemplate()); // TODO: find error concerning the cameras
343
344        // Attach the brick to the Centerpoint and set the position of the brick to be at the top middle.
345        this->center_->attach(brick);
346        float xPos = (this->center_->getWidth()/2 + ((this->center_->getWidth() % 2)*2-1)/2.0f)*this->center_->getStoneSize();
347        float yPos = (this->center_->getHeight()-0.5f)*this->center_->getStoneSize();
348        brick->setPosition(xPos, yPos, 0.0f);
349        brick->setGame(this);
350    }
351
352
353    /**
354    @brief
355        Get the player.
356    @return
357        Returns a pointer to the player. If there is no player, NULL is returned.
358    */
359    PlayerInfo* Tetris::getPlayer(void) const
360    {
361        return this->player_;
362    }
363
364    /*TetrisCenterpoint* Tetris::getCenterpoint(void) const
365    {
366        return this->center_;
367    }*/
368
369    /**
370    @brief Set the TetrisCenterpoint (the playing field).
371    @param center A pointer to the TetrisCenterpoint to be set.
372    */
373    void Tetris::setCenterpoint(TetrisCenterpoint* center)
374    {
375        this->center_ = center;
376    }
377
378}
Note: See TracBrowser for help on using the repository browser.