NLS Engine  v0.1
The Next Logical Step in game engine design.
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Defines
GridMover.cpp
Go to the documentation of this file.
00001 
00012 #include "GridMover.h"
00013 
00014 // System Library Includes
00015 
00016 // Application Library Includes
00017 
00018 // Local Includes
00019 #include "../../sharedbase/Entity.h"
00020 #include "../../sharedbase/ComponentInterface.h"
00021 #include "../../sharedbase/MessageRouter.h"
00022 #include "../../sharedbase/Envelope.h"
00023 
00024 // Forward Declarations
00025 
00026 // Typedefs and data structures
00027 
00028 // Constants
00029 
00030 // Class methods
00031 namespace Physics {
00032   #define SUBSCRIBE_BASIC(msgid, handler)   {std::shared_ptr<Subscriber> handler_sptr(new Subscriber(boost::bind((&handler), this, _1))); this->msgrouter->Subscribe((msgid), handler_sptr);}
00033   #define UNSUBSCRIBE_BASIC(msgid, handler) {std::shared_ptr<Subscriber> handler_sptr(new Subscriber(boost::bind((&handler), this, _1))); this->msgrouter->Unsubscribe((msgid), handler_sptr);}
00034 
00035   GridMover::GridMover( EntitySPTR owner, ModuleInterface* module, MessageRouter* msgrtr ) : InterfaceUpdateable(owner, module), msgrouter(msgrtr)  {
00036     preaction = false;
00037     postaction = false;
00038     this->scale = 32;
00039     this->path = nullptr;
00040     this->currentPoint = Point();
00041     this->nextPoint = Point();
00042     this->pauseDelay = 0.0f;
00043     this->currentDelay = 0.0f;
00044     SUBSCRIBE_BASIC(3100, GridMover::ActionComplete);
00045   }
00046 
00047   GridMover::~GridMover() {
00048 
00049   }
00050 
00051 
00052   bool GridMover::SetMovementScale( unsigned int size ) {
00053     this->scale = size;
00054     return true;
00055   }
00056 
00057   void GridMover::AddPointActionHandler( unsigned int timing, unsigned int actionhandler ) {
00058     this->actionHandlers[timing] = actionhandler;
00059   }
00060 
00061   void GridMover::RemovePointActionHandler( unsigned int timing ) {
00062     if (this->actionHandlers.find(timing) != this->actionHandlers.end()) {
00063       this->actionHandlers.erase(timing);
00064     }
00065   }
00066   bool GridMover::LoadObjectData( EnvelopeSPTR data ) {
00067     for (unsigned int i = 0; i < data.get()->GetCount(); ++i) { // Loop through each object
00068       EnvelopeSPTR object(data.get()->GetDataEnvelopeSPTR(i));
00069 
00070       HandlerData hd;
00071       Point p;
00072       hd.type = object.get()->GetDataString(0); // 0 - Type
00073       hd.name = object.get()->GetDataString(1); // 1 - Name
00074       hd.data = object.get()->GetDataString(2); // 2 - Data
00075       p.x = object.get()->GetDataInt(3) / 32;   // 3 - x
00076       p.y = object.get()->GetDataInt(4) / 32;   // 4 - y
00077 
00078       this->pointHandlerdata[p] = hd;
00079     }
00080 
00081     return true;
00082   }
00083 
00084   bool GridMover::SetPath( PointList* points ) {
00085     if (points != nullptr) {
00086       this->path = points;
00087       this->owner->location.x = (float)this->path->CurrentPoint().x * this->scale; // Stores the current point
00088       this->owner->location.y = (float)this->path->CurrentPoint().y * this->scale; // Stores the current point
00089       this->currentPoint = this->path->CurrentPoint(); // Set the currentPoint to the current point in the list
00090       this->nextPoint = this->path->PeekNextPoint(); // Peek what the next point is after that, and store it in nextPoint
00091       return true;
00092     }
00093 
00094     return false;
00095   }
00096 
00097   void GridMover::Update( double dt ) {
00098     // Wait for pause if currentDelay was reset upon entering a point
00099     if ((this->currentDelay + dt) < pauseDelay) {
00100       this->currentDelay += dt;
00101       return;
00102     }
00103 
00104     if (this->postaction) {
00105       // Check if there is a action for leaving the point
00106       if (this->actionHandlers.find(TIMING::POINT_LEAVE) != this->actionHandlers.end()) {
00107         unsigned int leaveActionID = actionHandlers[TIMING::POINT_LEAVE];
00108 
00109         // Send an envelope with the actionID as the msgid
00110         EnvelopeSPTR actionEnv(new Envelope());
00111         actionEnv->msgid = leaveActionID;
00112 
00113         // Add the x and y for the current point as 2 separate values as script doesn't yet known about the Point type.
00114         actionEnv->AddData(this->currentPoint.x);
00115         actionEnv->AddData(this->currentPoint.y);
00116 
00117         // Add the x and y for the current point as 2 separate values as script doesn't yet known about the Point type.
00118         if (this->pointHandlerdata.find(this->currentPoint) != this->pointHandlerdata.end()) {
00119           HandlerData hd = this->pointHandlerdata[this->currentPoint];
00120           actionEnv->AddData(hd.type);
00121           actionEnv->AddData(hd.name);
00122           actionEnv->AddData(hd.data);
00123           this->pointHandlerdata.erase(this->nextPoint);
00124         }
00125 
00126         this->msgrouter->SendSP(actionEnv);
00127       }
00128     }
00129 
00130     if ((!preaction) && (!postaction)) {
00131       if (this->owner != nullptr) {
00132         float x = this->owner->location.x;
00133         float y = this->owner->location.y;
00134 
00135         // Normalize it
00136         x /= this->scale;
00137         y /= this->scale;
00138         // Direction multipliers
00139         short leftright = 0; // Moving left to right (1) or right to left (-1), or not in this direction (0)
00140         short updown = 0; // Moving top to bottom (1) or bottom to top (-1), or not in this direction (0)
00141 
00143         // Left or right
00145 
00146         // Check if owner.location.x the same as nextPoint.x
00147         if (fabs((this->owner->location.x / this->scale) - this->nextPoint.x) > .001) { // It's not
00148           if (currentPoint.x < this->nextPoint.x) { // Moving left to right
00149             if ((x +  dt) < this->nextPoint.x) { // We wont pass it.
00150               leftright = 1;
00151             }
00152           }
00153           else if (currentPoint.x > this->nextPoint.x) { // Moving right to left
00154             if ((x + (-1 * dt)) > this->nextPoint.x) {  // We wont pass it.
00155               leftright = -1;
00156             }
00157           }
00158         }
00159 
00161         // Up or down
00163 
00164         // Check if owner.location.y the same as nextPoint.y
00165         if (fabs((this->owner->location.y / this->scale) - this->nextPoint.y) > .001) { // It's not
00166           if (currentPoint.y < this->nextPoint.y) { // Moving up to down
00167             if ((y +  dt) < this->nextPoint.y) { // We wont pass it.
00168               updown = 1;
00169             }
00170           }
00171           else if (currentPoint.y > this->nextPoint.y) { // Moving down to up
00172             if ((y + (-1 * dt)) > this->nextPoint.y) {  // We wont pass it.
00173               updown = -1;
00174             }
00175           }
00176         }
00177 
00178         // If we can't move leftright or upddown we have each the nextpoint
00179         if ((leftright == 0) && (updown == 0)) {
00180           Point prevPoint = this->currentPoint;
00181           this->currentPoint = this->nextPoint; // We arrived at the next point, update current point to reflected that
00182 
00183           // Path is either null or invalid
00184           if (this->path == nullptr)  {
00185             return;
00186           }
00187           if (this->path->PeekNextPoint().x == -1) {
00188             return;
00189           }
00190 
00191           // Check if the current point we are on is still the next point
00192           if ((this->currentPoint.x == this->path->PeekNextPoint().x) && (this->currentPoint.y == this->path->PeekNextPoint().y)) {
00193             this->path->NextPoint(); // Advance the next point
00194             this->nextPoint = this->path->PeekNextPoint(); // Peek what the next point is after that, and store it in nextPoint
00195           }
00196           else { // Our path changed
00197             Point nextPeek = this->path->PeekNextPoint();
00198             if ((abs(nextPeek.x - this->currentPoint.x) <= 1) && (abs(nextPeek.y - this->currentPoint.y) <= 1)) { // Movement will be 1 away so still good
00199               this->path->NextPoint(); // Set the currentPoint to the next point in the list (advances the list)
00200               this->nextPoint = this->path->PeekNextPoint(); // Peek what the next point is after that, and store it in nextPoint
00201             }
00202             else { // Moving to far so move back one
00203               this->nextPoint = prevPoint;
00204             }
00205           }
00206 
00207           // Check if there is an action upon entering the point
00208           // Reset the delay in ActionComplete
00209           if (this->actionHandlers.find(TIMING::POINT_ENTER) != this->actionHandlers.end()) {
00210             this->preaction = true;
00211             unsigned int enterActionID = this->actionHandlers[TIMING::POINT_ENTER];
00212 
00213             // Send an envelope with the actionID as the msgid
00214             EnvelopeSPTR actionEnv(new Envelope());
00215             actionEnv->msgid = enterActionID;
00216 
00217             actionEnv->AddData(this->currentPoint.x);
00218             actionEnv->AddData(this->currentPoint.y);
00219 
00220             // Add the x and y for the current point as 2 separate values as script doesn't yet known about the Point type.
00221             if (this->pointHandlerdata.find(this->currentPoint) != this->pointHandlerdata.end()) {
00222               HandlerData hd = this->pointHandlerdata[this->currentPoint];
00223               actionEnv->AddData(hd.type);
00224               actionEnv->AddData(hd.name);
00225               actionEnv->AddData(hd.data);
00226               //this->pointHandlerdata.erase(this->nextPoint);
00227             }
00228 
00229             this->msgrouter->SendSP(actionEnv);
00230           }
00231           else { // No actions so reset the delay
00232             this->currentDelay = 0.0f;
00233           }
00234         }
00235         else { // Move
00236           if (leftright == 0) {
00237             this->owner->location.x = (float)this->nextPoint.x * scale;
00238           }
00239           else {
00240             this->owner->location.x += (float)((double)leftright * dt) * scale;
00241           }
00242 
00243           if (updown == 0) {
00244             this->owner->location.y = (float)this->nextPoint.y * scale;
00245           }
00246           else {
00247             this->owner->location.y += (float)((double)updown * dt) * scale;
00248           }
00249         }
00250 
00251       }
00252     }
00253   }
00254 
00255   void GridMover::ActionComplete( EnvelopeSPTR env ) {
00256     unsigned int timing = env->GetDataUInt(0);
00257     if (timing == TIMING::POINT_ENTER) {
00258       this->preaction = false;
00259 
00260       this->postaction = true;
00261     }
00262 
00263     if (timing == TIMING::POINT_LEAVE) {
00264       this->postaction = false;
00265 
00266       this->currentDelay = 0.0f;
00267     }
00268   }
00269 
00270   bool GridMover::SetPauseDelay( float d ) {
00271     this->pauseDelay = d;
00272 
00273     return true;
00274   }
00275 }