/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2007 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Fabian 'x3n' Landau co-programmer: */ #include "sound/resource_sound_buffer.h" #include "util/loading/load_param_xml.h" #include "util/loading/load_param.h" #include "util/loading/factory.h" #include "mover.h" #define CLOSED 0 #define OPEN 1 #define MOVE 2 #define WAIT 3 #define NEXT 4 #define DELAY 5 #define STAY 6 ObjectListDefinition(Mover); CREATE_FACTORY(Mover); Mover::Mover(const TiXmlElement* root) { PRINTF(0)("1_1 Mover %p created\n", this); this->registerObject(this, Mover::_objectList); this->toList(OM_ENVIRON); this->bLoop = false; this->bRepeat = false; this->bWaitAfterEachStation = false; this->bOnlyMoveWhileTriggered = false; this->bAttachTrigger = false; this->bReopen = false; this->bReclose = false; this->triggers = 0; this->stations = 0; this->repeats = 0; this->state = CLOSED; this->station = 0; this->repeatsToGo = 0; this->time = 0; this->originCoor = Vector(0, 0, 0); this->originDir = Quaternion(0, Vector(0, 0, 0)); this->soundSource_starting.setSourceNode(this); this->soundSource_moving.setSourceNode(this); this->soundSource_ending.setSourceNode(this); PRINTF(0)("1_2\n"); if (root != NULL) this->loadParams(root); this->updateNode(0.001); this->originCoor = this->getAbsCoor(); this->originDir = this->getAbsDir(); PRINTF(0)("1_3\n"); if (this->stations) this->station = this->stations->getNextStation(0); PRINTF(0)("1_4\n"); if (this->triggers) this->triggers->setBaseCoor(this->getAbsCoor()); PRINTF(0)("1_5\n"); } Mover::~Mover() { if (this->triggers) delete this->triggers; if (this->stations) delete this->stations; if (this->soundSource_starting.isPlaying()) this->soundSource_starting.stop(); if (this->soundSource_moving.isPlaying()) this->soundSource_moving.stop(); if (this->soundSource_ending.isPlaying()) this->soundSource_ending.stop(); } void Mover::loadParams(const TiXmlElement* root) { PRINTF(0)("2_1\n"); WorldEntity::loadParams(root); LoadParam(root, "bLoop", this, Mover, setLoop) .describe("After getting triggered, the mover loops forever.") .defaultValues(false); LoadParam(root, "bRepeat", this, Mover, setRepeat) .describe("After getting triggered, the mover moves n times.") .defaultValues(1); LoadParam(root, "bWaitAfterEachStation", this, Mover, setWaitAfterEachStation) .describe("After each station, the mover waits until he gets triggered.") .defaultValues(false); LoadParam(root, "bOnlyMoveWhileTriggered", this, Mover, setOnlyMoveWhileTriggered) .describe("The mover stops as soon as he gets untriggered.") .defaultValues(false); LoadParam(root, "bAttachTrigger", this, Mover, setAttachTrigger) .describe("The trigger follows the mover.") .defaultValues(false); LoadParam(root, "bReopen", this, Mover, setReopen) .describe("Stops closing and reopens the mover when he gets triggered again.") .defaultValues(false); LoadParam(root, "bReclose", this, Mover, setReclose) .describe("Stops opening and recloses the mover when he gets untriggered.") .defaultValues(false); PRINTF(0)("2_2\n"); LoadParamXML(root, "triggers", this, Mover, setTriggers) .describe("Adds a trigger that releases the mover."); PRINTF(0)("2_3\n"); LoadParamXML(root, "stations", this, Mover, setStations) .describe("Adds a station to the movers stations-list."); PRINTF(0)("2_4\n"); } void Mover::setTriggers(const TiXmlElement* root) { PRINTF(0)("3_1\n"); this->triggers = new MoverTriggerList(); const TiXmlElement* element = root->FirstChildElement(); PRINTF(0)("3_2\n"); while (element != NULL) { PRINTF(0)("3_3\n"); // PRINTF(0)("TiXmlElement Value: %s\n", element->Value()); BaseObject *newObj = Factory::fabricate(element); // PRINTF(0)("BaseObject ClassName: %s\n", newObj->getClassCName()); // MoverTrigger *newTrigger = ((MoverTrigger*)(&newObj)); MoverTrigger *newTrigger = (dynamic_cast< MoverTrigger *> ( newObj )); this->triggers->addTrigger(newTrigger); // this->triggers->addTrigger(MoverTrigger::createTrigger(element)); PRINTF(0)("3_4\n"); element = element->NextSiblingElement(); PRINTF(0)("3_5\n"); } PRINTF(0)("3_6\n"); } void Mover::setStations(const TiXmlElement* root) { PRINTF(0)("4_1\n"); this->stations = new MoverStationList(); const TiXmlElement* element = root->FirstChildElement(); PRINTF(0)("4_2\n"); while (element != NULL) { PRINTF(0)("4_3\n"); this->stations->addStation(new MoverStation(element)); element = element->NextSiblingElement(); } PRINTF(0)("4_4\n"); } void Mover::tick(float dt) { // PRINTF(0)("15_1 mover state of mover %p is %i, triggerlist is %p\n", this, this->state, this->triggers); if (this->state == DELAY || this->state == MOVE || this->state == STAY) this->time += dt; if (this->state == NEXT) this->changeState(this->next()); if (this->state == WAIT) this->changeState(this->wait()); if (this->state == CLOSED) this->changeState(this->closed()); if (this->state == OPEN) this->changeState(this->open()); if (this->state == DELAY) this->changeState(this->delay()); if (this->state == MOVE) this->changeState(this->move(dt)); if (this->state == STAY) this->changeState(this->stay()); } void Mover::changeState(int state) { if (this->state == state) return; this->state = state; if (this->state == DELAY || this->state == STAY) this->time = 0; } int Mover::closed() { if (this->triggers && this->triggers->isTriggered()) { if (this->bRepeat) this->repeatsToGo = this->repeats; return DELAY; } return CLOSED; } int Mover::open() { if (this->triggers && !this->triggers->isTriggered()) { return DELAY; } return OPEN; } int Mover::wait() { if (this->triggers && this->triggers->isTriggered()) { this->soundSource_moving.play(); return MOVE; } return WAIT; } int Mover::next() { bool isOpen = false; bool isClosed = false; if (this->stations) { isOpen = this->stations->isOpen(station); isClosed = this->stations->isClosed(station); this->station = this->stations->getNextStation(this->station); } if (isClosed && this->bRepeat) this->repeatsToGo--; if (isClosed && (!this->bLoop && this->repeatsToGo <= 0)) return CLOSED; if (isOpen && (!this->bLoop && this->repeatsToGo <= 0)) return OPEN; if (this->bWaitAfterEachStation) return WAIT; if ((this->bLoop || this->repeats > 0) || (!isOpen && !isClosed)) return DELAY; return NEXT; } int Mover::delay() { if (!this->stations || (this->time < this->stations->getDelay(this->station))) return DELAY; if (this->stations->getStartingSound(this->station).loaded()) this->soundSource_starting.play(this->stations->getStartingSound(this->station)); if (this->stations->getMovingSound(this->station).loaded()) this->soundSource_moving.play(this->stations->getMovingSound(this->station), 1.0, true); this->time = 0; return MOVE; } int Mover::move(float dt) { if (this->stations) { this->shiftCoor(this->stations->getVelocity(this->station) * dt); this->setAbsDir(this->originDir * (this->stations->getRotation(this->station) * this->time)); } if (this->bAttachTrigger && this->triggers) this->triggers->setBaseCoor(this->getAbsCoor()); if (!this->bLoop && this->repeatsToGo <= 0) { if (this->stations && this->triggers && this->stations->changeDirection(this->bReopen, this->bReclose, this->triggers->isTriggered())) { this->time = this->stations->getMovingTime(this->station) - this->time; this->originCoor = this->originCoor - this->stations->getRelTargetCoor(this->station); this->originDir = this->originDir / this->stations->getRelTargetDir(this->station); } } if (/*this->reachedStationsTarget(dt) || */(this->stations && (this->time >= 1.1 * this->stations->getMovingTime(this->station)))) // if (this->stations && (this->time >= this->stations->getMovingTime(this->station))) { this->setAbsCoor(this->originCoor + this->stations->getRelTargetCoor(this->station)); this->setAbsDir(this->originDir * this->stations->getRelTargetDir(this->station)); if (this->stations->getEndingSound(this->station).loaded()) this->soundSource_ending.play(this->stations->getEndingSound(this->station)); this->soundSource_moving.stop(); this->originCoor = this->originCoor + this->stations->getRelTargetCoor(this->station); this->originDir = this->originDir * this->stations->getRelTargetDir(this->station); return STAY; } if (this->triggers && this->bOnlyMoveWhileTriggered && (!this->triggers->isTriggered())) { this->soundSource_moving.stop(); return WAIT; } return MOVE; } int Mover::stay() { if (!this->stations || (this->time < this->stations->getStayOpenTime(this->station))) return STAY; return NEXT; } bool Mover::reachedStationsTarget(float dt) { if (this->stations) if ((this->getAbsCoor() - (this->originCoor + this->stations->getRelTargetCoor(this->station))).len() <= 1.2 * (this->stations->getVelocity(this->station) * dt).len()) if (fabs((this->getAbsDir() / (this->originDir * this->stations->getRelTargetDir(this->station))).w) <= 1.2 * fabs(this->stations->getRotation(this->station).w * dt)) return true; return false; }