Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/presentation/src/world_entities/npcs/actionbox_enemy.cc @ 10734

Last change on this file since 10734 was 10734, checked in by snellen, 17 years ago

better flight behaviour for the ActionBox Enemy by rennerc

File size: 10.4 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Christoph Renner
13   co-programmer:
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
17
18#include "loading/factory.h"
19#include "debug.h"
20#include "loading/load_param.h"
21#include "util/loading/load_param_xml.h"
22#include "state.h"
23#include "player.h"
24#include "playable.h"
25
26#include "particles/dot_emitter.h"
27#include "particles/emitter_node.h"
28#include "particles/sprite_particles.h"
29
30#include "actionbox_enemy.h"
31
32ObjectListDefinition(ActionboxEnemy);
33CREATE_FACTORY(ActionboxEnemy);
34
35ActionboxEnemy::ActionboxEnemy(const TiXmlElement* root)
36  :weaponMan(this)
37{
38  PRINTF(0)("ActionboxEnemy\n");
39 
40  this->registerObject(this, ActionboxEnemy::_objectList);
41  this->toList(OM_GROUP_00);
42 
43  this->isActive = true;
44 
45  this->pitch = 0.0f;
46  this->dPitch = 0.0;
47 
48  this->maxSpeed = 30;
49  this->acceleration = 3;
50  this->speed = 0;
51  this->agility = 1;
52 
53  this->onEscape = false;
54  this->escaped = false;
55  this->endPoint = Vector(0, 0, 0);
56 
57  this->weaponMan.setParentEntity( this);
58  //weapons:
59
60  this->weaponMan.setParentEntity( this);
61
62  this->weaponMan.setSlotCount(8);
63
64  this->weaponMan.createWeaponSlot(0, 3.270, 1.028, .155, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
65  this->weaponMan.createWeaponSlot(1, 3.270, 1.028, -.155, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
66  this->weaponMan.createWeaponSlot(2, 4.385, .063, .876, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
67  this->weaponMan.createWeaponSlot(3, 4.385, -.063, -.876, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
68  this->weaponMan.createWeaponSlot(4, 1.635, -.612, 2.691, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
69  this->weaponMan.createWeaponSlot(5, 1.536, -.612, -2.691, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
70  this->weaponMan.createWeaponSlot(6, 1.536, -.612, 3.254, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
71  this->weaponMan.createWeaponSlot(7, 1.536, -.612, -3.254, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
72
73
74  this->weaponMan.addWeaponToSlot(0, 0, "RFCannon");
75  this->weaponMan.addWeaponToSlot(0, 1, "RFCannon");
76//   this->weaponMan.addWeaponToSlot(0, 2, "RFCannon");
77//   this->weaponMan.addWeaponToSlot(0, 3, "RFCannon");
78//   this->weaponMan.addWeaponToSlot(1, 0, "RFCannon");
79//   this->weaponMan.addWeaponToSlot(1, 1, "RFCannon");
80//   this->weaponMan.addWeaponToSlot(1, 2, "RFCannon");
81//   this->weaponMan.addWeaponToSlot(1, 3, "RFCannon");
82
83/*  this->weaponMan.addWeaponToSlot(0, 4, "NadionLaser");
84  this->weaponMan.addWeaponToSlot(0, 5, "NadionLaser");
85  this->weaponMan.addWeaponToSlot(2, 4, "NadionLaser");
86  this->weaponMan.addWeaponToSlot(2, 5, "NadionLaser");
87
88  this->weaponMan.addWeaponToSlot(0, 6, "Disruptor");
89  this->weaponMan.addWeaponToSlot(0, 7, "Disruptor");
90  this->weaponMan.addWeaponToSlot(3, 6, "Disruptor");
91  this->weaponMan.addWeaponToSlot(3, 7, "Disruptor");*/
92 
93  this->weaponMan.changeWeaponConfig(0);
94 
95  this->weaponMan.getFixedTarget()->setParent(this);
96  this->weaponMan.getFixedTarget()->setRelCoor(100000,0,0);
97  this->weaponMan.hideCrosshair();
98 
99  if ( root )
100  {
101    this->loadParams( root );
102  }
103}
104
105ActionboxEnemy::~ActionboxEnemy()
106{
107}
108
109void ActionboxEnemy::loadParams(const TiXmlElement* root)
110{
111  WorldEntity::loadParams( root );
112 
113  LoadParam(root, "endPoint", this, ActionboxEnemy, setEndPoint);
114  LoadParam(root, "maxSpeed", this, ActionboxEnemy, setMaxSpeed);
115  LoadParam(root, "agility", this, ActionboxEnemy, setAgility);
116  LoadParam(root, "acceleration", this, ActionboxEnemy, setAcceleration);
117}
118
119void ActionboxEnemy::tick( float dt )
120{
121  if ( escaped )
122  {
123    moveTowards( endPoint, endPoint - this->getAbsCoor(), dt );
124    return;
125  }
126 
127  weaponMan.tick( dt );
128  this->bFire = false;
129 
130  if ( !State::getPlayer() || !State::getPlayer()->getPlayable() )
131    return;
132 
133  Vector playerDir = State::getPlayer()->getPlayable()->getAbsDir().apply( Vector(1, 0, 0) );
134  Vector dist = this->getAbsCoor() - State::getPlayer()->getPlayable()->getAbsCoor();
135 
136  bool behindPlayer = playerDir.dot( dist ) < 0;
137 
138  if ( behindPlayer )
139  {
140    this->escaped = true;
141    PRINTF(0)("MOVING TOWARDS ENDPOINT\n");
142    return;
143  }
144 
145  myDir = this->getAbsDir();
146  myCoor = this->getAbsCoor();
147 
148  this->pitch += this->dPitch*dt;
149  while ( pitch > 2*PI )
150    pitch -= 2*PI;
151  while ( pitch < 0 )
152    pitch += 2*PI;
153 
154  myDir *= qPitch.inverse();
155 
156  qPitch = Quaternion( pitch, Vector( 1, 0, 0 ) );
157 
158  if ( isActive && State::getActionBox() )
159  {
160    ActionBox* box = State::getActionBox();
161    if ( box->isPointInBox( this->getAbsCoor() ) )
162    {
163      attackPlayer( box, dt );
164    }
165    else
166    {
167      moveTowardsBox( box, dt );
168      onEscape = false;
169    }
170  }
171 
172  myDir *= qPitch;
173 
174  this->setAbsDir( myDir );
175  this->setAbsCoor( myCoor );
176}
177
178void ActionboxEnemy::attackPlayer( ActionBox * box, float dt )
179{
180  if ( !State::getPlayer() || !State::getPlayer()->getPlayable() || !box )
181    return;
182 
183  float distance = (State::getPlayer()->getPlayable()->getAbsCoor() - getAbsCoor() ).len();
184 
185  if ( distance > box->getDepth()/4.0 && !onEscape )
186  {
187    Vector targetPos = State::getPlayer()->getPlayable()->getAbsCoor();
188    Vector targetDir = State::getPlayer()->getPlayable()->getAbsCoor()-this->getAbsCoor();
189    moveTowards( targetPos, targetDir, dt );
190    if ( this->getAbsDir().apply( Vector(1, 0, 0) ).dot(targetDir) > 0.9 )
191    {
192      this->bFire = true;
193      weaponMan.fire();
194    }
195  }
196  else
197  {
198    if ( !onEscape )
199    {
200      Vector ds = this->getAbsCoor() - State::getPlayer()->getPlayable()->getAbsCoor();
201      float projy = box->getAbsDir().apply( Vector(0, 1, 0) ).dot( ds );
202      float projz = box->getAbsDir().apply( Vector(0, 0, 1) ).dot( ds );
203      this->escapePoint = Vector( 0, projy, projz );
204      this->escapePoint.normalize();
205      this->escapePoint*= 2*box->getWidth_2();
206      PRINTF(0)("ESCAPE\n");
207    }
208    onEscape = true;
209   
210    Vector rEscapePoint = box->getAbsDir().apply(escapePoint + Vector( -10, 0, 0 ));
211    Vector targetPos = State::getPlayer()->getPlayable()->getAbsCoor() + rEscapePoint;
212    Vector targetDir = State::getPlayer()->getPlayable()->getAbsCoor() + rEscapePoint - this->getAbsCoor();
213    moveTowards( targetPos, targetDir, dt );
214  }
215}
216
217void ActionboxEnemy::moveTowards( Vector targetPos, Vector targetDir, float dt )
218{
219  Quaternion cur = myDir;
220  Quaternion rx( agility*dt, Vector( 0, 0, 1 ) );
221 
222  Quaternion tmp1 = cur * rx;
223  Quaternion tmp2 = cur * rx.inverse();
224 
225  Quaternion dec;
226  if ( tmp1.apply( Vector(1, 0, 0) ).dot(targetDir) > tmp2.apply( Vector(1, 0, 0)).dot(targetDir) )
227    dec = tmp1;
228  else
229    dec = tmp2;
230 
231  float dp = dec.apply( Vector(1, 0, 0) ).dot(Vector(0, 1, 0));
232  if ( dp > -0.9 && dp < 0.9 )
233  {
234    cur = dec;
235  }
236 
237  Quaternion ry( agility*dt, cur.inverse().apply( Vector( 0, 1, 0 ) ) );
238 
239  tmp1 = cur * ry;
240  tmp2 = cur * ry.inverse();
241 
242  if ( tmp1.apply( Vector(1, 0, 0) ).dot(targetDir) > tmp2.apply( Vector(1, 0, 0)).dot(targetDir) )
243    cur = tmp1;
244  else
245    cur = tmp2;
246 
247  myDir = cur;
248 
249  Vector fw = cur.apply( Vector(1, 0, 0) );
250 
251  this->speed += this->acceleration*dt;
252  if ( this->speed > this->maxSpeed )
253    this->speed = this->maxSpeed;
254  this->myCoor += fw*speed*dt;
255}
256
257void ActionboxEnemy::moveTowardsBox( ActionBox * box, float dt )
258{
259  Vector targetPos = box->getAbsCoor() + box->getAbsDir().apply( Vector( 1, 0, 0 ) )*box->getDepth()*0.66f;
260  Vector targetDir = targetPos - myCoor;
261 
262  Vector boxDir = box->getAbsDir().apply( Vector(1, 0, 0 ) );
263  float boxDist = boxDir.dot( targetDir );
264 
265  if ( boxDist > 0 )
266  {
267    Vector myRelCoor = this->getAbsCoor() - box->getAbsCoor();
268    float newDist = boxDir.dot( myRelCoor );
269    targetPos = box->getAbsCoor() + box->getAbsDir().apply( Vector( 1, 0, 0 ) )* newDist * 0.8;
270    targetDir = targetPos - myCoor;
271  }
272 
273  moveTowards(targetPos, targetDir, dt);
274}
275
276void ActionboxEnemy::draw( ) const
277{
278#if 0
279  Vector fw = this->getAbsDir().apply( Vector( 1, 0, 0 ) );
280  fw.normalize();
281  fw = fw * 100;
282 
283  Vector mp = this->getAbsCoor();
284  Vector op = mp + fw;
285 
286  Vector targetPos = State::getPlayer()->getPlayable()->getAbsCoor();
287  Vector dv = targetPos - this->getAbsCoor();
288  dv.normalize();
289  dv *= 100;
290  dv += mp;
291 
292  Vector spUp = this->getAbsDir().inverse().apply( this->getAbsDir().apply( Vector( 0, 1, 0 ) ) );
293  spUp.normalize();
294  spUp *= 100;
295  spUp += mp;
296 
297  Vector up = fw.cross( dv );
298  up += mp;
299 
300  //PRINTF(0)("DEBUG\n");
301  //mp.debug();
302  //op.debug();
303 
304  glMatrixMode(GL_MODELVIEW);
305  glPushMatrix();
306
307  glPushAttrib(GL_ENABLE_BIT);
308
309  glDisable(GL_LIGHTING);
310  glDisable(GL_TEXTURE_2D);
311  glDisable(GL_BLEND);
312  glLineWidth(2.0);
313  glColor3f(1.0, 0.0, 0.0 );
314 
315 
316  glBegin(GL_LINE_STRIP);
317    glVertex3f(mp.x, mp.y, mp.z);
318    glVertex3f(op.x, op.y, op.z);
319  glEnd();
320 
321  glColor3f(0.0, 1.0, 0.0 );
322  glBegin(GL_LINE_STRIP);
323    glVertex3f(mp.x, mp.y, mp.z);
324    glVertex3f(dv.x, dv.y, dv.z);
325  glEnd();
326 
327  glColor3f(0.0, 0.0, 1.0 );
328  glBegin(GL_LINE_STRIP);
329    glVertex3f(mp.x, mp.y, mp.z);
330    glVertex3f(up.x, up.y, up.z);
331  glEnd();
332 
333  glColor3f(1.0, 1.0, 1.0 );
334  glBegin(GL_LINE_STRIP);
335    glVertex3f(mp.x, mp.y, mp.z);
336    glVertex3f(spUp.x, spUp.y, spUp.z);
337  glEnd();
338
339  glPopMatrix();
340#endif
341  WorldEntity::draw();
342}
343
344void ActionboxEnemy::destroy( WorldEntity * killer )
345{
346  EmitterNode* node  = NULL;
347  DotEmitter* emitter = NULL;
348  SpriteParticles*  explosionParticles  = NULL;
349
350  explosionParticles = new SpriteParticles(200);
351  explosionParticles->setName("SpaceShipExplosionParticles");
352  explosionParticles->setLifeSpan(.3, .7);
353  explosionParticles->setRadius(0.0, 10.0);
354  explosionParticles->setRadius(.5, 6.0);
355  explosionParticles->setRadius(1.0, 3.0);
356  explosionParticles->setColor(0.0, 1,1,1,.9);
357  explosionParticles->setColor(0.1,  1,1,0,.9);
358  explosionParticles->setColor(0.5, .8,.4,0,.5);
359  explosionParticles->setColor(1.0, .2,.2,.2,.5);
360
361
362  emitter = new DotEmitter( 2000, 70, 360);
363  emitter->setEmissionRate( 200.0);
364
365  node  = new EmitterNode( .4f );
366  node->setupParticle( emitter, explosionParticles);
367  node->setAbsDir( this->getAbsDir());
368  node->setVelocity( this->getVelocity() * .9f);
369  node->setAbsCoor( this->getAbsCoor());
370  if( !node->start())
371    PRINTF(0)("Explosion node not correctly started!");
372 
373  this->setAbsCoor( this->getAbsCoor() + Vector(100,0,0) + Vector(1,0,0) * VECTOR_RAND(150).dot(Vector(1,0,0)));
374 
375  toList( OM_DEAD );
376}
Note: See TracBrowser for help on using the repository browser.