Esempio n. 1
0
/* called by Area(const Polygon&) */
double calc(const Point &rhs1, const Point &rhs2){
	vector<Point> p;
	bool in1 = (cmp(rhs1.Abs()-R) < 0);
	bool in2 = (cmp(rhs2.Abs()-R) < 0);
	if(in1){
		if(in2)
			return fabs(rhs1.Cross(rhs2)) / 2.0;
		else{
			p = Intersection(Line(rhs1, rhs2));
			return SectorArea(rhs2, p[0]) + fabs(rhs1.Cross(p[0])) / 2.0;
		}
	}else{
		if(in2){
			p = Intersection(Line(rhs1, rhs2));
			return SectorArea(p[0], rhs1) + fabs(rhs2.Cross(p[0])) / 2.0;
		}else{
			p = Intersection(Line(rhs1, rhs2));
			if((int)p.size() == 2){
				return SectorArea(rhs1, p[0]) + SectorArea(p[1], rhs2) + fabs(p[0].Cross(p[1])) / 2.0;
			}else{
				return SectorArea(rhs1, rhs2);
			}
		}
	}
}
Esempio n. 2
0
double Mask::Intersection(Point sA, Point vA) const
{
	// Keep track of the closest intersection point found.
	double closest = 1.;
	
	Point prev = outline.back();
	for(const Point &next : outline)
	{
		// Check if there is an intersection. (If not, the cross would be 0.) If
		// there is, handle it only if it is a point where the segment is
		// entering the polygon rather than exiting it (i.e. cross > 0).
		Point vB = next - prev;
		double cross = vB.Cross(vA);
		if(cross > 0.)
		{
			Point vS = prev - sA;
			double uB = vA.Cross(vS);
			double uA = vB.Cross(vS);
			// If the intersection occurs somewhere within this segment of the
			// outline, find out how far along the query vector it occurs and
			// remember it if it is the closest so far.
			if((uB >= 0.) & (uB < cross) & (uA >= 0.))
				closest = min(closest, uA / cross);
		}
		
		prev = next;
	}
	return closest;
}
Esempio n. 3
0
void AI::DoScatter(Ship &ship, Command &command, const list<shared_ptr<Ship>> &ships)
{
	if(!command.Has(Command::FORWARD))
		return;
	
	double turnRate = ship.TurnRate();
	double acceleration = ship.Acceleration();
	for(const shared_ptr<Ship> &other : ships)
	{
		if(other.get() == &ship)
			continue;
		
		// Check for any ships that have nearly the same movement profile as
		// this ship and are in nearly the same location.
		Point offset = other->Position() - ship.Position();
		if(offset.LengthSquared() > 400.)
			continue;
		if(fabs(other->TurnRate() / turnRate - 1.) > .05)
			continue;
		if(fabs(other->Acceleration() / acceleration - 1.) > .05)
			continue;
		
		// Move away from this ship. What side of me is it on?
		command.SetTurn(offset.Cross(ship.Facing().Unit()) > 0. ? 1. : -1.);
		return;
	}
}
Esempio n. 4
0
// Check if this ship is currently able to enter hyperspace to it target.
int Ship::CheckHyperspace() const
{
	if(commands.Has(Command::WAIT))
		return 0;
	
	// Find out where we're going and how we're getting there,
	const System *destination = GetTargetSystem();
	int type = HyperspaceType();
	
	// You can't jump to a system with no link to it.
	if(!type)
		return 0;
	
	if(fuel < type)
		return 0;
	
	Point direction = destination->Position() - currentSystem->Position();
	
	// The ship can only enter hyperspace if it is traveling slowly enough
	// and pointed in the right direction.
	if(type == 150)
	{
		double deviation = fabs(direction.Unit().Cross(velocity));
		if(deviation > attributes.Get("scram drive"))
			return 0;
	}
	else if(velocity.Length() > attributes.Get("jump speed"))
		return 0;
	
	if(type != 200)
	{
		// Figure out if we're within one turn step of facing this system.
		bool left = direction.Cross(angle.Unit()) < 0.;
		Angle turned = angle + TurnRate() * (left - !left);
		bool stillLeft = direction.Cross(turned.Unit()) < 0.;
	
		if(left == stillLeft)
			return 0;
	}
	
	return type;
}
Esempio n. 5
0
double AI::TurnToward(const Ship &ship, const Point &vector)
{
	static const double RAD_TO_DEG = 180. / 3.14159265358979;
	Point facing = ship.Facing().Unit();
	double cross = vector.Cross(facing);
	
	if(vector.Dot(facing) > 0.)
	{
		double angle = asin(cross / vector.Length()) * RAD_TO_DEG;
		if(fabs(angle) <= ship.TurnRate())
			return -angle / ship.TurnRate();
	}
	
	bool left = cross < 0.;
	return left - !left;
}
Esempio n. 6
0
DrawList::Item::Item(const Animation &animation, Point pos, Point unit, Point blur, float clip, int step)
	: position{static_cast<float>(pos.X()), static_cast<float>(pos.Y())},
	clip(clip), flags(animation.GetSwizzle())
{
	Animation::Frame frame = animation.Get(step);
	tex0 = frame.first;
	tex1 = frame.second;
	flags |= static_cast<uint32_t>(frame.fade * 256.f) << 8;
	
	double width = animation.Width();
	double height = animation.Height();
	Point uw = unit * width;
	Point uh = unit * height;
	
	if(clip < 1.)
	{
		// "clip" is the fraction of its height that we're clipping the sprite
		// to. We still want it to start at the same spot, though.
		pos -= uh * ((1. - clip) * .5);
		position[0] = static_cast<float>(pos.X());
		position[1] = static_cast<float>(pos.Y());
		uh *= clip;
	}
	
	// (0, -1) means a zero-degree rotation (since negative Y is up).
	transform[0] = -uw.Y();
	transform[1] = uw.X();
	transform[2] = -uh.X();
	transform[3] = -uh.Y();
	
	// Calculate the blur vector, in texture coordinates. This should be done by
	// projecting the blur vector onto the unit vector and then scaling it based
	// on the sprite size. But, the unit vector first has to be normalized (i.e.
	// divided by the unit vector length), and the sprite size also has to be
	// multiplied by the unit vector size, so:
	double zoomCorrection = 4. * unit.LengthSquared();
	this->blur[0] = unit.Cross(blur) / (width * zoomCorrection);
	this->blur[1] = -unit.Dot(blur) / (height * zoomCorrection);
}
DrawList::Item::Item(const Body &body, Point pos, Point blur, float cloak, float clip, int swizzle, int step)
	: position{static_cast<float>(pos.X()), static_cast<float>(pos.Y())}, clip(clip), flags(swizzle)
{
	Body::Frame frame = body.GetFrame(step);
	tex0 = frame.first;
	tex1 = frame.second;
	flags |= static_cast<uint32_t>(frame.fade * 256.f) << 8;
	
	double width = body.Width();
	double height = body.Height();
	Point unit = body.Facing().Unit();
	Point uw = unit * width;
	Point uh = unit * height;
	
	if(clip < 1.)
	{
		// "clip" is the fraction of its height that we're clipping the sprite
		// to. We still want it to start at the same spot, though.
		pos -= uh * ((1. - clip) * .5);
		position[0] = static_cast<float>(pos.X());
		position[1] = static_cast<float>(pos.Y());
		uh *= clip;
	}
	
	// (0, -1) means a zero-degree rotation (since negative Y is up).
	transform[0] = -uw.Y();
	transform[1] = uw.X();
	transform[2] = -uh.X();
	transform[3] = -uh.Y();
	
	// Calculate the blur vector, in texture coordinates.
	this->blur[0] = unit.Cross(blur) / (width * 4.);
	this->blur[1] = -unit.Dot(blur) / (height * 4.);

	if(cloak > 0.)
		Cloak(cloak);
}
Esempio n. 8
0
ll Area(const Point &a, const Point &b, const Point &c){
    return abs(a.Cross(b) + b.Cross(c) + c.Cross(a));
}
Esempio n. 9
0
// Only override the ones you need; the default action is to return false.
bool MapDetailPanel::KeyDown(SDL_Keycode key, Uint16 mod, const Command &command)
{
	if(command.Has(Command::MAP) || key == 'd' || key == SDLK_ESCAPE || (key == 'w' && (mod & (KMOD_CTRL | KMOD_GUI))))
		GetUI()->Pop(this);
	else if(key == SDLK_PAGEUP || key == SDLK_PAGEDOWN || key == 'i')
	{
		GetUI()->Pop(this);
		GetUI()->Push(new MissionPanel(*this));
	}
	else if(key == 'o')
	{
		GetUI()->Pop(this);
		GetUI()->Push(new MapOutfitterPanel(*this));
	}
	else if(key == 's')
	{
		GetUI()->Pop(this);
		GetUI()->Push(new MapShipyardPanel(*this));
	}
	else if((key == SDLK_TAB || command.Has(Command::JUMP)) && player.Flagship())
	{
		// Toggle to the next link connected to the "source" system. If the
		// shift key is down, the source is the end of the travel plan; otherwise
		// it is one step before the end.
		vector<const System *> &plan = player.TravelPlan();
		const System *source = plan.empty() ? player.GetSystem() : plan.front();
		const System *next = nullptr;
		Point previousUnit = Point(0., -1.);
		if(!plan.empty() && !(mod & KMOD_SHIFT))
		{
			previousUnit = plan.front()->Position();
			plan.erase(plan.begin());
			next = source;
			source = plan.empty() ? player.GetSystem() : plan.front();
			previousUnit = (previousUnit - source->Position()).Unit();
		}
		Point here = source->Position();
		
		// Depending on whether the flagship has a jump drive, the possible links
		// we can travel along are different:
		bool hasJumpDrive = player.Flagship()->Attributes().Get("jump drive");
		const vector<const System *> &links = hasJumpDrive ? source->Neighbors() : source->Links();
		
		double bestAngle = 2. * PI;
		for(const System *it : links)
		{
			if(!player.HasSeen(it))
				continue;
			if(!(hasJumpDrive || player.HasVisited(it) || player.HasVisited(source)))
				continue;
			
			Point unit = (it->Position() - here).Unit();
			double angle = acos(unit.Dot(previousUnit));
			if(unit.Cross(previousUnit) >= 0.)
				angle = 2. * PI - angle;
			
			if(angle <= bestAngle)
			{
				next = it;
				bestAngle = angle;
			}
		}
		if(next)
		{
			plan.insert(plan.begin(), next);
			Select(next);
		}
	}
	else if((key == SDLK_DELETE || key == SDLK_BACKSPACE) && player.HasTravelPlan())
	{
		vector<const System *> &plan = player.TravelPlan();
		plan.erase(plan.begin());
		Select(plan.empty() ? player.GetSystem() : plan.front());
	}
	else if(key == SDLK_DOWN)
	{
		if(commodity < 0 || commodity == 9)
			commodity = 0;
		else
			++commodity;
	}
	else if(key == SDLK_UP)
	{
		if(commodity <= 0)
			commodity = 9;
		else
			--commodity;
	}
	else if(key == 'f')
		GetUI()->Push(new Dialog(
			this, &MapDetailPanel::DoFind, "Search for:"));
	else if(key == '+' || key == '=')
		ZoomMap();
	else if(key == '-')
		UnzoomMap();
	else
		return false;
	
	return true;
}