Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core3/src/orxonox/objects/SpaceShipAI.cc @ 1591

Last change on this file since 1591 was 1591, checked in by landauf, 16 years ago

Again some heavy changes in ObjectList and Iterator:
there are now two types of iterators:

Iterator<ClassName> can iterate through any objectlist, either given by ObjectList<AnyClassName>::begin() or anyidentifier→getObjects()→begin(). Important note Iterator<ClassName> uses dynamic_cast.
And yes, it's possible to do this: Iterator<WorldEntity> it = ObjectList<SpaceShip>::begin()

ObjectList<ClassName>::iterator is the second iterator - it uses the ObjectList in a templated manner and therefore doesn't need dynamic_cast. But the only thing you can do is iterating through exactly the right ObjectList: ObjectList<ClassName>::iterator it = ObjectList<ClassName>::begin(). Anything else fails.

Those changes bring, at my system, something around +12% FPS compared with trunk and +25% FPS compared with the last revision of core3. Although I have to admit the FPS gain is only that high because iterating through objects is the main thing we're doing ingame right now. It would look totally different with physics, sound, AI, scripts, triggers and so on.

  • Property svn:eol-style set to native
File size: 10.5 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 "SpaceShipAI.h"
31
32#include <OgreMath.h>
33#include "Projectile.h"
34#include "ParticleSpawner.h"
35#include "core/CoreIncludes.h"
36#include "core/Iterator.h"
37#include "core/Executor.h"
38#include "core/ConsoleCommand.h"
39#include "core/XMLPort.h"
40#include "tools/ParticleInterface.h"
41
42#define ACTION_INTERVAL 1.0f
43
44namespace orxonox
45{
46    SetConsoleCommand(SpaceShipAI, createEnemy, true).setDefaultValue(0, 1);
47    SetConsoleCommand(SpaceShipAI, killEnemies, true).setDefaultValue(0, 0);
48
49    CreateFactory(SpaceShipAI);
50
51    SpaceShipAI::SpaceShipAI()
52    {
53        RegisterObject(SpaceShipAI);
54
55        this->target_ = 0;
56        this->bShooting_ = 0;
57        this->bHasTargetPosition_ = false;
58
59        this->setTeamNr((int)rnd(NUM_AI_TEAMS) % NUM_AI_TEAMS + 1);
60
61        if (NUM_AI_TEAMS > 0)
62            this->teamColours_[1] = ColourValue(1, 0, 0, 1);
63        if (NUM_AI_TEAMS > 1)
64            this->teamColours_[2] = ColourValue(0, 1, 0, 1);
65        if (NUM_AI_TEAMS > 2)
66            this->teamColours_[3] = ColourValue(0, 0, 1, 1);
67
68        for (int i = 4; i <= NUM_AI_TEAMS; ++i)
69            this->teamColours_[i] = ColourValue(rnd(), rnd(), rnd(), 1);
70    }
71
72    SpaceShipAI::~SpaceShipAI()
73    {
74        for (ObjectList<SpaceShipAI>::iterator it = ObjectList<SpaceShipAI>::begin(); it; ++it)
75            it->shipDied(this);
76    }
77
78    void SpaceShipAI::XMLPort(Element& xmlelement, XMLPort::Mode mode)
79    {
80        SpaceShip::XMLPort(xmlelement, mode);
81
82        this->actionTimer_.setTimer(ACTION_INTERVAL, true, this, createExecutor(createFunctor(&SpaceShipAI::action)));
83    }
84
85    void SpaceShipAI::createEnemy(int num)
86    {
87        for (int i = 0; i < num; ++i)
88        {
89            SpaceShipAI* newenemy = new SpaceShipAI();
90            newenemy->setMesh("assff.mesh");
91//            newenemy->setPosition(0, 0, 0);
92            newenemy->setPosition(Vector3(rnd(-3000, 3000), rnd(-3000, 3000), rnd(-3000, 3000)));
93            newenemy->setScale(10);
94            newenemy->setMaxSpeed(500);
95            newenemy->setMaxSideAndBackSpeed(50);
96            newenemy->setMaxRotation(1.0);
97            newenemy->setTransAcc(200);
98            newenemy->setRotAcc(3.0);
99            newenemy->setTransDamp(75);
100            newenemy->setRotDamp(1.0);
101            Element xmlelement;
102            newenemy->XMLPort(xmlelement, XMLPort::LoadObject);
103
104            ParticleSpawner* spawneffect = new ParticleSpawner("Orxonox/fairytwirl", LODParticle::normal, 2.0, 0.0, newenemy->getOrth());
105            spawneffect->setPosition(newenemy->getPosition() - newenemy->getOrth() * 50);
106            spawneffect->create();
107        }
108    }
109
110    void SpaceShipAI::killEnemies(int num)
111    {
112        int i = 0;
113        for (ObjectList<SpaceShipAI>::iterator it = ObjectList<SpaceShipAI>::begin(); it; )
114        {
115            (it++)->kill();
116            if (num && i >= num)
117                break;
118        }
119    }
120
121    ColourValue SpaceShipAI::getProjectileColour() const
122    {
123        return this->teamColours_[this->getTeamNr()];
124    }
125
126    void SpaceShipAI::action()
127    {
128        float random;
129        float maxrand = 100.0f / ACTION_INTERVAL;
130
131        // search enemy
132        random = rnd(maxrand);
133        if (random < 20 && (!this->target_))
134            this->searchNewTarget();
135
136        // forget enemy
137        random = rnd(maxrand);
138        if (random < 5 && (this->target_))
139            this->forgetTarget();
140
141        // next enemy
142        random = rnd(maxrand);
143        if (random < 10 && (this->target_))
144            this->searchNewTarget();
145
146        // fly somewhere
147        random = rnd(maxrand);
148        if (random < 40 && (!this->bHasTargetPosition_ && !this->target_))
149            this->searchNewTargetPosition();
150
151        // stop flying
152        random = rnd(maxrand);
153        if (random < 10 && (this->bHasTargetPosition_ && !this->target_))
154            this->bHasTargetPosition_ = false;
155
156        // fly somewhere else
157        random = rnd(maxrand);
158        if (random < 30 && (this->bHasTargetPosition_ && !this->target_))
159            this->searchNewTargetPosition();
160
161        // shoot
162        random = rnd(maxrand);
163        if (random < 75 && (this->target_ && !this->bShooting_))
164            this->bShooting_ = true;
165
166        // stop shooting
167        random = rnd(maxrand);
168        if (random < 25 && (this->bShooting_))
169            this->bShooting_ = false;
170    }
171
172    void SpaceShipAI::damage(float damage)
173    {
174        this->health_ -= damage;
175        if (this->health_ <= 0)
176        {
177            this->kill();
178            SpaceShipAI::createEnemy(1);
179        }
180    }
181
182    void SpaceShipAI::kill()
183    {
184        ParticleSpawner* explosion = new ParticleSpawner("Orxonox/BigExplosion1part1", LODParticle::low, 3.0);
185        explosion->setPosition(this->getPosition());
186        explosion->getParticleInterface()->setKeepParticlesInLocalSpace(true);
187        explosion->setScale(4);
188        explosion->create();
189
190        explosion = new ParticleSpawner("Orxonox/BigExplosion1part2", LODParticle::normal, 3.0);
191        explosion->setPosition(this->getPosition());
192        explosion->getParticleInterface()->setKeepParticlesInLocalSpace(true);
193        explosion->setScale(4);
194        explosion->create();
195        explosion = new ParticleSpawner("Orxonox/BigExplosion1part2", LODParticle::high, 3.0);
196        explosion->setPosition(this->getPosition());
197        explosion->getParticleInterface()->setKeepParticlesInLocalSpace(true);
198        explosion->setScale(4);
199        explosion->create();
200
201        Vector3 ringdirection = Vector3(rnd(), rnd(), rnd());
202        ringdirection.normalise();
203        explosion = new ParticleSpawner("Orxonox/BigExplosion1part3", LODParticle::normal, 3.0, 0.5, ringdirection);
204        explosion->setPosition(this->getPosition());
205        explosion->getParticleInterface()->setKeepParticlesInLocalSpace(true);
206        explosion->setScale(4);
207        explosion->create();
208        explosion = new ParticleSpawner("Orxonox/BigExplosion1part3", LODParticle::high, 3.0, 0.5, ringdirection);
209        explosion->setPosition(this->getPosition());
210        explosion->getParticleInterface()->setKeepParticlesInLocalSpace(true);
211        explosion->setScale(4);
212        explosion->create();
213
214        delete this;
215    }
216
217    void SpaceShipAI::tick(float dt)
218    {
219        if (!this->isActive())
220            return;
221
222        if (this->target_)
223            this->aimAtTarget();
224
225        if (this->bHasTargetPosition_)
226            this->moveToTargetPosition(dt);
227
228        if (this->bShooting_ && this->isCloseAtTarget(2500) && this->isLookingAtTarget(Ogre::Math::PI / 20.0))
229            this->doFire();
230
231        SpaceShip::tick(dt);
232    }
233
234    void SpaceShipAI::moveToTargetPosition(float dt)
235    {
236        Vector2 coord = get2DViewdirection(this->getPosition(), this->getDir(), this->getOrth(), this->targetPosition_);
237        this->setMoveYaw(0.8 * sgn(coord.x));
238        this->setMovePitch(0.8 * sgn(coord.y));
239
240        if ((this->targetPosition_ - this->getPosition()).length() > 500)
241            this->setMoveLongitudinal(0.8);
242
243        if (this->isCloseAtTarget(300) && this->target_)
244        {
245            if (this->getVelocity().length() > this->target_->getVelocity().length())
246                this->setMoveLongitudinal(-0.5);
247        }
248    }
249
250    void SpaceShipAI::searchNewTargetPosition()
251    {
252        this->targetPosition_ = Vector3(rnd(-5000,5000), rnd(-5000,5000), rnd(-5000,5000));
253        this->bHasTargetPosition_ = true;
254    }
255
256    void SpaceShipAI::searchNewTarget()
257    {
258        this->targetPosition_ = this->getPosition();
259        this->forgetTarget();
260
261        for (ObjectList<SpaceShip>::iterator it = ObjectList<SpaceShip>::begin(); it; ++it)
262        {
263            if (it->getTeamNr() != this->getTeamNr())
264            {
265                float speed = this->getVelocity().length();
266                Vector3 distanceCurrent = this->targetPosition_ - this->getPosition();
267                Vector3 distanceNew = it->getPosition() - this->getPosition();
268                if (!this->target_ || it->getPosition().squaredDistance(this->getPosition()) * (1.5f + acos((this->getOrientation() * Ogre::Vector3::UNIT_X).dotProduct(distanceNew) / speed / distanceNew.length()) / (2 * Ogre::Math::PI))
269                        < this->targetPosition_.squaredDistance(this->getPosition()) * (1.5f + acos((this->getOrientation() * Ogre::Vector3::UNIT_X).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / (2 * Ogre::Math::PI)) + rnd(-250, 250))
270                {
271                    this->target_ = (*it);
272                    this->targetPosition_ = it->getPosition();
273                }
274            }
275        }
276    }
277
278    void SpaceShipAI::forgetTarget()
279    {
280        this->target_ = 0;
281        this->bShooting_ = false;
282    }
283
284    void SpaceShipAI::aimAtTarget()
285    {
286        if (!this->target_)
287            return;
288
289        this->targetPosition_ = getPredictedPosition(this->getPosition(), Projectile::getSpeed(), this->target_->getPosition(), this->target_->getOrientation() * this->target_->getVelocity());
290        this->bHasTargetPosition_ = (this->targetPosition_ != Vector3::ZERO);
291    }
292
293    bool SpaceShipAI::isCloseAtTarget(float distance)
294    {
295        if (!this->target_)
296            return (this->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
297        else
298            return (this->getPosition().squaredDistance(this->target_->getPosition()) < distance*distance);
299    }
300
301    bool SpaceShipAI::isLookingAtTarget(float angle)
302    {
303        return (getAngle(this->getPosition(), this->getDir(), this->targetPosition_) < angle);
304    }
305
306    void SpaceShipAI::shipDied(SpaceShipAI* ship)
307    {
308        this->forgetTarget();
309        this->searchNewTargetPosition();
310    }
311}
Note: See TracBrowser for help on using the repository browser.