Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/orxonox/objects/worldentities/ControllableEntity.cc @ 2298

Last change on this file since 2298 was 2292, checked in by rgrieder, 17 years ago

Finally managed to work out some physics. According to my tests, collisions with simple spheres should work with dynamic/kinematic/static objects. There are currently only a limited number of XML parameters, but we're surely going to extend that. Furthermore there is some more thinking to be done concerning changes of btRigidBody properties when it's already added to the world.

  • Property svn:eol-style set to native
File size: 12.8 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#include "OrxonoxStableHeaders.h"
30#include "ControllableEntity.h"
31
32#include "core/CoreIncludes.h"
33#include "core/Core.h"
34#include "core/XMLPort.h"
35#include "core/Template.h"
36
37#include "objects/infos/PlayerInfo.h"
38#include "objects/worldentities/Camera.h"
39#include "objects/worldentities/CameraPosition.h"
40#include "overlays/OverlayGroup.h"
41
42namespace orxonox
43{
44    CreateFactory(ControllableEntity);
45
46    ControllableEntity::ControllableEntity(BaseObject* creator) : MovableEntity(creator)
47    {
48        RegisterObject(ControllableEntity);
49
50        this->bControlled_ = false;
51        this->server_overwrite_ = 0;
52        this->client_overwrite_ = 0;
53        this->player_ = 0;
54        this->playerID_ = network::OBJECTID_UNKNOWN;
55        this->hud_ = 0;
56        this->camera_ = 0;
57        this->bDestroyWhenPlayerLeft_ = false;
58
59        this->velocity_ = Vector3::ZERO;
60        this->acceleration_ = Vector3::ZERO;
61
62        this->server_position_ = Vector3::ZERO;
63        this->client_position_ = Vector3::ZERO;
64        this->server_velocity_ = Vector3::ZERO;
65        this->client_velocity_ = Vector3::ZERO;
66        this->server_orientation_ = Quaternion::IDENTITY;
67        this->client_orientation_ = Quaternion::IDENTITY;
68
69        this->registerVariables();
70    }
71
72    ControllableEntity::~ControllableEntity()
73    {
74        if (this->isInitialized())
75        {
76            if (this->bControlled_)
77                this->stopLocalControl();
78
79            if (this->hud_)
80                delete this->hud_;
81
82            if (this->camera_)
83                delete this->camera_;
84
85            if (this->getPlayer() && this->getPlayer()->getControllableEntity() == this)
86                this->getPlayer()->stopControl(this, false);
87        }
88    }
89
90    void ControllableEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode)
91    {
92        SUPER(ControllableEntity, XMLPort, xmlelement, mode);
93
94        XMLPortParam(ControllableEntity, "hudtemplate", setHudTemplate, getHudTemplate, xmlelement, mode);
95        XMLPortParam(ControllableEntity, "camerapositiontemplate", setCameraPositionTemplate, getCameraPositionTemkplate, xmlelement, mode);
96
97        XMLPortObject(ControllableEntity, CameraPosition, "camerapositions", addCameraPosition, getCameraPosition, xmlelement, mode);
98    }
99
100    void ControllableEntity::addCameraPosition(CameraPosition* position)
101    {
102        this->attach(position);
103        this->cameraPositions_.push_back(position);
104    }
105
106    CameraPosition* ControllableEntity::getCameraPosition(unsigned int index) const
107    {
108        unsigned int i = 0;
109        for (std::list<CameraPosition*>::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
110        {
111            if (i == index)
112                return (*it);
113            ++i;
114        }
115        return 0;
116    }
117
118    void ControllableEntity::switchCamera()
119    {
120        if (this->camera_)
121        {
122            if (this->camera_->getParent() == this && this->cameraPositions_.size() > 0)
123            {
124                this->cameraPositions_.front()->attachCamera(this->camera_);
125            }
126            else if (this->cameraPositions_.size() > 0)
127            {
128                for (std::list<CameraPosition*>::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
129                {
130                    if ((*it) == this->camera_->getParent())
131                    {
132                        ++it;
133                        if (it != this->cameraPositions_.end())
134                            (*it)->attachCamera(this->camera_);
135                        else
136                            (*this->cameraPositions_.begin())->attachCamera(this->camera_);
137                        break;
138                    }
139                }
140            }
141            else
142            {
143                this->attach(this->camera_);
144            }
145        }
146    }
147
148    void ControllableEntity::setPlayer(PlayerInfo* player)
149    {
150        if (!player)
151        {
152            this->removePlayer();
153            return;
154        }
155
156        this->player_ = player;
157        this->playerID_ = player->getObjectID();
158        this->bControlled_ = (player->isLocalPlayer() && player->isHumanPlayer());
159        if (this->bControlled_)
160        {
161            this->startLocalControl();
162
163            if (!Core::isMaster())
164            {
165                this->client_overwrite_ = this->server_overwrite_;
166COUT(0) << "CE: bidirectional synchronization" << std::endl;
167                this->setObjectMode(network::direction::bidirectional);
168            }
169        }
170    }
171
172    void ControllableEntity::removePlayer()
173    {
174        if (this->bControlled_)
175            this->stopLocalControl();
176
177        this->player_ = 0;
178        this->playerID_ = network::OBJECTID_UNKNOWN;
179        this->bControlled_ = false;
180        this->setObjectMode(network::direction::toclient);
181
182        if (this->bDestroyWhenPlayerLeft_)
183            delete this;
184    }
185
186    void ControllableEntity::networkcallback_changedplayerID()
187    {
188        // just do this in case the entity wasn't yet synchronized when the corresponding PlayerInfo got our objectID
189        if (this->playerID_ != network::OBJECTID_UNKNOWN)
190        {
191            this->player_ = dynamic_cast<PlayerInfo*>(network::Synchronisable::getSynchronisable(this->playerID_));
192            if (this->player_ && (this->player_->getControllableEntity() != this))
193                this->player_->startControl(this);
194        }
195    }
196
197    void ControllableEntity::startLocalControl()
198    {
199//        std::cout << this->getObjectID() << " ###### start local control" << std::endl;
200        this->camera_ = new Camera(this);
201        this->camera_->requestFocus();
202        if (this->cameraPositionTemplate_ != "")
203            this->addTemplate(this->cameraPositionTemplate_);
204        if (this->cameraPositions_.size() > 0)
205            this->cameraPositions_.front()->attachCamera(this->camera_);
206        else
207            this->attach(this->camera_);
208
209        if (this->hudtemplate_ != "")
210        {
211            this->hud_ = new OverlayGroup(this);
212            this->hud_->addTemplate(this->hudtemplate_);
213        }
214    }
215
216    void ControllableEntity::stopLocalControl()
217    {
218//        std::cout << "###### stop local control" << std::endl;
219        this->camera_->detachFromParent();
220        delete this->camera_;
221        this->camera_ = 0;
222
223        delete this->hud_;
224        this->hud_ = 0;
225    }
226
227    void ControllableEntity::tick(float dt)
228    {
229        if (this->isActive())
230        {
231            if (!this->isDynamic())
232            {
233                this->velocity_ += (dt * this->acceleration_);
234                this->node_->translate(dt * this->velocity_, Ogre::Node::TS_LOCAL);
235            }
236
237            if (Core::isMaster())
238            {
239                this->server_velocity_ = this->velocity_;
240                this->server_position_ = this->node_->getPosition();
241            }
242            else if (this->bControlled_)
243            {
244//                COUT(2) << "setting client position" << endl;
245                this->client_velocity_ = this->velocity_;
246                this->client_position_ = this->node_->getPosition();
247            }
248        }
249    }
250
251    void ControllableEntity::registerVariables()
252    {
253        REGISTERSTRING(this->cameraPositionTemplate_, network::direction::toclient);
254
255        REGISTERDATA(this->server_position_,    network::direction::toclient, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerPosition));
256        REGISTERDATA(this->server_velocity_,    network::direction::toclient, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerVelocity));
257        REGISTERDATA(this->server_orientation_, network::direction::toclient, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerOrientation));
258
259        REGISTERDATA(this->server_overwrite_,   network::direction::toclient, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processOverwrite));
260        REGISTERDATA(this->client_overwrite_,   network::direction::toserver);
261
262        REGISTERDATA(this->client_position_,    network::direction::toserver, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientPosition));
263        REGISTERDATA(this->client_velocity_,    network::direction::toserver, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientVelocity));
264        REGISTERDATA(this->client_orientation_, network::direction::toserver, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientOrientation));
265
266
267        REGISTERDATA(this->playerID_, network::direction::toclient, new network::NetworkCallback<ControllableEntity>(this, &ControllableEntity::networkcallback_changedplayerID));
268    }
269
270    void ControllableEntity::processServerPosition()
271    {
272        if (!this->bControlled_)
273            this->node_->setPosition(this->server_position_);
274    }
275
276    void ControllableEntity::processServerVelocity()
277    {
278        if (!this->bControlled_)
279            this->velocity_ = this->server_velocity_;
280    }
281
282    void ControllableEntity::processServerOrientation()
283    {
284        if (!this->bControlled_)
285            this->node_->setOrientation(this->server_orientation_);
286    }
287
288    void ControllableEntity::processOverwrite()
289    {
290        if (this->bControlled_)
291        {
292            this->setPosition(this->server_position_);
293            this->setVelocity(this->server_velocity_);
294            this->setOrientation(this->server_orientation_);
295
296            this->client_overwrite_ = this->server_overwrite_;
297        }
298    }
299
300    void ControllableEntity::processClientPosition()
301    {
302        if (this->server_overwrite_ == this->client_overwrite_)
303        {
304//            COUT(2) << "callback: setting client position" << endl;
305            this->node_->setPosition(this->client_position_);
306            this->server_position_ = this->client_position_;
307        }
308//        else
309//          COUT(2) << "callback: not setting client position" << endl;
310    }
311
312    void ControllableEntity::processClientVelocity()
313    {
314        if (this->server_overwrite_ == this->client_overwrite_)
315        {
316            this->velocity_ = this->client_velocity_;
317            this->server_velocity_ = this->client_velocity_;
318        }
319    }
320
321    void ControllableEntity::processClientOrientation()
322    {
323        if (this->server_overwrite_ == this->client_overwrite_)
324        {
325            this->node_->setOrientation(this->client_orientation_);
326            this->server_orientation_ = this->client_orientation_;
327        }
328    }
329
330    void ControllableEntity::positionChanged()
331    {
332        if (Core::isMaster())
333        {
334            this->server_position_ = this->node_->getPosition();
335            ++this->server_overwrite_;
336        }
337        else if (this->bControlled_)
338        {
339            this->client_position_ = this->node_->getPosition();
340        }
341    }
342
343    void ControllableEntity::orientationChanged()
344    {
345        if (Core::isMaster())
346        {
347            this->server_orientation_ = this->node_->getOrientation();
348            ++this->server_overwrite_;
349        }
350        else if (this->bControlled_)
351        {
352            this->client_orientation_ = this->node_->getOrientation();
353        }
354    }
355
356    void ControllableEntity::velocityChanged()
357    {
358        if (Core::isMaster())
359        {
360            this->server_velocity_ = this->velocity_;
361            ++this->server_overwrite_;
362        }
363        else if (this->bControlled_)
364        {
365            this->client_velocity_ = this->velocity_;
366        }
367    }
368
369    void ControllableEntity::setVelocity(const Vector3& velocity)
370    {
371        if (this->bControlled_ || Core::isMaster())
372        {
373            if (!this->isDynamic())
374            {
375                // no physics, we do it ourselves
376                internalSetVelocity(velocity);
377            }
378            else
379            {
380                this->physicalBody_->setLinearVelocity(btVector3(velocity.x, velocity.y, velocity.z));
381            }
382            velocityChanged();
383        }
384    }
385}
Note: See TracBrowser for help on using the repository browser.