示例#1
0
// ok, need thing to step down through bodies and find closest approach
// modify targpos directly to aim short of dangerous bodies
static bool ParentSafetyAdjust(Ship *ship, Frame *targframe, const vector3d &posoff, vector3d &targpos)
{
	Body *body = 0;
	Frame *frame = targframe->IsRotatingFrame() ? targframe->m_parent : targframe;
	while (frame)
	{
		double sdist = ship->GetPositionRelTo(frame).Length();				// ship position in that frame
		if (sdist < frame->GetRadius()) break;

		while (frame && !(body = frame->GetBodyFor()))
			frame = frame->m_parent;
		if (!frame) return false;

		frame = body->GetFrame()->m_parent;
		if (body->HasDoubleFrame()) frame = frame->m_parent;
	}
	if (!body) return false;

	// ok, so if body != 0, aim for zero velocity at distance to surface of that body
	// still along path to target

	vector3d targpos2 = targpos - ship->GetPosition();
	double targdist = targpos2.Length();
	double bodydist = body->GetPositionRelTo(ship).Length() - MaxEffectRad(body, ship)*1.5;
	if (targdist < bodydist) return false;
	targpos -= (targdist - bodydist) * targpos2 / targdist;
//	printf("Adjusted targpos for safety from %s: old = %.1f, new = %.1f\n",
//		body->GetLabel().c_str(), targdist, (targpos-ship->GetPosition()).Length());
	return true;
}
示例#2
0
文件: Game.cpp 项目: jfabrix/pioneer
Game::Game(const SystemPath &path, const vector3d &pos, double time) :
	m_time(time),
	m_state(STATE_NORMAL),
	m_wantHyperspace(false),
	m_timeAccel(TIMEACCEL_1X),
	m_requestedTimeAccel(TIMEACCEL_1X),
	m_forceTimeAccel(false)
{
	Pi::FlushCaches();

	m_space.reset(new Space(this, path));
	Body *b = m_space->FindBodyForPath(&path);
	assert(b);

	m_player.reset(new Player("kanara"));

	m_space->AddBody(m_player.get());

	m_player->SetFrame(b->GetFrame());

	m_player->SetPosition(pos);
	m_player->SetVelocity(vector3d(0,0,0));

	Polit::Init();

	CreateViews();
}
示例#3
0
/*
 * Method: GetGroundPosition
 *
 * Get latitude, longitude and altitude of a dynamic body close to the ground or nil the body is not a dynamic body
 * or is not close to the ground.
 *
 * > latitude, longitude, altitude = body:GetGroundPosition()
 *
 * Returns:
 *
 *   latitude - the latitude of the body in radians
 *   longitude - the longitude of the body in radians
 *   altitude - altitude above the ground in meters
 *
 * Examples:
 *
 * > -- Get ground position of the player
 * > local lat, long, alt = Game.player:GetGroundPosition()
 * > lat = math.rad2deg(lat)
 * > long = math.rad2deg(long)
 *
 * Availability:
 *
 *   July 2013
 *
 * Status:
 *
 *   experimental
 */
static int l_body_get_ground_position(lua_State *l)
{
	Body *b = LuaObject<Body>::CheckFromLua(1);
	if (!b->IsType(Object::DYNAMICBODY)) {
		lua_pushnil(l);
		return 1;
	}

	Frame *f = b->GetFrame();
	if (!f->IsRotFrame())
		return 0;

	vector3d pos = b->GetPosition();
	double latitude = atan2(pos.y, sqrt(pos.x * pos.x + pos.z * pos.z));
	double longitude = atan2(pos.x, pos.z);
	lua_pushnumber(l, latitude);
	lua_pushnumber(l, longitude);
	Body *astro = f->GetBody();
	if (astro->IsType(Object::TERRAINBODY)) {
		double radius = static_cast<TerrainBody *>(astro)->GetTerrainHeight(pos.Normalized());
		double altitude = pos.Length() - radius;
		lua_pushnumber(l, altitude);
	} else {
		lua_pushnil(l);
	}
	return 3;
}
示例#4
0
void Camera::Update()
{
	if (!m_frame) return;

	// make temporary camera frame
	m_camFrame = new Frame(m_frame, "camera", Frame::FLAG_ROTATING);

	// move and orient it to the camera position
	m_camFrame->SetOrient(m_orient);
	m_camFrame->SetPosition(m_pos);

	// make sure old orient and interpolated orient (rendering orient) are not rubbish
	m_camFrame->ClearMovement();
	m_camFrame->UpdateInterpTransform(1.0);			// update root-relative pos/orient

	// evaluate each body and determine if/where/how to draw it
	m_sortedBodies.clear();
	for (Space::BodyIterator i = Pi::game->GetSpace()->BodiesBegin(); i != Pi::game->GetSpace()->BodiesEnd(); ++i) {
		Body *b = *i;

		// prepare attrs for sorting and drawing
		BodyAttrs attrs;
		attrs.body = b;
		Frame::GetFrameRenderTransform(b->GetFrame(), m_camFrame, attrs.viewTransform);
		attrs.viewCoords = attrs.viewTransform * b->GetInterpPosition();
		attrs.camDist = attrs.viewCoords.Length();
		attrs.bodyFlags = b->GetFlags();
		m_sortedBodies.push_back(attrs);
	}

	// depth sort
	m_sortedBodies.sort();
}
示例#5
0
void Camera::Update()
{
	if (!m_body) return;

	// make temporary camera frame at the body
	m_camFrame = new Frame(m_body->GetFrame(), "camera", Frame::TEMP_VIEWING | Frame::FLAG_ROTATING);

	// interpolate between last physics tick position and current one,
	// to remove temporal aliasing
	const matrix3x3d &m = m_body->GetInterpOrient();
	m_camFrame->SetOrient(m * m_orient);
	m_camFrame->SetPosition(m * m_pos + m_body->GetInterpPosition());

	// make sure old orient and interpolated orient (rendering orient) are not rubbish
	m_camFrame->ClearMovement();
	m_camFrame->UpdateInterpTransform(1.0);			// update root-relative pos/orient

	// evaluate each body and determine if/where/how to draw it
	m_sortedBodies.clear();
	for (Space::BodyIterator i = Pi::game->GetSpace()->BodiesBegin(); i != Pi::game->GetSpace()->BodiesEnd(); ++i) {
		Body *b = *i;

		// prepare attrs for sorting and drawing
		BodyAttrs attrs;
		attrs.body = b;
		Frame::GetFrameRenderTransform(b->GetFrame(), m_camFrame, attrs.viewTransform);
		attrs.viewCoords = attrs.viewTransform * b->GetInterpPosition();
		attrs.camDist = attrs.viewCoords.Length();
		attrs.bodyFlags = b->GetFlags();
		m_sortedBodies.push_back(attrs);
	}

	// depth sort
	m_sortedBodies.sort();
}
示例#6
0
/*
 * Attribute: frameRotating
 *
 * Whether the frame this dynamic body is in is a rotating frame.
 *
 * Only valid for dynamic <Bodies>. For non-dynamic bodies <frameRotating>
 * will be nil.
 *
 * Availability:
 *
 *   alpha 12
 *
 * Status:
 *
 *   experimental
 */
static int l_body_attr_frame_rotating(lua_State *l)
{
	Body *b = LuaObject<Body>::CheckFromLua(1);
	if (!b->IsType(Object::DYNAMICBODY)) {
		lua_pushnil(l);
		return 1;
	}

	Frame *f = b->GetFrame();
	lua_pushboolean(l, f->IsRotFrame());
	return 1;
}
示例#7
0
/*
 * Attribute: frameBody
 *
 * The non-dynamic body attached to the frame this dynamic body is in.
 *
 * Only valid for dynamic <Bodies>. For non-dynamic bodies <frameBody> will be
 * nil.
 *
 * <frameBody> can also be nil if this dynamic body is in a frame with no
 * non-dynamic body. This most commonly occurs when the player is in
 * hyperspace.
 *
 * Availability:
 *
 *   alpha 12
 *
 * Status:
 *
 *   experimental
 */
static int l_body_attr_frame_body(lua_State *l)
{
	Body *b = LuaObject<Body>::CheckFromLua(1);
	if (!b->IsType(Object::DYNAMICBODY)) {
		lua_pushnil(l);
		return 1;
	}

	Frame *f = b->GetFrame();
	LuaObject<Body>::PushToLua(f->GetBody());
	return 1;
}
示例#8
0
Game::Game(const SystemPath &path, double time) :
	m_galaxy(GalaxyGenerator::Create()),
	m_time(time),
	m_state(STATE_NORMAL),
	m_wantHyperspace(false),
	m_timeAccel(TIMEACCEL_1X),
	m_requestedTimeAccel(TIMEACCEL_1X),
	m_forceTimeAccel(false)
{
	// Now that we have a Galaxy, check the starting location
	if (!path.IsBodyPath())
		throw InvalidGameStartLocation("SystemPath is not a body path");
	RefCountedPtr<const Sector> s = m_galaxy->GetSector(path);
	if (size_t(path.systemIndex) >= s->m_systems.size()) {
		char buf[128];
		std::sprintf(buf, "System %u in sector <%d,%d,%d> does not exist",
			unsigned(path.systemIndex), int(path.sectorX), int(path.sectorY), int(path.sectorZ));
		throw InvalidGameStartLocation(std::string(buf));
	}
	RefCountedPtr<StarSystem> sys = m_galaxy->GetStarSystem(path);
	if (path.bodyIndex >= sys->GetNumBodies()) {
		char buf[256];
		std::sprintf(buf, "Body %d in system <%d,%d,%d : %d ('%s')> does not exist", unsigned(path.bodyIndex),
			int(path.sectorX), int(path.sectorY), int(path.sectorZ), unsigned(path.systemIndex), sys->GetName().c_str());
		throw InvalidGameStartLocation(std::string(buf));
	}

	m_space.reset(new Space(this, m_galaxy, path));

	Body *b = m_space->FindBodyForPath(&path);
	assert(b);

	m_player.reset(new Player("kanara"));

	m_space->AddBody(m_player.get());

	m_player->SetFrame(b->GetFrame());

	if (b->GetType() == Object::SPACESTATION) {
		m_player->SetDockedWith(static_cast<SpaceStation*>(b), 0);
	} else {
		const SystemBody *sbody = b->GetSystemBody();
		m_player->SetPosition(vector3d(0, 1.5*sbody->GetRadius(), 0));
		m_player->SetVelocity(vector3d(0,0,0));
	}
	Polit::Init(m_galaxy);

	CreateViews();

	EmitPauseState(IsPaused());
}
示例#9
0
/*
 * Function: SpawnShipNear
 *
 * Create a ship and place it in space near the given <Body>.
 *
 * > ship = Space.SpawnShip(type, body, min, max, hyperspace)
 *
 * Parameters:
 *
 *   type - the name of the ship
 *
 *   body - the <Body> near which the ship should be spawned
 *
 *   min - minimum distance from the body to place the ship, in Km
 *
 *   max - maximum distance to place the ship
 *
 *   hyperspace - optional table containing hyperspace entry information. If
 *                this is provided the ship will not spawn directly. Instead,
 *                a hyperspace cloud will be created that the ship will exit
 *                from. The table contains two elements, a <SystemPath> for
 *                the system the ship is travelling from, and the due
 *                date/time that the ship should emerge from the cloud.
 *
 * Return:
 *
 *   ship - a <Ship> object for the new ship
 *
 * Example:
 *
 * > -- spawn a ship 10km from the player
 * > local ship = Ship.SpawnNear("viper_police_craft", Game.player, 10, 10)
 *
 * Availability:
 *
 *   alpha 10
 *
 * Status:
 *
 *   experimental
 */
static int l_space_spawn_ship_near(lua_State *l)
{
    if (!Pi::game)
        luaL_error(l, "Game is not started");

    LUA_DEBUG_START(l);

    const char *type = luaL_checkstring(l, 1);
    if (! ShipType::Get(type))
        luaL_error(l, "Unknown ship type '%s'", type);

    Body *nearbody = LuaObject<Body>::CheckFromLua(2);
    float min_dist = luaL_checknumber(l, 3);
    float max_dist = luaL_checknumber(l, 4);

    SystemPath *path = 0;
    double due = -1;
    _unpack_hyperspace_args(l, 5, path, due);

    Ship *ship = new Ship(type);
    assert(ship);

    Body *thing = _maybe_wrap_ship_with_cloud(ship, path, due);

    // XXX protect against spawning inside the body
    Frame * newframe = nearbody->GetFrame();
    const vector3d newPosition = (MathUtil::RandomPointOnSphere(min_dist, max_dist)* 1000.0) + nearbody->GetPosition();

    // If the frame is rotating and the chosen position is too far, use non-rotating parent.
    // Otherwise the ship will be given a massive initial velocity when it's bumped out of the
    // rotating frame in the next update
    if (newframe->IsRotFrame() && newframe->GetRadius() < newPosition.Length()) {
        assert(newframe->GetParent());
        newframe = newframe->GetParent();
    }

    thing->SetFrame(newframe);;
    thing->SetPosition(newPosition);
    thing->SetVelocity(vector3d(0,0,0));
    Pi::game->GetSpace()->AddBody(thing);

    LuaObject<Ship>::PushToLua(ship);

    LUA_DEBUG_END(l, 1);

    return 1;
}
示例#10
0
void Camera::Update()
{
	if (!m_body) return;

	if (m_shadersEnabled != Render::AreShadersEnabled()) {
		m_frustum = Render::Frustum(m_width, m_height, m_fovAng);
		m_shadersEnabled = !m_shadersEnabled;
	}

	// make temporary camera frame at the body
	m_camFrame = new Frame(m_body->GetFrame(), "camera", Frame::TEMP_VIEWING);

	// interpolate between last physics tick position and current one,
	// to remove temporal aliasing
	matrix4x4d bodyPose = m_body->GetInterpolatedTransform();
	m_camFrame->SetTransform(bodyPose * m_pose);

	// make sure old orient and interpolated orient (rendering orient) are not rubbish
	m_camFrame->ClearMovement();


	// evaluate each body and determine if/where/how to draw it
	m_sortedBodies.clear();
	for (Space::BodyIterator i = Pi::game->GetSpace()->BodiesBegin(); i != Pi::game->GetSpace()->BodiesEnd(); ++i) {
		Body *b = *i;

		// prepare attrs for sorting and drawing
		BodyAttrs attrs;
		attrs.body = b;
		Frame::GetFrameRenderTransform(b->GetFrame(), m_camFrame, attrs.viewTransform);
		attrs.viewCoords = attrs.viewTransform * b->GetInterpolatedPosition();
		attrs.camDist = attrs.viewCoords.Length();
		attrs.bodyFlags = b->GetFlags();
		m_sortedBodies.push_back(attrs);
	}

	// depth sort
	m_sortedBodies.sort();
}
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);
}
示例#12
0
Game::Game(const SystemPath &path, const vector3d &pos) :
	m_time(0),
	m_state(STATE_NORMAL),
	m_wantHyperspace(false),
	m_timeAccel(TIMEACCEL_1X),
	m_requestedTimeAccel(TIMEACCEL_1X),
	m_forceTimeAccel(false)
{
	m_space.Reset(new Space(this, path));
	Body *b = m_space->FindBodyForPath(&path);
	assert(b);

	CreatePlayer();

	m_space->AddBody(m_player.Get());

	m_player->Enable();
	m_player->SetFrame(b->GetFrame());

	m_player->SetPosition(pos);
	m_player->SetVelocity(vector3d(0,0,0));

	CreateViews();
}
示例#13
0
/*
 * Function: SpawnShipLandedNear
 *
 * Create a ship and place it on the surface near the given <Body>.
 *
 * > ship = Space.SpawnShipLandedNear(type, body, min, max)
 *
 * Parameters:
 *
 *   type - the name of the ship
 *
 *   body - the <Body> near which the ship should be spawned. It must be on the ground or close to it,
 *          i.e. it must be in the rotating frame of the planetary body.
 *
 *   min - minimum distance from the surface point below the body to place the ship, in Km
 *
 *   max - maximum distance to place the ship
 *
 * Return:
 *
 *   ship - a <Ship> object for the new ship
 *
 * Example:
 *
 * > -- spawn a ship 10km from the player
 * > local ship = Ship.SpawnShipLandedNear("viper_police", Game.player, 10, 10)
 *
 * Availability:
 *
 *   July 2013
 *
 * Status:
 *
 *   experimental
 */
static int l_space_spawn_ship_landed_near(lua_State *l)
{
    if (!Pi::game)
        luaL_error(l, "Game is not started");

    LUA_DEBUG_START(l);

    const char *type = luaL_checkstring(l, 1);
    if (! ShipType::Get(type))
        luaL_error(l, "Unknown ship type '%s'", type);

    Body *nearbody = LuaObject<Body>::CheckFromLua(2);
    const float min_dist = luaL_checknumber(l, 3);
    const float max_dist = luaL_checknumber(l, 4);
    if (min_dist > max_dist)
        luaL_error(l, "min_dist must not be larger than max_dist");

    Ship *ship = new Ship(type);
    assert(ship);

    // XXX protect against spawning inside the body
    Frame * newframe = nearbody->GetFrame()->GetRotFrame();
    if (!newframe->IsRotFrame())
        luaL_error(l, "Body must be in rotating frame");
    SystemBody *sbody = newframe->GetSystemBody();
    if (sbody->GetSuperType() != SystemBody::SUPERTYPE_ROCKY_PLANET)
        luaL_error(l, "Body is not on a rocky planet");
    if (max_dist > sbody->GetRadius())
        luaL_error(l, "max_dist too large for planet radius");
    // We assume that max_dist is much smaller than the planet radius, i.e. that our area is reasonably flat
    // So, we
    const vector3d up = nearbody->GetPosition().Normalized();
    vector3d x;
    vector3d y;
    // Calculate a orthonormal basis for a horizontal plane. For numerical reasons we do that determining the smallest
    // coordinate and take the cross product with (1,0,0), (0,1,0) or (0,0,1) respectively to calculate the first vector.
    // The second vector is just the cross product of the up-vector and out first vector.
    if (up.x <= up.y && up.x <= up.z) {
        x = vector3d(0.0, up.z, -up.y).Normalized();
        y = vector3d(-up.y*up.y - up.z*up.z, up.x*up.y, up.x*up.z).Normalized();
    } else if (up.y <= up.x && up.y <= up.z) {
        x = vector3d(-up.z, 0.0, up.x).Normalized();
        y = vector3d(up.x*up.y, -up.x*up.x - up.z*up.z, up.y*up.z).Normalized();
    } else {
        x = vector3d(up.y, -up.x, 0.0).Normalized();
        y = vector3d(up.x*up.z, up.y*up.z, -up.x*up.x - up.y*up.y).Normalized();
    }
    Planet *planet = static_cast<Planet*>(newframe->GetBody());
    const double radius = planet->GetSystemBody()->GetRadius();
    const vector3d planar = MathUtil::RandomPointInCircle(min_dist * 1000.0, max_dist * 1000.0);
    vector3d pos = (radius * up + x * planar.x + y * planar.y).Normalized();
    float latitude = atan2(pos.y, sqrt(pos.x*pos.x + pos.z * pos.z));
    float longitude = atan2(pos.x, pos.z);

    Pi::game->GetSpace()->AddBody(ship);
    ship->SetLandedOn(planet, latitude, longitude);

    LuaObject<Ship>::PushToLua(ship);

    LUA_DEBUG_END(l, 1);

    return 1;
}