void render_gl_term(GLTerminal* term) { glMatrixMode(GL_TEXTURE); glLoadIdentity(); glBindFramebuffer(GL_FRAMEBUFFER, term->render_target_fb); glClearColor(0.0f,0.0f,0.0f,0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); int i=0; glColor3d(1,1,1); glDisable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); // glOrtho(0, TERM_SIZE*3, 0, TERM_SIZE, -1,1); glOrtho(0,TERM_SIZE*3,0,TERM_SIZE*1.5,-1,1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glEnable(GL_TEXTURE_2D); int row=0; int col=0; glBindTexture(GL_TEXTURE_2D,term->font_texture); glBegin(GL_QUADS); char cur_char[2]; cur_char[1]=0; VTermPos cur_pos; VTermScreenCell cell; VTermPos cursor_pos; vterm_state_get_cursorpos( vterm_obtain_state(term->vt),&cursor_pos); cursor_pos.row = cursor_pos.row+(25 - CHAR_PIXEL_H); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); for(col=0; col<80; col++) { for(row=0; row<25; row++) { cur_pos.row = row+(25-CHAR_PIXEL_H); cur_pos.col = col; cur_char[0] = term->contents[row][col]; vterm_screen_get_cell(term->vts,cur_pos,&cell); glColor3d(cell.bg.red,cell.bg.green,cell.bg.blue); OGLCONSOLE_DrawString(" ",col*(TERM_SIZE/80),row*(TERM_SIZE/25),CHAR_PIXEL_W,CHAR_PIXEL_H,0); glEnable(GL_TEXTURE_2D); glColor3d(cell.fg.red,cell.fg.green,cell.fg.blue); OGLCONSOLE_DrawString(cur_char,col*(TERM_SIZE/80),row*(TERM_SIZE/25),CHAR_PIXEL_W,CHAR_PIXEL_H,0); } } OGLCONSOLE_DrawString("_",cursor_pos.col*(TERM_SIZE/80),cursor_pos.row*(TERM_SIZE/25),CHAR_PIXEL_W,CHAR_PIXEL_H,0); glEnd(); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glBindFramebuffer(GL_FRAMEBUFFER,0); }
// render void PlayerOverlaySpecial::Render(unsigned int aId, float aTime, const Transform2 &aTransform) { // get the player Player *player = Database::player.Get(aId); // get the player entity (HACK) unsigned int id = player->GetId(); // get "special" ammo resource (HACK) Resource *specialresource = Database::resource.Get(id).Get(0xd940d530 /* "special" */); if (!specialresource) return; int new_special = xs_FloorToInt(specialresource->GetValue()); // if the special has not changed... if (new_special == cur_special && !wasreset) { // call the existing draw list glCallList(special_handle); return; } // update special cur_special = new_special; // start a new draw list list glNewList(special_handle, GL_COMPILE_AND_EXECUTE); // draw the special ammo icon glColor4f(0.4f, 0.5f, 1.0f, 1.0f); glPushMatrix(); glTranslatef(specialpos.x, specialpos.y, 0.0f); glScalef(4, 4, 1); glCallList(Database::drawlist.Get(0x8cdedbba /* "circle16" */)); glPopMatrix(); // draw remaining special ammo char special[16]; sprintf(special, "x%d", cur_special); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, OGLCONSOLE_glFontHandle); glColor4f(0.4f, 0.5f, 1.0f, 1.0f); glBegin(GL_QUADS); float w = 8; float h = -8; float x = specialpos.x + 8; float y = specialpos.y - 0.5f * h; float z = 0; OGLCONSOLE_DrawString(special, x, y, w, h, z); glEnd(); glDisable(GL_TEXTURE_2D); glEndList(); }
// render void PlayerOverlayLives::Render(unsigned int aId, float aTime, const Transform2 &aTransform) { // get the player Player *player = Database::player.Get(aId); // get player lives count int new_lives = player->mLives; if (new_lives == INT_MAX) return; // if the lives count has not changed... if (new_lives == cur_lives && !wasreset) { // call the existing draw list glCallList(lives_handle); return; } // update lives cur_lives = new_lives; // start a new draw list list glNewList(lives_handle, GL_COMPILE_AND_EXECUTE); // draw the player ship glColor4f(0.4f, 0.5f, 1.0f, 1.0f); glPushMatrix(); glTranslatef(livespos.x, livespos.y, 0.0f); glScalef(-0.5f, -0.5f, 1); glCallList(Database::drawlist.Get(0xeec1dafa /* "playership" */)); glPopMatrix(); // draw remaining lives char lives[16]; sprintf(lives, "x%d", cur_lives); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, OGLCONSOLE_glFontHandle); glColor4f(0.4f, 0.5f, 1.0f, 1.0f); glBegin(GL_QUADS); float w = 8; float h = -8; float x = livespos.x + 8; float y = livespos.y - 0.5f * h; float z = 0; OGLCONSOLE_DrawString(lives, x, y, w, h, z); glEnd(); glDisable(GL_TEXTURE_2D); glEndList(); }
// common run state void RunState() { #if defined(USE_SDL) // last ticks unsigned int ticks = SDL_GetTicks(); #elif defined(USE_SFML) // timer sf::Clock timer; // start timer timer.Reset(); #elif defined(USE_GLFW) double prevtime = glfwGetTime(); #endif // input logging TiXmlDocument inputlog(RECORD_CONFIG.c_str()); TiXmlElement *inputlogroot; TiXmlElement *inputlognext; if (playback) { if (!inputlog.LoadFile()) DebugPrint("error loading recording file \"%s\": %s\n", RECORD_CONFIG.c_str(), inputlog.ErrorDesc()); inputlogroot = inputlog.RootElement(); inputlognext = inputlogroot->FirstChildElement(); } else if (record) { inputlogroot = inputlog.LinkEndChild(new TiXmlElement("journal"))->ToElement(); inputlognext = NULL; } else { inputlogroot = NULL; inputlognext = NULL; } #ifdef GET_PERFORMANCE_DETAILS PerfTimer::Init(); PerfTimer control_timer; PerfTimer simulate_timer; PerfTimer collide_timer; PerfTimer update_timer; PerfTimer render_timer; PerfTimer overlay_timer; PerfTimer display_timer; PerfTimer total_timer; total_timer.Stamp(); #endif #ifdef COLLECT_DEBUG_DRAW // create a new draw list GLuint debugdraw = glGenLists(1); #endif // wait for user exit do { #ifdef GET_PERFORMANCE_DETAILS PerfTimer::Next(); control_timer.Clear(); simulate_timer.Clear(); collide_timer.Clear(); update_timer.Clear(); render_timer.Clear(); overlay_timer.Clear(); display_timer.Clear(); total_timer.Clear(); #endif // INPUT PHASE #if defined(USE_SDL) // event handler SDL_Event event; // process events while( SDL_PollEvent( &event ) ) { /* Give the console first dibs on event processing */ if (OGLCONSOLE_SDLEvent(&event)) continue; switch (event.type) { case SDL_KEYDOWN: input.OnPress( Input::TYPE_KEYBOARD, event.key.which, event.key.keysym.sym ); switch (event.key.keysym.sym) { case SDLK_F4: if (event.key.keysym.mod & KMOD_ALT) setgamestate = STATE_QUIT; break; case SDLK_RETURN: if (event.key.keysym.mod & KMOD_ALT) { CloseWindow(); SCREEN_FULLSCREEN = !SCREEN_FULLSCREEN; OpenWindow(); } break; case SDLK_ESCAPE: if (curgamestate == STATE_PLAY) { if (escape) EscapeMenuExit(); else EscapeMenuEnter(); } break; case SDLK_PAUSE: if (event.key.keysym.mod & KMOD_SHIFT) { paused = true; singlestep = true; } else { paused = !paused; } if (paused) Pause(); else Resume(); break; case SDLK_PRINT: Screenshot(); break; } break; case SDL_KEYUP: input.OnRelease( Input::TYPE_KEYBOARD, event.key.which, event.key.keysym.sym ); break; case SDL_MOUSEMOTION: input.OnAxis( Input::TYPE_MOUSE_AXIS, event.motion.which, 0, float(event.motion.x * 2 - SCREEN_WIDTH) / float(SCREEN_HEIGHT) ); input.OnAxis( Input::TYPE_MOUSE_AXIS, event.motion.which, 1, float(event.motion.y * 2 - SCREEN_HEIGHT) / float(SCREEN_HEIGHT) ); input.OnAxis( Input::TYPE_MOUSE_AXIS, event.motion.which, 2, event.motion.xrel / 32.0f ); input.OnAxis( Input::TYPE_MOUSE_AXIS, event.motion.which, 3, event.motion.yrel / 32.0f ); break; case SDL_MOUSEBUTTONDOWN: input.OnPress( Input::TYPE_MOUSE_BUTTON, event.button.which, event.button.button ); break; case SDL_MOUSEBUTTONUP: input.OnRelease( Input::TYPE_MOUSE_BUTTON, event.button.which, event.button.button ); break; case SDL_JOYAXISMOTION: input.OnAxis( Input::TYPE_JOYSTICK_AXIS, event.jaxis.which, event.jaxis.axis, event.jaxis.value / 32767.0f ); break; case SDL_JOYBUTTONDOWN: input.OnPress( Input::TYPE_JOYSTICK_BUTTON, event.jaxis.which, event.jbutton.button ); break; case SDL_JOYBUTTONUP: input.OnRelease( Input::TYPE_JOYSTICK_BUTTON, event.jbutton.which, event.jbutton.button ); break; case SDL_QUIT: setgamestate = STATE_QUIT; break; } } // get loop time in ticks unsigned int nextticks = SDL_GetTicks(); float delta = (nextticks - ticks) / 1000.0f; ticks = nextticks; #elif defined(USE_SFML) sf::Event event; while (window.GetEvent(event)) { /* Give the console first dibs on event processing */ if (OGLCONSOLE_SFMLEvent(&event)) continue; // Some code for stopping application on close or when escape is pressed... switch (event.Type) { case sf::Event::Resized: glViewport(0, 0, event.Size.Width, event.Size.Height); break; case sf::Event::KeyPressed: input.OnPress( Input::TYPE_KEYBOARD, 0, event.Key.Code ); switch(event.Key.Code) { case sf::Key::F4: if (event.Key.Alt) setgamestate = STATE_QUIT; break; case sf::Key::Return: if (event.Key.Alt) { CloseWindow(); SCREEN_FULLSCREEN = !SCREEN_FULLSCREEN; OpenWindow(); } break; case sf::Key::Escape: if (curgamestate == STATE_PLAY) { if (escape) EscapeMenuExit(); else EscapeMenuEnter(); } break; case sf::Key::Pause: if (event.Key.Shift) { paused = true; singlestep = true; } else { paused = !paused; } if (paused) Pause(); else Resume(); break; } break; case sf::Event::KeyReleased: input.OnRelease( Input::TYPE_KEYBOARD, 0, event.Key.Code ); break; case sf::Event::MouseMoved: input.OnAxis( Input::TYPE_MOUSE_AXIS, 0, 0, float(int(event.MouseMove.X) * 2 - SCREEN_WIDTH) / float(SCREEN_HEIGHT) ); input.OnAxis( Input::TYPE_MOUSE_AXIS, 0, 1, float(int(event.MouseMove.Y) * 2 - SCREEN_HEIGHT) / float(SCREEN_HEIGHT) ); break; case sf::Event::MouseButtonPressed: input.OnPress( Input::TYPE_MOUSE_BUTTON, 0, event.MouseButton.Button ); break; case sf::Event::MouseButtonReleased: input.OnRelease( Input::TYPE_MOUSE_BUTTON, 0, event.MouseButton.Button ); break; case sf::Event::JoyMoved: input.OnAxis( Input::TYPE_JOYSTICK_AXIS, event.JoyMove.JoystickId, event.JoyMove.Axis, event.JoyMove.Position / 100.0f ); break; case sf::Event::JoyButtonPressed: input.OnPress( Input::TYPE_JOYSTICK_BUTTON, event.JoyButton.JoystickId, event.JoyButton.Button ); break; case sf::Event::JoyButtonReleased: input.OnRelease( Input::TYPE_JOYSTICK_BUTTON, event.JoyButton.JoystickId, event.JoyButton.Button ); break; case sf::Event::Closed: setgamestate = STATE_QUIT; break; } } // get loop time in ticks float delta = timer.GetElapsedTime(); timer.Reset(); //ticks += delta; #elif defined(USE_GLFW) if (glfwGetJoystickParam(0, GLFW_PRESENT)) { // get joystick axis positions int axiscount = glfwGetJoystickParam(0, GLFW_AXES); float *axis = static_cast<float *>(_alloca(axiscount * sizeof(float))); axiscount = glfwGetJoystickPos(0, axis, axiscount); for (int i = 0; i < axiscount; ++i) input.OnAxis(Input::TYPE_JOYSTICK_AXIS, 0, i, axis[i]); // get joystick button states int buttoncount = glfwGetJoystickParam(0, GLFW_BUTTONS); unsigned char *button = static_cast<unsigned char *>(_alloca(buttoncount * sizeof(unsigned char))); buttoncount = glfwGetJoystickButtons(0, button, buttoncount); for (int i = 0; i < buttoncount; ++i) input.OnAxis(Input::TYPE_JOYSTICK_BUTTON, 0, i, button[i]); } double nexttime = glfwGetTime(); float delta = float(nexttime - prevtime); prevtime = nexttime; #endif // clamp ticks to something sensible // (while debugging, for example) if (delta > 0.1f) delta = 0.1f; // frame time and turns if (singlestep) { // advance 1/60th of a second frame_time = TIME_SCALE / 60.0f; frame_turns = frame_time * sim_rate; } else if (paused || escape) { // freeze time frame_time = 0.0f; frame_turns = 0.0f; } else if (FIXED_STEP) { // advance one simulation step frame_time = TIME_SCALE * sim_step; frame_turns = TIME_SCALE; } else { // advance by frame time frame_time = delta * TIME_SCALE; frame_turns = frame_time * sim_rate; } // turns per motion-blur step float step_turns = std::min(TIME_SCALE * MOTIONBLUR_TIME * sim_rate, 1.0f) / MOTIONBLUR_STEPS; // advance to beginning of motion blur steps sim_fraction += frame_turns; sim_fraction -= MOTIONBLUR_STEPS * step_turns; // for each motion-blur step for (int blur = 0; blur < MOTIONBLUR_STEPS; ++blur) { // clear the screen glClear( GL_COLOR_BUFFER_BIT #ifdef ENABLE_DEPTH_TEST | GL_DEPTH_BUFFER_BIT #endif ); // set projection glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glFrustum( -0.5*VIEW_SIZE*SCREEN_WIDTH/SCREEN_HEIGHT, 0.5*VIEW_SIZE*SCREEN_WIDTH/SCREEN_HEIGHT, 0.5f*VIEW_SIZE, -0.5f*VIEW_SIZE, 256.0f*1.0f, 256.0f*5.0f ); // set base modelview matrix glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( 0.0f, 0.0f, -256.0f ); glScalef( -1.0f, -1.0f, -1.0f ); // advance the sim timer sim_fraction += step_turns; if (escape) { input.Update(); input.Step(); } // while simulation turns to run... else while ((singlestep || !paused) && sim_fraction >= 1.0f) { // deduct a turn sim_fraction -= 1.0f; // advance the turn counter ++sim_turn; // save original fraction float save_fraction = sim_fraction; // switch fraction to simulation mode sim_fraction = 0.0f; #ifdef COLLECT_DEBUG_DRAW // collect any debug draw glNewList(debugdraw, GL_COMPILE); #endif // seed the random number generator Random::Seed(0x92D68CA2 ^ sim_turn); (void)Random::Int(); // update database Database::Update(); if (curgamestate == STATE_PLAY) { if (playback) { // quit if out of turns if (!inputlognext) { setgamestate = STATE_SHELL; break; } // get the next turn value int turn = -1; inputlognext->QueryIntAttribute("turn", &turn); // if the turn matches the simulation turn... if ((unsigned int)turn == sim_turn) { // update the control values input.Playback(inputlognext); // go to the next entry inputlognext = inputlognext->NextSiblingElement(); } } else if (record) { // save original input values float prev[Input::NUM_LOGICAL]; memcpy(prev, input.output, sizeof(prev)); // update input values input.Update(); // if any controls have changed... bool changed = false; for (int i = 0; i < Input::NUM_LOGICAL; ++i) { if (input.output[i] != prev[i]) { changed = true; break; } } if (changed) { // create an input turn entry TiXmlElement item( "input" ); item.SetAttribute( "turn", sim_turn ); // add changed control values input.Record(&item, prev); // add the new input entry inputlogroot->InsertEndChild(item); } } else { // update input values input.Update(); } } // do any pending turn actions DoTurn(); // CONTROL PHASE #ifdef GET_PERFORMANCE_DETAILS control_timer.Start(); #endif // control all entities Controller::ControlAll(sim_step); #ifdef GET_PERFORMANCE_DETAILS control_timer.Stop(); simulate_timer.Start(); #endif // SIMULATION PHASE // (generate forces) Simulatable::SimulateAll(sim_step); #ifdef GET_PERFORMANCE_DETAILS simulate_timer.Stop(); collide_timer.Start(); #endif // COLLISION PHASE // (apply forces and update positions) Collidable::CollideAll(sim_step); #ifdef GET_PERFORMANCE_DETAILS collide_timer.Stop(); update_timer.Start(); #endif // UPDATE PHASE // (use updated positions) Updatable::UpdateAll(sim_step); #ifdef GET_PERFORMANCE_DETAILS update_timer.Stop(); #endif // step inputs for next turn input.Step(); #ifdef COLLECT_DEBUG_DRAW // finish the draw list glEndList(); #endif // restore original fraction sim_fraction = save_fraction; } // clear single-step singlestep = false; // seed the random number generator FloatInt floatint; floatint.f = sim_fraction; Random::Seed(0x92D68CA2 ^ sim_turn ^ floatint.u); (void)Random::Int(); #ifdef PRINT_SIMULATION_TIMER DebugPrint("delta=%f ticks=%d sim_t=%f\n", delta, ticks, sim_fraction); #endif #ifdef GET_PERFORMANCE_DETAILS render_timer.Start(); #endif // RENDERING PHASE // push camera transform glPushMatrix(); // get interpolated track position Vector2 viewpos(Lerp(camerapos[0], camerapos[1], sim_fraction)); // set view position glTranslatef( -viewpos.x, -viewpos.y, 0 ); // calculate view area AlignedBox2 view; view.min.x = viewpos.x - VIEW_SIZE * 0.5f * SCREEN_WIDTH / SCREEN_HEIGHT; view.max.x = viewpos.x + VIEW_SIZE * 0.5f * SCREEN_WIDTH / SCREEN_HEIGHT; view.min.y = viewpos.y - VIEW_SIZE * 0.5f; view.max.y = viewpos.y + VIEW_SIZE * 0.5f; // render all entities // (send interpolation ratio and offset from simulation time) Renderable::RenderAll(view); // reset camera transform glPopMatrix(); // if performing motion blur... if (MOTIONBLUR_STEPS > 1) { // accumulate the image glAccum(blur ? GL_ACCUM : GL_LOAD, 1.0f / float(MOTIONBLUR_STEPS)); } #ifdef GET_PERFORMANCE_DETAILS render_timer.Stop(); #endif } #ifdef GET_PERFORMANCE_DETAILS render_timer.Start(); #endif // if performing motion blur... if (MOTIONBLUR_STEPS > 1) { // return the accumulated image glAccum(GL_RETURN, 1); } // switch blend mode glPushAttrib(GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); #ifdef GET_PERFORMANCE_DETAILS render_timer.Stop(); overlay_timer.Start(); #endif #ifdef COLLECT_DEBUG_DRAW if (DEBUG_DRAW) { // push camera transform glPushMatrix(); // get interpolated track position Vector2 viewpos(Lerp(camerapos[0], camerapos[1], sim_fraction)); // set camera to track position glTranslatef( -viewpos.x, -viewpos.y, 0 ); // debug draw glCallList(debugdraw); // pop camera transform glPopMatrix(); } #endif // push projection transform glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 640, 480, 0, -1, 1); // use 640x480 screen coordinates glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // render all overlays Overlay::RenderAll(); #ifdef GET_PERFORMANCE_DETAILS overlay_timer.Stop(); if (!OPENGL_SWAPCONTROL) { display_timer.Start(); // wait for rendering to finish glFinish(); display_timer.Stop(); } #ifdef DRAW_PERFORMANCE_DETAILS if (PROFILER_OUTPUTSCREEN) { struct BandInfo { const LONGLONG * time; float r; float g; float b; float a; }; static BandInfo band_info[] = { { control_timer.mHistory, 1.0f, 0.0f, 0.0f, 0.5f }, { simulate_timer.mHistory, 1.0f, 1.0f, 0.0f, 0.5f }, { collide_timer.mHistory, 0.0f, 1.0f, 0.0f, 0.5f }, { update_timer.mHistory, 0.0f, 0.5f, 1.0f, 0.5f }, { render_timer.mHistory, 1.0f, 0.0f, 1.0f, 0.5f }, { overlay_timer.mHistory, 1.0f, 0.5f, 0.0f, 0.5f }, { display_timer.mHistory, 0.5f, 0.5f, 0.5f, 0.5f }, }; // generate y samples float sample_y[SDL_arraysize(band_info)+1][PerfTimer::NUM_SAMPLES]; int index = PerfTimer::mIndex; for (int i = 0; i < PerfTimer::NUM_SAMPLES; ++i) { float y = 480.0f; sample_y[0][i] = y; for (int band = 0; band < SDL_arraysize(band_info); ++band) { y -= 60.0f * 480.0f * band_info[band].time[index] / PerfTimer::mFrequency; sample_y[band+1][i] = y; } if (++index >= PerfTimer::NUM_SAMPLES) index = 0; } glBegin(GL_QUADS); for (int band = 0; band < SDL_arraysize(band_info); ++band) { glColor4fv(&band_info[band].r); float x = 0; float dx = 640.0f / PerfTimer::NUM_SAMPLES; for (int i = 0; i < PerfTimer::NUM_SAMPLES; i++) { glVertex3f(x, sample_y[band][i], 0); glVertex3f(x+dx, sample_y[band][i], 0); glVertex3f(x+dx, sample_y[band+1][i], 0); glVertex3f(x, sample_y[band+1][i], 0); x += dx; } } glEnd(); } #endif #ifdef PRINT_PERFORMANCE_DETAILS if (PROFILER_OUTPUTPRINT) { DebugPrint("C=%d S=%d P=%d U=%d R=%d O=%d D=%d\n", control_timer.Microseconds(), simulate_timer.Microseconds(), collide_timer.Microseconds(), update_timer.Microseconds(), render_timer.Microseconds(), overlay_timer.Microseconds(), display_timer.Microseconds()); } #endif // update frame timer total_timer.Stamp(); #if defined(PRINT_PERFORMANCE_FRAMERATE) || defined(DRAW_PERFORMANCE_FRAMERATE) if (FRAMERATE_OUTPUTSCREEN || FRAMERATE_OUTPUTPRINT) { // compute minimum, maximum, and average frame times over the past second LONGLONG total_min = LLONG_MAX; LONGLONG total_max = LLONG_MIN; LONGLONG total_sum = 0; LONGLONG total_samples = 0; int i = PerfTimer::mIndex; do { total_min = std::min(total_min, total_timer.mHistory[i]); total_max = std::max(total_max, total_timer.mHistory[i]); total_sum += total_timer.mHistory[i]; ++total_samples; i = (i > 0) ? i - 1 : PerfTimer::NUM_SAMPLES - 1; } while (total_sum <= PerfTimer::mFrequency && i != PerfTimer::mIndex && total_samples != PerfTimer::mCount); total_sum /= total_samples; // compute frame rates double rate_max = (double)PerfTimer::mFrequency / total_min; double rate_avg = (double)PerfTimer::mFrequency / total_sum; double rate_min = (double)PerfTimer::mFrequency / total_max; #if defined(DRAW_PERFORMANCE_FRAMERATE) if (FRAMERATE_OUTPUTSCREEN) { // draw frame rate indicator glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, OGLCONSOLE_glFontHandle); glBegin(GL_QUADS); char fps[16]; sprintf(fps, "%.2f max", rate_max); glColor4f(0.5f, 0.5f, 0.5f, 1.0f); OGLCONSOLE_DrawString(fps, 640 - 16 - 8 * strlen(fps), 16, 8, -8, 0); sprintf(fps, "%.2f avg", rate_avg); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); OGLCONSOLE_DrawString(fps, 640 - 16 - 8 * strlen(fps), 24, 8, -8, 0); sprintf(fps, "%.2f min", rate_min); glColor4f(0.5f, 0.5f, 0.5f, 1.0f); OGLCONSOLE_DrawString(fps, 640 - 16 - 8 * strlen(fps), 32, 8, -8, 0); glEnd(); glDisable(GL_TEXTURE_2D); } #endif #if defined(PRINT_PERFORMANCE_FRAMERATE) if (FRAMERATE_OUTPUTPRINT) { DebugPrint("%.2f<%.2f<%.2f\n", rate_min, rate_avg, rate_max); } #endif } #endif #endif // reset camera transform glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); // restore blend mode glPopAttrib(); /* Render our console */ OGLCONSOLE_Draw(); // show the back buffer Platform::Present(); #if 0 #ifdef GET_PERFORMANCE_DETAILS if (OPENGL_SWAPCONTROL) #endif // wait for rendering to finish glFinish(); #endif // clear device reset flag wasreset = false; } while( setgamestate == curgamestate ); if (record) { // save input log inputlog.SaveFile(); } }
// render void PlayerOverlayLevel::Render(unsigned int aId, float aTime, const Transform2 &aTransform) { // get the player Player *player = Database::player.Get(aId); // get the attached entity identifier unsigned int id = player->mAttach; // get level resource Resource *levelresource = Database::resource.Get(id).Get(0x9b99e7dd /* "level" */); if (!levelresource) return; int new_level = xs_FloorToInt(levelresource->GetValue()); float new_part = levelresource->GetValue() - new_level; // if the level has not changed... if (new_part == cur_part && new_level == cur_level && !wasreset) { // call the existing draw list glCallList(level_handle); return; } // update level cur_level = new_level; cur_part = new_part; // start a new draw list list glNewList(level_handle, GL_COMPILE_AND_EXECUTE); // draw level gauge glBegin(GL_QUADS); // background glColor4fv(levelcolor[cur_level]); glVertex2f(levelrect.x, levelrect.y); glVertex2f(levelrect.x + levelrect.w, levelrect.y); glVertex2f(levelrect.x + levelrect.w, levelrect.y + levelrect.h); glVertex2f(levelrect.x, levelrect.y + levelrect.h); // fill gauge glColor4fv(levelcolor[cur_level+1]); glVertex2f(levelrect.x, levelrect.y); glVertex2f(levelrect.x + levelrect.w * cur_part, levelrect.y); glVertex2f(levelrect.x + levelrect.w * cur_part, levelrect.y + levelrect.h); glVertex2f(levelrect.x, levelrect.y + levelrect.h); glEnd(); // draw the level icon glColor4f(0.4f, 0.5f, 1.0f, 1.0f); glPushMatrix(); glTranslatef(levelpos.x, levelpos.y, 0.0f); glScalef(4, 4, 1); glCallList(Database::drawlist.Get(0x8cdedbba /* "circle16" */)); glPopMatrix(); // draw level number char level[16]; sprintf(level, "x%d", cur_level); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, OGLCONSOLE_glFontHandle); glColor4f(0.4f, 0.5f, 1.0f, 1.0f); glBegin(GL_QUADS); float w = 8; float h = -8; float x = levelpos.x + 8; float y = levelpos.y - 0.5f * h; float z = 0; OGLCONSOLE_DrawString(level, x, y, w, h, z); glEnd(); glDisable(GL_TEXTURE_2D); glEndList(); }
/* This function draws a single specific console; if you only use one console in * your program, use Draw() instead */ void OGLCONSOLE_Render(OGLCONSOLE_Console console) { /* Don't render hidden console */ if (C->visible == 0 && C->transitionComplete == 0) return; glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadMatrixd(C->pMatrix); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadMatrixd(C->mvMatrix); glPushAttrib(GL_ALL_ATTRIB_BITS); /* glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE);*/ /* TODO: This SHOULD become an option at some point because the * infrastructure for "real" consoles in the game (like you could walk up to * a computer terminal and manipulate a console on a computer using * oglconsole) already exists; you'd want depth testing in that case */ glDisable(GL_DEPTH_TEST); /* With SDL, we have SDL_GetTicks(), so we can do a slide transition */ #ifdef OGLCONSOLE_SLIDE if (C->transitionComplete) { unsigned int t = SDL_GetTicks(); if (t < C->transitionComplete) { double d = (C->transitionComplete - t) / (double)SLIDE_MS; if (!C->visible) d = 1 - d; glTranslated(0, d, 0); } else { C->transitionComplete = 0; if (!C->visible) return; } } #endif #if 0 /* Render hiding / showing console in a special manner. Zero means hidden. 1 * means visible. All other values are traveling toward zero or one. TODO: * Make this time dependent */ if (C->visibility != 1) { double d; /* bra size */ int v = C->visibility; /* Count down in both directions */ if (v < 0) { v ^= -1; C->visibility++; } else { v = SLIDE_STEPS - v; C->visibility--; } d = 0.04 * v; glTranslated(0, 1-d, 0); } #endif /* First we draw our console's background TODO: Add something fancy? */ glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR); glColor4d(.1,0,0, 0.5); glBegin(GL_QUADS); glVertex3d(0,0,0); glVertex3d(1,0,0); glVertex3d(1,1,0); glVertex3d(0,1,0); glEnd(); // Change blend mode for drawing text glBlendFunc(GL_ONE, GL_ONE); /* Select the console font */ glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, OGLCONSOLE_glFontHandle); /* Recolor text */ glColor3d(0,1,0); /* Render console contents */ glBegin(GL_QUADS); { /* Graphical line, and line in lines[] */ int gLine, tLine = C->lineScrollIndex; /* Iterate through each line being displayed */ for (gLine = 0; gLine < C->textHeight; gLine++) { /* Draw this line of text adjusting for user scrolling up/down */ OGLCONSOLE_DrawString(C->lines + (tLine * C->textWidth), 0, (C->textHeight - gLine) * C->characterHeight, C->characterWidth, C->characterHeight, 0); /* Grab next line of text using wheel-queue wrapping */ if (++tLine >= C->maxLines) tLine = 0; } /* Here we draw the current commandline, it will either be a line from * the command history or the line being edited atm */ if (C->historyScrollIndex >= 0) { glColor3d(1,0,0); OGLCONSOLE_DrawString( C->history[C->historyScrollIndex], 0, 0, C->characterWidth, C->characterHeight, 0); } else { /* Draw input line cyan */ glColor3d(0,1,1); OGLCONSOLE_DrawString(C->inputLine, 0, 0, C->characterWidth, C->characterHeight, 0); /* Draw cursor beige */ glColor3d(1,1,.5); OGLCONSOLE_DrawCharacter('_', C->inputCursorPos * C->characterWidth, 0, C->characterWidth, C->characterHeight, 0); } } glEnd(); /* Relinquish our rendering settings */ glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPopAttrib(); }