speed relative to target. fiddle with planet draw distance. make check (tests.cpp).

git-svn-id: https://pioneer.svn.sourceforge.net/svnroot/pioneer/trunk@260 e632f14b-6550-0410-b89e-a82653faca30
master
tompox 2009-05-03 20:38:45 +00:00
parent 068477b226
commit 75d9ce8d40
13 changed files with 848 additions and 681 deletions

View File

@ -132,3 +132,18 @@ void Body::OrientOnSurface(double radius, double latitude, double longitude)
rot = rot.InverseOf();
SetRotMatrix(rot);
}
vector3d Body::GetVelocityRelativeTo(const Frame *f) const
{
matrix4x4d m;
Frame::GetFrameTransform(GetFrame(), f, m);
return (m.ApplyRotationOnly(GetVelocity()) + Frame::GetFrameRelativeVelocity(GetFrame(), f));
}
vector3d Body::GetVelocityRelativeTo(const Body *other) const
{
return GetVelocity() - other->GetVelocityRelativeTo(GetFrame());
}

View File

@ -33,6 +33,8 @@ public:
virtual void TimeStepUpdate(const float timeStep) {}
// Override to clear any pointers you hold to the dying body.
virtual void NotifyDeath(const Body* const dyingBody) {}
vector3d GetVelocityRelativeTo(const Body *other) const;
vector3d GetVelocityRelativeTo(const Frame *f) const;
// for putting on planet surface, oriented +y up
void OrientOnSurface(double radius, double latitude, double longitude);
vector3d GetPositionRelTo(const Frame *);

View File

@ -112,6 +112,35 @@ void Frame::ApplyEnteringTransform(matrix4x4d &m) const
m = m * m_orient.InverseOf() * matrix4x4d::Translation(-m_pos);
}
vector3d Frame::GetFrameRelativeVelocity(const Frame *fFrom, const Frame *fTo)
{
if (fFrom == fTo) return vector3d(0,0,0);
vector3d v1 = vector3d(0,0,0);
vector3d v2 = vector3d(0,0,0);
matrix4x4d m = matrix4x4d::Identity();
const Frame *f = fFrom;
const Frame *root = Space::rootFrame;
// move forwards from origin to root
while ((f!=root) && (fTo != f)) {
v1 += m.ApplyRotationOnly(-f->GetVelocity());
m = m * f->m_orient.InverseOf();
f = f->m_parent;
}
// move backwards from target to root
while (fTo != f) {
v2 = fTo->m_orient.ApplyRotationOnly(fTo->GetVelocity() + v2);
fTo = fTo->m_parent;
}
vector3d out = v1 + m.ApplyRotationOnly(v2);
// printf("v1: %.2f,%.2f,%.2f v2: %.2f,%.2f,%.2f ~= %.2f,%.2f,%.2f\n", v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, out.x, out.y, out.z);
return out;
}
void Frame::GetFrameTransform(const Frame *fFrom, const Frame *fTo, matrix4x4d &m)
{
matrix4x4d m2 = matrix4x4d::Identity();

View File

@ -47,6 +47,7 @@ public:
void ApplyEnteringTransform(matrix4x4d &m) const;
static void GetFrameTransform(const Frame *fFrom, const Frame *fTo, matrix4x4d &m);
static vector3d GetFrameRelativeVelocity(const Frame *fFrom, const Frame *fTo);
bool IsLocalPosInFrame(const vector3d &pos) {
return (pos.Length() < m_radius);

View File

@ -21,9 +21,18 @@ pioneer_SOURCES = main.cpp glfreetype.cpp Body.cpp Space.cpp Ship.cpp Player.cpp
StarSystem.cpp Sector.cpp SystemInfoView.cpp GenericSystemView.cpp utils.cpp SpaceStation.cpp \
SpaceStationView.cpp ModelBody.cpp ShipType.cpp InfoView.cpp ModelCollMeshData.cpp \
ObjectViewerView.cpp custom_starsystems.cpp Serializer.cpp Sfx.cpp Ship-AI.cpp MarketAgent.cpp \
EquipType.cpp CargoBody.cpp NameGenerator.cpp perlin.cpp GeoSphere.cpp
EquipType.cpp CargoBody.cpp NameGenerator.cpp perlin.cpp GeoSphere.cpp Pi.cpp
pioneer_LDADD = sbre/libsbre.a collider/libcollider.a mods/libmods.a libgui.a
sbreviewer_SOURCES = SbreViewer.cpp glfreetype.cpp
sbreviewer_LDADD = sbre/libsbre.a collider/libcollider.a libgui.a
check_PROGRAMS = tests
tests_SOURCES = tests.cpp glfreetype.cpp Body.cpp Space.cpp Ship.cpp Player.cpp DynamicBody.cpp Planet.cpp \
Star.cpp Frame.cpp ShipCpanel.cpp SectorView.cpp mtrand.cpp WorldView.cpp SystemView.cpp \
StarSystem.cpp Sector.cpp SystemInfoView.cpp GenericSystemView.cpp utils.cpp SpaceStation.cpp \
SpaceStationView.cpp ModelBody.cpp ShipType.cpp InfoView.cpp ModelCollMeshData.cpp \
ObjectViewerView.cpp custom_starsystems.cpp Serializer.cpp Sfx.cpp Ship-AI.cpp MarketAgent.cpp \
EquipType.cpp CargoBody.cpp NameGenerator.cpp perlin.cpp GeoSphere.cpp Pi.cpp
tests_LDADD = collider/libcollider.a libgui.a mods/libmods.a sbre/libsbre.a

670
src/Pi.cpp Normal file
View File

@ -0,0 +1,670 @@
#include "libs.h"
#include "Pi.h"
#include "Gui.h"
#include "glfreetype.h"
#include "Player.h"
#include "Space.h"
#include "Planet.h"
#include "Star.h"
#include "Frame.h"
#include "ShipCpanel.h"
#include "SectorView.h"
#include "SystemView.h"
#include "SystemInfoView.h"
#include "WorldView.h"
#include "ObjectViewerView.h"
#include "StarSystem.h"
#include "SpaceStation.h"
#include "SpaceStationView.h"
#include "CargoBody.h"
#include "InfoView.h"
#include "Serializer.h"
#include "NameGenerator.h"
#include "mods/Mods.h"
float Pi::timeAccel = 1.0f;
int Pi::scrWidth;
int Pi::scrHeight;
float Pi::scrAspect;
SDL_Surface *Pi::scrSurface;
sigc::signal<void, SDL_keysym*> Pi::onKeyPress;
sigc::signal<void, SDL_keysym*> Pi::onKeyRelease;
sigc::signal<void, int, int, int> Pi::onMouseButtonUp;
sigc::signal<void, int, int, int> Pi::onMouseButtonDown;
sigc::signal<void> Pi::onPlayerChangeHyperspaceTarget;
sigc::signal<void> Pi::onPlayerHyperspaceToNewSystem;
char Pi::keyState[SDLK_LAST];
char Pi::mouseButton[5];
int Pi::mouseMotion[2];
enum Pi::MapView Pi::mapView;
Player *Pi::player;
View *Pi::currentView;
WorldView *Pi::worldView;
ObjectViewerView *Pi::objectViewerView;
SpaceStationView *Pi::spaceStationView;
InfoView *Pi::infoView;
SectorView *Pi::sectorView;
SystemView *Pi::systemView;
SystemInfoView *Pi::systemInfoView;
ShipCpanel *Pi::cpan;
StarSystem *Pi::selectedSystem;
StarSystem *Pi::currentSystem;
MTRand Pi::rng;
double Pi::gameTime;
float Pi::frameTime;
GLUquadric *Pi::gluQuadric;
bool Pi::showDebugInfo;
int Pi::statSceneTris;
void Pi::Init(IniConfig &config)
{
int width = config.Int("ScrWidth");
int height = config.Int("ScrHeight");
const SDL_VideoInfo *info = NULL;
Uint32 sdlInitFlags = SDL_INIT_VIDEO;
#if defined _WIN32 && defined _DEBUG
sdlInitFlags |= SDL_INIT_NOPARACHUTE;
#endif
if (SDL_Init(sdlInitFlags) < 0) {
fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError());
exit(-1);
}
info = SDL_GetVideoInfo();
switch (config.Int("ScrDepth")) {
case 16:
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
break;
case 32:
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
break;
default:
fprintf(stderr, "Fatal error. Invalid screen depth in config.ini.\n");
Pi::Quit();
}
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
Uint32 flags = SDL_OPENGL;
if (config.Int("StartFullscreen")) flags |= SDL_FULLSCREEN;
if ((Pi::scrSurface = SDL_SetVideoMode(width, height, info->vfmt->BitsPerPixel, flags)) == 0) {
// fall back on 16-bit depth buffer...
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
fprintf(stderr, "Failed to set video mode. (%s). Re-trying with 16-bit depth buffer.\n", SDL_GetError());
if ((Pi::scrSurface = SDL_SetVideoMode(width, height, info->vfmt->BitsPerPixel, flags)) == 0) {
fprintf(stderr, "Video mode set failed: %s\n", SDL_GetError());
exit(-1);
}
}
glewInit();
SDL_WM_SetCaption("Pioneer","Pioneer");
Pi::scrWidth = width;
Pi::scrHeight = height;
Pi::scrAspect = width / (float)height;
Pi::rng.seed(time(NULL));
NameGenerator::Init();
InitOpenGL();
GLFTInit();
Space::Init();
Gui::Init(scrWidth, scrHeight, 800, 600);
Mods::Init();
}
void Pi::InitOpenGL()
{
glShadeModel(GL_SMOOTH);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0,0,0,0);
glViewport(0, 0, scrWidth, scrHeight);
gluQuadric = gluNewQuadric ();
fprintf(stderr, "GL_ARB_vertex_buffer_object: %s\n", GLEW_ARB_vertex_buffer_object ? "Yes" : "No");
}
void Pi::Quit()
{
SDL_Quit();
exit(0);
}
void Pi::SetTimeAccel(float s)
{
// don't want player to spin like mad when hitting time accel
if (s > 10) {
player->SetAngVelocity(vector3d(0,0,0));
player->SetTorque(vector3d(0,0,0));
player->SetAngThrusterState(0, 0.0f);
player->SetAngThrusterState(1, 0.0f);
player->SetAngThrusterState(2, 0.0f);
}
timeAccel = s;
}
void Pi::SetMapView(enum MapView v)
{
mapView = v;
if (v == MAP_SECTOR)
SetView(sectorView);
else
SetView(systemView);
}
void Pi::SetView(View *v)
{
if (currentView) currentView->HideAll();
currentView = v;
currentView->OnSwitchTo();
currentView->ShowAll();
}
void Screendump(char *destFile)
{
const int W = Pi::GetScrWidth();
const int H = Pi::GetScrHeight();
std::vector<char> pixel_data(3*W*H);
short TGAhead[] = {0, 2, 0, 0, 0, 0, W, H, 24};
FILE *out = fopen(destFile, "w");
if (!out) goto error;
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, W, H, GL_BGR, GL_UNSIGNED_BYTE, &pixel_data[0]);
if (fwrite(&TGAhead, sizeof(TGAhead), 3, out) != 3) goto error;
if (fwrite(&pixel_data[0], 3*W*H, 1, out) != 1) goto error;
fclose(out);
return;
error:
printf("Failed to write screendump.\n");
}
void Pi::HandleEvents()
{
SDL_Event event;
Pi::mouseMotion[0] = Pi::mouseMotion[1] = 0;
while (SDL_PollEvent(&event)) {
Gui::HandleSDLEvent(&event);
switch (event.type) {
case SDL_KEYDOWN:
if (KeyState(SDLK_LCTRL) && (event.key.keysym.sym == SDLK_q)) Pi::Quit();
if (event.key.keysym.sym == SDLK_i) Pi::showDebugInfo = !Pi::showDebugInfo;
if ((event.key.keysym.sym == SDLK_PRINT) && KeyState(SDLK_LCTRL)) {
char buf[256];
const time_t t = time(0);
struct tm *_tm = localtime(&t);
strftime(buf, sizeof(buf), "screenshot-%Y%m%d-%H%M%S.tga", _tm);
Screendump(buf);
}
#ifdef DEBUG
if (event.key.keysym.sym == SDLK_F12) {
matrix4x4d m; Pi::player->GetRotMatrix(m);
vector3d dir = m*vector3d(0,0,-1);
/* add test object */
if (KeyState(SDLK_LSHIFT)) {
Frame *rotFrame = new Frame(Pi::player->GetFrame(), "Station rot frame");
rotFrame->SetRadius(3000.0);//(1.1*sbody->GetRadius());
rotFrame->SetPosition(Pi::player->GetPosition()+5000.0*dir);
rotFrame->SetAngVelocity(vector3d(0,2*M_PI/10,0));
SpaceStation *station = new SpaceStation(SpaceStation::JJHOOP);
station->SetLabel("Poemi-chan's Folly");
station->SetFrame(rotFrame);
station->SetRotMatrix(matrix4x4d::RotateZMatrix(M_PI));
Space::AddBody(station);
} else if (KeyState(SDLK_RSHIFT)) {
CargoBody *cargo = new CargoBody(Equip::HYDROGEN);
cargo->SetFrame(Pi::player->GetFrame());
cargo->SetPosition(Pi::player->GetPosition()+100.0*dir);
cargo->SetVelocity(Pi::player->GetVelocity());
Space::AddBody(cargo);
} else {
Ship *ship = new Ship(ShipType::LADYBIRD);
ship->AIInstruct(Ship::DO_KILL, Pi::player);
ship->SetFrame(Pi::player->GetFrame());
ship->SetPosition(Pi::player->GetPosition()+100.0*dir);
ship->SetVelocity(Pi::player->GetVelocity());
Space::AddBody(ship);
}
}
#endif /* DEBUG */
if (event.key.keysym.sym == SDLK_F11) SDL_WM_ToggleFullScreen(Pi::scrSurface);
if (event.key.keysym.sym == SDLK_F10) Pi::SetView(Pi::objectViewerView);
if (event.key.keysym.sym == SDLK_F9) Serializer::Write::Game("quicksave.sav");
Pi::keyState[event.key.keysym.sym] = 1;
Pi::onKeyPress.emit(&event.key.keysym);
break;
case SDL_KEYUP:
Pi::keyState[event.key.keysym.sym] = 0;
Pi::onKeyRelease.emit(&event.key.keysym);
break;
case SDL_MOUSEBUTTONDOWN:
Pi::mouseButton[event.button.button] = 1;
Pi::onMouseButtonDown.emit(event.button.button,
event.button.x, event.button.y);
break;
case SDL_MOUSEBUTTONUP:
Pi::mouseButton[event.button.button] = 0;
Pi::onMouseButtonUp.emit(event.button.button,
event.button.x, event.button.y);
break;
case SDL_MOUSEMOTION:
Pi::mouseMotion[0] += event.motion.xrel;
Pi::mouseMotion[1] += event.motion.yrel;
// SDL_GetRelativeMouseState(&Pi::mouseMotion[0], &Pi::mouseMotion[1]);
break;
case SDL_QUIT:
Pi::Quit();
break;
}
}
}
static void draw_intro(float _time)
{
static float lightCol[4] = { 1,1,1,0 };
static float lightDir[4] = { 0,1,0,0 };
static ObjParams params = {
{ 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0.0f, 0.0f, -1.0f }, { 0.0f, 0.0f, 0.0f },
{ // pColor[3]
{ { .2f, .2f, .5f }, { 1, 1, 1 }, { 0, 0, 0 }, 100.0 },
{ { 0.5f, 0.5f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
{ { 0.8f, 0.8f, 0.8f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 } },
{ "PIONEER" },
};
glRotatef(_time*10, 1, 0, 0);
Pi::worldView->DrawBgStars();
glPushAttrib(GL_ALL_ATTRIB_BITS);
sbreSetDepthRange(Pi::GetScrWidth()*0.5, 0.0f, 1.0f);
sbreSetDirLight (lightCol, lightDir);
matrix4x4d rot = matrix4x4d::RotateYMatrix(_time) * matrix4x4d::RotateZMatrix(0.6*_time) *
matrix4x4d::RotateXMatrix(_time*.7);
vector3d p(0, 0, -80);
sbreRenderModel(&p.x, &rot[0], 61, &params);
glPopAttrib();
}
static void draw_tombstone(float _time)
{
static float lightCol[4] = { 1,1,1,0 };
static float lightDir[4] = { 0,1,0,0 };
static ObjParams params = {
{ 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f },
{ // pColor[3]
{ { 1.0f, 1.0f, 1.0f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
{ { 0.8f, 0.6f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
{ { 0.5f, 0.5f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 } },
{ "RIP OLD BEAN" },
};
glPushAttrib(GL_ALL_ATTRIB_BITS);
sbreSetDepthRange(Pi::GetScrWidth()*0.5, 0.0f, 1.0f);
sbreSetDirLight (lightCol, lightDir);
matrix4x4d rot = matrix4x4d::RotateYMatrix(_time*2);
vector3d p(0, 0, -MAX(150 - 30*_time, 30));
sbreRenderModel(&p.x, &rot[0], 91, &params);
glPopAttrib();
}
void Pi::TombStoneLoop()
{
Uint32 last_time = SDL_GetTicks();
float _time = 0;
cpan->HideAll();
currentView->HideAll();
do {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float fracH = 1.0 / Pi::GetScrAspect();
glFrustum(-1, 1, -fracH, fracH, 1.0f, 10000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Pi::HandleEvents();
SDL_ShowCursor(1);
SDL_WM_GrabInput(SDL_GRAB_OFF);
draw_tombstone(_time);
Gui::Draw();
glFlush();
SDL_GL_SwapBuffers();
Pi::frameTime = 0.001*(SDL_GetTicks() - last_time);
_time += Pi::frameTime;
last_time = SDL_GetTicks();
} while (!((_time > 2.0) && ((Pi::MouseButtonState(1)) || Pi::KeyState(SDLK_SPACE)) ));
}
void Pi::Start()
{
player = new Player(ShipType::SWANKY);
player->m_equipment.Set(Equip::SLOT_ENGINE, 0, Equip::DRIVE_CLASS1);
player->m_equipment.Set(Equip::SLOT_LASER, 0, Equip::LASER_2MW_BEAM);
player->m_equipment.Set(Equip::SLOT_LASER, 1, Equip::LASER_4MW_BEAM);
player->m_equipment.Add(Equip::SLOT_CARGO, Equip::HYDROGEN);
player->m_equipment.Add(Equip::SLOT_CARGO, Equip::HYDROGEN);
player->m_equipment.Add(Equip::SLOT_CARGO, Equip::HYDROGEN);
player->SetLabel("me");
player->SetMoney(1000);
Space::AddBody(player);
cpan = new ShipCpanel();
sectorView = new SectorView();
systemView = new SystemView();
systemInfoView = new SystemInfoView();
worldView = new WorldView();
objectViewerView = new ObjectViewerView();
spaceStationView = new SpaceStationView();
infoView = new InfoView();
Gui::Fixed *splash = new Gui::Fixed(Gui::Screen::GetWidth(), Gui::Screen::GetHeight());
Gui::Screen::AddBaseWidget(splash, 0, 0);
splash->SetTransparency(true);
const float w = Gui::Screen::GetWidth() / 2;
const float h = Gui::Screen::GetHeight() / 2;
const int OPTS = 4;
Gui::ToggleButton *opts[OPTS];
opts[0] = new Gui::ToggleButton(); opts[0]->SetShortcut(SDLK_1, KMOD_NONE);
opts[1] = new Gui::ToggleButton(); opts[1]->SetShortcut(SDLK_2, KMOD_NONE);
opts[2] = new Gui::ToggleButton(); opts[2]->SetShortcut(SDLK_3, KMOD_NONE);
opts[3] = new Gui::ToggleButton(); opts[3]->SetShortcut(SDLK_4, KMOD_NONE);
splash->Add(opts[0], w, h-64);
splash->Add(new Gui::Label("New game starting on Earth"), w+32, h-64);
splash->Add(opts[1], w, h-32);
splash->Add(new Gui::Label("New game starting on debug point"), w+32, h-32);
splash->Add(opts[2], w, h);
splash->Add(new Gui::Label("Load quicksave"), w+32, h);
splash->Add(opts[3], w, h+32);
splash->Add(new Gui::Label("Quit"), w+32, h+32);
splash->ShowAll();
int choice = 0;
Uint32 last_time = SDL_GetTicks();
float _time = 0;
do {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float fracH = 1.0 / Pi::GetScrAspect();
glFrustum(-1, 1, -fracH, fracH, 1.0f, 10000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Pi::HandleEvents();
SDL_ShowCursor(1);
SDL_WM_GrabInput(SDL_GRAB_OFF);
draw_intro(_time);
Gui::Draw();
glFlush();
SDL_GL_SwapBuffers();
Pi::frameTime = 0.001*(SDL_GetTicks() - last_time);
_time += Pi::frameTime;
last_time = SDL_GetTicks();
// poll ui instead of using callbacks :-J
for (int i=0; i<OPTS; i++) if (opts[i]->GetPressed()) choice = i+1;
} while (!choice);
splash->HideAll();
if (choice == 1) {
/* Earth start point */
SBodyPath path(0,0,0);
HyperspaceTo(&path);
//Frame *pframe = *(++(++(Space::rootFrame->m_children.begin())));
//player->SetFrame(pframe);
// XXX there isn't a sensible way to find stations for a planet.
SpaceStation *station = 0;
for (Space::bodiesIter_t i = Space::bodies.begin(); i!=Space::bodies.end(); i++) {
if ((*i)->IsType(Object::SPACESTATION)) { station = (SpaceStation*)*i; break; }
}
assert(station);
player->SetPosition(vector3d(0,0,0));
player->SetFrame(station->GetFrame());
player->SetDockedWith(station, 0);
MainLoop();
} else if (choice == 2) {
/* debug start point */
SBodyPath path(0,0,1);
path.elem[0] = 0; // zeroth child of root body
path.elem[1] = 4;
HyperspaceTo(&path);
player->SetPosition(vector3d(0,0,2*EARTH_RADIUS));
/* Frame *stationFrame = new Frame(pframe, "Station frame...");
stationFrame->SetRadius(5000);
stationFrame->m_sbody = 0;
stationFrame->SetPosition(vector3d(0,0,zpos));
stationFrame->SetAngVelocity(vector3d(0,0,0.5));
for (int i=0; i<4; i++) {
Ship *body = new Ship(ShipType::LADYBIRD);
char buf[64];
snprintf(buf,sizeof(buf),"X%c-0%02d", 'A'+i, i);
body->SetLabel(buf);
body->SetFrame(stationFrame);
body->SetPosition(vector3d(200*(i+1), 0, 2000));
Space::AddBody(body);
}
SpaceStation *station = new SpaceStation(SpaceStation::JJHOOP);
station->SetLabel("Poemi-chan's Folly");
station->SetFrame(stationFrame);
station->SetPosition(vector3d(0,0,0));
Space::AddBody(station);
SpaceStation *station2 = new SpaceStation(SpaceStation::GROUND_FLAVOURED);
station2->SetLabel("Conor's End");
station2->SetFrame(*pframe->m_children.begin()); // rotating frame of planet
station2->OrientOnSurface(EARTH_RADIUS, M_PI/4, M_PI/4);
Space::AddBody(station2);
*/
// player->SetDockedWith(station2, 0);
MainLoop();
} else if (choice == 3) {
// load quicksave
Serializer::Read::Game("quicksave.sav");
MainLoop();
}
}
void Pi::MainLoop()
{
cpan->ShowAll();
SetView(worldView);
Uint32 last_stats = SDL_GetTicks();
int frame_stat = 0;
int phys_stat = 0;
char fps_readout[128];
Uint32 time_before_frame = SDL_GetTicks();
Uint32 last_phys_update = time_before_frame;
for (;;) {
frame_stat++;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
currentView->Draw3D();
// XXX HandleEvents at the moment must be after view->Draw3D and before
// Gui::Draw so that labels drawn to screen can have mouse events correctly
// detected. Gui::Draw wipes memory of label positions.
Pi::HandleEvents();
// hide cursor for ship control.
if (Pi::MouseButtonState(3)) {
SDL_ShowCursor(0);
SDL_WM_GrabInput(SDL_GRAB_ON);
} else {
SDL_ShowCursor(1);
SDL_WM_GrabInput(SDL_GRAB_OFF);
}
Gui::Draw();
//#ifdef DEBUG
if (Pi::showDebugInfo) {
Gui::Screen::EnterOrtho();
glColor3f(1,1,1);
Gui::Screen::RenderString(fps_readout);
Gui::Screen::LeaveOrtho();
}
//#endif /* DEBUG */
glFlush();
SDL_GL_SwapBuffers();
//if (glGetError()) printf ("GL: %s\n", gluErrorString (glGetError ()));
Pi::frameTime = 0.001*(SDL_GetTicks() - time_before_frame);
time_before_frame = SDL_GetTicks();
// Fixed 62.5hz physics
int num_steps = 0;
while (time_before_frame - last_phys_update > 16) {
last_phys_update += 16;
const float step = Pi::GetTimeStep();
if (step) Space::TimeStep(step);
gameTime += step;
phys_stat++;
if (++num_steps > 3) break;
}
currentView->Update();
if (SDL_GetTicks() - last_stats > 1000) {
snprintf(fps_readout, sizeof(fps_readout), "%d fps, %d phys updates, %d triangles, %.3f M tris/sec", frame_stat, phys_stat, Pi::statSceneTris, Pi::statSceneTris*frame_stat*1e-6);
frame_stat = 0;
phys_stat = 0;
last_stats += 1000;
}
Pi::statSceneTris = 0;
}
}
StarSystem *Pi::GetSelectedSystem()
{
int sector_x, sector_y, system_idx;
Pi::sectorView->GetSelectedSystem(&sector_x, &sector_y, &system_idx);
if (system_idx == -1) {
selectedSystem = 0;
return NULL;
}
if (selectedSystem) {
if (!selectedSystem->IsSystem(sector_x, sector_y, system_idx)) {
delete selectedSystem;
selectedSystem = 0;
}
}
if (!selectedSystem) {
selectedSystem = new StarSystem(sector_x, sector_y, system_idx);
}
return selectedSystem;
}
void Pi::HyperspaceTo(const SBodyPath *dest)
{
bool new_system = false;
if (currentSystem) {
if (!currentSystem->IsSystem(dest->sectorX, dest->sectorY, dest->systemIdx)) {
delete currentSystem;
currentSystem = 0;
}
}
if (!currentSystem) {
currentSystem = new StarSystem(dest->sectorX, dest->sectorY, dest->systemIdx);
Space::Clear();
Space::BuildSystem();
new_system = true;
}
SBody *targetBody = currentSystem->GetBodyByPath(dest);
Frame *pframe = Space::GetFrameWithSBody(targetBody);
assert(pframe);
float longitude = rng.Double(M_PI);
float latitude = rng.Double(M_PI);
float dist = (0.4 + rng.Double(0.2)) * AU;
Pi::player->SetPosition(vector3d(sin(longitude)*cos(latitude)*dist,
sin(latitude)*dist,
cos(longitude)*cos(latitude)*dist));
Pi::player->SetVelocity(vector3d(0.0));
Pi::player->SetFrame(pframe);
if (new_system) Pi::onPlayerHyperspaceToNewSystem.emit();
}
void Pi::Serialize()
{
using namespace Serializer::Write;
StarSystem::Serialize(selectedSystem);
wr_double(gameTime);
StarSystem::Serialize(currentSystem);
Space::Serialize();
sectorView->Save();
worldView->Save();
}
void Pi::Unserialize()
{
using namespace Serializer::Read;
selectedSystem = StarSystem::Unserialize();
gameTime = rd_double();
currentSystem = StarSystem::Unserialize();
Space::Clear();
if (Pi::player) {
Pi::player->MarkDead();
Space::bodies.remove(Pi::player);
delete Pi::player;
Pi::player = 0;
}
Space::Unserialize();
sectorView->Load();
worldView->Load();
}
IniConfig::IniConfig(const char *filename)
{
FILE *f = fopen_or_die(filename, "r");
char buf[1024];
while (fgets(buf, sizeof(buf), f)) {
if (buf[0] == '#') continue;
char *sep = strchr(buf, '=');
char *kend = sep;
if (!sep) continue;
*sep = 0;
// strip whitespace
while (isspace(*(--kend))) *kend = 0;
while (isspace(*(++sep))) *sep = 0;
// snip \r, \n
char *vend = sep;
while (*(++vend)) if ((*vend == '\r') || (*vend == '\n')) { *vend = 0; break; }
std::string key = std::string(buf);
std::string val = std::string(sep);
(*this)[key] = val;
}
fclose(f);
}

View File

@ -89,7 +89,7 @@ void Planet::SetRadius(double radius)
assert(0);
}
double Planet::GetTerrainHeight(vector3d &pos)
double Planet::GetTerrainHeight(const vector3d pos)
{
double radius = GetRadius();
if (m_geosphere) {
@ -321,20 +321,20 @@ void Planet::Render(const Frame *a_camFrame)
{
glPushMatrix();
double rad = sbody->GetRadius();
matrix4x4d ftran;
Frame::GetFrameTransform(GetFrame(), a_camFrame, ftran);
vector3d fpos = ftran * GetPosition();
double rad = GetRadius();
double apparent_size = rad / fpos.Length();
double len = fpos.Length();
double origLen = len;
do {
while ((len-rad)*0.25 > 32*WORLDVIEW_ZNEAR) {
rad *= 0.25;
fpos = 0.25*fpos;
len *= 0.25;
} while ((len-rad)*0.25 > 4*WORLDVIEW_ZNEAR);
}
glTranslatef(fpos.x, fpos.y, fpos.z);
glColor3f(1,1,1);

View File

@ -21,7 +21,7 @@ public:
virtual void SetFrame(Frame *f);
virtual bool OnCollision(Body *b, Uint32 flags) { return true; }
virtual double GetMass() const { return m_mass; }
double GetTerrainHeight(vector3d &pos);
double GetTerrainHeight(const vector3d pos);
protected:
virtual void Save();
virtual void Load();

View File

@ -84,6 +84,8 @@ void Player::SetDockedWith(SpaceStation *s, int port)
void Player::TimeStepUpdate(const float timeStep)
{
Body *b;
vector3d v;
ClearThrusterState();
if (Pi::GetView() == Pi::worldView) PollControls();
@ -109,7 +111,14 @@ void Player::TimeStepUpdate(const float timeStep)
}
break;
case CONTROL_FIXSPEED:
AIAccelToModelRelativeVelocity(vector3d(0,0,-m_setSpeed));
b = (GetCombatTarget() ? GetCombatTarget() : GetNavTarget());
v = -m_setSpeed;
if (b) {
matrix4x4d m;
GetRotMatrix(m);
v += m.InverseOf() * b->GetVelocityRelativeTo(this->GetFrame());
}
AIAccelToModelRelativeVelocity(v);
break;
case CONTROL_AUTOPILOT:
break;
@ -224,8 +233,15 @@ void Player::DrawHUD(const Frame *cam_frame)
// Direction indicator
const float sz = HUD_CROSSHAIR_SIZE;
vector3d vel = GetVelocity();
vel -= GetFrame()->GetStasisVelocityAtPosition(GetPosition());
vector3d vel;
Body *velRelTo = (GetCombatTarget() ? GetCombatTarget() : GetNavTarget());
if (velRelTo) {
vel = GetVelocityRelativeTo(velRelTo);
} else {
vel = GetVelocity() - GetFrame()->GetStasisVelocityAtPosition(GetPosition());
}
//vector3d Frame::GetFrameRelativeVelocity(const Frame *fFrom, const Frame *fTo)
vector3d loc_v = cam_frame->GetOrientation().InverseOf() * vel;
if (loc_v.z < 0) {
@ -302,12 +318,13 @@ void Player::DrawHUD(const Frame *cam_frame)
}
{
double _vel = sqrt(vel[0]*vel[0] + vel[1]*vel[1] + vel[2]*vel[2]);
double _vel = vel.Length();
char buf[128];
const char *rel_to = (velRelTo ? velRelTo->GetLabel().c_str() : GetFrame()->GetLabel());
if (_vel > 1000) {
snprintf(buf,sizeof(buf), "Velocity: %.2f km/s", _vel*0.001);
snprintf(buf,sizeof(buf), "Velocity: %.2f km/s (relative to %s)", _vel*0.001, rel_to);
} else {
snprintf(buf,sizeof(buf), "Velocity: %.0f m/s", _vel);
snprintf(buf,sizeof(buf), "Velocity: %.0f m/s (relative to %s)", _vel, rel_to);
}
glPushMatrix();
glTranslatef(2, Gui::Screen::GetHeight()-Gui::Screen::GetFontHeight()-66, 0);

View File

@ -112,7 +112,10 @@ Frame *GetFrameWithSBody(const SBody *b)
void MoveOrbitingObjectFrames(Frame *f)
{
if (f->m_sbody) {
if (f == Space::rootFrame) {
f->SetPosition(vector3d(0,0,0));
f->SetVelocity(vector3d(0,0,0));
} else if (f->m_sbody) {
// this isn't very smegging efficient
vector3d pos = f->m_sbody->orbit.CartesianPosAtTime(Pi::GetGameTime());
vector3d pos2 = f->m_sbody->orbit.CartesianPosAtTime(Pi::GetGameTime()+1.0);

View File

@ -740,7 +740,7 @@ void StarSystem::MakePlanetsAround(SBody *primary)
discMax = MIN(discMax, fixed(1,3)*primary->CalcHillRadius());
}
printf("Around %s: Range %f -> %f AU\n", primary->name.c_str(), discMin.ToDouble(), discMax.ToDouble());
//printf("Around %s: Range %f -> %f AU\n", primary->name.c_str(), discMin.ToDouble(), discMax.ToDouble());
fixed initialJump = rand.NFixed(5);
fixed pos = (fixed(1,1) - initialJump)*discMin + (initialJump*discMax);
@ -842,7 +842,6 @@ void SBody::PickPlanetType(StarSystem *system, MTRand &rand)
fixed minDistToStar, maxDistToStar, averageDistToStar;
const SBody *star = FindStarAndTrueOrbitalRange(minDistToStar, maxDistToStar);
averageDistToStar = (minDistToStar+maxDistToStar)>>1;
printf("Star of %s is %s\n", name.c_str(), star->name.c_str());
/* this is all of course a total fucking joke and un-physical */
int bbody_temp;

View File

@ -1,671 +1,6 @@
#include <signal.h>
#include "libs.h"
#include "Pi.h"
#include "Gui.h"
#include "glfreetype.h"
#include "Player.h"
#include "Space.h"
#include "Planet.h"
#include "Star.h"
#include "Frame.h"
#include "ShipCpanel.h"
#include "SectorView.h"
#include "SystemView.h"
#include "SystemInfoView.h"
#include "WorldView.h"
#include "ObjectViewerView.h"
#include "StarSystem.h"
#include "SpaceStation.h"
#include "SpaceStationView.h"
#include "CargoBody.h"
#include "InfoView.h"
#include "Serializer.h"
#include "NameGenerator.h"
#include "mods/Mods.h"
float Pi::timeAccel = 1.0f;
int Pi::scrWidth;
int Pi::scrHeight;
float Pi::scrAspect;
SDL_Surface *Pi::scrSurface;
sigc::signal<void, SDL_keysym*> Pi::onKeyPress;
sigc::signal<void, SDL_keysym*> Pi::onKeyRelease;
sigc::signal<void, int, int, int> Pi::onMouseButtonUp;
sigc::signal<void, int, int, int> Pi::onMouseButtonDown;
sigc::signal<void> Pi::onPlayerChangeHyperspaceTarget;
sigc::signal<void> Pi::onPlayerHyperspaceToNewSystem;
char Pi::keyState[SDLK_LAST];
char Pi::mouseButton[5];
int Pi::mouseMotion[2];
enum Pi::MapView Pi::mapView;
Player *Pi::player;
View *Pi::currentView;
WorldView *Pi::worldView;
ObjectViewerView *Pi::objectViewerView;
SpaceStationView *Pi::spaceStationView;
InfoView *Pi::infoView;
SectorView *Pi::sectorView;
SystemView *Pi::systemView;
SystemInfoView *Pi::systemInfoView;
ShipCpanel *Pi::cpan;
StarSystem *Pi::selectedSystem;
StarSystem *Pi::currentSystem;
MTRand Pi::rng;
double Pi::gameTime;
float Pi::frameTime;
GLUquadric *Pi::gluQuadric;
bool Pi::showDebugInfo;
int Pi::statSceneTris;
void Pi::Init(IniConfig &config)
{
int width = config.Int("ScrWidth");
int height = config.Int("ScrHeight");
const SDL_VideoInfo *info = NULL;
Uint32 sdlInitFlags = SDL_INIT_VIDEO;
#if defined _WIN32 && defined _DEBUG
sdlInitFlags |= SDL_INIT_NOPARACHUTE;
#endif
if (SDL_Init(sdlInitFlags) < 0) {
fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError());
exit(-1);
}
info = SDL_GetVideoInfo();
switch (config.Int("ScrDepth")) {
case 16:
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
break;
case 32:
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
break;
default:
fprintf(stderr, "Fatal error. Invalid screen depth in config.ini.\n");
Pi::Quit();
}
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
Uint32 flags = SDL_OPENGL;
if (config.Int("StartFullscreen")) flags |= SDL_FULLSCREEN;
if ((Pi::scrSurface = SDL_SetVideoMode(width, height, info->vfmt->BitsPerPixel, flags)) == 0) {
// fall back on 16-bit depth buffer...
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
fprintf(stderr, "Failed to set video mode. (%s). Re-trying with 16-bit depth buffer.\n", SDL_GetError());
if ((Pi::scrSurface = SDL_SetVideoMode(width, height, info->vfmt->BitsPerPixel, flags)) == 0) {
fprintf(stderr, "Video mode set failed: %s\n", SDL_GetError());
exit(-1);
}
}
glewInit();
SDL_WM_SetCaption("Pioneer","Pioneer");
Pi::scrWidth = width;
Pi::scrHeight = height;
Pi::scrAspect = width / (float)height;
Pi::rng.seed(time(NULL));
NameGenerator::Init();
InitOpenGL();
GLFTInit();
Space::Init();
Gui::Init(scrWidth, scrHeight, 800, 600);
Mods::Init();
}
void Pi::InitOpenGL()
{
glShadeModel(GL_SMOOTH);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0,0,0,0);
glViewport(0, 0, scrWidth, scrHeight);
gluQuadric = gluNewQuadric ();
fprintf(stderr, "GL_ARB_vertex_buffer_object: %s\n", GLEW_ARB_vertex_buffer_object ? "Yes" : "No");
}
void Pi::Quit()
{
SDL_Quit();
exit(0);
}
void Pi::SetTimeAccel(float s)
{
// don't want player to spin like mad when hitting time accel
if (s > 10) {
player->SetAngVelocity(vector3d(0,0,0));
player->SetTorque(vector3d(0,0,0));
player->SetAngThrusterState(0, 0.0f);
player->SetAngThrusterState(1, 0.0f);
player->SetAngThrusterState(2, 0.0f);
}
timeAccel = s;
}
void Pi::SetMapView(enum MapView v)
{
mapView = v;
if (v == MAP_SECTOR)
SetView(sectorView);
else
SetView(systemView);
}
void Pi::SetView(View *v)
{
if (currentView) currentView->HideAll();
currentView = v;
currentView->OnSwitchTo();
currentView->ShowAll();
}
void Screendump(char *destFile)
{
const int W = Pi::GetScrWidth();
const int H = Pi::GetScrHeight();
std::vector<char> pixel_data(3*W*H);
short TGAhead[] = {0, 2, 0, 0, 0, 0, W, H, 24};
FILE *out = fopen(destFile, "w");
if (!out) goto error;
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, W, H, GL_BGR, GL_UNSIGNED_BYTE, &pixel_data[0]);
if (fwrite(&TGAhead, sizeof(TGAhead), 3, out) != 3) goto error;
if (fwrite(&pixel_data[0], 3*W*H, 1, out) != 1) goto error;
fclose(out);
return;
error:
printf("Failed to write screendump.\n");
}
void Pi::HandleEvents()
{
SDL_Event event;
Pi::mouseMotion[0] = Pi::mouseMotion[1] = 0;
while (SDL_PollEvent(&event)) {
Gui::HandleSDLEvent(&event);
switch (event.type) {
case SDL_KEYDOWN:
if (KeyState(SDLK_LCTRL) && (event.key.keysym.sym == SDLK_q)) Pi::Quit();
if (event.key.keysym.sym == SDLK_i) Pi::showDebugInfo = !Pi::showDebugInfo;
if ((event.key.keysym.sym == SDLK_PRINT) && KeyState(SDLK_LCTRL)) {
char buf[256];
const time_t t = time(0);
struct tm *_tm = localtime(&t);
strftime(buf, sizeof(buf), "screenshot-%Y%m%d-%H%M%S.tga", _tm);
Screendump(buf);
}
#ifdef DEBUG
if (event.key.keysym.sym == SDLK_F12) {
matrix4x4d m; Pi::player->GetRotMatrix(m);
vector3d dir = m*vector3d(0,0,-1);
/* add test object */
if (KeyState(SDLK_LSHIFT)) {
Frame *rotFrame = new Frame(Pi::player->GetFrame(), "Station rot frame");
rotFrame->SetRadius(3000.0);//(1.1*sbody->GetRadius());
rotFrame->SetPosition(Pi::player->GetPosition()+5000.0*dir);
rotFrame->SetAngVelocity(vector3d(0,2*M_PI/10,0));
SpaceStation *station = new SpaceStation(SpaceStation::JJHOOP);
station->SetLabel("Poemi-chan's Folly");
station->SetFrame(rotFrame);
station->SetRotMatrix(matrix4x4d::RotateZMatrix(M_PI));
Space::AddBody(station);
} else if (KeyState(SDLK_RSHIFT)) {
CargoBody *cargo = new CargoBody(Equip::HYDROGEN);
cargo->SetFrame(Pi::player->GetFrame());
cargo->SetPosition(Pi::player->GetPosition()+100.0*dir);
cargo->SetVelocity(Pi::player->GetVelocity());
Space::AddBody(cargo);
} else {
Ship *ship = new Ship(ShipType::LADYBIRD);
ship->AIInstruct(Ship::DO_KILL, Pi::player);
ship->SetFrame(Pi::player->GetFrame());
ship->SetPosition(Pi::player->GetPosition()+100.0*dir);
ship->SetVelocity(Pi::player->GetVelocity());
Space::AddBody(ship);
}
}
#endif /* DEBUG */
if (event.key.keysym.sym == SDLK_F11) SDL_WM_ToggleFullScreen(Pi::scrSurface);
if (event.key.keysym.sym == SDLK_F10) Pi::SetView(Pi::objectViewerView);
if (event.key.keysym.sym == SDLK_F9) Serializer::Write::Game("quicksave.sav");
Pi::keyState[event.key.keysym.sym] = 1;
Pi::onKeyPress.emit(&event.key.keysym);
break;
case SDL_KEYUP:
Pi::keyState[event.key.keysym.sym] = 0;
Pi::onKeyRelease.emit(&event.key.keysym);
break;
case SDL_MOUSEBUTTONDOWN:
Pi::mouseButton[event.button.button] = 1;
Pi::onMouseButtonDown.emit(event.button.button,
event.button.x, event.button.y);
break;
case SDL_MOUSEBUTTONUP:
Pi::mouseButton[event.button.button] = 0;
Pi::onMouseButtonUp.emit(event.button.button,
event.button.x, event.button.y);
break;
case SDL_MOUSEMOTION:
Pi::mouseMotion[0] += event.motion.xrel;
Pi::mouseMotion[1] += event.motion.yrel;
// SDL_GetRelativeMouseState(&Pi::mouseMotion[0], &Pi::mouseMotion[1]);
break;
case SDL_QUIT:
Pi::Quit();
break;
}
}
}
static void draw_intro(float _time)
{
static float lightCol[4] = { 1,1,1,0 };
static float lightDir[4] = { 0,1,0,0 };
static ObjParams params = {
{ 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0.0f, 0.0f, -1.0f }, { 0.0f, 0.0f, 0.0f },
{ // pColor[3]
{ { .2f, .2f, .5f }, { 1, 1, 1 }, { 0, 0, 0 }, 100.0 },
{ { 0.5f, 0.5f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
{ { 0.8f, 0.8f, 0.8f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 } },
{ "PIONEER" },
};
glRotatef(_time*10, 1, 0, 0);
Pi::worldView->DrawBgStars();
glPushAttrib(GL_ALL_ATTRIB_BITS);
sbreSetDepthRange(Pi::GetScrWidth()*0.5, 0.0f, 1.0f);
sbreSetDirLight (lightCol, lightDir);
matrix4x4d rot = matrix4x4d::RotateYMatrix(_time) * matrix4x4d::RotateZMatrix(0.6*_time) *
matrix4x4d::RotateXMatrix(_time*.7);
vector3d p(0, 0, -80);
sbreRenderModel(&p.x, &rot[0], 61, &params);
glPopAttrib();
}
static void draw_tombstone(float _time)
{
static float lightCol[4] = { 1,1,1,0 };
static float lightDir[4] = { 0,1,0,0 };
static ObjParams params = {
{ 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f },
{ // pColor[3]
{ { 1.0f, 1.0f, 1.0f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
{ { 0.8f, 0.6f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
{ { 0.5f, 0.5f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 } },
{ "RIP OLD BEAN" },
};
glPushAttrib(GL_ALL_ATTRIB_BITS);
sbreSetDepthRange(Pi::GetScrWidth()*0.5, 0.0f, 1.0f);
sbreSetDirLight (lightCol, lightDir);
matrix4x4d rot = matrix4x4d::RotateYMatrix(_time*2);
vector3d p(0, 0, -MAX(150 - 30*_time, 30));
sbreRenderModel(&p.x, &rot[0], 91, &params);
glPopAttrib();
}
void Pi::TombStoneLoop()
{
Uint32 last_time = SDL_GetTicks();
float _time = 0;
cpan->HideAll();
currentView->HideAll();
do {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float fracH = 1.0 / Pi::GetScrAspect();
glFrustum(-1, 1, -fracH, fracH, 1.0f, 10000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Pi::HandleEvents();
SDL_ShowCursor(1);
SDL_WM_GrabInput(SDL_GRAB_OFF);
draw_tombstone(_time);
Gui::Draw();
glFlush();
SDL_GL_SwapBuffers();
Pi::frameTime = 0.001*(SDL_GetTicks() - last_time);
_time += Pi::frameTime;
last_time = SDL_GetTicks();
} while (!((_time > 2.0) && ((Pi::MouseButtonState(1)) || Pi::KeyState(SDLK_SPACE)) ));
}
void Pi::Start()
{
player = new Player(ShipType::SWANKY);
player->m_equipment.Set(Equip::SLOT_ENGINE, 0, Equip::DRIVE_CLASS1);
player->m_equipment.Set(Equip::SLOT_LASER, 0, Equip::LASER_2MW_BEAM);
player->m_equipment.Set(Equip::SLOT_LASER, 1, Equip::LASER_4MW_BEAM);
player->m_equipment.Add(Equip::SLOT_CARGO, Equip::HYDROGEN);
player->m_equipment.Add(Equip::SLOT_CARGO, Equip::HYDROGEN);
player->m_equipment.Add(Equip::SLOT_CARGO, Equip::HYDROGEN);
player->SetLabel("me");
player->SetMoney(1000);
Space::AddBody(player);
cpan = new ShipCpanel();
sectorView = new SectorView();
systemView = new SystemView();
systemInfoView = new SystemInfoView();
worldView = new WorldView();
objectViewerView = new ObjectViewerView();
spaceStationView = new SpaceStationView();
infoView = new InfoView();
Gui::Fixed *splash = new Gui::Fixed(Gui::Screen::GetWidth(), Gui::Screen::GetHeight());
Gui::Screen::AddBaseWidget(splash, 0, 0);
splash->SetTransparency(true);
const float w = Gui::Screen::GetWidth() / 2;
const float h = Gui::Screen::GetHeight() / 2;
const int OPTS = 4;
Gui::ToggleButton *opts[OPTS];
opts[0] = new Gui::ToggleButton(); opts[0]->SetShortcut(SDLK_1, KMOD_NONE);
opts[1] = new Gui::ToggleButton(); opts[1]->SetShortcut(SDLK_2, KMOD_NONE);
opts[2] = new Gui::ToggleButton(); opts[2]->SetShortcut(SDLK_3, KMOD_NONE);
opts[3] = new Gui::ToggleButton(); opts[3]->SetShortcut(SDLK_4, KMOD_NONE);
splash->Add(opts[0], w, h-64);
splash->Add(new Gui::Label("New game starting on Earth"), w+32, h-64);
splash->Add(opts[1], w, h-32);
splash->Add(new Gui::Label("New game starting on debug point"), w+32, h-32);
splash->Add(opts[2], w, h);
splash->Add(new Gui::Label("Load quicksave"), w+32, h);
splash->Add(opts[3], w, h+32);
splash->Add(new Gui::Label("Quit"), w+32, h+32);
splash->ShowAll();
int choice = 0;
Uint32 last_time = SDL_GetTicks();
float _time = 0;
do {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float fracH = 1.0 / Pi::GetScrAspect();
glFrustum(-1, 1, -fracH, fracH, 1.0f, 10000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Pi::HandleEvents();
SDL_ShowCursor(1);
SDL_WM_GrabInput(SDL_GRAB_OFF);
draw_intro(_time);
Gui::Draw();
glFlush();
SDL_GL_SwapBuffers();
Pi::frameTime = 0.001*(SDL_GetTicks() - last_time);
_time += Pi::frameTime;
last_time = SDL_GetTicks();
// poll ui instead of using callbacks :-J
for (int i=0; i<OPTS; i++) if (opts[i]->GetPressed()) choice = i+1;
} while (!choice);
splash->HideAll();
if (choice == 1) {
/* Earth start point */
SBodyPath path(0,0,0);
HyperspaceTo(&path);
//Frame *pframe = *(++(++(Space::rootFrame->m_children.begin())));
//player->SetFrame(pframe);
// XXX there isn't a sensible way to find stations for a planet.
SpaceStation *station = 0;
for (Space::bodiesIter_t i = Space::bodies.begin(); i!=Space::bodies.end(); i++) {
if ((*i)->IsType(Object::SPACESTATION)) { station = (SpaceStation*)*i; break; }
}
assert(station);
player->SetFrame(station->GetFrame());
player->SetDockedWith(station, 0);
MainLoop();
} else if (choice == 2) {
/* debug start point */
SBodyPath path(0,0,1);
path.elem[0] = 0; // zeroth child of root body
HyperspaceTo(&path);
player->SetPosition(vector3d(0,0,2*EARTH_RADIUS));
/* Frame *stationFrame = new Frame(pframe, "Station frame...");
stationFrame->SetRadius(5000);
stationFrame->m_sbody = 0;
stationFrame->SetPosition(vector3d(0,0,zpos));
stationFrame->SetAngVelocity(vector3d(0,0,0.5));
for (int i=0; i<4; i++) {
Ship *body = new Ship(ShipType::LADYBIRD);
char buf[64];
snprintf(buf,sizeof(buf),"X%c-0%02d", 'A'+i, i);
body->SetLabel(buf);
body->SetFrame(stationFrame);
body->SetPosition(vector3d(200*(i+1), 0, 2000));
Space::AddBody(body);
}
SpaceStation *station = new SpaceStation(SpaceStation::JJHOOP);
station->SetLabel("Poemi-chan's Folly");
station->SetFrame(stationFrame);
station->SetPosition(vector3d(0,0,0));
Space::AddBody(station);
SpaceStation *station2 = new SpaceStation(SpaceStation::GROUND_FLAVOURED);
station2->SetLabel("Conor's End");
station2->SetFrame(*pframe->m_children.begin()); // rotating frame of planet
station2->OrientOnSurface(EARTH_RADIUS, M_PI/4, M_PI/4);
Space::AddBody(station2);
*/
// player->SetDockedWith(station2, 0);
MainLoop();
} else if (choice == 3) {
// load quicksave
Serializer::Read::Game("quicksave.sav");
MainLoop();
}
}
void Pi::MainLoop()
{
cpan->ShowAll();
SetView(worldView);
Uint32 last_stats = SDL_GetTicks();
int frame_stat = 0;
int phys_stat = 0;
char fps_readout[128];
Uint32 time_before_frame = SDL_GetTicks();
Uint32 last_phys_update = time_before_frame;
for (;;) {
frame_stat++;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
currentView->Draw3D();
// XXX HandleEvents at the moment must be after view->Draw3D and before
// Gui::Draw so that labels drawn to screen can have mouse events correctly
// detected. Gui::Draw wipes memory of label positions.
Pi::HandleEvents();
// hide cursor for ship control.
if (Pi::MouseButtonState(3)) {
SDL_ShowCursor(0);
SDL_WM_GrabInput(SDL_GRAB_ON);
} else {
SDL_ShowCursor(1);
SDL_WM_GrabInput(SDL_GRAB_OFF);
}
Gui::Draw();
//#ifdef DEBUG
if (Pi::showDebugInfo) {
Gui::Screen::EnterOrtho();
glColor3f(1,1,1);
Gui::Screen::RenderString(fps_readout);
Gui::Screen::LeaveOrtho();
}
//#endif /* DEBUG */
glFlush();
SDL_GL_SwapBuffers();
//if (glGetError()) printf ("GL: %s\n", gluErrorString (glGetError ()));
Pi::frameTime = 0.001*(SDL_GetTicks() - time_before_frame);
time_before_frame = SDL_GetTicks();
// Fixed 62.5hz physics
int num_steps = 0;
while (time_before_frame - last_phys_update > 16) {
last_phys_update += 16;
const float step = Pi::GetTimeStep();
if (step) Space::TimeStep(step);
gameTime += step;
phys_stat++;
if (++num_steps > 3) break;
}
currentView->Update();
if (SDL_GetTicks() - last_stats > 1000) {
snprintf(fps_readout, sizeof(fps_readout), "%d fps, %d phys updates, %d triangles, %.3f M tris/sec", frame_stat, phys_stat, Pi::statSceneTris, Pi::statSceneTris*frame_stat*1e-6);
frame_stat = 0;
phys_stat = 0;
last_stats += 1000;
}
Pi::statSceneTris = 0;
}
}
StarSystem *Pi::GetSelectedSystem()
{
int sector_x, sector_y, system_idx;
Pi::sectorView->GetSelectedSystem(&sector_x, &sector_y, &system_idx);
if (system_idx == -1) {
selectedSystem = 0;
return NULL;
}
if (selectedSystem) {
if (!selectedSystem->IsSystem(sector_x, sector_y, system_idx)) {
delete selectedSystem;
selectedSystem = 0;
}
}
if (!selectedSystem) {
selectedSystem = new StarSystem(sector_x, sector_y, system_idx);
}
return selectedSystem;
}
void Pi::HyperspaceTo(const SBodyPath *dest)
{
bool new_system = false;
if (currentSystem) {
if (!currentSystem->IsSystem(dest->sectorX, dest->sectorY, dest->systemIdx)) {
delete currentSystem;
currentSystem = 0;
}
}
if (!currentSystem) {
currentSystem = new StarSystem(dest->sectorX, dest->sectorY, dest->systemIdx);
Space::Clear();
Space::BuildSystem();
new_system = true;
}
SBody *targetBody = currentSystem->GetBodyByPath(dest);
Frame *pframe = Space::GetFrameWithSBody(targetBody);
assert(pframe);
float longitude = rng.Double(M_PI);
float latitude = rng.Double(M_PI);
float dist = (0.4 + rng.Double(0.2)) * AU;
Pi::player->SetPosition(vector3d(sin(longitude)*cos(latitude)*dist,
sin(latitude)*dist,
cos(longitude)*cos(latitude)*dist));
Pi::player->SetVelocity(vector3d(0.0));
Pi::player->SetFrame(pframe);
if (new_system) Pi::onPlayerHyperspaceToNewSystem.emit();
}
void Pi::Serialize()
{
using namespace Serializer::Write;
StarSystem::Serialize(selectedSystem);
wr_double(gameTime);
StarSystem::Serialize(currentSystem);
Space::Serialize();
sectorView->Save();
worldView->Save();
}
void Pi::Unserialize()
{
using namespace Serializer::Read;
selectedSystem = StarSystem::Unserialize();
gameTime = rd_double();
currentSystem = StarSystem::Unserialize();
Space::Clear();
if (Pi::player) {
Pi::player->MarkDead();
Space::bodies.remove(Pi::player);
delete Pi::player;
Pi::player = 0;
}
Space::Unserialize();
sectorView->Load();
worldView->Load();
}
IniConfig::IniConfig(const char *filename)
{
FILE *f = fopen_or_die(filename, "r");
char buf[1024];
while (fgets(buf, sizeof(buf), f)) {
if (buf[0] == '#') continue;
char *sep = strchr(buf, '=');
char *kend = sep;
if (!sep) continue;
*sep = 0;
// strip whitespace
while (isspace(*(--kend))) *kend = 0;
while (isspace(*(++sep))) *sep = 0;
// snip \r, \n
char *vend = sep;
while (*(++vend)) if ((*vend == '\r') || (*vend == '\n')) { *vend = 0; break; }
std::string key = std::string(buf);
std::string val = std::string(sep);
(*this)[key] = val;
}
fclose(f);
}
#include <signal.h>
void sigsegv_handler(int signum)
{

87
src/tests.cpp Normal file
View File

@ -0,0 +1,87 @@
#include "Pi.h"
#include "Frame.h"
#include "Space.h"
#define CRAP 0.00001
static void test(vector3d a, vector3d b)
{
vector3d c = a-b;
c.x = fabs(c.x);
c.y = fabs(c.y);
c.z = fabs(c.z);
if ((c.x < CRAP) && (c.y < CRAP) && (c.z < CRAP)) {
printf("PASSED\n");
} else {
printf("\nFAILED-------------------\n");
}
}
static void dump_frames(Frame *f, int depth)
{
for(int i=0; i<depth; i++) putchar('\t');
printf("%s: Vel %f\n", f->GetLabel(), f->GetVelocity().Length());
std::list<Frame*> m_children;
for (std::list<Frame*>::iterator i = f->m_children.begin(); i!=f->m_children.end(); ++i) {
dump_frames(*i, depth+1);
}
}
static void test_frames()
{
printf("Testing FOR\n");
matrix4x4d m;
vector3d a,b;
Frame *root = new Frame(0, "Root");
Space::rootFrame = root;
Frame *fa1 = new Frame(root, "Fa1");
fa1->SetVelocity(vector3d(0,0,10));
Frame *fa2 = new Frame(fa1, "Fa2");
fa2->SetVelocity(vector3d(0,0,1));
Frame *fb1 = new Frame(root, "Fb1");
fb1->SetVelocity(vector3d(0,0,10));
Frame *fb2 = new Frame(fb1, "Fb2");
fb2->SetVelocity(vector3d(0,0,5));
a = Frame::GetFrameRelativeVelocity(fb1, root);
b = Frame::GetFrameRelativeVelocity(root, fb1);
test(a, vector3d(0,0,-10));
test(b, vector3d(0,0,10));
a = Frame::GetFrameRelativeVelocity(fb2, root);
b = Frame::GetFrameRelativeVelocity(root, fb2);
test(a, vector3d(0,0,-15));
test(b, vector3d(0,0,15));
a = Frame::GetFrameRelativeVelocity(fb2, fa2);
b = Frame::GetFrameRelativeVelocity(fa2, fb2);
test(a, vector3d(0, 0, -4));
test(b, vector3d(0, 0, 4));
// ----------- make some frames rotated --------
m = matrix4x4d::RotateYMatrix(M_PI/2);
fb2->SetOrientation(m);
m = matrix4x4d::RotateYMatrix(M_PI);
fb1->SetOrientation(m);
a = Frame::GetFrameRelativeVelocity(fb2, root);
b = Frame::GetFrameRelativeVelocity(root, fb2);
test(a, vector3d(-10, 0, -5));
test(b, vector3d(5, 0, -10));
a = Frame::GetFrameRelativeVelocity(fb2, fa2);
b = Frame::GetFrameRelativeVelocity(fa2, fb2);
test(a, vector3d(-21, 0, -5));
test(b, vector3d(5, 0, -21));
}
int main(int argc, char *argv[])
{
test_frames();
return 0;
}