New grow and skid sounds from remaxim
[supertux.git] / src / mainloop.cpp
index 5f9230f..444d3d2 100644 (file)
 #include "scripting/time_scheduler.hpp"
 #include "scripting/squirrel_util.hpp"
 #include "gameconfig.hpp"
+#include "constants.hpp"
 #include "main.hpp"
 #include "resources.hpp"
 #include "screen.hpp"
 #include "screen_fade.hpp"
 #include "timer.hpp"
 #include "player_status.hpp"
+#include "video/renderer.hpp"
 #include "random_generator.hpp"
 
-// the engine will be run with a logical framerate of 64fps.
-// We chose 64fps here because it is a power of 2, so 1/64 gives an "even"
-// binary fraction...
-static const float LOGICAL_FPS = 64.0;
 /** ticks (as returned from SDL_GetTicks) per frame */
 static const Uint32 TICKS_PER_FRAME = (Uint32) (1000.0 / LOGICAL_FPS);
 /** don't skip more than every 2nd frame */
 static const int MAX_FRAME_SKIP = 2;
 
+float game_speed = 1.0f;
+
 MainLoop* main_loop = NULL;
 
 MainLoop::MainLoop()
-  : speed(1.0), nextpop(false), nextpush(false)
+  : speed(1.0), nextpop(false), nextpush(false), fps(0), screenshot_requested(false)
 {
   using namespace Scripting;
   TimeScheduler::instance = new TimeScheduler();
@@ -74,7 +74,7 @@ MainLoop::push_screen(Screen* screen, ScreenFade* screen_fade)
   this->screen_fade.reset(screen_fade);
   nextpush = !nextpop;
   nextpop = false;
-  speed = 1.0;
+  speed = 1.0f;
 }
 
 void
@@ -109,14 +109,26 @@ MainLoop::set_speed(float speed)
   this->speed = speed;
 }
 
+float
+MainLoop::get_speed() const
+{
+  return speed;
+}
+
+bool
+MainLoop::has_no_pending_fadeout() const
+{
+  return screen_fade.get() == NULL || screen_fade->done();
+}
+
 void
 MainLoop::draw_fps(DrawingContext& context, float fps_fps)
 {
   char str[60];
   snprintf(str, sizeof(str), "%3.1f", fps_fps);
   const char* fpstext = "FPS";
-  context.draw_text(white_text, fpstext, Vector(SCREEN_WIDTH - white_text->get_text_width(fpstext) - gold_text->get_text_width(" 99999") - BORDER_X, BORDER_Y + 20), ALIGN_LEFT, LAYER_HUD);
-  context.draw_text(gold_text, str, Vector(SCREEN_WIDTH - BORDER_X, BORDER_Y + 20), ALIGN_RIGHT, LAYER_HUD);
+  context.draw_text(small_font, fpstext, Vector(SCREEN_WIDTH - small_font->get_text_width(fpstext) - small_font->get_text_width(" 99999") - BORDER_X, BORDER_Y + 20), ALIGN_LEFT, LAYER_HUD);
+  context.draw_text(small_font, str, Vector(SCREEN_WIDTH - BORDER_X, BORDER_Y + 20), ALIGN_RIGHT, LAYER_HUD);
 }
 
 void
@@ -135,6 +147,11 @@ MainLoop::draw(DrawingContext& context)
   if(config->show_fps)
     draw_fps(context, fps);
 
+  // if a screenshot was requested, pass request on to drawing_context
+  if (screenshot_requested) {
+    context.take_screenshot();
+    screenshot_requested = false;
+  }
   context.do_drawing();
 
   /* Calculate frames per second */
@@ -157,6 +174,8 @@ MainLoop::update_gamelogic(float elapsed_time)
   Scripting::update_debugger();
   Scripting::TimeScheduler::instance->update(game_time);
   current_screen->update(elapsed_time);
+  if (Menu::current() != NULL)
+       Menu::current()->update();
   if(screen_fade.get() != NULL)
     screen_fade->update(elapsed_time);
   Console::instance->update(elapsed_time);
@@ -166,25 +185,60 @@ void
 MainLoop::process_events()
 {
   main_controller->update();
+  Uint8* keystate = SDL_GetKeyState(NULL);
   SDL_Event event;
-  while(SDL_PollEvent(&event)) {
-    main_controller->process_event(event);
-    if(Menu::current() != NULL)
-      Menu::current()->event(event);
-    if(event.type == SDL_QUIT)
-      quit();
-    else if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_F11) {
-      config->use_fullscreen = !config->use_fullscreen;
-      init_video();
+  while(SDL_PollEvent(&event)) 
+    {
+      main_controller->process_event(event);
+
+      if(Menu::current() != NULL)
+        Menu::current()->event(event);
+
+      switch(event.type)
+        {
+          case SDL_QUIT:
+            quit();
+            break;
+              
+          case SDL_VIDEORESIZE:
+            Renderer::instance()->resize(event.resize.w, event.resize.h);
+            Menu::recalc_pos();
+            break;
+            
+          case SDL_KEYDOWN:
+            if (event.key.keysym.sym == SDLK_F10)
+              {
+                config->show_fps = !config->show_fps;
+              }
+            if (event.key.keysym.sym == SDLK_F11) 
+              {
+                config->use_fullscreen = !config->use_fullscreen;
+                init_video();
+                Menu::recalc_pos();
+              }
+            else if (event.key.keysym.sym == SDLK_PRINT ||
+                     event.key.keysym.sym == SDLK_F12)
+              {
+                take_screenshot();
+              }
+            else if (event.key.keysym.sym == SDLK_F1 &&
+                     (keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) &&
+                     keystate[SDLK_c])
+              {
+                Console::instance->toggle();
+                config->console_enabled = true;
+                config->save();
+              }
+            break;
+        }
     }
-  }
 }
 
 void
 MainLoop::handle_screen_switch()
 {
   while( (next_screen.get() != NULL || nextpop) &&
-      (screen_fade.get() == NULL || screen_fade->done())) {
+      has_no_pending_fadeout()) {
     if(current_screen.get() != NULL) {
       current_screen->leave();
     }
@@ -204,9 +258,11 @@ MainLoop::handle_screen_switch()
     nextpush = false;
     nextpop = false;
     speed = 1.0;
-    if(next_screen.get() != NULL)
-      next_screen->setup();
-    current_screen.reset(next_screen.release());
+    Screen* next_screen_ptr = next_screen.release();
+    next_screen.reset(0);
+    if(next_screen_ptr)
+      next_screen_ptr->setup();
+    current_screen.reset(next_screen_ptr);
     screen_fade.reset(NULL);
 
     waiting_threads.wakeup();
@@ -214,10 +270,8 @@ MainLoop::handle_screen_switch()
 }
 
 void
-MainLoop::run()
+MainLoop::run(DrawingContext &context)
 {
-  DrawingContext context;
-
   Uint32 last_ticks = 0;
   Uint32 elapsed_ticks = 0;
 
@@ -232,18 +286,28 @@ MainLoop::run()
     elapsed_ticks += ticks - last_ticks;
     last_ticks = ticks;
 
-    if (elapsed_ticks > TICKS_PER_FRAME*4) {
+    Uint32 ticks_per_frame = (Uint32) (TICKS_PER_FRAME * game_speed);
+
+    if (elapsed_ticks > ticks_per_frame*4) {
       // when the game loads up or levels are switched the
-      // elapsed_ticks grows extremly large, so we just ignore those
+      // elapsed_ticks grows extremely large, so we just ignore those
       // large time jumps
       elapsed_ticks = 0;
     }
 
+    if(elapsed_ticks < ticks_per_frame)
+      {
+        Uint32 delay_ticks = ticks_per_frame - elapsed_ticks;
+        SDL_Delay(delay_ticks);
+        last_ticks += delay_ticks;
+        elapsed_ticks += delay_ticks;
+      }
+
     int frames = 0;
 
-    if (elapsed_ticks > TICKS_PER_FRAME) {
-      while(elapsed_ticks > TICKS_PER_FRAME && frames < MAX_FRAME_SKIP) {
-        elapsed_ticks -= TICKS_PER_FRAME;
+    while(elapsed_ticks >= ticks_per_frame && frames < MAX_FRAME_SKIP) 
+      {
+        elapsed_ticks -= ticks_per_frame;
         float timestep = 1.0 / LOGICAL_FPS;
         real_time += timestep;
         timestep *= speed;
@@ -254,11 +318,15 @@ MainLoop::run()
         frames += 1;
       }
 
-      draw(context);
-    }
+    draw(context);
 
     sound_manager->update();
-
-    SDL_Delay(0);
   }
 }
+
+void 
+MainLoop::take_screenshot()
+{
+  screenshot_requested = true;
+}
+