| [10423] | 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: Fabian 'x3n' Landau | 
|---|
 | 13 |    co-programmer: | 
|---|
 | 14 | */ | 
|---|
| [10487] | 15 |  | 
|---|
 | 16 | #include "sound/resource_sound_buffer.h" | 
|---|
| [10423] | 17 | #include "util/loading/load_param.h" | 
|---|
 | 18 | #include "util/loading/factory.h" | 
|---|
 | 19 | #include "debug.h" | 
|---|
 | 20 |  | 
|---|
 | 21 | #include "mover.h" | 
|---|
| [10519] | 22 | #include "state.h" | 
|---|
| [10618] | 23 | #include "tools/camera.h" | 
|---|
| [10423] | 24 |  | 
|---|
 | 25 |  | 
|---|
 | 26 | ObjectListDefinition(Mover); | 
|---|
 | 27 | CREATE_FACTORY(Mover); | 
|---|
 | 28 |  | 
|---|
 | 29 | /** | 
|---|
 | 30 |  *  initializes the Mover from a XmlElement | 
|---|
 | 31 | */ | 
|---|
 | 32 | Mover::Mover(const TiXmlElement* root) | 
|---|
 | 33 | { | 
|---|
| [10487] | 34 |     this->registerObject(this, Mover::_objectList); | 
|---|
| [10519] | 35 |     this->toList(OM_ENVIRON); | 
|---|
| [10423] | 36 |  | 
|---|
| [10487] | 37 |     this->targetCoordinates = Vector(0, 0, 0); | 
|---|
 | 38 |     this->originCoordinates = Vector(0, 87, -256); | 
|---|
 | 39 |     this->actionRadius = 40.0; | 
|---|
 | 40 |     this->actionTime = 1.0; | 
|---|
| [10423] | 41 |  | 
|---|
| [10487] | 42 |     if (root != NULL) | 
|---|
 | 43 |         this->loadParams(root); | 
|---|
 | 44 |  | 
|---|
 | 45 |     this->updateNode(0.001); | 
|---|
 | 46 |     this->originCoordinates = this->getAbsCoor(); | 
|---|
 | 47 |     this->state = Closed; | 
|---|
 | 48 |  | 
|---|
 | 49 |     this->soundSource_starting.setSourceNode(this); | 
|---|
 | 50 |     this->soundSource_moving.setSourceNode(this); | 
|---|
 | 51 |     this->soundSource_ending.setSourceNode(this); | 
|---|
 | 52 |  | 
|---|
 | 53 | //    this->soundSource_starting.setRolloffFactor(0.0); | 
|---|
 | 54 | //    this->soundSource_moving.setRolloffFactor(0.0); | 
|---|
 | 55 | //    this->soundSource_ending.setRolloffFactor(0.0); | 
|---|
| [10423] | 56 | } | 
|---|
 | 57 |  | 
|---|
 | 58 | Mover::~Mover() | 
|---|
 | 59 | { | 
|---|
| [10487] | 60 |     if (this->soundSource_starting.isPlaying()) | 
|---|
 | 61 |         this->soundSource_starting.stop(); | 
|---|
 | 62 |     if (this->soundSource_moving.isPlaying()) | 
|---|
 | 63 |         this->soundSource_moving.stop(); | 
|---|
 | 64 |     if (this->soundSource_ending.isPlaying()) | 
|---|
 | 65 |         this->soundSource_ending.stop(); | 
|---|
| [10423] | 66 | } | 
|---|
 | 67 |  | 
|---|
 | 68 | /** | 
|---|
 | 69 |  * loads the Settings of the Mover from an XML-element. | 
|---|
 | 70 |  * @param root the XML-element to load the Movers's properties from | 
|---|
 | 71 |  */ | 
|---|
 | 72 | void Mover::loadParams(const TiXmlElement* root) | 
|---|
 | 73 | { | 
|---|
| [10487] | 74 |     WorldEntity::loadParams(root); | 
|---|
| [10423] | 75 |  | 
|---|
| [10487] | 76 |     LoadParam(root, "rel-target-coor", this, Mover, setTargetCoordinates) | 
|---|
 | 77 |         .describe("sets the relative target coordinates of the door"); | 
|---|
 | 78 |     LoadParam(root, "action-radius", this, Mover, setActionRadius) | 
|---|
 | 79 |         .describe("sets the action radius of the door") | 
|---|
 | 80 |         .defaultValues(40.0); | 
|---|
 | 81 |     LoadParam(root, "action-time", this, Mover, setActionTime) | 
|---|
 | 82 |         .describe("sets the action time of the door") | 
|---|
 | 83 |         .defaultValues(1.0); | 
|---|
| [10643] | 84 |     LoadParam(root, "stay-open-time", this, Mover, setStayOpenTime) | 
|---|
 | 85 |         .describe("sets the time, the door must stay open") | 
|---|
 | 86 |         .defaultValues(0.0); | 
|---|
| [10487] | 87 |     LoadParam(root, "opening-sound", this, Mover, setOpeningSoundFile) | 
|---|
 | 88 |         .describe("Sets the file of the opening sound source"); | 
|---|
 | 89 |     LoadParam(root, "opened-sound", this, Mover, setOpenedSoundFile) | 
|---|
 | 90 |         .describe("Sets the file of the opened sound source"); | 
|---|
 | 91 |     LoadParam(root, "moving-sound", this, Mover, setMovingSoundFile) | 
|---|
 | 92 |         .describe("Sets the file of the moving sound source"); | 
|---|
 | 93 |     LoadParam(root, "closing-sound", this, Mover, setClosingSoundFile) | 
|---|
 | 94 |         .describe("Sets the file of the closing sound source"); | 
|---|
 | 95 |     LoadParam(root, "closed-sound", this, Mover, setClosedSoundFile) | 
|---|
 | 96 |         .describe("Sets the file of the closed sound source"); | 
|---|
| [10423] | 97 | } | 
|---|
 | 98 |  | 
|---|
| [10487] | 99 | void Mover::setOpeningSoundFile(const std::string& fileName) | 
|---|
 | 100 | { | 
|---|
 | 101 |     this->soundBuffer_opening = OrxSound::ResourceSoundBuffer(fileName); | 
|---|
 | 102 | } | 
|---|
 | 103 |  | 
|---|
 | 104 | void Mover::setOpenedSoundFile(const std::string& fileName) | 
|---|
 | 105 | { | 
|---|
 | 106 |     this->soundBuffer_opened = OrxSound::ResourceSoundBuffer(fileName); | 
|---|
 | 107 | } | 
|---|
 | 108 |  | 
|---|
 | 109 | void Mover::setMovingSoundFile(const std::string& fileName) | 
|---|
 | 110 | { | 
|---|
 | 111 |     this->soundBuffer_moving = OrxSound::ResourceSoundBuffer(fileName); | 
|---|
 | 112 | } | 
|---|
 | 113 |  | 
|---|
 | 114 | void Mover::setClosingSoundFile(const std::string& fileName) | 
|---|
 | 115 | { | 
|---|
 | 116 |     this->soundBuffer_closing = OrxSound::ResourceSoundBuffer(fileName); | 
|---|
 | 117 | } | 
|---|
 | 118 |  | 
|---|
 | 119 | void Mover::setClosedSoundFile(const std::string& fileName) | 
|---|
 | 120 | { | 
|---|
 | 121 |     this->soundBuffer_closed = OrxSound::ResourceSoundBuffer(fileName); | 
|---|
 | 122 | } | 
|---|
 | 123 |  | 
|---|
| [10423] | 124 | /** | 
|---|
 | 125 |  * tick function | 
|---|
 | 126 |  */ | 
|---|
 | 127 | void Mover::tick(float dt) | 
|---|
 | 128 | { | 
|---|
 | 129 |     if (this->state == Closed) | 
|---|
 | 130 |     { | 
|---|
 | 131 |         if (this->checkPlayerInActionRadius()) | 
|---|
 | 132 |         { | 
|---|
 | 133 |             this->state = Opening; | 
|---|
| [10487] | 134 |             if (this->soundBuffer_opening.loaded()) | 
|---|
 | 135 |                 this->soundSource_starting.play(this->soundBuffer_opening); | 
|---|
 | 136 |             if (this->soundBuffer_moving.loaded()) | 
|---|
 | 137 |                 this->soundSource_moving.play(this->soundBuffer_moving, 1.0, true); | 
|---|
| [10423] | 138 |         } | 
|---|
 | 139 |     } | 
|---|
 | 140 |     else if (this->state == Opening) | 
|---|
 | 141 |     { | 
|---|
 | 142 |         if (this->checkOpen(dt)) | 
|---|
 | 143 |         { | 
|---|
 | 144 |             this->state = Open; | 
|---|
 | 145 |             this->setAbsCoor(this->originCoordinates + this->targetCoordinates); | 
|---|
| [10487] | 146 |             if (this->soundBuffer_opened.loaded()) | 
|---|
 | 147 |                 this->soundSource_ending.play(this->soundBuffer_opened); | 
|---|
 | 148 |             if (this->soundBuffer_moving.loaded()) | 
|---|
 | 149 |                 this->soundSource_moving.stop(); | 
|---|
| [10423] | 150 |         } | 
|---|
| [10643] | 151 |         this->openTime = 0; | 
|---|
| [10423] | 152 |     } | 
|---|
 | 153 |     else if (this->state == Open) | 
|---|
 | 154 |     { | 
|---|
| [10643] | 155 |         this->openTime += dt; | 
|---|
 | 156 |         if (this->openTime >= this->stayOpenTime) | 
|---|
| [10423] | 157 |         { | 
|---|
| [10643] | 158 |             if (!this->checkPlayerInActionRadius()) | 
|---|
 | 159 |             { | 
|---|
 | 160 |                 this->state = Closing; | 
|---|
 | 161 |                 if (this->soundBuffer_closing.loaded()) | 
|---|
 | 162 |                     this->soundSource_starting.play(this->soundBuffer_closing); | 
|---|
 | 163 |                 if (this->soundBuffer_moving.loaded()) | 
|---|
 | 164 |                     this->soundSource_moving.play(this->soundBuffer_moving, 1.0, true); | 
|---|
 | 165 |             } | 
|---|
| [10423] | 166 |         } | 
|---|
 | 167 |     } | 
|---|
 | 168 |     else if (this->state == Closing) | 
|---|
 | 169 |     { | 
|---|
 | 170 |         if (this->checkClosed(dt)) | 
|---|
 | 171 |         { | 
|---|
 | 172 |             this->state = Closed; | 
|---|
 | 173 |             this->setAbsCoor(this->originCoordinates); | 
|---|
| [10487] | 174 |             if (this->soundBuffer_closed.loaded()) | 
|---|
 | 175 |                 this->soundSource_ending.play(this->soundBuffer_closed); | 
|---|
 | 176 |             if (this->soundBuffer_moving.loaded()) | 
|---|
 | 177 |                 this->soundSource_moving.stop(); | 
|---|
| [10423] | 178 |         } | 
|---|
 | 179 |         if (this->checkPlayerInActionRadius()) | 
|---|
 | 180 |         { | 
|---|
 | 181 |             this->state = Opening; | 
|---|
 | 182 |         } | 
|---|
 | 183 |     } | 
|---|
 | 184 |  | 
|---|
 | 185 |     if (this->state == Opening) | 
|---|
 | 186 |     { | 
|---|
 | 187 |         this->shiftCoor(this->targetCoordinates / this->actionTime * dt); | 
|---|
 | 188 |     } | 
|---|
 | 189 |     else if (this->state == Closing) | 
|---|
 | 190 |     { | 
|---|
 | 191 |         this->shiftCoor(this->targetCoordinates * (-1) / this->actionTime * dt); | 
|---|
 | 192 |     } | 
|---|
 | 193 | } | 
|---|
 | 194 |  | 
|---|
 | 195 | /** | 
|---|
 | 196 |  * checks if the door is open | 
|---|
 | 197 |  */ | 
|---|
 | 198 | bool Mover::checkOpen(float dt) | 
|---|
 | 199 | { | 
|---|
 | 200 |     if (fabs((this->originCoordinates - (this->getAbsCoor() - this->targetCoordinates)).len()) < fabs(2 * (this->targetCoordinates / this->actionTime * dt).len())) | 
|---|
 | 201 |         return true; | 
|---|
 | 202 |      | 
|---|
 | 203 |     return false; | 
|---|
 | 204 | } | 
|---|
 | 205 |  | 
|---|
 | 206 | /** | 
|---|
 | 207 |  * checks if the door is closed | 
|---|
 | 208 |  */ | 
|---|
 | 209 | bool Mover::checkClosed(float dt) | 
|---|
 | 210 | { | 
|---|
 | 211 |     if (fabs((this->getAbsCoor() - this->originCoordinates).len()) < fabs(2 * (this->targetCoordinates / this->actionTime * dt).len())) | 
|---|
 | 212 |         return true; | 
|---|
 | 213 |  | 
|---|
 | 214 |     return false; | 
|---|
 | 215 | } | 
|---|
 | 216 |  | 
|---|
 | 217 | #include "playable.h" | 
|---|
 | 218 | #include "generic_npc.h" | 
|---|
 | 219 | /** | 
|---|
 | 220 |  * checks if the player is within the action radius | 
|---|
 | 221 |  */ | 
|---|
 | 222 | bool Mover::checkPlayerInActionRadius() | 
|---|
 | 223 | { | 
|---|
| [10487] | 224 |     WorldEntity* entity; | 
|---|
 | 225 |     float distance; | 
|---|
| [10423] | 226 |  | 
|---|
| [10487] | 227 |     for (ObjectList<Playable>::const_iterator it = Playable::objectList().begin(); | 
|---|
 | 228 |         it != Playable::objectList().end(); | 
|---|
 | 229 |         ++it) | 
|---|
 | 230 |     // for all players | 
|---|
 | 231 |     { | 
|---|
 | 232 |         entity = (*it); | 
|---|
 | 233 |         distance = (this->originCoordinates - entity->getAbsCoor()).len(); | 
|---|
 | 234 |         if (distance < this->actionRadius) | 
|---|
 | 235 |         { | 
|---|
| [10519] | 236 |             this->soundSource_starting.setSourceNode((PNode*)State::getCamera());   // bad hack! | 
|---|
 | 237 |             this->soundSource_moving.setSourceNode((PNode*)State::getCamera());     // TODO: make the sound louder without | 
|---|
 | 238 |             this->soundSource_ending.setSourceNode((PNode*)State::getCamera());     // attaching him to the player | 
|---|
| [10487] | 239 |             return true; | 
|---|
 | 240 |         } | 
|---|
 | 241 |     } | 
|---|
| [10423] | 242 |  | 
|---|
| [10487] | 243 |     for (ObjectList<GenericNPC>::const_iterator it = GenericNPC::objectList().begin(); | 
|---|
 | 244 |         it != GenericNPC::objectList().end(); | 
|---|
 | 245 |         ++it) | 
|---|
 | 246 |     { | 
|---|
 | 247 |         entity = (*it); | 
|---|
 | 248 |         distance = (this->originCoordinates - entity->getAbsCoor()).len(); | 
|---|
 | 249 |         if (distance < this->actionRadius) | 
|---|
 | 250 |             return true; | 
|---|
 | 251 |     } | 
|---|
| [10423] | 252 |  | 
|---|
| [10487] | 253 |     return false; | 
|---|
| [10423] | 254 | } | 
|---|