void PathfindingBehavior::MoveTo(RuntimeScene & scene, float x, float y) { if ( parentScene != &scene ) //Parent scene has changed { parentScene = &scene; sceneManager = parentScene ? &ScenePathfindingObstaclesManager::managers[&scene] : NULL; } path.clear(); //First be sure that there is a path to compute. int targetCellX = GDRound(x/(float)cellWidth); int targetCellY = GDRound(y/(float)cellHeight); int startCellX = GDRound(object->GetX()/(float)cellWidth); int startCellY = GDRound(object->GetY()/(float)cellHeight); if ( startCellX == targetCellX && startCellY == targetCellY ) { path.push_back(sf::Vector2f(object->GetX(), object->GetY())); path.push_back(sf::Vector2f(x, y)); EnterSegment(0); pathFound = true; return; } //Start searching for a path //TODO: Customizable heuristic. ::SearchContext ctx(*sceneManager, allowDiagonals); ctx.SetCellSize(cellWidth, cellHeight).SetStartPosition(object->GetX(), object->GetY()); ctx.SetObjectSize(object->GetX()-object->GetDrawableX()+extraBorder, object->GetY()-object->GetDrawableY()+extraBorder, object->GetWidth()-(object->GetX()-object->GetDrawableX())+extraBorder, object->GetHeight()-(object->GetY()-object->GetDrawableY())+extraBorder); if (ctx.ComputePathTo(x, y)) { //Path found: memorize it const ::Node * node = ctx.GetFinalNode(); while (node) { path.push_back(sf::Vector2f(node->pos.x*(float)cellWidth, node->pos.y*(float)cellHeight)); node = node->parent; } std::reverse(path.begin(), path.end()); path[0] = sf::Vector2f(object->GetX(), object->GetY()); EnterSegment(0); pathFound = true; return; } //Not path found pathFound = false; }
void PathBehavior::Reverse() { float tempTimeOnSegment = timeOnSegment; std::reverse(path.begin(), path.end()); EnterSegment(path.size() - currentSegment - 2); timeOnSegment = totalSegmentTime - tempTimeOnSegment; }
/** * Called at each frame before events : * Position the object on the path */ void PathBehavior::DoStepPreEvents(RuntimeScene & scene) { if(!isPathLoaded) { LoadPath(scene); Reset(); } // add to the current time along the path timeOnSegment += static_cast<double>(scene.GetTimeManager().GetElapsedTime()) / 1000000.0 * speed; // if I reached the end of this segment, move to a new segment if (timeOnSegment >= totalSegmentTime && currentSegment < path.size()) EnterSegment(currentSegment + 1); //Position object on the segment sf::Vector2f newPos; if ( !path.empty() && currentSegment < path.size()-1 ) newPos = offset + path[currentSegment] + (path[currentSegment + 1] - path[currentSegment]) * (timeOnSegment / totalSegmentTime); else { if ( stopAtEnd && !path.empty()) newPos = path.back() + offset; else if (reverseAtEnd) { std::reverse(path.begin(), path.end()); EnterSegment(0); if (!path.empty()) newPos = path.front() + offset; } else { EnterSegment(0); if (!path.empty()) newPos = path.front() + offset; } } object->SetX(newPos.x); object->SetY(newPos.y); return; }
void PathBehavior::DoStepPostEvents(RuntimeScene & scene) { if(!isPathLoaded) { LoadPath(scene); Reset(); } if(futureSegment != -1) { EnterSegment(futureSegment); futureSegment = -1; } if(futurePosition != -1) { timeOnSegment = futurePosition * totalSegmentTime; futurePosition = -1; } }
void PathfindingBehavior::DoStepPreEvents(RuntimeScene & scene) { if ( parentScene != &scene ) //Parent scene has changed { parentScene = &scene; sceneManager = parentScene ? &ScenePathfindingObstaclesManager::managers[&scene] : NULL; } if ( !sceneManager ) return; if (path.empty() || reachedEnd) return; //Update the speed of the object float timeDelta = static_cast<double>(scene.GetTimeManager().GetElapsedTime()) / 1000000.0; speed += acceleration*timeDelta; if ( speed > maxSpeed ) speed = maxSpeed; angularSpeed = angularMaxSpeed; //No acceleration for angular speed for now //Update the time on the segment and change segment if needed timeOnSegment += speed*timeDelta; if (timeOnSegment >= totalSegmentTime && currentSegment < path.size()) EnterSegment(currentSegment + 1); //Position object on the segment and update its angle sf::Vector2f newPos; float pathAngle = object->GetAngle(); if ( currentSegment < path.size()-1 ) { newPos = path[currentSegment] + (path[currentSegment + 1] - path[currentSegment]) * (timeOnSegment / totalSegmentTime); pathAngle = atan2(path[currentSegment+1].y - path[currentSegment].y, path[currentSegment+1].x - path[currentSegment].x)*180/3.14159+angleOffset; } else newPos = path.back(); object->SetX(newPos.x); object->SetY(newPos.y); //Also update angle if needed if ( rotateObject ) object->RotateTowardAngle(pathAngle, angularSpeed, scene); }
void PathBehavior::Reset() { EnterSegment(0); }