Esempio n. 1
0
static bool AIHasClearLine(
    Vec2i from, Vec2i to, IsBlockedFunc isBlockedFunc)
{
    // Find all tiles that overlap with the line (from, to)
    // Uses Bresenham that crosses interiors of tiles
    HasClearLineData data;
    data.IsBlocked = isBlockedFunc;
    data.data = &gMap;

    return HasClearLineXiaolinWu(from, to, &data);
}
Esempio n. 2
0
void SoundPlayAtPlusDistance(
	SoundDevice *device, Mix_Chunk *data,
	const Vec2i pos, const int plusDistance)
{
	int distance, bearing;
	Vec2i closestLeftEar, closestRightEar;
	Vec2i origin;

	// Find closest set of ears to the sound
	if (CHEBYSHEV_DISTANCE(
		pos.x, pos.y, device->earLeft1.x, device->earLeft1.y) <
		CHEBYSHEV_DISTANCE(
		pos.x, pos.y, device->earLeft2.x, device->earLeft2.y))
	{
		closestLeftEar = device->earLeft1;
	}
	else
	{
		closestLeftEar = device->earLeft2;
	}
	if (CHEBYSHEV_DISTANCE(
		pos.x, pos.y, device->earRight1.x, device->earRight1.y) <
		CHEBYSHEV_DISTANCE(
		pos.x, pos.y, device->earRight2.x, device->earRight2.y))
	{
		closestRightEar = device->earRight1;
	}
	else
	{
		closestRightEar = device->earRight2;
	}

	origin = CalcClosestPointOnLineSegmentToPoint(
		closestLeftEar, closestRightEar, pos);
	CalcChebyshevDistanceAndBearing(origin, pos, &distance, &bearing);
	HasClearLineData lineData;
	lineData.IsBlocked = IsPosNoSee;
	lineData.data = &gMap;
	bool isMuffled = false;
	if (!HasClearLineXiaolinWu(pos, origin, &lineData))
	{
		isMuffled = true;
	}
	SoundPlayAtPosition(
		&gSoundDevice, data, distance + plusDistance, bearing, isMuffled);
}
Esempio n. 3
0
// Perform LOS by casting rays from the centre to the edges, terminating
// whenever an obstruction or out-of-range is reached.
void DrawBufferLOS(DrawBuffer *buffer, Vec2i center)
{
	int sightRange = gConfig.Game.SightRange;	// Note: can be zero
	LOSData data;
	data.b = buffer;
	data.center.x = center.x / TILE_WIDTH - buffer->xStart;
	data.center.y = center.y / TILE_HEIGHT - buffer->yStart;
	data.sightRange2 = sightRange * sightRange;

	// First mark center tile and all adjacent tiles as visible
	// +-+-+-+
	// |V|V|V|
	// +-+-+-+
	// |V|C|V|
	// +-+-+-+
	// |V|V|V|  (C=center, V=visible)
	// +-+-+-+
	Vec2i end;
	for (end.x = data.center.x - 1; end.x < data.center.x + 2; end.x++)
	{
		for (end.y = data.center.y - 1; end.y < data.center.y + 2; end.y++)
		{
			Tile *tile = GetTile(buffer, end);
			if (tile)
			{
				tile->flags |= MAPTILE_IS_VISIBLE;
			}
		}
	}

	// Work out the perimeter of the LOS casts
	Vec2i origin = Vec2iZero();
	if (sightRange > 0)
	{
		// Limit the perimeter to the sight range
		origin.x = MAX(origin.x, data.center.x - sightRange);
		origin.y = MAX(origin.y, data.center.y - sightRange);
	}
	Vec2i perimSize = Vec2iScale(Vec2iMinus(data.center, origin), 2);

	// Start from the top-left cell, and proceed clockwise around
	end = origin;
	HasClearLineData lineData;
	lineData.IsBlocked = IsNextTileBlockedAndSetVisibility;
	lineData.data = &data;
	// Top edge
	for (; end.x < origin.x + perimSize.x; end.x++)
	{
		HasClearLineXiaolinWu(data.center, end, &lineData);
	}
	// right edge
	for (; end.y < origin.y + perimSize.y; end.y++)
	{
		HasClearLineXiaolinWu(data.center, end, &lineData);
	}
	// bottom edge
	for (; end.x > origin.x; end.x--)
	{
		HasClearLineXiaolinWu(data.center, end, &lineData);
	}
	// left edge
	for (; end.y > origin.y; end.y--)
	{
		HasClearLineXiaolinWu(data.center, end, &lineData);
	}

	// Second pass: make any non-visible obstructions that are adjacent to
	// visible non-obstructions visible too
	// This is to ensure runs of walls stay visible
	for (end.y = origin.y; end.y < origin.y + perimSize.y; end.y++)
	{
		for (end.x = origin.x; end.x < origin.x + perimSize.x; end.x++)
		{
			Tile *tile = GetTile(buffer, end);
			if (!tile || !(tile->flags & MAPTILE_NO_SEE))
			{
				continue;
			}
			// Check sight range
			if (data.sightRange2 > 0 &&
				DistanceSquared(data.center, end) >= data.sightRange2)
			{
				continue;
			}
			SetObstructionVisible(buffer, end, tile);
		}
	}
}