/*! @brief Calculates the difference between the current state and the stationary object @param theObject the stationary field object you want the relative coordinates @return the difference between the current field state and theObject, otherwise known as the relative location of theObject [distance, bearing] */ std::vector<float> Self::CalculateDifferenceFromStationaryObject(const StationaryObject& theObject) { std::vector<float> fieldlocation(2,0); fieldlocation[0] = theObject.X(); fieldlocation[1] = theObject.Y(); return CalculateDifferenceFromFieldLocation(fieldlocation); }
/*! @brief Calculate the distance to a stationary object */ float Self::CalculateDistanceToStationaryObject(const StationaryObject& theObject) { float selfX = WorldModelLocation[0]; float selfY = WorldModelLocation[1]; float diffX = theObject.X() - selfX; float diffY = theObject.Y() - selfY; float distance = sqrt( diffX * diffX + diffY * diffY ); return distance; }
/*! @brief Calculate the bearing to a stationary object */ float Self::CalculateBearingToStationaryObject(const StationaryObject& theObject) { float selfX = WorldModelLocation[0]; float selfY = WorldModelLocation[1]; float selfHeading = WorldModelLocation[2]; float diffX = theObject.X() - selfX; float diffY = theObject.Y() - selfY; float positionHeading = atan2(diffY, diffX); float bearing = normaliseAngle(positionHeading - selfHeading); return bearing; }
/*! @brief Calculates the angular width (in radians) of the goal from the mobile object */ float Self::CalculateAngularWidthOfGoalFromMobileObject(const StationaryObject& goalpost, const MobileObject& mobileobject) { float mobileX = mobileobject.X(); float mobileY = mobileobject.Y(); float goalX = goalpost.X(); float goalY = 0; float diffX = goalX - mobileX; float diffY = goalY - mobileY; if( (diffX == 0) && (diffY == 0)) diffY = 0.0001; float distance = sqrt( diffX * diffX + diffY * diffY ); float bearing = atan2(diffY, diffX); // bearing FROM the mobile object to the goal (from the field x-axis) float width = 2*fabs(goalpost.Y()); // python: angularwidth = numpy.arctan2(width*numpy.cos(bearing), 2*distance + width*numpy.sin(bearing)) + numpy.arctan2(width*numpy.cos(bearing), 2*distance - width*numpy.sin(bearing)) float angularwidth = atan2(width*cos(bearing), 2*distance + width*sin(bearing)) + atan2(width*cos(bearing), 2*distance - width*sin(bearing)); return angularwidth; }
/*! @brief Calculates the angular width of the goal (in radians) from the current state */ float Self::CalculateAngularWidthOfGoal(const StationaryObject& goalpost) { std::vector<float> location = CalculateDifferenceFromGoal(goalpost); float distance = location[0]; float bearing = normaliseAngle(location[1] + Heading()); // bearing from the field x-axis! float width = 2*fabs(goalpost.Y()); // python: angularwidth = numpy.arctan2(width*numpy.cos(bearing), 2*distance + width*numpy.sin(bearing)) + numpy.arctan2(width*numpy.cos(bearing), 2*distance - width*numpy.sin(bearing)) float angularwidth = atan2(width*cos(bearing), 2*distance + width*sin(bearing)) + atan2(width*cos(bearing), 2*distance - width*sin(bearing)); return angularwidth; }
/*! @brief Calculates the position to stand in to protect the goal from a mobile object @return [x,y] of the position relative to the current state */ std::vector<float> Self::CalculatePositionToProtectGoalFromMobileObject(const MobileObject& mobileobject, const StationaryObject& goalpost, float blockingwidth) { vector<float> prediction = CalculateClosestInterceptToMobileObject(mobileobject); if (prediction[0] < 4 and mobileobject.estimatedDistance() > 30) { // if the ball is moving go to where the ball will be! vector<float> prediction_position(2,0); prediction_position[0] = prediction[1]; prediction_position[1] = prediction[2]; #if DEBUG_BEHAVIOUR_VERBOSITY > 1 debug << "protectGoal Predicated x:" << prediction_position[0] << " y: " << prediction_position[1] << " ballx: " << ball.estimatedDistance()*cos(heading) << " bally: " << ball.estimatedDistance()*sin(heading) << endl; #endif return prediction_position; } else { float goal_angular_width = fabs(CalculateAngularWidthOfGoalFromMobileObject(goalpost, mobileobject)); float goal_width = 2*fabs(goalpost.Y()); float distancebetween = sqrt(pow(mobileobject.X() - goalpost.X(), 2) + pow(mobileobject.Y(),2)); float distancefrommobile = (0.5*blockingwidth)/tan(0.5*goal_angular_width); vector<float> position(2,0); if (distancebetween < 0.7*goal_width) { // if the mobile object is inside the goal then the calculation will break --- just go to the mobile object float b_r = mobileobject.estimatedDistance()*cos(mobileobject.estimatedElevation()); // get the flat distance! float b_b = mobileobject.estimatedBearing(); position[0] = b_r*cos(b_b); position[1] = b_r*sin(b_b); return position; } // clip the distancefrommobile so that we don't go back into the goal. if (distancebetween - distancefrommobile < 0.7*goal_width) distancefrommobile = distancebetween - 0.7*goal_width; return CalculatePositionBetweenMobileObjectAndGoal(mobileobject, goalpost, distancefrommobile); } }
void Game::draw() { al_clear_to_color(al_map_rgb(0, 0, 0)); // draw player float x1 = m_player->getX(); float x2 = x1 + (m_player->getWidth() * PLAYER_WIDTH); float y1 = m_player->getY(); float y2 = y1 + (m_player->getHeight() * PLAYER_HEIGHT); al_draw_filled_rectangle(x1, y1, x2, y2, al_map_rgb(0, 255, 0)); float playerX = x1; // move camera if (playerX <= SCREEN_WIDTH / 2) //camX = 0; ; else if (playerX >= m_levelWidth - SCREEN_WIDTH / 2) m_camX = m_levelWidth - SCREEN_WIDTH; //; else { m_camX = playerX - SCREEN_WIDTH / 2; } ALLEGRO_TRANSFORM trans; al_identity_transform(&trans); al_translate_transform(&trans, -m_camX, 0); al_use_transform(&trans); for (list<StationaryObject*>::iterator it = m_stationaryobjects.begin(); it != m_stationaryobjects.end(); it++) { StationaryObject* current = *it; int width = current->getWidth() * TILE_WIDTH; int height = current->getHeight() * TILE_HEIGHT; float x1 = current->getX(); float x2 = x1 + width; float y1 = current->getY(); float y2 = y1 + height; if (x2 >= m_camX || x1 >= m_camX) { char tile = current->getTile(); switch (tile) { case 'w': al_draw_filled_rectangle(x1, y1, x2, y2, al_map_rgb(255, 0, 0)); break; case 's': al_draw_filled_rectangle(x1, y1, x2, y2, al_map_rgb(255, 255, 0)); break; } } } al_flip_display(); }
void locWmGlDisplay::drawStationaryObjectLabel(const StationaryObject& object) { QString displayString("(%1,%2)"); renderText(object.X(), object.Y(),1,displayString.arg(object.measuredDistance(),0,'f',1).arg(object.measuredBearing(),0,'f',3)); }
StationaryObject::StationaryObject(const StationaryObject& otherObject): Object(otherObject.getID(), otherObject.getName()), fieldLocation(otherObject.getFieldLocation()) { }
/*! @brief Calculates the difference from a goal @return the difference between the current position and the goal [distance, bearing] */ std::vector<float> Self::CalculateDifferenceFromGoal(const StationaryObject& goalpost) { std::vector<float> fieldlocation(2,0); fieldlocation[0] = goalpost.X(); return CalculateDifferenceFromFieldLocation(fieldlocation); }
int Game::parseMapFile() // returns value for m_levelWidth { ifstream mapFile; mapFile.open(m_mapFile); if (!mapFile.is_open()) { fprintf(stderr, "Could not open map file.\n"); exit(0); } int highest_x = 0; int lineNum = 1; string line; int commaCount = 0; while (getline(mapFile, line)) { char tile; int row, col, width, height; int num = -1; for (size_t k = 0; k < line.length(); k++) { if (line[k] == ',') { commaCount++; //num = -1; } else if (isdigit(line[k])) { if (num != -1) { num = (num * 10) + (line[k] - '0'); } else num = line[k] - '0'; continue; } if (k == 0) // tile char { tile = line[k]; if (tile != 'w' && tile != 'p' && tile != 's' && tile != 'm') { fprintf(stderr, "%s %c %s %d \n", "Map file error:\nInvalid tile char: '", tile, "' at line: ", lineNum); exit(0); } } else { switch (commaCount) { case 1: break; case 2: // row row = num; num = -1; if (row < 0 || row >= NUM_ROWS) { fprintf(stderr, "%s %d %s %d \n", "Map file error:\nInvalid row: '", row, "' at line: ", lineNum); exit(0); } break; case 3: // col col = num; num = -1; if (col < 0 || col >= MAX_NUM_COLS) { fprintf(stderr, "%s %d %s %d \n", "Map file error:\nInvalid col: '", col, "' at line: ", lineNum); exit(0); } break; case 4: // width width = num; num = -1; if (width < 1 || width > MAX_NUM_COLS) { fprintf(stderr, "%s %d %s %d \n", "Map file error:\nInvalid width: '", width, "' at line: ", lineNum); exit(0); } break; case 5: // height height = num; num = -1; if (height < 1 || height > NUM_ROWS) { fprintf(stderr, "%s %d %s %d \n", "Map file error:\nInvalid height: '", height, "' at line: ", lineNum); exit(0); } break; default: fprintf(stderr, "%s %d \n", "Map file error:\nExtra parameters at line: ", lineNum); exit(0); } } } // create the gameobject switch (tile) { case 'w': addNewStationaryObject(new Wall(row, col, width, height, this, lineNum)); break; case 'p': { if (m_player != NULL) { fprintf(stderr, "%s%d\n", "Map file error:\nCan only have one player. Extra player at line: ", lineNum); exit(0); } m_player = new Player(row, col, width, height, this, lineNum); break; } case 's': addNewStationaryObject(new StationaryEnemy(row, col, width, height, this, lineNum)); break; case 'm': break; } if (tile == 'w' || tile == 's') { StationaryObject* last = m_stationaryobjects.back(); int last_x = last->getX(); if (last_x > highest_x) highest_x = last_x; } lineNum++; commaCount = 0; } if (m_player == NULL) { fprintf(stderr, "%s\n", "Map file error:\nA player must be added."); exit(0); } // remove chars in map for player int player_row = m_player->getR(); int player_col = m_player->getC(); for (int r = player_row; r < (player_row + m_player->getHeight()); r++) { for (int c = player_col; c < (player_col + m_player->getWidth()); c++) setMap(r, c, NULL); } // remove chars in map for movingobjects // not yet implemented because there are not movingobjects yet. mapFile.close(); return highest_x; }
bool Game::removeStationaryObject(StationaryObject* toDelete) { int pos = toDelete->getPos(); if (m_stationaryCount - pos < pos) { list<StationaryObject*>::reverse_iterator it = m_stationaryobjects.rbegin(); StationaryObject* temp = *it; for (; it != m_stationaryobjects.rend(); it++) { temp = *it; if (pos == temp->getPos()) break; } if (pos != temp->getPos()) // object to be deleted not found return false; for (list<StationaryObject*>::reverse_iterator it2 = m_stationaryobjects.rbegin(); it2 != it; it2++) { StationaryObject* changePos = *it2; changePos->setPos(changePos->getPos() - 1); } m_stationaryobjects.erase(--it.base()); delete toDelete; } else { list<StationaryObject*>::iterator it = m_stationaryobjects.begin(); StationaryObject* temp = *it; for (; it != m_stationaryobjects.end(); it++) { temp = *it; if (pos == temp->getPos()) break; } if (pos != temp->getPos()) // object to be deleted not found return false; for (list<StationaryObject*>::iterator it2 = m_stationaryobjects.begin(); it2 != it; it2++) { StationaryObject* changePos = *it2; changePos->setPos(changePos->getPos() - 1); } m_stationaryobjects.erase(it); delete toDelete; } m_stationaryCount--; return true; }