From: Matthias Braun Date: Wed, 30 Mar 2005 12:01:02 +0000 (+0000) Subject: -Some cleanups in text scrolling code X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=073795dd0afc7d7e4c093db5f83fc26c10501d61;p=supertux.git -Some cleanups in text scrolling code -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 --- diff --git a/data/credits.txt b/data/credits.txt index a6c9b1abd..5c209d992 100644 --- a/data/credits.txt +++ b/data/credits.txt @@ -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 index 000000000..157ee76eb 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 index 000000000..e8747a14e 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 index 000000000..a13531112 Binary files /dev/null and b/data/images/shared/bell/bell-r.png differ diff --git a/data/levels/test/bonusblock.stl b/data/levels/test/bonusblock.stl index 7db74262c..1ee605378 100644 --- a/data/levels/test/bonusblock.stl +++ b/data/levels/test/bonusblock.stl @@ -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) @@ -135,6 +135,15 @@ (path )) + (infoblock + (x 128) + (y 800) + (message (_ +"-Info +#This is an info block +#(WOW GREAT) +#This rocks")) + ) ) ) diff --git a/lib/video/drawing_context.cpp b/lib/video/drawing_context.cpp index bba6d36c2..6257b9fbc 100644 --- a/lib/video/drawing_context.cpp +++ b/lib/video/drawing_context.cpp @@ -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; } diff --git a/lib/video/drawing_context.h b/lib/video/drawing_context.h index 7ef8de954..3da8dcce5 100644 --- a/lib/video/drawing_context.h +++ b/lib/video/drawing_context.h @@ -21,18 +21,19 @@ #include #include +#include #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; diff --git a/lib/video/font.cpp b/lib/video/font.cpp index 12d96c741..e01cedc4b 100644 --- a/lib/video/font.cpp +++ b/lib/video/font.cpp @@ -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 names; - - std::string filename = datadir + "/" + file; - lisp::Parser parser; - try { - std::auto_ptr 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; -} - diff --git a/lib/video/font.h b/lib/video/font.h index 429cf97e1..58e1e761c 100644 --- a/lib/video/font.h +++ b/lib/video/font.h @@ -22,6 +22,7 @@ #define SUPERTUX_FONT_H #include +#include #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*/ diff --git a/src/gameloop.cpp b/src/gameloop.cpp index 3b593f955..6e6b79037 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -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") { diff --git a/src/gameloop.h b/src/gameloop.h index 73e26b0c5..2f13e3508 100644 --- a/src/gameloop.h +++ b/src/gameloop.h @@ -22,6 +22,7 @@ #ifndef SUPERTUX_GAMELOOP_H #define SUPERTUX_GAMELOOP_H +#include #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; diff --git a/src/object/block.cpp b/src/object/block.cpp index 3bd32096d..4bc343407 100644 --- a/src/object/block.cpp +++ b/src/object/block.cpp @@ -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 diff --git a/src/object/block.h b/src/object/block.h index d70bc6d3c..9f5404982 100644 --- a/src/object/block.h +++ b/src/object/block.h @@ -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 index 000000000..dc6b8c858 --- /dev/null +++ b/src/object/infoblock.cpp @@ -0,0 +1,34 @@ +#include + +#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 index 000000000..3b9a93eba --- /dev/null +++ b/src/object/infoblock.h @@ -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 + diff --git a/src/object/invisible_block.cpp b/src/object/invisible_block.cpp index f9e274869..f8e864416 100644 --- a/src/object/invisible_block.cpp +++ b/src/object/invisible_block.cpp @@ -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 index 000000000..9038ede31 --- /dev/null +++ b/src/textscroller.cpp @@ -0,0 +1,278 @@ +#include + +#include "textscroller.h" + +#include +#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& 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 lines; + + std::string filename = datadir + "/" + file; + lisp::Parser parser; + try { + std::auto_ptr 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 index 000000000..806b0163d --- /dev/null +++ b/src/textscroller.h @@ -0,0 +1,40 @@ +#ifndef __TEXTSCROLLER_H__ +#define __TEXTSCROLLER_H__ + +#include +#include + +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 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 + diff --git a/src/title.cpp b/src/title.cpp index df500cfab..791cbfbd7 100644 --- a/src/title.cpp +++ b/src/title.cpp @@ -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; diff --git a/src/title.h b/src/title.h index eb1b32f0e..0f24f1951 100644 --- a/src/title.h +++ b/src/title.h @@ -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 // - diff --git a/src/worldmap.cpp b/src/worldmap.cpp index 80a21d773..59da5f234 100644 --- a/src/worldmap.cpp +++ b/src/worldmap.cpp @@ -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; }