Example #1
0
/**
 * @brief Performs box traces against the world and all inline models, gives the hit position back
 * @param[in] mapTiles List of tiles the current (RMA-)map is composed of
 * @param[in] traceLine The start/stop position of the trace.
 * @param[in] traceBox The minimum/maximum extents of the collision box that is projected.
 * @param[in] levelmask A mask of the game levels to trace against. Mask 0x100 filters clips.
 * @param[in] brushmask Any brush detected must at least have one of these contents.
 * @param[in] brushreject Any brush detected with any of these contents will be ignored.
 * @param[in] list The local models list (a local model has a name starting with * followed by the model number)
 * @return a trace_t with the information of the closest brush intersected.
 * @sa CM_CompleteBoxTrace
 * @sa CM_HintedTransformedBoxTrace
 */
trace_t CM_EntCompleteBoxTrace (mapTiles_t* mapTiles, const Line& traceLine, const AABB* traceBox, int levelmask, int brushmask, int brushreject, const char** list)
{
	AABB lineBox(*traceBox);
	lineBox.shift(traceLine.start);		/* the traceBox in starting position */
	AABB lineBoxTemp(*traceBox);
	lineBoxTemp.shift(traceLine.stop);	/* in end position */
	lineBox.add(lineBoxTemp);			/* bounding box for the whole trace */
	/* Now lineBox specifies the whole volume to be traced through. */

	/* reconstruct a levelmask */
	const vec_t minZ = lineBox.getMinZ();
	const vec_t maxZ = lineBox.getMaxZ();
	int newLevelMask = 0;
	if (levelmask & TL_FLAG_ACTORCLIP)		/* if the passed levelmask contains the bit for the cliplevels, */
		newLevelMask = TL_FLAG_ACTORCLIP;	/* preserve it */
	for (int i = 0; i < PATHFINDING_HEIGHT; i++) {
		const vec_t lower = i * UNIT_HEIGHT;	/* the height bounds of the level */
		const vec_t upper = (i + 1) * UNIT_HEIGHT;
		if (minZ > upper || maxZ < lower)
			continue;
		newLevelMask |= (1 << i);
	}

	/* trace against world first */
	const trace_t tr = CM_CompleteBoxTrace(mapTiles, traceLine, *traceBox, newLevelMask, brushmask, brushreject);
	if (!list || tr.fraction == 0.0)
		return tr;

	trace_t trace = tr;
	for (const char** name = list; *name; name++) {
		/* check whether this is really an inline model */
		if (*name[0] != '*')
			Com_Error(ERR_DROP, "name in the inlineList is no inline model: '%s'", *name);
		const cBspModel_t* model = CM_InlineModel(mapTiles, *name);
		assert(model);
		if (model->headnode >= mapTiles->mapTiles[model->tile].numnodes + 6)
			continue;

		AABB modelBox;
		/* Quickly calculate the bounds of this model to see if they can overlap. */
		CM_CalculateWidestBoundingBox(model, modelBox);

		/* If the bounds of the extents box and the line do not overlap, then skip tracing this model. */
		if (!lineBox.doesIntersect(modelBox))
			continue;

		const trace_t newtr = CM_HintedTransformedBoxTrace(mapTiles->mapTiles[model->tile], traceLine, *traceBox,
				model->headnode, brushmask, brushreject, model->origin, model->angles, model->shift, trace.fraction);

		/* memorize the trace with the minimal fraction */
		if (newtr.fraction == 0.0)
			return newtr;
		if (newtr.fraction < trace.fraction)
			trace = newtr;
	}
	return trace;
}
Example #2
0
bool PolyQtAnnotation::contains(const QPointF & point) const {
  if (shape().controlPointRect().contains(point)) {
    QPointF imgPoint = this->mapToScene(point) / _scale;
    double curSelectionSensitivity = (_selectionSensitivity * _lineAnnotationSelectedThickness / _currentLoD);
    double curSelectionSensitivitySquared = curSelectionSensitivity * curSelectionSensitivity;
    double imgX = imgPoint.x();
    double imgY = imgPoint.y();
    std::vector<Point> coords = _annotation->getCoordinates();
    double minDist = std::numeric_limits<double>::max();
    _lastClickedFirstCoordinateIndex = -1;
    _lastClickedSecondCoordinateIndex = -1;

    // Quickly check if a seed point was hit
    for (unsigned int i = 0; i < coords.size(); ++i) {
      Point pt1 = coords[i];
      double coord1X = pt1.getX(); double coord1Y = pt1.getY();
      double distSquared = pow(imgX - coord1X, 2) + pow(imgY - coord1Y, 2);
      if (distSquared < curSelectionSensitivitySquared && distSquared < minDist) {
        _lastClickedFirstCoordinateIndex = i;
        _lastClickedSecondCoordinateIndex = -1;
        _lastClickedLinePoint = QPointF();
        minDist = distSquared;
      }
    }
    if (_lastClickedFirstCoordinateIndex >= 0) {
      return true;
    }

    minDist = std::numeric_limits<double>::max();
    // If not, check if a line was hit
    std::vector<QPointF> polyInImgCoords;
    unsigned int polyIndex = 0;
    if (_type == "spline") {
      for (QPolygonF::const_iterator it = _polys.begin(); it != _polys.end(); ++it) {
        polyInImgCoords.push_back(this->mapToScene(*it) / _scale);
      }
    }
    for (unsigned int i = 0; i < coords.size(); ++i) {
      Point pt1 = coords[i];
      Point pt2 = i == coords.size() -1 ? coords[0] : coords[i + 1];
      double coord1X = pt1.getX(); double coord1Y = pt1.getY();
      double coord2X = pt2.getX(); double coord2Y = pt2.getY();
      QRectF hitbox(imgX - curSelectionSensitivity / 2., imgY - curSelectionSensitivity / 2., curSelectionSensitivity * 2., curSelectionSensitivity * 2.);
      QRectF lineBox(QPointF(std::min(coord1X, coord2X), std::max(coord1Y, coord2Y)), QPointF(std::max(coord1X, coord2X), std::min(coord1Y, coord2Y)));       
      if (hitbox.intersects(lineBox)) {
        if (_type == "spline") {
          for (unsigned int j = 0; j < polyInImgCoords.size(); ++j) {
            QPointF polyPt1 = polyInImgCoords[polyIndex];
            QPointF polyPt2 = polyIndex == polyInImgCoords.size() - 1 ? polyInImgCoords[0] : polyInImgCoords[polyIndex + 1];
            if (QPoint(polyPt1.x(), polyPt1.y()) == QPoint(coord2X, coord2Y)) {
              break;
            }
            double polyCoord1X = polyPt1.x(); double polyCoord1Y = polyPt1.y();
            double polyCoord2X = polyPt2.x(); double polyCoord2Y = polyPt2.y();
            QRectF polyBox(QPointF(std::min(polyCoord1X, polyCoord2X), std::max(polyCoord1Y, polyCoord2Y)), QPointF(std::max(polyCoord1X, polyCoord2X), std::min(polyCoord1Y, polyCoord2Y)));
            if (hitbox.intersects(polyBox)) {
              double lineLengthSquared = pow(polyCoord1X - polyCoord2X, 2) + pow(polyCoord1Y - polyCoord2Y, 2);
              double t = ((imgX - polyCoord2X) * (polyCoord1X - polyCoord2X) + (imgY - polyCoord2Y) * (polyCoord1Y - polyCoord2Y)) / lineLengthSquared;
              double projX = polyCoord2X + t * (polyCoord1X - polyCoord2X);
              double projY = polyCoord2Y + t * (polyCoord1Y - polyCoord2Y);
              double distSquared = pow(imgX - projX, 2) + pow(imgY - projY, 2);
              if (distSquared < curSelectionSensitivitySquared && distSquared < minDist) {
                _lastClickedFirstCoordinateIndex = i;
                _lastClickedSecondCoordinateIndex = i + 1 == coords.size() ? 0 : i + 1;
                _lastClickedLinePoint = QPointF(projX, projY);
              }
            }
            ++polyIndex;
          }
        }
        else {
          double lineLengthSquared = pow(coord1X - coord2X, 2) + pow(coord1Y - coord2Y, 2);
          double t = ((imgX - coord2X) * (coord1X - coord2X) + (imgY - coord2Y) * (coord1Y - coord2Y)) / lineLengthSquared;
          double projX = coord2X + t * (coord1X - coord2X);
          double projY = coord2Y + t * (coord1Y - coord2Y);
          double distSquared = pow(imgX - projX, 2) + pow(imgY - projY, 2);
          if (distSquared < curSelectionSensitivitySquared && distSquared < minDist) {
            _lastClickedFirstCoordinateIndex = i;
            _lastClickedSecondCoordinateIndex = i + 1 == coords.size() ? 0 : i + 1;
            _lastClickedLinePoint = QPointF(projX, projY);
          }
        }
      }
    }
    if (_lastClickedFirstCoordinateIndex < 0) {
      return false;
    }
    else {
      return true;
    }
  }
  return false;
}
Example #3
0
void EnemyList::checkCollisions(PlayerProjectiles& playerProjectiles)
{
	for (unsigned int i = 0; i < enemyList.size(); i++)
	{
		Point enemy(enemyList[i].getCompX(), enemyList[i].getCompY());
		for (unsigned int j = 0; j < playerProjectiles.getSize(); j++)
		{
			Bullet* b = playerProjectiles.getBullet(j);
			Point bulPoint(b->getX(), b->getY());
			if (enemyList[i].enemyType == 0 && Collision().checkCollision(playerProjectiles.getVector()[j].box, enemy, 0.97))
			{
				b->destroy();
				enemyList[i].enemyHP--;
				Explosion explosion;
				if (enemyList[i].enemyHP <= 0)
				{
					enemyList[i].destroyed = true;
					if (enemyList[i].enemyType == 0)
					{
						explosion = Explosion(enemyList[i].compX, enemyList[i].compY, 1, explosionTextureID);
					}
					else
					{
						explosion = Explosion(enemyList[i].compX, enemyList[i].compY, 2, explosionTextureID);
					}
					
					explosionList.addExplosion(explosion);
				}
			}
			else if (enemyList[i].enemyType == 1 && Collision().isIntersect(enemyList[i].box,
				enemy,
				b->box,
				bulPoint,
				28,
				minTransDist))
			{
				b->destroy();
				enemyList[i].enemyHP--;
				if (enemyList[i].enemyHP <= 0)
				{
					enemyList[i].destroyed = true;
					Explosion explosion(enemyList[i].compX, enemyList[i].compY, 1, explosionTextureID);
					explosionList.addExplosion(explosion);
				}
			}
		}

		for (unsigned int j = 0; j < enemyList.size(); j++)
		{
			Point p2(enemyList[j].getCompX(), enemyList[j].getCompY());
			if (i != j && Collision().isIntersect(enemyList[i].box, enemy, enemyList[j].box, p2, 28, minTransDist))
			{
				if (enemyList[i].enemyType == 1)
				{
					enemyList[j].setMinTransDist(minTransDist.pointX, minTransDist.pointY);
				}
				else if (enemyList[j].enemyType == 1)
				{
					enemyList[i].setMinTransDist(minTransDist.pointX, minTransDist.pointY);
				}
				else
				{
					enemyList[i].setMinTransDist(minTransDist.pointX * 0.5, minTransDist.pointY * 0.5);
					enemyList[j].setMinTransDist(-minTransDist.pointX * 0.5, -minTransDist.pointY * 0.5);
				}
			}
		}

		Point playerPos(playerShipX, playerShipY);
		//std::cout << playerPos.pointX << "\t" << playerPos.pointY << "\t" << enemy.pointX << "\t" << enemy.pointY << std::endl;
		BoundingQuad lineBox(playerPos, playerPos, enemy, enemy);
		bool result = true;
		for (unsigned int j = 0; j < asteroidMapListRef->asteroidField.size(); j++)
		{
			Point p2(asteroidMapListRef->asteroidField[j].getRoidX(), asteroidMapListRef->asteroidField[j].getRoidY());
			if (Collision().isIntersect(enemyList[i].box, 
				enemy,
				asteroidMapListRef->asteroidField[j].box, 
				p2,
				28,
				minTransDist))
			{
				enemyList[i].setMinTransDist(minTransDist.pointX * 2, minTransDist.pointY * 2);
				enemyList[i].turnAround();
			}
			if (!Collision().hasLineOfSight(enemy, playerPos, lineBox, asteroidMapListRef->asteroidField[j].box, p2, 28))
			{
				result = false;
			}
		}
		enemyList[i].setLOS(result);
	}

	for (unsigned int i = 0; i < playerProjectiles.getSize(); i++)
	{
		Bullet* b = playerProjectiles.getBullet(i);
		Point p1(b->getX(), b->getY());
		
		for (unsigned int j = 0; j < asteroidMapListRef->asteroidField.size(); j++)
		{
			Point p2(asteroidMapListRef->asteroidField[j].getRoidX(), asteroidMapListRef->asteroidField[j].getRoidY());
			if (Collision().isIntersect(b->box, p1, asteroidMapListRef->asteroidField[j].box, p2, 40, minTransDist))
			{
				Explosion explosion(b->box.pointsN[2].pointX, b->box.pointsN[2].pointY, 0.3, explosionTextureID);
				explosionList.addExplosion(explosion);
				b->destroyed = true;
			}
		}
	}
}