Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tetris/src/modules/pong/PongBall.cc @ 8572

Last change on this file since 8572 was 8106, checked in by dafrick, 14 years ago

And even more documentation.
Also moved some of the documentation out of Groups.dox into seperate files located in the new groups folder.

  • Property svn:eol-style set to native
File size: 9.7 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 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file PongBall.cc
31    @brief Implementation of the PongBall class.
32*/
33
34#include "PongBall.h"
35
36#include "core/CoreIncludes.h"
37#include "core/GameMode.h"
38
39#include "gametypes/Gametype.h"
40
41#include "PongBat.h"
42
43namespace orxonox
44{
45    CreateFactory(PongBall);
46
47    const float PongBall::MAX_REL_Z_VELOCITY = 1.5;
48
49    /**
50    @brief
51        Constructor. Registers and initializes the object.
52    */
53    PongBall::PongBall(BaseObject* creator)
54        : MovableEntity(creator)
55    {
56        RegisterObject(PongBall);
57
58        this->speed_ = 0;
59        this->accelerationFactor_ = 1.0f;
60        this->bat_ = 0;
61        this->bDeleteBats_ = false;
62        this->batID_ = new unsigned int[2];
63        this->batID_[0] = OBJECTID_UNKNOWN;
64        this->batID_[1] = OBJECTID_UNKNOWN;
65        this->relMercyOffset_ = 0.05f;
66
67        this->registerVariables();
68    }
69
70    /**
71    @brief
72        Destructor.
73    */
74    PongBall::~PongBall()
75    {
76        if (this->isInitialized())
77        {
78            if (this->bDeleteBats_)
79                delete[] this->bat_;
80
81            delete[] this->batID_;
82        }
83    }
84
85    /**
86    @brief
87        Register variables to synchronize over the network.
88    */
89    void PongBall::registerVariables()
90    {
91        registerVariable( this->fieldWidth_ );
92        registerVariable( this->fieldHeight_ );
93        registerVariable( this->batlength_ );
94        registerVariable( this->speed_ );
95        registerVariable( this->relMercyOffset_ );
96        registerVariable( this->batID_[0] );
97        registerVariable( this->batID_[1], VariableDirection::ToClient, new NetworkCallback<PongBall>( this, &PongBall::applyBats) );
98    }
99
100    /**
101    @brief
102        Is called every tick.
103        Handles the movement of the ball and its interaction with the boundaries and bats.
104    @param dt
105        The time since the last tick.
106    */
107    void PongBall::tick(float dt)
108    {
109        SUPER(PongBall, tick, dt);
110
111        // Get the current position, velocity and acceleration of the ball.
112        Vector3 position = this->getPosition();
113        Vector3 velocity = this->getVelocity();
114        Vector3 acceleration = this->getAcceleration();
115
116        // If the ball has gone over the top or bottom boundary of the playing field (i.e. the ball has hit the top or bottom delimiters).
117        if (position.z > this->fieldHeight_ / 2 || position.z < -this->fieldHeight_ / 2)
118        {
119            // Its velocity in z-direction is inverted (i.e. it bounces off).
120            velocity.z = -velocity.z;
121            // And its position is set as to not overstep the boundary it has just crossed.
122            if (position.z > this->fieldHeight_ / 2)
123                position.z = this->fieldHeight_ / 2;
124            if (position.z < -this->fieldHeight_ / 2)
125                position.z = -this->fieldHeight_ / 2;
126
127            this->fireEvent();
128        }
129
130        // If the ball has crossed the left or right boundary of the playing field (i.e. a player has just scored, if the bat isn't there to parry).
131        if (position.x > this->fieldWidth_ / 2 || position.x < -this->fieldWidth_ / 2)
132        {
133            float distance = 0;
134
135            if (this->bat_ != NULL) // If there are bats.
136            {
137                // If the right boundary has been crossed.
138                if (position.x > this->fieldWidth_ / 2 && this->bat_[1] != NULL)
139                {
140                    // Calculate the distance (in z-direction) between the ball and the center of the bat, weighted by half of the effective length of the bat (with additional 10%)
141                    distance = (position.z - this->bat_[1]->getPosition().z) / (this->fieldHeight_ * (this->batlength_ * 1.10f) / 2);
142                    if (fabs(distance) <= 1) // If the bat is there to parry.
143                    {
144                        // Set the ball to be exactly at the boundary.
145                        position.x = this->fieldWidth_ / 2;
146                        // Invert its velocity in x-direction (i.e. it bounces off).
147                        velocity.x = -velocity.x;
148                        // Adjust the velocity in the z-direction, depending on where the ball hit the bat.
149                        velocity.z = distance * distance * sgn(distance) * PongBall::MAX_REL_Z_VELOCITY * this->speed_;
150                        acceleration = this->bat_[1]->getVelocity() * this->accelerationFactor_ * -1;
151
152                        this->fireEvent();
153                    }
154                    // If the left player scores.
155                    else if (GameMode::isMaster() && position.x > this->fieldWidth_ / 2 * (1 + this->relMercyOffset_))
156                    {
157                        if (this->getGametype() && this->bat_[0])
158                        {
159                            this->getGametype()->playerScored(this->bat_[0]->getPlayer());
160                            return;
161                        }
162                    }
163                }
164                // If the left boundary has been crossed.
165                else if (position.x < -this->fieldWidth_ / 2 && this->bat_[0] != NULL)
166                {
167                    // Calculate the distance (in z-direction) between the ball and the center of the bat, weighted by half of the effective length of the bat (with additional 10%)
168                    distance = (position.z - this->bat_[0]->getPosition().z) / (this->fieldHeight_ * (this->batlength_ * 1.10f) / 2);
169                    if (fabs(distance) <= 1) // If the bat is there to parry.
170                    {
171                        // Set the ball to be exactly at the boundary.
172                        position.x = -this->fieldWidth_ / 2;
173                        // Invert its velocity in x-direction (i.e. it bounces off).
174                        velocity.x = -velocity.x;
175                        // Adjust the velocity in the z-direction, depending on where the ball hit the bat.
176                        velocity.z = distance * distance * sgn(distance) * PongBall::MAX_REL_Z_VELOCITY * this->speed_;
177                        acceleration = this->bat_[0]->getVelocity() * this->accelerationFactor_ * -1;
178
179                        this->fireEvent();
180                    }
181                    // If the right player scores.
182                    else if (GameMode::isMaster() && position.x < -this->fieldWidth_ / 2 * (1 + this->relMercyOffset_))
183                    {
184                        if (this->getGametype() && this->bat_[1])
185                        {
186                            this->getGametype()->playerScored(this->bat_[1]->getPlayer());
187                            return;
188                        }
189                    }
190                }
191            }
192        }
193
194        // Set the position, velocity and acceleration of the ball, if they have changed.
195        if (acceleration != this->getAcceleration())
196            this->setAcceleration(acceleration);
197        if (velocity != this->getVelocity())
198            this->setVelocity(velocity);
199        if (position != this->getPosition())
200            this->setPosition(position);
201    }
202
203    /**
204    @brief
205        Set the speed of the ball (in x-direction).
206    @param speed
207        The speed to be set.
208    */
209    void PongBall::setSpeed(float speed)
210    {
211        if (speed != this->speed_) // If the speed changes
212        {
213            this->speed_ = speed;
214
215            // Set the speed in the direction of the balls current velocity.
216            Vector3 velocity = this->getVelocity();
217            if (velocity.x != 0)
218                velocity.x = sgn(velocity.x) * this->speed_;
219            else // If the balls current velocity is zero, the speed is set in a random direction.
220                velocity.x = this->speed_ * sgn(rnd(-1,1));
221
222            this->setVelocity(velocity);
223        }
224    }
225
226    /**
227    @brief
228        Set the bats for the ball.
229    @param bats
230        An array (of size 2) of weak pointers, to be set as the new bats.
231    */
232    void PongBall::setBats(WeakPtr<PongBat>* bats)
233    {
234        if (this->bDeleteBats_) // If there are already some bats, delete them.
235        {
236            delete[] this->bat_;
237            this->bDeleteBats_ = false;
238        }
239
240        this->bat_ = bats;
241        // Also store their object IDs, for synchronization.
242        this->batID_[0] = this->bat_[0]->getObjectID();
243        this->batID_[1] = this->bat_[1]->getObjectID();
244    }
245
246    /**
247    @brief
248        Get the bats over the network.
249    */
250    void PongBall::applyBats()
251    {
252        // Make space for the bats, if they don't exist, yet.
253        if (this->bat_ == NULL)
254        {
255            this->bat_ = new WeakPtr<PongBat>[2];
256            this->bDeleteBats_ = true;
257        }
258
259        if (this->batID_[0] != OBJECTID_UNKNOWN)
260            this->bat_[0] = orxonox_cast<PongBat*>(Synchronisable::getSynchronisable(this->batID_[0]));
261        if (this->batID_[1] != OBJECTID_UNKNOWN)
262            this->bat_[1] = orxonox_cast<PongBat*>(Synchronisable::getSynchronisable(this->batID_[1]));
263    }
264}
Note: See TracBrowser for help on using the repository browser.