Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/orxonox/objects/SpaceShipAI.cc @ 1479

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

added something like an AI… or at least something thats pretty close to what we call AI. it's not that clever, sometimes it does some sign errors. but hey, I don't care, at least it makes the game look more living.

File size: 9.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 <OgreMath.h>
30
31#include "SpaceShipAI.h"
32#include "Projectile.h"
33#include "core/CoreIncludes.h"
34#include "core/Iterator.h"
35#include "core/Executor.h"
36#include "core/ConsoleCommand.h"
37#include "core/XMLPort.h"
38
39#define ACTION_INTERVAL 1.0f
40
41namespace orxonox
42{
43    SetConsoleCommand(SpaceShipAI, createEnemy, true).setDefaultValue(0, 1);
44    SetConsoleCommand(SpaceShipAI, killEnemies, true).setDefaultValue(0, 0);
45
46    CreateFactory(SpaceShipAI);
47
48    SpaceShipAI::SpaceShipAI()
49    {
50        RegisterObject(SpaceShipAI);
51
52        this->alive_ = true;
53        this->setPosition(Vector3(rnd(-1000, 1000), rnd(-1000, 1000), rnd(-1000, 0000)));
54        this->target_ = 0;
55        this->bShooting_ = 0;
56        this->bHasTargetPosition_ = false;
57
58        this->setTeamNr((int)rnd(NUM_AI_TEAMS) % NUM_AI_TEAMS + 1);
59
60        if (NUM_AI_TEAMS > 0)
61            this->teamColours_[1] = ColourValue(1, 0, 0, 1);
62        if (NUM_AI_TEAMS > 1)
63            this->teamColours_[2] = ColourValue(0, 1, 0, 1);
64        if (NUM_AI_TEAMS > 2)
65            this->teamColours_[3] = ColourValue(0, 0, 1, 1);
66
67        for (int i = 4; i <= NUM_AI_TEAMS; ++i)
68            this->teamColours_[i] = ColourValue(rnd(), rnd(), rnd(), 1);
69
70        actionTimer_.setTimer(ACTION_INTERVAL, true, this, createExecutor(createFunctor(&SpaceShipAI::action)));
71    }
72
73    void SpaceShipAI::createEnemy(int num)
74    {
75        for (int i = 0; i < num; ++i)
76        {
77            SpaceShipAI* newenemy = new SpaceShipAI();
78            newenemy->setMesh("assff.mesh");
79//            newenemy->setPosition(0, 0, 0);
80            newenemy->setScale(10);
81            newenemy->setMaxSpeed(500);
82            newenemy->setMaxSideAndBackSpeed(50);
83            newenemy->setMaxRotation(1.0);
84            newenemy->setTransAcc(200);
85            newenemy->setRotAcc(3.0);
86            newenemy->setTransDamp(75);
87            newenemy->setRotDamp(1.0);
88            Element xmlelement;
89            newenemy->create();
90        }
91    }
92
93    void SpaceShipAI::killEnemies(int num)
94    {
95        int i = 0;
96        for (Iterator<SpaceShipAI> it = ObjectList<SpaceShipAI>::begin(); it; )
97        {
98            delete *(it++);
99            ++i;
100            if (num && i >= num)
101                break;
102        }
103    }
104
105    ColourValue SpaceShipAI::getProjectileColour() const
106    {
107        return this->teamColours_[this->getTeamNr()];
108    }
109
110    void SpaceShipAI::action()
111    {
112        float random;
113        float maxrand = 100.0f / ACTION_INTERVAL;
114
115        // search enemy
116        random = rnd(maxrand);
117//std::cout << "search enemy: " << random << std::endl;
118        if (random < 20 && (!this->target_))
119        {
120            this->searchNewTarget();
121        }
122
123        // forget enemy
124        random = rnd(maxrand);
125//std::cout << "forget enemy: " << random << std::endl;
126        if (random < 5 && (this->target_))
127        {
128            this->forgetTarget();
129        }
130
131        // next enemy
132        random = rnd(maxrand);
133//std::cout << "next enemy: " << random << std::endl;
134        if (random < 10 && (this->target_))
135        {
136            this->searchNewTarget();
137        }
138
139        // fly somewhere
140        random = rnd(maxrand);
141//std::cout << "fly somewhere: " << random << std::endl;
142        if (random < 40 && (!this->bHasTargetPosition_ && !this->target_))
143        {
144            this->searchNewTargetPosition();
145        }
146
147        // stop flying
148        random = rnd(maxrand);
149//std::cout << "stop flying: " << random << std::endl;
150        if (random < 10 && (this->bHasTargetPosition_ && !this->target_))
151        {
152            this->bHasTargetPosition_ = false;
153        }
154
155        // fly somewhere else
156        random = rnd(maxrand);
157//std::cout << "fly somewhere else: " << random << std::endl;
158        if (random < 30 && (this->bHasTargetPosition_ && !this->target_))
159        {
160            this->searchNewTargetPosition();
161        }
162
163        // shoot
164        random = rnd(maxrand);
165//std::cout << "shoot: " << random << std::endl;
166        if (random < 75 && (this->target_ && !this->bShooting_))
167        {
168            this->bShooting_ = true;
169        }
170
171        // stop shooting
172        random = rnd(maxrand);
173//std::cout << "stop shooting: " << random << std::endl;
174        if (random < 25 && (this->bShooting_))
175        {
176            this->bShooting_ = false;
177        }
178    }
179
180    void SpaceShipAI::tick(float dt)
181    {
182        if (this->target_)
183            this->aimAtTarget();
184
185        if (this->bHasTargetPosition_)
186            this->moveToTargetPosition(dt);
187
188        if (this->bShooting_ && this->isCloseAtTarget(2000) && this->isLookingAtTarget(Ogre::Math::PI / 10.0f))
189            this->doFire();
190
191        SpaceShip::tick(dt);
192    }
193
194    void SpaceShipAI::moveToTargetPosition(float dt)
195    {
196        static Radian RadianZERO(0);
197
198//        float dotprod = (this->getOrientation() * Ogre::Vector3::UNIT_X).dotProduct(this->targetPosition_ - this->getPosition());
199        Quaternion rotation = (this->getOrientation() * Ogre::Vector3::UNIT_X).getRotationTo(this->targetPosition_ - this->getPosition());
200/*
201std::cout << "scalprod: " << dotprod << std::endl;
202std::cout << "dist: " << this->targetPosition_ - this->getPosition() << std::endl;
203std::cout << "yaw: " << rotation.getYaw().valueRadians() << std::endl;
204std::cout << "pitch: " << rotation.getPitch().valueRadians() << std::endl;
205std::cout << "roll: " << rotation.getRoll().valueRadians() << std::endl;
206*/
207        this->setMoveYaw(-rotation.getRoll().valueRadians());
208        this->setMovePitch(rotation.getYaw().valueRadians());
209
210        if ((this->targetPosition_ - this->getPosition()).length() > 100)
211        {
212            this->setMoveLongitudinal(1);
213        }
214
215    }
216
217    void SpaceShipAI::searchNewTargetPosition()
218    {
219        this->targetPosition_ += Vector3(rnd(-10000,10000), rnd(-10000,10000), rnd(-10000,10000));
220        this->bHasTargetPosition_ = true;
221    }
222
223    void SpaceShipAI::searchNewTarget()
224    {
225        this->targetPosition_ = this->getPosition();
226        this->forgetTarget();
227
228        for (Iterator<SpaceShip> it = ObjectList<SpaceShip>::begin(); it; ++it)
229        {
230            if (it->getTeamNr() != this->getTeamNr())
231            {
232                float speed = this->getVelocity().length();
233                Vector3 distanceCurrent = this->targetPosition_ - this->getPosition();
234                Vector3 distanceNew = it->getPosition() - this->getPosition();
235                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))
236                        < this->targetPosition_.squaredDistance(this->getPosition()) * (1.5f + acos((this->getOrientation() * Ogre::Vector3::UNIT_X).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / (2 * Ogre::Math::PI)))
237                {
238                    this->target_ = (*it);
239                    this->targetPosition_ = it->getPosition();
240                }
241            }
242        }
243   }
244
245    void SpaceShipAI::forgetTarget()
246    {
247        this->target_ = 0;
248        this->bShooting_ = false;
249    }
250
251    void SpaceShipAI::aimAtTarget()
252    {
253        if (!this->target_)
254            return;
255/*
256        Vector3 enemymovement = this->target_->getVelocity();
257        Vector3 distance_normalised = this->target_->getPosition() - this->getPosition();
258        distance_normalised.normalise();
259
260        float scalarprod = enemymovement.dotProduct(distance_normalised);
261        float aimoffset = scalarprod*scalarprod + Projectile::getSpeed() * Projectile::getSpeed() - this->target_->getVelocity().squaredLength();
262        if (aimoffset < 0)
263        {
264            this->bHasTargetPosition_ = false;
265            return;
266        }
267        aimoffset = -scalarprod + sqrt(aimoffset);
268        this->targetPosition_ = enemymovement + distance_normalised * aimoffset;
269        this->bHasTargetPosition_ = true;
270
271        std::cout << "targetpos: " << this->targetPosition_ << std::endl;
272*/
273        this->targetPosition_ = this->target_->getPosition();
274        this->bHasTargetPosition_ = true;
275    }
276
277    bool SpaceShipAI::isCloseAtTarget(float distance)
278    {
279        return (this->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
280    }
281
282    bool SpaceShipAI::isLookingAtTarget(float angle)
283    {
284        return (this->getOrientation() * Ogre::Vector3::UNIT_X).directionEquals(this->targetPosition_ - this->getPosition(), Radian(angle));
285    }
286}
Note: See TracBrowser for help on using the repository browser.