//--------------------------- BoundsAvoidance -------------------------------- // // This returns a steering force that will keep the agent in an area //------------------------------------------------------------------------ Vector2D SteeringBehavior::BoundsAvoidance() { std::vector<Vector2D> m_Feelers(3); const float m_dWallDetectionFeelerLength = 20; //feeler pointing straight in front m_Feelers[0] = m_pMovingEntity->Pos() + m_dWallDetectionFeelerLength * m_pMovingEntity->Heading(); //feeler to left Vector2D temp = m_pMovingEntity->Heading(); Vec2DRotateAroundOrigin(temp, HalfPi * 3.5f); m_Feelers[1] = m_pMovingEntity->Pos() + m_dWallDetectionFeelerLength/2.0f * temp; //feeler to right temp = m_pMovingEntity->Heading(); Vec2DRotateAroundOrigin(temp, HalfPi * 0.5f); m_Feelers[2] = m_pMovingEntity->Pos() + m_dWallDetectionFeelerLength/2.0f * temp; float DistToThisIP = 0.0; float DistToClosestIP = MaxDouble; Vector2D wallsv[5] = {Vector2D(m_bounds.left, m_bounds.top), Vector2D(m_bounds.left, m_bounds.top+m_bounds.height), Vector2D(m_bounds.left+m_bounds.width, m_bounds.top+m_bounds.height), Vector2D(m_bounds.left+m_bounds.width, m_bounds.top), Vector2D(m_bounds.left, m_bounds.top) }; //this will hold an index into the vector of walls int ClosestWall = -1; Vector2D SteeringForce, point, //used for storing temporary info ClosestPoint; //holds the closest intersection point //examine each feeler in turn for (unsigned int flr=0; flr<m_Feelers.size(); ++flr) { //run through each wall checking for any intersection points for (int i = 0; i < 4; i++) { if (LineIntersection2D(m_pMovingEntity->Pos(), m_Feelers[flr], wallsv[i], wallsv[i+1], DistToThisIP, point)) { //is this the closest found so far? If so keep a record if (DistToThisIP < DistToClosestIP) { DistToClosestIP = DistToThisIP; ClosestWall = i; ClosestPoint = point; } } }//next wall //if an intersection point has been detected, calculate a force //that will direct the agent away if (ClosestWall != -1) { //calculate by what distance the projected position of the agent //will overshoot the wall Vector2D OverShoot = m_Feelers[flr] - ClosestPoint; Vector2D temp = Vec2DNormalize(wallsv[ClosestWall] - wallsv[ClosestWall+1]); Vector2D normal (-temp.y,temp.x); //create a force in the direction of the wall normal, with a //magnitude of the overshoot SteeringForce = normal * OverShoot.Length(); } }//next feeler return SteeringForce; }
//----------------------- TestSensors ------------------------------------ // // This function checks for any intersections between the sweeper's // sensors and the objects in its environment //------------------------------------------------------------------------ void CMinesweeper::TestSensors(vector<SPoint> &objects) { m_bCollided = false; //first we transform the sensors into world coordinates m_tranSensors = m_Sensors; WorldTransform(m_tranSensors, 1); //scale is 1 //flush the sensors m_vecdSensors.clear(); m_vecFeelers.clear(); //now to check each sensor against the objects in the world for (int sr=0; sr<m_tranSensors.size(); ++sr) { bool bHit = false; double dist = 0; for (int seg=0; seg<objects.size(); seg+=2) { if (LineIntersection2D(SPoint(m_vPosition.x, m_vPosition.y), m_tranSensors[sr], objects[seg], objects[seg+1], dist)) { bHit = true; break; } } if (bHit) { m_vecdSensors.push_back(dist); //implement very simple collision detection if (dist < CParams::dCollisionDist) { m_bCollided = true; } } else { m_vecdSensors.push_back(-1); } //check how many times the minesweeper has visited the cell //at the current position int HowOften = m_MemoryMap.TicksLingered(m_tranSensors[sr].x, m_tranSensors[sr].y); //Update the memory info according to HowOften. The maximum //value is 1 (because we want all the inputs into the //ANN to be scaled between -1 < n < 1) if (HowOften == 0) { m_vecFeelers.push_back(-1); continue; } if (HowOften < 10) { m_vecFeelers.push_back(0); continue; } if (HowOften < 20) { m_vecFeelers.push_back(0.2); continue; } if (HowOften < 30) { m_vecFeelers.push_back(0.4); continue; } if (HowOften < 50) { m_vecFeelers.push_back(0.6); continue; } if (HowOften < 80) { m_vecFeelers.push_back(0.8); continue; } m_vecFeelers.push_back(1); }//next sensor }
//----------------------- TestSensors ------------------------------------ // // This function checks for any intersections between the sweeper's // sensors and the objects in its environment //------------------------------------------------------------------------ void CMinesweeper::TestSensors(vector<SPoint> &objects) { m_bCollided = false; //first we transform the sensors into world coordinates m_tranSensors = m_Sensors; WorldTransform(m_tranSensors, 1); //scale is 1 //flush the sensors m_vecdSensors.clear(); m_vecFeelers.clear(); //now to check each sensor against the objects in the world for (int sr=0; sr<m_tranSensors.size(); ++sr) { bool bHit = false; double dist = 0; for (int seg=0; seg<objects.size(); seg+=2) { if (LineIntersection2D(SPoint(m_vPosition.x, m_vPosition.y), m_tranSensors[sr], objects[seg], objects[seg+1], dist)) { bHit = true; break; } } if (bHit) { m_vecdSensors.push_back(dist); //implement very simple collision detection if (dist < CParams::dCollisionDist) { m_bCollided = true; } } else { m_vecdSensors.push_back(-1); } }//next sensor if (!m_bCollided) { if (m_vPosition.y < 15) { m_bCollided = true; return; } if (m_vPosition.y > 170) { m_bCollided = true; return; } if (m_vPosition.y < 100) { if (m_vPosition.x > 230) { m_bCollided = true; return; } if (m_vPosition.x < 150) { m_bCollided = true; return; } } } }