-Some cleanups in text scrolling code
authorMatthias Braun <matze@braunis.de>
Wed, 30 Mar 2005 12:01:02 +0000 (12:01 +0000)
committerMatthias Braun <matze@braunis.de>
Wed, 30 Mar 2005 12:01:02 +0000 (12:01 +0000)
-Added the (temporary) bell graphics which I forgot yesterday
-Implemented an infoblock object (the textbox isn't finished yet) and it also
 needs new graphics

SVN-Revision: 2298

21 files changed:
data/credits.txt
data/images/shared/bell/bell-l.png [new file with mode: 0644]
data/images/shared/bell/bell-m.png [new file with mode: 0644]
data/images/shared/bell/bell-r.png [new file with mode: 0644]
data/levels/test/bonusblock.stl
lib/video/drawing_context.cpp
lib/video/drawing_context.h
lib/video/font.cpp
lib/video/font.h
src/gameloop.cpp
src/gameloop.h
src/object/block.cpp
src/object/block.h
src/object/infoblock.cpp [new file with mode: 0644]
src/object/infoblock.h [new file with mode: 0644]
src/object/invisible_block.cpp
src/textscroller.cpp [new file with mode: 0644]
src/textscroller.h [new file with mode: 0644]
src/title.cpp
src/title.h
src/worldmap.cpp

index a6c9b1a..5c209d9 100644 (file)
@@ -1,6 +1,7 @@
 ; Credits text
 (supertux-text
   (background "oiltux.jpg")
+  (speed 1.5)
 
   (text (_ "-- SuperTux -
        Milestone 1
diff --git a/data/images/shared/bell/bell-l.png b/data/images/shared/bell/bell-l.png
new file mode 100644 (file)
index 0000000..157ee76
Binary files /dev/null and b/data/images/shared/bell/bell-l.png differ
diff --git a/data/images/shared/bell/bell-m.png b/data/images/shared/bell/bell-m.png
new file mode 100644 (file)
index 0000000..e8747a1
Binary files /dev/null and b/data/images/shared/bell/bell-m.png differ
diff --git a/data/images/shared/bell/bell-r.png b/data/images/shared/bell/bell-r.png
new file mode 100644 (file)
index 0000000..a135311
Binary files /dev/null and b/data/images/shared/bell/bell-r.png differ
index 7db7426..1ee6053 100644 (file)
@@ -55,7 +55,7 @@
         0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
         ))
     (tilemap
-      (layer  "main")
+      (layer  "interactive")
       (solid #t)
       (speed  1.000000)
       (width  30)
       (path
     ))
 
+    (infoblock
+      (x 128)
+      (y 800)
+      (message (_ 
+"-Info
+#This is an info block
+#(WOW GREAT)
+#This rocks"))
+    )
    )
  )
 
index bba6d36..6257b9f 100644 (file)
@@ -39,7 +39,7 @@ DrawingContext::~DrawingContext()
 
 void
 DrawingContext::draw_surface(const Surface* surface, const Vector& position,
-    int layer, Uint32 drawing_effect)
+    int layer, uint32_t drawing_effect)
 {
   assert(surface != 0);
   
@@ -63,7 +63,7 @@ DrawingContext::draw_surface(const Surface* surface, const Vector& position,
 
 void
 DrawingContext::draw_surface_part(const Surface* surface, const Vector& source,
-    const Vector& size, const Vector& dest, int layer, Uint32 drawing_effect)
+    const Vector& size, const Vector& dest, int layer, uint32_t drawing_effect)
 {
   assert(surface != 0);
 
@@ -101,9 +101,9 @@ DrawingContext::draw_surface_part(const Surface* surface, const Vector& source,
 }
 
 void
-DrawingContext::draw_text(Font* font, const std::string& text,
-    const Vector& position, int allignment, int layer,
-    Uint32 drawing_effect)
+DrawingContext::draw_text(const Font* font, const std::string& text,
+    const Vector& position, FontAlignment alignment, int layer,
+    uint32_t drawing_effect)
 {
   DrawingRequest request;
 
@@ -117,18 +117,18 @@ DrawingContext::draw_text(Font* font, const std::string& text,
   TextRequest* textrequest = new TextRequest;
   textrequest->font = font;
   textrequest->text = text;
-  textrequest->allignment = allignment;
+  textrequest->alignment = alignment;
   request.request_data = textrequest;
 
   drawingrequests.push_back(request);
 }
 
 void
-DrawingContext::draw_center_text(Font* font, const std::string& text,
-    const Vector& position, int layer, Uint32 drawing_effect)
+DrawingContext::draw_center_text(const Font* font, const std::string& text,
+    const Vector& position, int layer, uint32_t drawing_effect)
 {
-draw_text(font, text, Vector(position.x + screen->w/2, position.y),
-          CENTER_ALLIGN, layer, drawing_effect);
+  draw_text(font, text, Vector(position.x + screen->w/2, position.y),
+      CENTER_ALLIGN, layer, drawing_effect);
 }
 
 void
@@ -240,7 +240,8 @@ DrawingContext::draw_text(DrawingRequest& request)
 {
   TextRequest* textrequest = (TextRequest*) request.request_data;
 
-  textrequest->font->draw(textrequest->text, request.pos, textrequest->allignment, request.drawing_effect, request.alpha);
+  textrequest->font->draw(textrequest->text, request.pos,
+      textrequest->alignment, request.drawing_effect, request.alpha);
 
   delete textrequest;
 }
index 7ef8de9..3da8dcc 100644 (file)
 
 #include <vector>
 #include <string>
+#include <stdint.h>
 
 #include "SDL.h"
 
 #include "math/vector.h"
 #include "video/screen.h"
 #include "video/surface.h"
+#include "video/font.h"
 
 namespace SuperTux
   {
 
   class Surface;
-  class Font;
 
   // some constants for predefined layer values
   enum {
@@ -59,23 +60,23 @@ namespace SuperTux
       ~DrawingContext();
 
       /// Adds a drawing request for a surface into the request list.
-      void draw_surface(const Surface* surface, const Vector& position, int layer,
-                        Uint32 drawing_effect = NONE_EFFECT);
+      void draw_surface(const Surface* surface, const Vector& position,
+          int layer, uint32_t drawing_effect = NONE_EFFECT);
       /// Adds a drawing request for part of a surface.
       void draw_surface_part(const Surface* surface, const Vector& source,
                              const Vector& size, const Vector& dest, int layer,
-                             Uint32 drawing_effect = NONE_EFFECT);
+                             uint32_t drawing_effect = NONE_EFFECT);
       /// Draws a text.
-      void draw_text(Font* font, const std::string& text, const Vector& position,
-                     int allignment, int layer,
-                     Uint32 drawing_effect = NONE_EFFECT);
+      void draw_text(const Font* font, const std::string& text,
+          const Vector& position, FontAlignment alignment, int layer,
+          uint32_t drawing_effect = NONE_EFFECT);
 
       /// Draws text on screen center (feed Vector.x with a 0).
       /// This is the same as draw_text() with a screen->w/2 position and
-      /// allignment set to LEFT_ALLIGN
-      void draw_center_text(Font* font, const std::string& text,
+      /// alignment set to LEFT_ALLIGN
+      void draw_center_text(const Font* font, const std::string& text,
                            const Vector& position, int layer,
-                           Uint32 drawing_effect = NONE_EFFECT);
+                           uint32_t drawing_effect = NONE_EFFECT);
       /// Draws a color gradient onto the whole screen */
       void draw_gradient(Color from, Color to, int layer);
       /// Fills a rectangle.
@@ -87,7 +88,7 @@ namespace SuperTux
 
       const Vector& get_translation() const
       {  return transform.translation;  }
-      Uint32 get_drawing_effect() const
+      uint32_t get_drawing_effect() const
       {  return transform.drawing_effect;  }
 
       void set_translation(const Vector& newtranslation)
@@ -108,7 +109,7 @@ namespace SuperTux
       {
       public:
         Vector translation;
-        Uint32 drawing_effect;
+        uint32_t drawing_effect;
         float zoom;
         int alpha;
 
@@ -140,9 +141,9 @@ namespace SuperTux
 
       struct TextRequest
         {
-          Font* font;
+          const Font* font;
           std::string text;
-          int allignment;
+          FontAlignment alignment;
         };
 
       struct GradientRequest
@@ -163,7 +164,7 @@ namespace SuperTux
           Vector pos;                
           
           int layer;
-          Uint32 drawing_effect;
+          uint32_t drawing_effect;
           float zoom;
           int alpha;
 
index 12d96c7..e01cedc 100644 (file)
@@ -119,10 +119,11 @@ Font::get_height() const
 }
 
 void
-Font::draw(const std::string& text, const Vector& pos_, int allignment, Uint32 drawing_effect, int alpha)
+Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment,
+    uint32_t drawing_effect, uint8_t alpha) const
 {
   /* Cut lines changes into seperate strings, needed to support center/right text
-     allignments with break lines.
+     alignments with break lines.
      Feel free to replace this hack with a more elegant solution
   */
   char temp[1024];
@@ -141,11 +142,11 @@ Font::draw(const std::string& text, const Vector& pos_, int allignment, Uint32 d
 
     temp[text.copy(temp, l - i, i)] = '\0';
 
-    // calculate X positions based on the allignment type
+    // calculate X positions based on the alignment type
     Vector pos = Vector(pos_);
-    if(allignment == CENTER_ALLIGN)
+    if(alignment == CENTER_ALLIGN)
       pos.x -= get_text_width(temp) / 2;
-    else if(allignment == RIGHT_ALLIGN)
+    else if(alignment == RIGHT_ALLIGN)
       pos.x -= get_text_width(temp);
 
     draw_text(temp, pos + Vector(0,y), drawing_effect, alpha);
@@ -156,7 +157,8 @@ Font::draw(const std::string& text, const Vector& pos_, int allignment, Uint32 d
 }
 
 void
-Font::draw_text(const std::string& text, const Vector& pos, Uint32 drawing_effect, int alpha)
+Font::draw_text(const std::string& text, const Vector& pos, 
+    uint32_t drawing_effect, uint8_t alpha) const
 {
   if(shadowsize > 0)
     draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize),
@@ -167,7 +169,7 @@ Font::draw_text(const std::string& text, const Vector& pos, Uint32 drawing_effec
 
 void
 Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
-                 Uint32 drawing_effect, int alpha)
+                 uint32_t drawing_effect, uint8_t alpha) const
 {
   SurfaceImpl* impl = pchars->impl;
 
@@ -197,170 +199,3 @@ Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
   }
 }
 
-/* --- SCROLL TEXT FUNCTION --- */
-
-#define MAX_VEL     10
-#define SPEED_INC   0.01
-#define SCROLL      60
-#define ITEMS_SPACE 4
-
-void SuperTux::display_text_file(const std::string& file, float scroll_speed,
-    Font* heading_font, Font* normal_font, Font* small_font,
-    Font* reference_font)
-{
-  std::string text;
-  std::string background_file;
-  std::vector<std::string> names;
-
-  std::string filename = datadir + "/" + file;
-  lisp::Parser parser;
-  try {
-    std::auto_ptr<lisp::Lisp> root (parser.parse(filename));
-
-    const lisp::Lisp* text_lisp = root->get_lisp("supertux-text");
-    if(!text_lisp)
-      throw std::runtime_error("File isn't a supertux-text file");
-    
-    if(!text_lisp->get("text", text))
-      throw std::runtime_error("file doesn't contain a text field");
-    if(!text_lisp->get("background", background_file))
-      throw std::runtime_error("file doesn't contain a background file");
-  } catch(std::exception& e) {
-    std::cerr << "Couldn't load file '" << filename << "': " << e.what() <<
-      "\n";
-    return;
-  }
-
-  // Split text string lines into a vector
-  names.clear();
-  std::string::size_type i, l;
-  i = 0;
-  while(true)
-    {
-    l = text.find("\n", i);
-
-    if(l == std::string::npos)
-      {
-      char temp[1024];
-      temp[text.copy(temp, text.size() - i, i)] = '\0';
-      names.push_back(temp);
-      break;
-      }
-
-    char temp[1024];
-    temp[text.copy(temp, l-i, i)] = '\0';
-    names.push_back(temp);
-
-    i = l+1;
-    }
-
-  // load background image
-  Surface* background = new Surface(datadir + "/images/background/" + background_file, false);
-
-  int done = 0;
-  float scroll = 0;
-  float speed = scroll_speed / 50;
-  float left_border = 50;
-
-  DrawingContext context;
-  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
-
-  Uint32 lastticks = SDL_GetTicks();
-  while(!done)
-    {
-      /* in case of input, exit */
-      SDL_Event event;
-      while(SDL_PollEvent(&event))
-        switch(event.type)
-          {
-          case SDL_KEYDOWN:
-            switch(event.key.keysym.sym)
-              {
-              case SDLK_UP:
-                speed -= SPEED_INC;
-                break;
-              case SDLK_DOWN:
-                speed += SPEED_INC;
-                break;
-              case SDLK_SPACE:
-              case SDLK_RETURN:
-                if(speed >= 0)
-                  scroll += SCROLL;
-                break;
-              case SDLK_ESCAPE:
-                done = 1;
-                break;
-              default:
-                break;
-              }
-            break;
-          case SDL_QUIT:
-            done = 1;
-            break;
-          default:
-            break;
-          }
-
-      if(speed > MAX_VEL)
-        speed = MAX_VEL;
-      else if(speed < -MAX_VEL)
-        speed = -MAX_VEL;
-
-      /* draw the credits */
-      context.draw_surface(background, Vector(0,0), 0);
-
-      float y = 0;
-      for(size_t i = 0; i < names.size(); i++) {
-        if(names[i].size() == 0) {
-          y += normal_font->get_height() + ITEMS_SPACE;
-          continue;
-        }
-
-        Font* font = 0;
-        bool center = true;
-        switch(names[i][0])
-        {
-          case ' ': font = small_font; break;
-          case '\t': font = normal_font; break;
-          case '-': font = heading_font; break;
-          case '*': font = reference_font; break;
-          case '#': font = normal_font; center = false; break;
-          default: 
-            break;
-        }
-        
-        if(font) {
-          if(center) {
-            context.draw_text(font,
-                              names[i].substr(1, names[i].size()-1),
-                              Vector(screen->w/2, screen->h + y - scroll),
-                              CENTER_ALLIGN, LAYER_FOREGROUND1);
-          } else {
-            context.draw_text(font,
-                              names[i].substr(1, names[i].size()-1),
-                              Vector(left_border, screen->h + y - scroll),
-                              LEFT_ALLIGN, LAYER_FOREGROUND1);
-          }
-        }                   
-          
-        y += font->get_height() + ITEMS_SPACE;
-      }
-
-      context.do_drawing();
-
-      if(screen->h+y-scroll < 0 && 20+screen->h+y-scroll < 0)
-        done = 1;
-
-      Uint32 ticks = SDL_GetTicks();
-      scroll += speed * (ticks - lastticks);
-      lastticks = ticks;
-      if(scroll < 0)
-        scroll = 0;
-
-      SDL_Delay(10);
-    }
-
-  SDL_EnableKeyRepeat(0, 0);    // disables key repeating
-  delete background;
-}
-
index 429cf97..58e1e76 100644 (file)
@@ -22,6 +22,7 @@
 #define SUPERTUX_FONT_H
 
 #include <string>
+#include <stdint.h>
 
 #include "video/surface.h"
 #include "math/vector.h"
@@ -29,7 +30,7 @@
 namespace SuperTux
   {
 
-  enum {
+  enum FontAlignment {
     LEFT_ALLIGN,
     CENTER_ALLIGN,
     RIGHT_ALLIGN
@@ -45,7 +46,8 @@ namespace SuperTux
         NUM   // only images for numbers
       };
 
-      Font(const std::string& file, FontType type, int w, int h, int shadowsize=2);
+      Font(const std::string& file, FontType type, int w, int h,
+          int shadowsize=2);
       ~Font();
 
       /** returns the width of a given text. (Note that I won't add a normal
@@ -69,17 +71,17 @@ namespace SuperTux
       /** Draws the given text to the screen. Also needs the position.
        * Type of alignment, drawing effect and alpha are optional. */
       void draw(const std::string& text, const Vector& pos,
-                int allignment = LEFT_ALLIGN,
-                Uint32 drawing_effect = NONE_EFFECT, int alpha = 255);
+          FontAlignment allignment = LEFT_ALLIGN,
+          uint32_t drawing_effect = NONE_EFFECT, uint8_t alpha = 255) const;
 
     private:
       friend class DrawingContext;
 
       void draw_text(const std::string& text, const Vector& pos,
-                Uint32 drawing_effect = NONE_EFFECT, int alpha = 255);
+          uint32_t drawing_effect = NONE_EFFECT, uint8_t alpha = 255) const;
 
       void draw_chars(Surface* pchars, const std::string& text,
-                      const Vector& position, Uint32 drawing_effect, int alpha);
+          const Vector& position, uint32_t drawing_effect, uint8_t alpha) const;
 
       Surface* chars;
       Surface* shadow_chars;
@@ -93,12 +95,6 @@ namespace SuperTux
       /// the number of the last character that is represented in the font
       int last_char;
     };
-
-
-  /** Reads a text file (using LispReader, so it as to be in its formatting)
-      and displays it in a StarTrek fashion */
-  void display_text_file(const std::string& file, float scroll_speed, Font* heading_font, Font* normal_font, Font* small_font, Font* reference_font );
-
 } //namespace SuperTux
 
 #endif /*SUPERTUX_FONT_H*/
index 3b593f9..6e6b790 100644 (file)
@@ -62,6 +62,7 @@
 #include "statistics.h"
 #include "timer.h"
 #include "object/fireworks.h"
+#include "textscroller.h"
 
 GameSession* GameSession::current_ = 0;
 
@@ -103,15 +104,6 @@ GameSession::restart_level()
 
   last_keys.clear();
 
-#if 0
-  Vector tux_pos = Vector(-1,-1);
-  if (currentsector)
-    { 
-      // Tux has lost a life, so we try to respawn him at the nearest reset point
-      tux_pos = currentsector->player->base;
-    }
-#endif
-  
   delete level;
   currentsector = 0;
 
@@ -571,11 +563,10 @@ void
 GameSession::action(float elapsed_time)
 {
   // advance timers
-  if (exit_status == ES_NONE && !currentsector->player->growing_timer.check())
-    {
-      // Update Tux and the World
-      currentsector->action(elapsed_time);
-    }
+  if(!currentsector->player->growing_timer.started()) {
+    // Update Tux and the World
+    currentsector->action(elapsed_time);
+  }
 
   // respawning in new sector?
   if(newsector != "" && newspawnpoint != "") {
@@ -594,46 +585,46 @@ GameSession::draw()
   drawstatus(*context);
 
   if(game_pause)
-    {
-      int x = screen->h / 20;
-      for(int i = 0; i < x; ++i)
-        {
-          context->draw_filled_rect(
-              Vector(i % 2 ? (pause_menu_frame * i)%screen->w :
-                -((pause_menu_frame * i)%screen->w)
-                ,(i*20+pause_menu_frame)%screen->h),
-              Vector(screen->w,10),
-              Color(20,20,20, rand() % 20 + 1), LAYER_FOREGROUND1+1);
-        }
-      context->draw_filled_rect(
-          Vector(0,0), Vector(screen->w, screen->h),
-          Color(rand() % 50, rand() % 50, rand() % 50, 128), LAYER_FOREGROUND1);
-      context->draw_text(blue_text, _("PAUSE - Press 'P' To Play"),
-          Vector(screen->w/2, 230), CENTER_ALLIGN, LAYER_FOREGROUND1+2);
-
-      char str1[60];
-      char str2[124];
-      sprintf(str1, _("Playing: "));
-      sprintf(str2, level->name.c_str());
-
-      context->draw_text(blue_text, str1,
-          Vector((screen->w - (blue_text->get_text_width(str1) + white_text->get_text_width(str2)))/2, 340),
-          LEFT_ALLIGN, LAYER_FOREGROUND1+2);
-      context->draw_text(white_text, str2,
-          Vector(((screen->w - (blue_text->get_text_width(str1) + white_text->get_text_width(str2)))/2)+blue_text->get_text_width(str1), 340),
-          LEFT_ALLIGN, LAYER_FOREGROUND1+2);
-    }
+    draw_pause();
 
-  if(Menu::current())
-    {
-      Menu::current()->draw(*context);
-      mouse_cursor->draw(*context);
-    }
+  if(Menu::current()) {
+    Menu::current()->draw(*context);
+    mouse_cursor->draw(*context);
+  }
 
   context->do_drawing();
 }
 
 void
+GameSession::draw_pause()
+{
+  int x = screen->h / 20;
+  for(int i = 0; i < x; ++i) {
+    context->draw_filled_rect(
+        Vector(i % 2 ? (pause_menu_frame * i)%screen->w :
+          -((pause_menu_frame * i)%screen->w)
+          ,(i*20+pause_menu_frame)%screen->h),
+        Vector(screen->w,10),
+        Color(20,20,20, rand() % 20 + 1), LAYER_FOREGROUND1+1);
+  }
+  context->draw_filled_rect(
+      Vector(0,0), Vector(screen->w, screen->h),
+      Color(rand() % 50, rand() % 50, rand() % 50, 128), LAYER_FOREGROUND1);
+  context->draw_text(blue_text, _("PAUSE - Press 'P' To Play"),
+      Vector(screen->w/2, 230), CENTER_ALLIGN, LAYER_FOREGROUND1+2);
+
+  const char* str1 = _("Playing: ");
+  const char* str2 = level->get_name().c_str();
+
+  context->draw_text(blue_text, str1,
+      Vector((screen->w - (blue_text->get_text_width(str1) + white_text->get_text_width(str2)))/2, 340),
+      LEFT_ALLIGN, LAYER_FOREGROUND1+2);
+  context->draw_text(white_text, str2,
+      Vector(((screen->w - (blue_text->get_text_width(str1) + white_text->get_text_width(str2)))/2)+blue_text->get_text_width(str1), 340),
+      LEFT_ALLIGN, LAYER_FOREGROUND1+2);
+}
+  
+void
 GameSession::process_menu()
 {
   Menu* menu = Menu::current();
@@ -781,6 +772,29 @@ GameSession::set_reset_point(const std::string& sector, const Vector& pos)
 }
 
 void
+GameSession::display_info_box(const std::string& text)
+{
+  InfoBox* box = new InfoBox(text);
+
+  bool running = true;
+  while(running)  {
+    SDL_Event event;
+    while (SDL_PollEvent(&event)) {
+      switch(event.type) {
+        case SDL_KEYDOWN:
+          running = false;
+          break;
+      }
+    }
+
+    box->draw(*context);
+    draw();
+  }
+
+  delete box;
+}
+
+void
 GameSession::start_sequence(const std::string& sequencename)
 {
   if(sequencename == "endsequence" || sequencename == "fireworks") {
index 73e26b0..2f13e35 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef SUPERTUX_GAMELOOP_H
 #define SUPERTUX_GAMELOOP_H
 
+#include <SDL.h>
 #include "timer.h"
 #include "statistics.h"
 
@@ -79,6 +80,7 @@ public:
       const std::string& spawnpointname);
   void set_reset_point(const std::string& sectorname,
       const Vector& pos);
+  void display_info_box(const std::string& text);
   Sector* get_current_sector()
   { return currentsector; }
 
@@ -95,12 +97,12 @@ private:
   void levelintro();
   void drawstatus(DrawingContext& context);
   void drawendscreen();
-  void drawresultscreen(void);
+  void drawresultscreen();
+  void draw_pause();
 
   void on_escape_press();
   void process_menu();
 
-
   Uint32 fps_ticks;
   Timer2 endsequence_timer;
   Level* level;
index 3bd3209..4bc3434 100644 (file)
@@ -7,6 +7,7 @@
 #include "special/sprite.h"
 #include "special/sprite_manager.h"
 #include "video/drawing_context.h"
+#include "lisp/lisp.h"
 #include "gameobjs.h"
 #include "specialriser.h"
 #include "growup.h"
@@ -22,13 +23,11 @@ static const float BOUNCY_BRICK_MAX_OFFSET=8;
 static const float BOUNCY_BRICK_SPEED=90;
 static const float EPSILON = .0001;
 
-Block::Block(const Vector& pos, Sprite* newsprite)
+Block::Block(Sprite* newsprite)
   : sprite(newsprite), bouncing(false), bounce_dir(0), bounce_offset(0)
 {
-  bbox.set_pos(pos);
   bbox.set_size(32, 32.1);
   flags |= FLAG_SOLID;
-  original_y = pos.y;
 }
 
 Block::~Block()
@@ -97,10 +96,49 @@ Block::start_bounce()
 
 //---------------------------------------------------------------------------
 
-BonusBlock::BonusBlock(const Vector& pos, int newdata)
-  : Block(pos, sprite_manager->create("bonusblock")), data(newdata)
+BonusBlock::BonusBlock(const Vector& pos, int data)
+  : Block(sprite_manager->create("bonusblock"))
 {
+  bbox.set_pos(pos);
   sprite->set_action("default");
+  switch(data) {
+    case 1: contents = CONTENT_COIN; break;
+    case 2: contents = CONTENT_FIREGROW; break;
+    case 3: contents = CONTENT_STAR; break;
+    case 4: contents = CONTENT_1UP; break;
+    case 5: contents = CONTENT_ICEGROW; break;
+    default:
+      std::cerr << "Invalid box contents!\n";
+      contents = CONTENT_COIN;
+      break;
+  }          
+}
+
+BonusBlock::BonusBlock(const lisp::Lisp& lisp)
+  : Block(sprite_manager->create("bonusblock"))
+{
+  Vector pos;
+  lisp.get("x", pos.x);
+  lisp.get("y", pos.y);
+  bbox.set_pos(pos);
+
+  std::string contentstring;
+  contents = CONTENT_COIN;
+  if(lisp.get("contents", contentstring)) {
+    if(contentstring == "coin") {
+      contents = CONTENT_COIN;
+    } else if(contentstring == "firegrow") {
+      contents = CONTENT_FIREGROW;
+    } else if(contentstring == "icegrow") {
+      contents = CONTENT_ICEGROW;
+    } else if(contentstring == "star") {
+      contents = CONTENT_STAR;
+    } else if(contentstring == "1up") {
+      contents = CONTENT_1UP;
+    } else {
+      std::cerr << "Invalid box contents '" << contentstring << "'.\n";
+    }
+  }
 }
 
 void
@@ -119,13 +157,13 @@ BonusBlock::try_open()
   
   Sector* sector = Sector::current();
   Player& player = *(sector->player);
-  switch(data) {
-    case 1: // coin
+  switch(contents) {
+    case CONTENT_COIN:
       Sector::current()->add_object(new BouncyCoin(get_pos()));
       player.get_status().incCoins();
       break;
 
-    case 2: // grow/fireflower
+    case CONTENT_FIREGROW:
       if(player.size == SMALL) {
         SpecialRiser* riser = new SpecialRiser(
             new GrowUp(get_pos() + Vector(0, -32)));
@@ -138,7 +176,7 @@ BonusBlock::try_open()
       SoundManager::get()->play_sound(IDToSound(SND_UPGRADE));
       break;
 
-    case 5: // grow/iceflower
+    case CONTENT_ICEGROW:
       if(player.size == SMALL) {
         SpecialRiser* riser = new SpecialRiser(
             new GrowUp(get_pos() + Vector(0, -32)));
@@ -151,11 +189,11 @@ BonusBlock::try_open()
       SoundManager::get()->play_sound(IDToSound(SND_UPGRADE));
       break;
 
-    case 3: // star
+    case CONTENT_STAR:
       sector->add_object(new Star(get_pos() + Vector(0, -32)));
       break;
 
-    case 4: // 1up
+    case CONTENT_1UP:
       sector->add_object(new OneUp(get_pos()));
       break;
 
@@ -167,14 +205,15 @@ BonusBlock::try_open()
   sprite->set_action("empty");
 }
 
-//IMPLEMENT_FACTORY(BonusBlock, "bonusblock")
+IMPLEMENT_FACTORY(BonusBlock, "bonusblock")
 
 //---------------------------------------------------------------------------
 
 Brick::Brick(const Vector& pos, int data)
-  : Block(pos, sprite_manager->create("brick")), breakable(false),
+  : Block(sprite_manager->create("brick")), breakable(false),
     coin_counter(0)
 {
+  bbox.set_pos(pos);
   if(data == 1)
     coin_counter = 5;
   else
index d70bc6d..9f54049 100644 (file)
@@ -2,6 +2,7 @@
 #define __BLOCK_H__
 
 #include "special/moving_object.h"
+#include "lisp/lisp.h"
 
 namespace SuperTux {
   class Sprite;
@@ -13,7 +14,7 @@ using namespace SuperTux;
 class Block : public MovingObject
 {
 public:
-  Block(const Vector& pos, Sprite* sprite);
+  Block(Sprite* sprite = 0);
   ~Block();
 
   virtual HitResponse collision(GameObject& other, const CollisionHit& hit);
@@ -35,6 +36,7 @@ class BonusBlock : public Block
 {
 public:
   BonusBlock(const Vector& pos, int data);
+  BonusBlock(const lisp::Lisp& lisp);
 
   void try_open();
 
@@ -42,7 +44,15 @@ protected:
   virtual void hit(Player& player);
 
 private:
-  int data;
+  enum Contents {
+    CONTENT_COIN,
+    CONTENT_FIREGROW,
+    CONTENT_ICEGROW,
+    CONTENT_STAR,
+    CONTENT_1UP
+  };
+
+  Contents contents;
 };
 
 class Brick : public Block
diff --git a/src/object/infoblock.cpp b/src/object/infoblock.cpp
new file mode 100644 (file)
index 0000000..dc6b8c8
--- /dev/null
@@ -0,0 +1,34 @@
+#include <config.h>
+
+#include "infoblock.h"
+#include "gameloop.h"
+#include "resources.h"
+#include "special/sprite_manager.h"
+#include "object_factory.h"
+#include "lisp/lisp.h"
+
+InfoBlock::InfoBlock(const lisp::Lisp& lisp)
+  : Block(sprite_manager->create("bonusblock"))
+{
+  Vector pos;
+  lisp.get("x", pos.x);
+  lisp.get("y", pos.y);
+  bbox.set_pos(pos);
+
+  if(!lisp.get("message", message)) {
+    std::cerr << "No message in InfoBlock!\n";
+  }
+}
+
+InfoBlock::~InfoBlock()
+{
+}
+
+void
+InfoBlock::hit(Player& )
+{
+  GameSession::current()->display_info_box(message);
+  start_bounce();
+}
+
+IMPLEMENT_FACTORY(InfoBlock, "infoblock")
diff --git a/src/object/infoblock.h b/src/object/infoblock.h
new file mode 100644 (file)
index 0000000..3b9a93e
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __INFOBLOCK_H__
+#define __INFOBLOCK_H__
+
+#include "block.h"
+
+class InfoBlock : public Block
+{
+public:
+  InfoBlock(const lisp::Lisp& lisp);
+  virtual ~InfoBlock();
+  
+protected:
+  virtual void hit(Player& player);
+  std::string message;
+};
+
+#endif
+
index f9e2748..f8e8644 100644 (file)
@@ -8,8 +8,9 @@
 #include "object_factory.h"
 
 InvisibleBlock::InvisibleBlock(const Vector& pos)
-  : Block(pos, sprite_manager->create("invisibleblock")), visible(false)
+  : Block(sprite_manager->create("invisibleblock")), visible(false)
 {
+  bbox.set_pos(pos);
   flags &= ~FLAG_SOLID;
 }
 
diff --git a/src/textscroller.cpp b/src/textscroller.cpp
new file mode 100644 (file)
index 0000000..9038ede
--- /dev/null
@@ -0,0 +1,278 @@
+#include <config.h>
+
+#include "textscroller.h"
+
+#include <stdexcept>
+#include "resources.h"
+#include "video/font.h"
+#include "video/drawing_context.h"
+#include "app/globals.h"
+#include "lisp/parser.h"
+#include "lisp/lisp.h"
+
+static const float DEFAULT_SPEED = 1.0;
+static const float MAX_VEL = 10;
+static const float SPEED_INC = 0.01;
+static const float SCROLL = 60;
+static const float ITEMS_SPACE = 4;
+
+static void split_text(const std::string& text, std::vector<std::string>& lines)
+{
+  // Split text string lines into a vector
+  lines.clear();
+  std::string::size_type i, l;
+  i = 0;
+  while(true) {
+    l = text.find("\n", i);
+
+    if(l == std::string::npos) {
+      lines.push_back(text.substr(i, text.size()-i));
+      break;
+    }
+
+    lines.push_back(text.substr(i, l-i));
+    i = l+1;
+  }
+}
+
+void display_text_file(const std::string& file)
+{
+  const Font* heading_font = white_big_text;
+  const Font* normal_font = white_text;
+  const Font* small_font = white_small_text;
+  const Font* reference_font = blue_text;
+  float speed = DEFAULT_SPEED;
+  
+  std::string text;
+  std::string background_file;
+  std::vector<std::string> lines;
+
+  std::string filename = datadir + "/" + file;
+  lisp::Parser parser;
+  try {
+    std::auto_ptr<lisp::Lisp> root (parser.parse(filename));
+
+    const lisp::Lisp* text_lisp = root->get_lisp("supertux-text");
+    if(!text_lisp)
+      throw std::runtime_error("File isn't a supertux-text file");
+    
+    if(!text_lisp->get("text", text))
+      throw std::runtime_error("file doesn't contain a text field");
+    if(!text_lisp->get("background", background_file))
+      throw std::runtime_error("file doesn't contain a background file");
+    text_lisp->get("speed", speed);
+  } catch(std::exception& e) {
+    std::cerr << "Couldn't load file '" << filename << "': " << e.what() <<
+      "\n";
+    return;
+  }
+
+  // Split text string lines into a vector
+  split_text(text, lines);
+
+  // load background image
+  Surface* background = new Surface(
+      get_resource_filename("images/background/" + background_file), false);
+
+  int done = 0;
+  float scroll = 0;
+  speed /= 50.0;
+  float left_border = 50;
+
+  DrawingContext context;
+  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+
+  Uint32 lastticks = SDL_GetTicks();
+  while(!done)
+    {
+      /* in case of input, exit */
+      SDL_Event event;
+      while(SDL_PollEvent(&event))
+        switch(event.type)
+          {
+          case SDL_KEYDOWN:
+            switch(event.key.keysym.sym)
+              {
+              case SDLK_UP:
+                speed -= SPEED_INC;
+                break;
+              case SDLK_DOWN:
+                speed += SPEED_INC;
+                break;
+              case SDLK_SPACE:
+              case SDLK_RETURN:
+                if(speed >= 0)
+                  scroll += SCROLL;
+                break;
+              case SDLK_ESCAPE:
+                done = 1;
+                break;
+              default:
+                break;
+              }
+            break;
+          case SDL_QUIT:
+            done = 1;
+            break;
+          default:
+            break;
+          }
+
+      if(speed > MAX_VEL)
+        speed = MAX_VEL;
+      else if(speed < -MAX_VEL)
+        speed = -MAX_VEL;
+
+      /* draw the credits */
+      context.draw_surface(background, Vector(0,0), 0);
+
+      float y = 0;
+      for(size_t i = 0; i < lines.size(); i++) {
+        const std::string& line = lines[i];
+        if(line.size() == 0) {
+          y += normal_font->get_height() + ITEMS_SPACE;
+          continue;
+        }
+
+        const Font* font = 0;
+        bool center = true;
+        switch(line[0])
+        {
+          case ' ': font = small_font; break;
+          case '\t': font = normal_font; break;
+          case '-': font = heading_font; break;
+          case '*': font = reference_font; break;
+          case '#': font = normal_font; center = false; break;
+          default:
+            std::cerr << "Warning: text contains an unformated line.\n";
+            font = normal_font;
+            center = false;
+            break;
+        }
+        
+        if(center) {
+          context.draw_text(font,
+              line.substr(1, line.size()-1),
+              Vector(screen->w/2, screen->h + y - scroll),
+              CENTER_ALLIGN, LAYER_FOREGROUND1);
+        } else {
+          context.draw_text(font,
+              line.substr(1, line.size()-1),
+              Vector(left_border, screen->h + y - scroll),
+              LEFT_ALLIGN, LAYER_FOREGROUND1);
+        }
+          
+        y += font->get_height() + ITEMS_SPACE;
+      }
+
+      context.do_drawing();
+
+      if(screen->h+y-scroll < 0 && 20+screen->h+y-scroll < 0)
+        done = 1;
+
+      Uint32 ticks = SDL_GetTicks();
+      scroll += speed * (ticks - lastticks);
+      lastticks = ticks;
+      if(scroll < 0)
+        scroll = 0;
+
+      SDL_Delay(10);
+    }
+
+  SDL_EnableKeyRepeat(0, 0);    // disables key repeating
+  delete background;
+}
+
+InfoBox::InfoBox(const std::string& text)
+  : firstline(0)
+{
+  split_text(text, lines);
+}
+
+InfoBox::~InfoBox()
+{
+}
+
+void
+InfoBox::draw(DrawingContext& context)
+{
+  const Font* heading_font = white_big_text;
+  const Font* normal_font = white_text;
+  const Font* small_font = white_small_text;
+  const Font* reference_font = blue_text;
+  
+  float x1 = 200;
+  float y1 = 100;
+  float width = 400;
+  float height = 200;
+  
+  context.draw_filled_rect(Vector(x1, y1), Vector(width, height),
+      Color(150, 180, 200, 125), LAYER_GUI-1);
+
+  float y = y1;
+  for(size_t i = firstline; i < lines.size(); ++i) {
+    const std::string& line = lines[i];
+    if(y >= y1 + height)
+      break;
+
+    if(line.size() == 0) {
+      y += normal_font->get_height() + ITEMS_SPACE;    
+      continue;                                        
+    }
+
+    const Font* font = 0;
+    bool center = true;
+    switch(line[0])
+    {
+      case ' ': font = small_font; break;
+      case '\t': font = normal_font; break;
+      case '-': font = heading_font; break;
+      case '*': font = reference_font; break;
+      case '#': font = normal_font; center = false; break;
+      default:
+        std::cerr << "Warning: text contains an unformated line.\n";
+        font = normal_font;
+        center = false;
+        break;
+    }
+    
+    if(center) {
+      context.draw_text(font,
+          line.substr(1, line.size()-1),
+          Vector(screen->w/2, y),
+          CENTER_ALLIGN, LAYER_GUI);
+    } else {
+      context.draw_text(font,
+          line.substr(1, line.size()-1),
+          Vector(x1, y),
+          LEFT_ALLIGN, LAYER_GUI);
+    }
+      
+    y += font->get_height() + ITEMS_SPACE;
+  }
+}
+
+void
+InfoBox::scrollup()
+{
+  if(firstline > 0)
+    firstline--;
+}
+
+void
+InfoBox::scrolldown()
+{
+  if(firstline < lines.size()-1)
+    firstline++;
+}
+
+void
+InfoBox::pageup()
+{
+}
+
+void
+InfoBox::pagedown()
+{
+}
+
diff --git a/src/textscroller.h b/src/textscroller.h
new file mode 100644 (file)
index 0000000..806b016
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef __TEXTSCROLLER_H__
+#define __TEXTSCROLLER_H__
+
+#include <vector>
+#include <string>
+
+namespace SuperTux {
+class DrawingContext;
+}
+
+using namespace SuperTux;
+
+/** This class is displaying a box with information text inside the game
+ */
+class InfoBox
+{
+public:
+  InfoBox(const std::string& text);
+  ~InfoBox();
+
+  void draw(DrawingContext& context);
+  void scrolldown();
+  void scrollup();
+  void pagedown();
+  void pageup();
+  
+private:
+  size_t firstline;
+  std::vector<std::string> lines;
+};
+
+/** Reads a text file (using LispReader, so it as to be in its formatting)
+ * and scroll it over the screen
+ * (this call blocks until all text scrolled through or the user aborted the
+ *  textscrolling)
+ */
+void display_text_file(const std::string& file);
+
+#endif
+
index df500cf..791cbfb 100644 (file)
@@ -60,6 +60,7 @@
 #include "resources.h"
 #include "app/gettext.h"
 #include "misc.h"
+#include "textscroller.h"
 
 static Surface* bkg_title;
 static Surface* logo;
@@ -387,7 +388,7 @@ void title(void)
                   fadeout(500);
                   credits_music = SoundManager::get()->load_music(datadir + "/music/credits.ogg");
                   SoundManager::get()->play_music(credits_music);
-                  display_text_file("credits.txt", SCROLL_SPEED_CREDITS, white_big_text , white_text, white_small_text, blue_text );
+                  display_text_file("credits.txt");
                   fadeout(500);
                   Menu::set_current(main_menu);
                   break;
index eb1b32f..0f24f19 100644 (file)
@@ -31,14 +31,7 @@ enum MainMenuIDs {
   MNID_QUITMAINMENU
   };
   
-/* Scrolling text speed */
-
-#define SCROLL_SPEED_CREDITS 1.5
-#define SCROLL_SPEED_MESSAGE 1.0
-
-void title(void);
+void title();
 
 #endif //SUPERTUX_TITLE_H
 
-// EOF //
-
index 80a21d7..59da5f2 100644 (file)
@@ -44,6 +44,7 @@
 #include "resources.h"
 #include "misc.h"
 #include "player_status.h"
+#include "textscroller.h"
 
 #define map_message_TIME 2.8
 
@@ -835,8 +836,7 @@ WorldMap::update(float delta)
         if (!level->extro_filename.empty()) {
           // Display a text file
           std::string filename = levels_path + level->extro_filename;
-          display_text_file(filename, SCROLL_SPEED_MESSAGE,
-                            white_big_text , white_text, white_small_text, blue_text );
+          display_text_file(filename);
         }
 
         if (!level->next_worldmap.empty())
@@ -1040,8 +1040,7 @@ WorldMap::display()
 
   if(!intro_displayed && intro_filename != "") {
     std::string filename = levels_path + intro_filename;
-    display_text_file(filename, SCROLL_SPEED_MESSAGE,
-                      white_big_text, white_text, white_small_text, blue_text);
+    display_text_file(filename);
     intro_displayed = true;
   }