Пример #1
0
/**
 * Returns 0 if intersections
 * Returns -1 if same m
 * Returns -2 if no intersections, circles out of range
 * Returns -3 if no intersection, circles includes another one
 */
int Trigonometric::intersectionsCircleCircle(BW_Point m1, float r1, BW_Point m2, float r2, BW_Point* i1, BW_Point* i2) {
	if (m1 == m2)
		return -1; // same point, no intersections

	float d, a, h, dx, dy;

	d = m1.distanceTo(m2);

	if (d > r1 + r2)
		return (-2); //no intersections

	dx = m2.x - m1.x;
	dy = m2.y - m1.y;

	a = (r1 * r1 - r2 * r2 + d * d) / (2 * d);

	h = sqrt(r1 * r1 - a * a);

	i1->x = m1.x + (a / d) * dx - (h / d) * dy;
	i1->y = m1.y + (a / d) * dy + (h / d) * dx;

	i2->x = m1.x + (a / d) * dx + (h / d) * dy;
	i2->y = m1.y + (a / d) * dy - (h / d) * dx;

	//Returns -3 if no intersection, circles includes another one
	if(isnan(i1->x) || isnan(i1->y) || isnan(i2->x) || isnan(i2->y))
		return -3;

	return (0);
}
Пример #2
0
void BW_Sprite::updateMovePosition(float dt) {
	if (_currentAnimation != MOVE)
		return;

	BW_Point currentPosition = getPositionBW();

	float moveDistance = _speed * dt * 0.85; //multiply by 0.85 to achieve the same speed as the old move to version
	float maxDist = getPositionBW().distanceTo(_movingTo);
	BW_Point newPos;
	if (moveDistance >= maxDist) {
		newPos = _movingTo;
		spriteMoveFinished(_sprite);
	} else {
		float mult = moveDistance / maxDist;

		float x = _movingTo.x - currentPosition.x;
		float y = _movingTo.y - currentPosition.y;

		float xDelta = x * mult;
		float yDelta = y * mult;
		newPos = BW_Point(getPositionBW().x + xDelta, getPositionBW().y + yDelta);
	}

	if (!_isUnit) {
		//on projectiles there is no walk collition
		setPosition(newPos);
		return;
	}

	//we are a unit here, consider walk collition

	//get nearest unit to this point
	std::list<Unit*> allUnits = Model::getInstance()->getMyArmy(LEFT)->getUnits();
	std::list<Unit*> rightUnits = Model::getInstance()->getMyArmy(RIGHT)->getUnits();
	allUnits.insert(allUnits.end(), rightUnits.begin(), rightUnits.end());

	//get nearest position of other units
	BW_Point nearest;
	float minDist = -1;
	for (std::list<Unit*>::iterator it = allUnits.begin(); it != allUnits.end(); ++it) {
		if ((*it) == this)
			continue;

		BW_Point currentPos = (*it)->getPositionBW();
		float currentDist = newPos.distanceTo(currentPos);
		if (minDist == -1 || currentDist < minDist) {
			minDist = currentDist;
			nearest = currentPos;
		}
	}

	//check nearest position
	float minDistanceToOtherUnits = 50;
	if (minDist == -1 || minDist > minDistanceToOtherUnits) {
		//no problem
		setPosition(newPos);
		return;
	}

	//calculate intersections
	BW_Point i1, i2;
	int res = Trigonometric::intersectionsCircleCircle(getPositionBW(), moveDistance, nearest, minDistanceToOtherUnits, &i1, &i2);

	/**
	 * Returns 0 if intersections
	 * Returns -1 if same m
	 * Returns -2 if no intersections
	 */

	if (res == 0) {
		//intersections found
		newPos = _movingTo.distanceTo(i1) < _movingTo.distanceTo(i2) ? i1 : i2;
	} else if (res == -3 || res == -1) {
		//circle includes another one, move away
		BW_Point directionPoint;
		if (res == -3) {
			directionPoint.x = currentPosition.x - (nearest.x - currentPosition.x);
			directionPoint.y = currentPosition.y - (nearest.y - currentPosition.y);
		} else {
			//same points, move away in random direction
			//to be easy, just move in run direction
			directionPoint.x = Tools::random(0, Model::getInstance()->getFieldWidth());
			directionPoint.y = Tools::random(0, Model::getInstance()->getFieldHeigth());
		}
		// now scale this to moveDistance
		float scale = moveDistance / directionPoint.distanceTo(currentPosition);
		float distX = currentPosition.x - directionPoint.x;
		float distY = currentPosition.y - directionPoint.y;

		newPos.x -= distX * scale;
		newPos.y -= distY * scale;
	}

	//if (res == -2) no problem
	setPosition(newPos);
    
    float dx = _movingTo.x - currentPosition.x;
    float dy = _movingTo.y - currentPosition.y;
    if (dx == 0 && dy == 0) {
        doIdle();
    }

}