; Credits text
(supertux-text
(background "oiltux.jpg")
+ (speed 1.5)
(text (_ "-- SuperTux -
Milestone 1
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"))
+ )
)
)
void
DrawingContext::draw_surface(const Surface* surface, const Vector& position,
- int layer, Uint32 drawing_effect)
+ int layer, uint32_t drawing_effect)
{
assert(surface != 0);
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);
}
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;
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
{
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;
}
#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 {
~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.
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)
{
public:
Vector translation;
- Uint32 drawing_effect;
+ uint32_t drawing_effect;
float zoom;
int alpha;
struct TextRequest
{
- Font* font;
+ const Font* font;
std::string text;
- int allignment;
+ FontAlignment alignment;
};
struct GradientRequest
Vector pos;
int layer;
- Uint32 drawing_effect;
+ uint32_t drawing_effect;
float zoom;
int alpha;
}
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];
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);
}
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),
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;
}
}
-/* --- 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;
-}
-
#define SUPERTUX_FONT_H
#include <string>
+#include <stdint.h>
#include "video/surface.h"
#include "math/vector.h"
namespace SuperTux
{
- enum {
+ enum FontAlignment {
LEFT_ALLIGN,
CENTER_ALLIGN,
RIGHT_ALLIGN
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
/** 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;
/// 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*/
#include "statistics.h"
#include "timer.h"
#include "object/fireworks.h"
+#include "textscroller.h"
GameSession* GameSession::current_ = 0;
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;
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 != "") {
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();
}
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") {
#ifndef SUPERTUX_GAMELOOP_H
#define SUPERTUX_GAMELOOP_H
+#include <SDL.h>
#include "timer.h"
#include "statistics.h"
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; }
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;
#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"
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()
//---------------------------------------------------------------------------
-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
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)));
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)));
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;
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
#define __BLOCK_H__
#include "special/moving_object.h"
+#include "lisp/lisp.h"
namespace SuperTux {
class Sprite;
class Block : public MovingObject
{
public:
- Block(const Vector& pos, Sprite* sprite);
+ Block(Sprite* sprite = 0);
~Block();
virtual HitResponse collision(GameObject& other, const CollisionHit& hit);
{
public:
BonusBlock(const Vector& pos, int data);
+ BonusBlock(const lisp::Lisp& lisp);
void try_open();
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
--- /dev/null
+#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")
--- /dev/null
+#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
+
#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;
}
--- /dev/null
+#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()
+{
+}
+
--- /dev/null
+#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
+
#include "resources.h"
#include "app/gettext.h"
#include "misc.h"
+#include "textscroller.h"
static Surface* bkg_title;
static Surface* logo;
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;
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 //
-
#include "resources.h"
#include "misc.h"
#include "player_status.h"
+#include "textscroller.h"
#define map_message_TIME 2.8
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())
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;
}