#include "libs.h" #include "l3d.h" #include "gui.h" #include "glfreetype.h" #include "player.h" #include "space.h" #include "planet.h" #include "star.h" #include "frame.h" #include "ship_cpanel.h" #include "sector_view.h" #include "system_view.h" #include "system_info_view.h" #include "world_view.h" #include "object_viewer_view.h" #include "star_system.h" #include "space_station.h" #include "space_station_view.h" #include "info_view.h" float L3D::timeAccel = 1.0f; int L3D::scrWidth; int L3D::scrHeight; float L3D::scrAspect; SDL_Surface* L3D::scrSurface; sigc::signal L3D::onKeyPress; sigc::signal L3D::onKeyRelease; sigc::signal L3D::onMouseButtonUp; sigc::signal L3D::onMouseButtonDown; char L3D::keyState[SDLK_LAST]; char L3D::mouseButton[5]; int L3D::mouseMotion[2]; enum L3D::CamType L3D::camType; enum L3D::MapView L3D::mapView; Player* L3D::player; View* L3D::currentView; WorldView* L3D::worldView; ObjectViewerView* L3D::objectViewerView; SpaceStationView* L3D::spaceStationView; InfoView* L3D::infoView; SectorView* L3D::sectorView; SystemView* L3D::systemView; SystemInfoView* L3D::systemInfoView; ShipCpanel* L3D::cpan; StarSystem* L3D::selectedSystem; StarSystem* L3D::currentSystem; MTRand L3D::rng; double L3D::gameTime; float L3D::frameTime; GLUquadric* L3D::gluQuadric; int L3D::playerLocSecX; int L3D::playerLocSecY; int L3D::playerLocSysIdx; bool L3D::showDebugInfo; void L3D::Init(IniConfig& config) { int width = config.Int("ScrWidth"); int height = config.Int("ScrHeight"); const SDL_VideoInfo* info = NULL; if(SDL_Init(SDL_INIT_VIDEO) < 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"); L3D::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((L3D::scrSurface = SDL_SetVideoMode(width, height, info->vfmt->BitsPerPixel, flags)) == 0) { /* Fall back to 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((L3D::scrSurface = SDL_SetVideoMode(width, height, info->vfmt->BitsPerPixel, flags)) == 0) { fprintf(stderr, "video mode set failed: %s\n", SDL_GetError()); exit(-1); } } L3D::scrWidth = width; L3D::scrHeight = height; L3D::scrAspect = width / (float)height; L3D::rng.seed(time(NULL)); InitOpenGL(); dInitODE(); GLFTInit(); Space::Init(); } void L3D::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(); } void L3D::Quit(void) { SDL_Quit(); exit(0); } void L3D::SetTimeAccel(float s) { /* We don't want player spinning like crazy when hitting time accel. */ if(s > 10) { player->SetAngVelocity(vector3d(0,0,0)); dBodySetTorque(player->m_body, 0, 0, 0); player->SetAngThrusterState(0, 0.0f); player->SetAngThrusterState(1, 0.0f); player->SetAngThrusterState(2, 0.0f); } timeAccel = s; } void L3D::SetCamType(enum CamType c) { camType = c; mapView = MAP_NOMAP; SetView(worldView); } void L3D::SetMapView(enum MapView v) { mapView = v; if(v == MAP_SECTOR) SetView(sectorView); else SetView(systemView); } void L3D::SetView(View* v) { if(currentView) currentView->HideAll(); currentView = v; currentView->ShowAll(); } void L3D::HandleEvents(void) { SDL_Event event; L3D::mouseMotion[0] = L3D::mouseMotion[1] = 0; while(SDL_PollEvent(&event)) { Gui::HandleSDLEvent(&event); switch(event.type) { case SDL_KEYDOWN: if(event.key.keysym.sym == SDLK_ESCAPE) L3D::Quit(); if(event.key.keysym.sym == SDLK_i) L3D::showDebugInfo = !L3D::showDebugInfo; #ifdef DEBUG if(event.key.keysym.sym == SDLK_F12) { /* Add test object. */ Ship* body = new Ship(ShipType::LADYBIRD); body->SetLabel("A friend"); body->SetFrame(L3D::player->GetFrame()); body->SetPosition(L3D::player->GetPosition()+vector3d(0,0,-1000)); Space::AddBody(body); } #endif if(event.key.keysym.sym == SDLK_F11) SDL_WM_ToggleFullScreen(L3D::scrSurface); if(event.key.keysym.sym == SDLK_F10) L3D::SetView(L3D::objectViewerView); L3D::keyState[event.key.keysym.sym] = 1; L3D::onKeyPress.emit(&event.key.keysym); break; case SDL_KEYUP: L3D::keyState[event.key.keysym.sym] = 0; L3D::onKeyRelease.emit(&event.key.keysym); break; case SDL_MOUSEBUTTONDOWN: L3D::mouseButton[event.button.button] = 1; L3D::onMouseButtonDown.emit(event.button.button, event.button.x, event.button.y); break; case SDL_MOUSEBUTTONUP: L3D::mouseButton[event.button.button] = 1; L3D::onMouseButtonUp.emit(event.button.button, event.button.x, event.button.y); break; case SDL_MOUSEMOTION: L3D::mouseMotion[0] += event.motion.xrel; L3D::mouseMotion[1] += event.motion.yrel; //SDL_GetRelativeMouseState(&L3D::mouseMotion[0], &L3D::mouseMotion[1]); break; case SDL_QUIT: L3D::Quit(); break; } } } void L3D::MainLoop(void) { player = new Player(ShipType::SLEEK); player->SetLabel("Me"); Space::AddBody(player); StarSystem s(0, 0, 0); HyperspaceTo(&s); const float zpos = EARTH_RADIUS * 3; Frame* pframe = *(++(++(Space::rootFrame->m_children.begin()))); 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::SLEEK/*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("Dfighter's point"); station2->SetFrame(*pframe->m_children.begin()); /* Rotating frame of planet. */ station2->OrientOnSurface(EARTH_RADIUS, M_PI/4, M_PI/4); Space::AddBody(station2); player->SetFrame(pframe); //player->SetPosition(vector3d(0,0,0)); player->OrientOnSurface(EARTH_RADIUS*1.001, M_PI/4, M_PI/4); //player->SetPosition(vector3d(0,0,2000)); //player->SetFrame(pframe); Gui::Init(scrWidth, scrHeight, 800, 600); cpan = new ShipCpanel(); cpan->ShowAll(); sectorView = new SectorView(); systemView = new SystemView(); systemInfoView = new SystemInfoView(); worldView = new WorldView(); objectViewerView = new ObjectViewerView(); spaceStationView = new SpaceStationView(); infoView = new InfoView(); SetView(worldView); player->SetDockedWith(station2, 0); Uint32 last_stats = SDL_GetTicks(); int frame_stat = 0; char fps_readout[32]; Uint32 time_before_frame = SDL_GetTicks(); for(;;) { frame_stat++; glMatrixMode(GL_MODELVIEW); glLoadIdentity(); currentView->Draw3D(); /* * TODO: 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. */ L3D::HandleEvents(); /* Hide cursor for ship control. */ if(L3D::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(L3D::showDebugInfo) { Gui::Screen::EnterOrtho(); glColor3f(1, 1, 1); glTranslatef(0, Gui::Screen::GetHeight()-20, 0); Gui::Screen::RenderString(fps_readout); Gui::Screen::LeaveOrtho(); } #endif glFlush(); SDL_GL_SwapBuffers(); //if(glGetError()) printf("GL: %s\n", gluErrorString(glGetError())); L3D::frameTime = 0.001*(SDL_GetTicks() - time_before_frame); float step = L3D::timeAccel * L3D::frameTime; time_before_frame = SDL_GetTicks(); /* Game state update stuff. */ if(step) { Space::TimeStep(step); gameTime += step; } currentView->Update(); if(SDL_GetTicks() - last_stats > 1000) { snprintf(fps_readout, sizeof(fps_readout), "%d fps", frame_stat); frame_stat = 0; last_stats += 1000; } } } StarSystem* L3D::GetSelectedSystem(void) { int sector_x, sector_y, system_idx; L3D::sectorView->GetSelectedSystem(§or_x, §or_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 L3D::HyperspaceTo(StarSystem* dest) { int sec_x, sec_y, sys_idx; dest->GetPos(&sec_x, &sec_y, &sys_idx); if(currentSystem) delete currentSystem; currentSystem = new StarSystem(sec_x, sec_y, sys_idx); Space::Clear(); Space::BuildSystem(); float ang = rng.Double(M_PI); L3D::player->SetPosition(vector3d(sin(ang)*AU, cos(ang)*AU,0)); L3D::player->SetVelocity(vector3d(0.0)); dest->GetPos(&L3D::playerLocSecX, &L3D::playerLocSecY, &L3D::playerLocSysIdx); } IniConfig::IniConfig(const char* filename) { FILE* f = fopen(filename, "r"); if(!f) { fprintf(stderr, "Could not open '%s'.\n", filename); L3D::Quit(); } 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); } int main(int argc, char** argv) { printf("Lephisto3D's super high tech demo!\n"); IniConfig cfg("config.ini"); L3D::Init(cfg); L3D::MainLoop(); return 0; }