(bkgd_red_bottom 255)
(bkgd_green_bottom 255)
(bkgd_blue_bottom 255)
- (time 60)
(gravity 10.0)
(particle_system "snow")
(theme "antarctica")
(reset-points
)
(objects
+ (leveltime
+ (time 60)
+ )
(spiky (x 2171) (y 348))
(spiky (x 2035) (y 312))
(spiky (x 1947) (y 323))
(properties
(name (_ "Bonus Island I"))
(music "salcon.mod")
- (start_pos_x 35)
- (start_pos_y 2)
+ )
+ (spawnpoint
+ (name "main")
+ (x 35)
+ (y 2)
)
(tilemap
(width 70)
(version 2)
(name (_ "Menu Level"))
(author "SuperTux Team")
- (time 500)
(sector
(name "main")
(music "theme.ogg")
-# German translations for world package
+# German translations for world package
# German messages for world.
# Copyright (C) 2004 THE world'S COPYRIGHT HOLDER
# This file is distributed under the same license as the world package.
"Last-Translator: <matze@braunis.de>\n"
"Language-Team: German <de@li.org>\n"
"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"\n"
"#Tux und Penny sassen gemtlich beim Picknick\n"
"#in den eisigen Ebenen der Antarktis.\n"
-"#Pl�zlich sprang eine dunkle Kreatur hinter\n"
+"#Plötzlich sprang eine dunkle Kreatur hinter\n"
"#einem Felsen hervor. Tux sah einen grellen\n"
-"#Blitz, dann wurde er ohnm�htig.\n"
+"#Blitz, dann wurde er ohnmächtig.\n"
"\n"
"#Als er aufwachte bemerkte er, dass Penny\n"
"#verschwunden war. Wo sie eben noch gesessen\n"
#: basest/levels/world1/level13.stl:5
msgid "Above the Arctic Skies"
-msgstr "�er den Wolken"
+msgstr "Über den Wolken"
#: basest/levels/world1/level14.stl:5
msgid "Entrance to the Cave"
-msgstr "H�leneingang"
+msgstr "Höhleneingang"
#: basest/levels/world1/level15.stl:5
msgid "Under the Ice"
#: basest/levels/world1/level16.stl:5
msgid "Living in a Fridge"
-msgstr "Leben im Khlschrank"
+msgstr "Leben im Kühlschrank"
#: basest/levels/world1/level17.stl:5
msgid "'...or is it just me?'"
#: basest/levels/world1/level24.stl:5
msgid "The Shattered Bridge"
-msgstr "Brckentrmmer"
+msgstr "Die zertrümmerte Brücke"
#: basest/levels/world1/level25.stl:5
msgid "Arctic Ruins"
#: basest/levels/world1/level3.stl:5
msgid "Via Nostalgica"
-msgstr "Nostalgiestra�"
+msgstr "Nostalgiestraße"
#: basest/levels/world1/level4.stl:5
msgid "Tobgle Road"
#: basest/levels/world1/level7.stl:5
msgid "Oh no! More Snowballs!"
-msgstr "Oh Nein! Noch mehr Schneeb�le!"
+msgstr "Oh Nein! Noch mehr Schneebälle!"
#: basest/levels/world1/level8.stl:5
msgid "Stone Cold"
#: basest/levels/world1/level9.stl:5
msgid "Grumbel's Sense of Snow"
-msgstr "Grumbels Schneegespr"
+msgstr "Grumbels Gespür für Schnee"
#: basest/levels/world1/extro.txt:7
msgid ""
"#dennoch vergeblich. Mit jeder meiner\n"
"#Festungen die du eroberst, werde ich zu\n"
"#einer weiteren fliehen. Sei nicht dumm,\n"
-"#es w�e das beste jetzt aufzugeben.\n"
+"#es wäre das beste jetzt aufzugeben.\n"
"\n"
"#Tux verliess traurig den Saal, als etwas\n"
"#unter seinem Fuss raschelte...\n"
"#Ein Briefumschlag mit seinem Namen!\n"
"#In dem Umschlag war eine grobe Karte,\n"
-"#die Festungen in verschiedenen L�dern\n"
+"#die Festungen in verschiedenen Ländern\n"
"#zeigte. Auf der Rckseite der Karte war\n"
"#Pennys Zeichen, das Bild einer Eisblume.\n"
"\n"
"#Tux nahm die Karte in die Hand und rannte\n"
-"#aus der Festung. Nein, er wrde nicht\n"
+"#aus der Festung. Nein, er würde nicht\n"
"#einfach aufgeben. Penny verliess sich auf\n"
"#ihn.\n"
(name (_ "Icyisland"))
(intro-filename "intro.txt")
(music "salcon.mod")
- (start_pos_x 4)
- (start_pos_y 5))
+ )
+ (spawnpoint
+ (name "main")
+ (x 4)
+ (y 5)
+ )
(tilemap
(width 40)
(height 30)
+ (solid #t)
(tiles
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 11 12 9 9 9 9 9 9 9 9 9 9 9 9
return ABORT_MOVE;
}
// hit from above?
- if(player.get_movement().y > 0 && player.get_bbox().p2.y <
+ if(player.get_movement().y - get_movement().y > 0 && player.get_bbox().p2.y <
(get_bbox().p1.y + get_bbox().p2.y) / 2) {
// if it's not is it possible to squish us, then this will hurt
if(!collision_squished(player))
if(i != min_joybuttons-1)
joy_button_map.insert(std::make_pair(i, MENU_SELECT));
}
+
+ // some joysticks or SDL seem to produce some bogus events after being opened
+ Uint32 ticks = SDL_GetTicks();
+ while(SDL_GetTicks() - ticks < 200) {
+ SDL_Event event;
+ SDL_PollEvent(&event);
+ }
}
JoystickKeyboardController::~JoystickKeyboardController()
}
void
+JoystickKeyboardController::reset()
+{
+ Controller::reset();
+ for(size_t i = 0; i < sizeof(last_keys); ++i)
+ last_keys[i] = 0;
+}
+
+void
JoystickKeyboardController::process_event(const SDL_Event& event)
{
switch(event.type) {
void write(lisp::Writer& writer);
void read(const lisp::Lisp& lisp);
bool check_cheatcode(const std::string& cheatcode);
+ void reset();
Menu* get_key_options_menu();
Menu* get_joystick_options_menu();
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
-
#include <config.h>
#include "flip_level_transformer.h"
#include "badguy/badguy.h"
#include "sector.h"
#include "tile_manager.h"
+#include "spawn_point.h"
void
FlipLevelTransformer::transform_sector(Sector* sector)
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
-
#ifndef __FLIP_LEVEL_TRANSFORMER_H__
#define __FLIP_LEVEL_TRANSFORMER_H__
global_stats.reset();
global_stats.set_total_points(COINS_COLLECTED_STAT, level->get_total_coins());
global_stats.set_total_points(BADGUYS_KILLED_STAT, level->get_total_badguys());
- global_stats.set_total_points(TIME_NEEDED_STAT, level->timelimit);
+ //global_stats.set_total_points(TIME_NEEDED_STAT, level->timelimit);
if(reset_sector != "") {
currentsector = level->get_sector(reset_sector);
if(mode == ST_GL_PLAY || mode == ST_GL_LOAD_LEVEL_FILE)
levelintro();
- start_timers();
currentsector->play_music(LEVEL_MUSIC);
if(capture_file != "")
wait_for_event(1.0, 3.0);
}
-/* Reset Timers */
-void
-GameSession::start_timers()
-{
- time_left.start(level->timelimit);
-}
-
void
GameSession::on_escape_press()
{
void
GameSession::try_cheats()
{
+ if(currentsector == 0)
+ return;
Player& tux = *currentsector->player;
// Cheating words (the goal of this is really for debugging,
if(Menu::current()) {
Menu::current()->draw(*context);
- mouse_cursor->draw(*context);
}
context->do_drawing();
//frame_rate.update();
- /* Handle time: */
- if (time_left.check() && !end_sequence)
- currentsector->player->kill(Player::KILL);
-
/* Handle music: */
if (currentsector->player->invincible_timer.started() && !end_sequence)
{
}
// just in case
+ currentsector = 0;
main_controller->reset();
return exit_status;
}
void
-GameSession::finish()
+GameSession::finish(bool win)
{
- exit_status = ES_LEVEL_FINISHED;
+ if(win)
+ exit_status = ES_LEVEL_FINISHED;
+ else
+ exit_status = ES_LEVEL_ABORT;
}
void
sound_manager->play_music(level_end_song, 0);
currentsector->player->invincible_timer.start(7.0);
- // add left time to stats
- global_stats.set_points(TIME_NEEDED_STAT,
- int(time_left.get_period() - time_left.get_timeleft()));
-
if(sequencename == "fireworks") {
currentsector->add_object(new Fireworks());
}
void
GameSession::drawstatus(DrawingContext& context)
{
- char str[60];
-
- snprintf(str, 60, " %d", global_stats.get_points(SCORE_STAT));
- context.draw_text(white_text, _("SCORE"), Vector(0, 0), LEFT_ALLIGN, LAYER_FOREGROUND1);
- context.draw_text(gold_text, str, Vector(96, 0), LEFT_ALLIGN, LAYER_FOREGROUND1);
-
- if(mode == ST_GL_TEST) {
- context.draw_text(white_text, _("Press ESC To Return"), Vector(0,20),
- LEFT_ALLIGN, LAYER_FOREGROUND1);
- }
-
- if(time_left.get_timeleft() < 0) {
- context.draw_text(white_text, _("TIME's UP"), Vector(SCREEN_WIDTH/2, 0),
- CENTER_ALLIGN, LAYER_FOREGROUND1);
- } else if (time_left.get_timeleft() > TIME_WARNING
- || int(global_time * 2.5) % 2) {
- sprintf(str, " %d", int(time_left.get_timeleft()));
- context.draw_text(white_text, _("TIME"),
- Vector(SCREEN_WIDTH/2, 0), CENTER_ALLIGN, LAYER_FOREGROUND1);
- context.draw_text(gold_text, str,
- Vector(SCREEN_WIDTH/2 + 4*16, 0), CENTER_ALLIGN, LAYER_FOREGROUND1);
- }
-
- sprintf(str, " %d", player_status.coins);
- context.draw_text(white_text, _("COINS"),
- Vector(SCREEN_WIDTH - white_text->get_text_width(_("COINS"))-white_text->get_text_width(" 99"), 0),
- LEFT_ALLIGN, LAYER_FOREGROUND1);
- context.draw_text(gold_text, str,
- Vector(SCREEN_WIDTH - gold_text->get_text_width(" 99"), 0),LEFT_ALLIGN, LAYER_FOREGROUND1);
-
- if (player_status.lives >= 5)
- {
- sprintf(str, "%dx", player_status.lives);
- float x = SCREEN_WIDTH - gold_text->get_text_width(str) - tux_life->w;
- context.draw_text(gold_text, str, Vector(x, 20), LEFT_ALLIGN, LAYER_FOREGROUND1);
- context.draw_surface(tux_life, Vector(SCREEN_WIDTH - 16, 20),
- LAYER_FOREGROUND1);
- }
- else
- {
- for(int i= 0; i < player_status.lives; ++i)
- context.draw_surface(tux_life,
- Vector(SCREEN_WIDTH - tux_life->w*4 +(tux_life->w*i), 20),
- LAYER_FOREGROUND1);
- }
-
- context.draw_text(white_text, _("LIVES"),
- Vector(SCREEN_WIDTH - white_text->get_text_width(_("LIVES")) - white_text->get_text_width(" 99"), 20),
- LEFT_ALLIGN, LAYER_FOREGROUND1);
+ player_status.draw(context);
if(config->show_fps) {
- sprintf(str, "%2.1f", fps_fps);
+ char str[60];
+ snprintf(str, sizeof(str), "%2.1f", fps_fps);
context.draw_text(white_text, "FPS",
Vector(SCREEN_WIDTH -
white_text->get_text_width("FPS "), 40),
public:
DrawingContext* context;
- Timer time_left;
GameSession(const std::string& levelfile, GameSessionMode mode,
Statistics* statistics=0);
{ current_ = this; }
static GameSession* current() { return current_; }
- /// ends the level as finished
- void finish();
+ /// ends the current level
+ void finish(bool win = true);
void respawn(const std::string& sectorname,
const std::string& spawnpointname);
void set_reset_point(const std::string& sectorname,
void restart_level();
void check_end_conditions();
- void start_timers();
void process_events();
void capture_demo_step();
static inline const char* _(const char* message)
{
- return dictionary_manager.get_dictionary().translate(message).c_str();
+ return dictionary_manager.get_dictionary().translate(message);
+}
+
+static inline std::string _(const std::string& message)
+{
+ return dictionary_manager.get_dictionary().translate(message);
}
static inline const char* N_(const char* id, const char* id2, int num)
while(true)
{
SDL_Event event;
-
- if(event.type == SDL_QUIT)
- throw std::runtime_error("received window close event");
-
while (SDL_PollEvent(&event)) {
+ if(event.type == SDL_QUIT)
+ throw std::runtime_error("received window close event");
+ main_controller->process_event(event);
dialog->event(event);
}
void
Menu::draw(DrawingContext& context)
{
+ if(MouseCursor::current()) {
+ MouseCursor::current()->draw(context);
+ }
+
int menu_height = get_height();
int menu_width = get_width();
cur_state = state_before_click;
}
- context.draw_surface_part(cursor, Vector(w, h*cur_state),
+ context.draw_surface_part(cursor, Vector(0, h*cur_state),
Vector(w, h), Vector(x-mid_x, y-mid_y), LAYER_GUI+100);
}
using namespace std;
Level::Level()
- : name("noname"), author("Mr. X"), timelimit(500)
+ : name("noname"), author("Mr. X")
{
}
iter.value()->get(name);
} else if(token == "author") {
iter.value()->get(author);
- } else if(token == "time") {
- iter.value()->get(timelimit);
} else if(token == "sector") {
Sector* sector = new Sector;
sector->parse(*(iter.lisp()));
{
reader.get("name", name);
reader.get("author", author);
- reader.get("time", timelimit);
Sector* sector = new Sector;
sector->parse_old_format(reader);
writer->write_string("name", name, true);
writer->write_string("author", author);
- writer->write_int("time", timelimit);
for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) {
Sector* sector = *i;
public:
std::string name;
std::string author;
- int timelimit;
typedef std::vector<Sector*> Sectors;
Sectors sectors;
{
if(translate) {
dictionary_manager = new TinyGetText::DictionaryManager();
+ dictionary_manager->set_charset("ISO8859-1");
}
}
static void init_tinygettext()
{
dictionary_manager.add_directory(datadir + "/locale");
- dictionary_manager.set_charset("iso8859-1");
+ dictionary_manager.set_charset("ISO8859-1");
}
static void print_usage(const char* argv0)
--- /dev/null
+#include <config.h>
+
+#include "level_time.h"
+
+#include <stdexcept>
+#include "main.h"
+#include "resources.h"
+#include "sector.h"
+#include "gettext.h"
+#include "object_factory.h"
+#include "object/player.h"
+#include "video/drawing_context.h"
+#include "lisp/list_iterator.h"
+
+/** When to alert player they're low on time! */
+static const float TIME_WARNING = 20;
+
+LevelTime::LevelTime(const lisp::Lisp& reader)
+{
+ float time = -1;
+ lisp::ListIterator iter(&reader);
+ while(iter.next()) {
+ if(iter.item() == "time") {
+ iter.value()->get(time);
+ break;
+ } else {
+ std::cerr << "Unknown token '" << iter.item()
+ << "' in LevelTime object.\n";
+ }
+ }
+ if(time < 0)
+ throw std::runtime_error("Invalid leveltime specified");
+ time_left.start(time);
+}
+
+LevelTime::~LevelTime()
+{}
+
+void
+LevelTime::update(float )
+{
+ if(time_left.check()) {
+ Sector::current()->player->kill(Player::KILL);
+ }
+}
+
+void
+LevelTime::draw(DrawingContext& context)
+{
+ context.push_transform();
+ context.set_translation(Vector(0, 0));
+
+ char str[60];
+
+ if(time_left.get_timeleft() < 0) {
+ context.draw_text(white_text, _("TIME's UP"), Vector(SCREEN_WIDTH/2, 0),
+ CENTER_ALLIGN, LAYER_FOREGROUND1);
+ } else if (time_left.get_timeleft() > TIME_WARNING
+ || int(global_time * 2.5) % 2) {
+ snprintf(str, sizeof(str), " %d", int(time_left.get_timeleft()));
+ context.draw_text(white_text, _("TIME"),
+ Vector(SCREEN_WIDTH/2, 0), CENTER_ALLIGN, LAYER_FOREGROUND1);
+ context.draw_text(gold_text, str, Vector(SCREEN_WIDTH/2 + 4*16, 0),
+ CENTER_ALLIGN, LAYER_FOREGROUND1);
+ }
+
+ context.pop_transform();
+}
+
+IMPLEMENT_FACTORY(LevelTime, "leveltime");
--- /dev/null
+#ifndef __LEVELTIME_H__
+#define __LEVELTIME_H__
+
+#include "game_object.h"
+#include "timer.h"
+#include "lisp/lisp.h"
+
+class LevelTime : public GameObject
+{
+public:
+ LevelTime(const lisp::Lisp& reader);
+ virtual ~LevelTime();
+
+ void update(float elapsed_time);
+ void draw(DrawingContext& context);
+
+private:
+ Timer time_left;
+};
+
+#endif
+
static const float TUX_INVINCIBLE_TIME = 10.0;
static const float TUX_INVINCIBLE_TIME_WARNING = 2.0;
static const float TUX_FLAPPING_TIME = 1; /* How long Tux can flap his wings to gain additional jump height */
-static const float TIME_WARNING = 20; /* When to alert player they're low on time! */
static const float GROWING_TIME = 1.0;
static const int GROWING_FRAMES = 7;
flags |= FLAG_SOLID;
}
-TileMap::TileMap(const lisp::Lisp& reader)
- : solid(false), speed(1), width(0), height(0), layer(LAYER_TILES),
+TileMap::TileMap(const lisp::Lisp& reader, TileManager* new_tile_manager)
+ : solid(false), speed(1), width(-1), height(-1), layer(LAYER_TILES),
drawing_effect(0)
{
- tilemanager = tile_manager;
+ tilemanager = new_tile_manager;
+ if(tilemanager == 0)
+ tilemanager = tile_manager;
std::string layer_str;
if(reader.get("layer", layer_str)) {
}
if(solid)
flags |= FLAG_SOLID;
-
- if(!reader.get("width", width) ||
- !reader.get("height", height))
- throw std::runtime_error("No width or height specified in tilemap.");
+
+ reader.get("width", width);
+ reader.get("height", height);
+ if(width < 0 || height < 0)
+ throw std::runtime_error("Invalid/No width/height specified in tilemap.");
if(!reader.get_vector("tiles", tiles))
throw std::runtime_error("No tiles in tilemap.");
/** if we don't round here, we'll have a 1 pixel gap on screen sometimes.
* I have no idea why */
float start_x = roundf(context.get_translation().x);
- if(start_x < 0) start_x = 0;
+ if(start_x < 0)
+ start_x = 0;
float start_y = roundf(context.get_translation().y);
- if(start_y < 0) start_y = 0;
+ if(start_y < 0)
+ start_y = 0;
float end_x = std::min(start_x + SCREEN_WIDTH, float(width * 32));
float end_y = std::min(start_y + SCREEN_HEIGHT, float(height * 32));
start_x -= int(start_x) % 32;
{
public:
TileMap();
- TileMap(const lisp::Lisp& reader);
+ TileMap(const lisp::Lisp& reader, TileManager* tile_manager = 0);
TileMap(int layer_, bool solid_, size_t width_, size_t height_);
virtual ~TileMap();
#include "lisp/lisp.h"
#include "player_status.h"
#include "resources.h"
+#include "gettext.h"
+#include "video/drawing_context.h"
+#include "main.h"
static const int START_LIVES = 4;
static const int MAX_LIVES = 99;
lisp.get("max-score-multiplier", max_score_multiplier);
}
+void
+PlayerStatus::draw(DrawingContext& context)
+{
+ context.push_transform();
+ context.set_translation(Vector(0, 0));
+
+ char str[60];
+
+ sprintf(str, " %d", player_status.coins);
+ const char* coinstext = _("COINS");
+ context.draw_text(white_text, coinstext,
+ Vector(SCREEN_WIDTH - white_text->get_text_width(coinstext)
+ - white_text->get_text_width(" 99"), 0),
+ LEFT_ALLIGN, LAYER_FOREGROUND1);
+ context.draw_text(gold_text, str,
+ Vector(SCREEN_WIDTH - gold_text->get_text_width(" 99"), 0),
+ LEFT_ALLIGN, LAYER_FOREGROUND1);
+
+ if (player_status.lives >= 5) {
+ sprintf(str, "%dx", player_status.lives);
+ float x = SCREEN_WIDTH - gold_text->get_text_width(str) - tux_life->w;
+ context.draw_text(gold_text, str, Vector(x, 20), LEFT_ALLIGN,
+ LAYER_FOREGROUND1);
+ context.draw_surface(tux_life, Vector(SCREEN_WIDTH - 16, 20),
+ LAYER_FOREGROUND1);
+ } else {
+ for(int i= 0; i < player_status.lives; ++i)
+ context.draw_surface(tux_life,
+ Vector(SCREEN_WIDTH - tux_life->w*4 +(tux_life->w*i), 20),
+ LAYER_FOREGROUND1);
+ }
+
+ const char* livestext = _("LIVES");
+ context.draw_text(white_text, livestext,
+ Vector(SCREEN_WIDTH - white_text->get_text_width(livestext)
+ - white_text->get_text_width(" 99"), 20),
+ LEFT_ALLIGN, LAYER_FOREGROUND1);
+
+ context.pop_transform();
+}
enum BonusType {
NO_BONUS, GROWUP_BONUS, FIRE_BONUS, ICE_BONUS
};
+class DrawingContext;
/**
* This class memorizes player status between different game sessions (for
void write(lisp::Writer& writer);
void read(const lisp::Lisp& lisp);
+ void draw(DrawingContext& context);
+
int coins;
int lives;
BonusType bonus;
#include "collision_grid_iterator.h"
#include "object_factory.h"
#include "collision.h"
+#include "spawn_point.h"
#include "math/rect.h"
#include "math/aatriangle.h"
#include "object/coin.h"
iter.value()->get(song_title);
load_music();
} else if(token == "spawnpoint") {
- const lisp::Lisp* spawnpoint_lisp = iter.lisp();
-
- SpawnPoint* sp = new SpawnPoint;
- spawnpoint_lisp->get("name", sp->name);
- spawnpoint_lisp->get("x", sp->pos.x);
- spawnpoint_lisp->get("y", sp->pos.y);
+ SpawnPoint* sp = new SpawnPoint(iter.lisp());
spawnpoints.push_back(sp);
} else if(token == "init-script") {
iter.value()->get(init_script);
class Bullet;
class CollisionGrid;
class ScriptInterpreter;
-
-class SpawnPoint
-{
-public:
- std::string name;
- Vector pos;
-};
+class SpawnPoint;
enum MusicType {
LEVEL_MUSIC,
return msgid;
}
}
+
+const char*
+Dictionary::translate(const char* msgid)
+{
+ Entries::iterator i = entries.find(msgid);
+ if(i == entries.end() || i->second.empty()) {
+#ifdef TRANSLATION_DBEUG
+ std::cout << "Error: Couldn't translate: " << msgid << std::endl;
+#endif
+ return msgid;
+ }
+
+ return i->second.c_str();
+}
void
Dictionary::add_translation(const std::string& msgid, const std::string& ,
{
state = WANT_MSGID;
line_num = 0;
+ char c = in.get();
+ if(c == (char) 0xef) { // skip UTF-8 intro that some texteditors produce
+ in.get();
+ in.get();
+ } else {
+ in.unget();
+ }
tokenize_po(in);
}
/** Translate the string \a msgid. */
std::string translate(const std::string& msgid);
+
+ const char* translate(const char* msgid);
/** Add a translation from \a msgid to \a msgstr to the dictionary,
where \a msgid is the singular form of the message, msgid2 the
// TODO: slots should be available for contrib maps
worldmap.loadgame(user_dir + "/save/" + subset.name + "-slot1.stsg");
-
worldmap.display(); // run the map
Menu::set_current(main_menu);
resume_demo();
} else if (current_subset != index) {
current_subset = index;
- // FIXME: This shouln't be busy looping
LevelSubset& subset = * (contrib_subsets[index]);
current_contrib_subset = ⊂
Menu::set_current(main_menu);
}
- mouse_cursor->draw(context);
-
context.do_drawing();
//frame_rate.update();
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA\r
// 02111-1307, USA.\r
//\r
-\r
#include <config.h>\r
+\r
#include <sstream>\r
\r
#include "scripttrigger.h"\r
}\r
}\r
\r
-IMPLEMENT_FACTORY(ScriptTrigger, "scripttrigger")\r
+IMPLEMENT_FACTORY(ScriptTrigger, "scripttrigger");\r
+\r
}
Surface::Surface(SDL_Surface* surf, bool use_alpha)
- : data(surf, use_alpha), w(0), h(0)
+ : impl(0), data(surf, use_alpha), w(0), h(0)
{
impl = data.create();
if (impl)
}
Surface::Surface(const std::string& file, bool use_alpha)
- : data(file, use_alpha), w(0), h(0)
+ : impl(0), data(file, use_alpha), w(0), h(0)
{
impl = data.create();
if (impl)
}
Surface::Surface(const std::string& file, int x, int y, int w_, int h_, bool use_alpha)
- : data(file, x, y, w_, h_, use_alpha), w(0), h(0)
+ : impl(0), data(file, x, y, w_, h_, use_alpha), w(0), h(0)
{
impl = data.create();
if (impl)
}
Surface::Surface(Color top_background, Color bottom_background, int w_, int h_)
- : data(top_background, bottom_background, w_, h_), w(0), h(0)
+ : impl(0), data(top_background, bottom_background, w_, h_), w(0), h(0)
{
impl = data.create();
if (impl)
SDL_Surface * conv;
temp = IMG_Load(file.c_str());
-
- if (temp == NULL) {
+ if (temp == 0) {
std::stringstream msg;
msg << "Couldn't load '" << file << "': " << SDL_GetError();
throw std::runtime_error(msg.str());
SDL_Surface* temp;
temp = IMG_Load(file.c_str());
-
- if (temp == NULL) {
+ if (temp == 0) {
std::stringstream msg;
msg << "Couldn't load file '" << file << "': " << SDL_GetError();
throw std::runtime_error(msg.str());
//---------------------------------------------------------------------------
SurfaceImpl::SurfaceImpl()
+ : sdl_surface(0)
{}
SurfaceImpl::~SurfaceImpl()
{
- SDL_FreeSurface(sdl_surface);
+ if(sdl_surface != 0)
+ SDL_FreeSurface(sdl_surface);
}
SDL_Surface* SurfaceImpl::get_sdl_surface() const
class Surface
{
public:
- SurfaceData data;
SurfaceImpl* impl;
+ SurfaceData data;
int w;
int h;
#include "player_status.h"
#include "textscroller.h"
#include "main.h"
+#include "spawn_point.h"
#include "file_system.h"
#include "gui/menu.h"
#include "gui/mousecursor.h"
#include "control/joystickkeyboardcontroller.h"
+#include "object/background.h"
+#include "object/tilemap.h"
Menu* worldmap_menu = 0;
offset = 0;
moving = false;
- tile_pos.x = worldmap->get_start_x();
- tile_pos.y = worldmap->get_start_y();
direction = D_NONE;
input_direction = D_NONE;
}
break;
}
- return Vector((int)x, (int)y);
+ return Vector(x, y);
}
void
//---------------------------------------------------------------------------
WorldMap::WorldMap()
+ : tux(0), solids(0)
{
tile_manager = new TileManager("images/worldmap.strf");
- width = 20;
- height = 15;
-
- start_x = 4;
- start_y = 5;
-
tux = new Tux(this);
-
- leveldot_green = new Surface(datadir + "/images/tiles/worldmap/leveldot_green.png", true);
- leveldot_red = new Surface(datadir + "/images/tiles/worldmap/leveldot_red.png", true);
- messagedot = new Surface(datadir + "/images/tiles/worldmap/messagedot.png", true);
- teleporterdot = new Surface(datadir + "/images/tiles/worldmap/teleporterdot.png", true);
+ add_object(tux);
+
+ leveldot_green
+ = new Surface(datadir + "/images/tiles/worldmap/leveldot_green.png", true);
+ leveldot_red
+ = new Surface(datadir + "/images/tiles/worldmap/leveldot_red.png", true);
+ messagedot
+ = new Surface(datadir + "/images/tiles/worldmap/messagedot.png", true);
+ teleporterdot
+ = new Surface(datadir + "/images/tiles/worldmap/teleporterdot.png", true);
name = "<no title>";
music = "salcon.mod";
WorldMap::~WorldMap()
{
- delete tux;
+ clear_objects();
+ for(SpawnPoints::iterator i = spawn_points.begin();
+ i != spawn_points.end(); ++i) {
+ delete *i;
+ }
+
delete tile_manager;
delete leveldot_green;
delete teleporterdot;
}
+void
+WorldMap::add_object(GameObject* object)
+{
+ TileMap* tilemap = dynamic_cast<TileMap*> (object);
+ if(tilemap != 0 && tilemap->is_solid()) {
+ solids = tilemap;
+ }
+
+ game_objects.push_back(object);
+}
+
+void
+WorldMap::clear_objects()
+{
+ for(GameObjects::iterator i = game_objects.begin();
+ i != game_objects.end(); ++i)
+ delete *i;
+ game_objects.clear();
+ solids = 0;
+ tux = new Tux(this);
+ add_object(tux);
+}
+
// Don't forget to set map_filename before calling this
void
WorldMap::load_map()
if(!lisp)
throw new std::runtime_error("file isn't a supertux-worldmap file.");
+ clear_objects();
lisp::ListIterator iter(lisp);
while(iter.next()) {
if(iter.item() == "tilemap") {
- if(tilemap.size() > 0)
- throw new std::runtime_error("multiple tilemaps specified");
-
- const lisp::Lisp* tilemap_lisp = iter.lisp();
- tilemap_lisp->get("width", width);
- tilemap_lisp->get("height", height);
- tilemap_lisp->get_vector("tiles", tilemap);
+ add_object(new TileMap(*(iter.lisp()), tile_manager));
+ } else if(iter.item() == "background") {
+ add_object(new Background(*(iter.lisp())));
} else if(iter.item() == "properties") {
const lisp::Lisp* props = iter.lisp();
props->get("name", name);
props->get("music", music);
props->get("intro-filename", intro_filename);
- props->get("start_pos_x", start_x);
- props->get("start_pos_y", start_y);
+ } else if(iter.item() == "spawnpoint") {
+ SpawnPoint* sp = new SpawnPoint(iter.lisp());
+ spawn_points.push_back(sp);
} else if(iter.item() == "level") {
parse_level_tile(iter.lisp());
} else if(iter.item() == "special-tile") {
std::cerr << "Unknown token '" << iter.item() << "' in worldmap.\n";
}
}
+ if(solids == 0)
+ throw std::runtime_error("No solid tilemap specified");
+
+ // search for main spawnpoint
+ for(SpawnPoints::iterator i = spawn_points.begin();
+ i != spawn_points.end(); ++i) {
+ SpawnPoint* sp = *i;
+ if(sp->name == "main") {
+ Vector p = sp->pos;
+ tux->set_tile_pos(p);
+ break;
+ }
+ }
- delete tux;
- tux = new Tux(this);
} catch(std::exception& e) {
std::stringstream msg;
msg << "Problem when parsing worldmap '" << map_filename << "': " <<
{
*new_pos = get_next_tile(old_pos, direction);
- if (!(new_pos->x >= 0 && new_pos->x < width
- && new_pos->y >= 0 && new_pos->y < height))
+ if (!(new_pos->x >= 0 && new_pos->x < solids->get_width()
+ && new_pos->y >= 0 && new_pos->y < solids->get_height()))
{ // New position is outsite the tilemap
return false;
}
return;
}
+ // update GameObjects
+ for(GameObjects::iterator i = game_objects.begin();
+ i != game_objects.end(); ++i) {
+ GameObject* object = *i;
+ object->update(delta);
+ }
+ // remove old GameObjects
+ for(GameObjects::iterator i = game_objects.begin();
+ i != game_objects.end(); ) {
+ GameObject* object = *i;
+ if(!object->is_valid()) {
+ delete object;
+ i = game_objects.erase(i);
+ } else {
+ ++i;
+ }
+ }
+
bool enter_level = false;
if(main_controller->pressed(Controller::ACTION)
|| main_controller->pressed(Controller::JUMP)
if (dir != D_NONE)
{
tux->set_direction(dir);
- //tux->update(delta);
}
}
}
}
else
{
- tux->update(delta);
// tux->set_direction(input_direction);
}
}
const Tile*
WorldMap::at(Vector p)
{
- assert(p.x >= 0
- && p.x < width
- && p.y >= 0
- && p.y < height);
-
- int x = int(p.x);
- int y = int(p.y);
- return tile_manager->get(tilemap[width * y + x]);
+ return solids->get_tile((int) p.x, (int) p.y);
}
WorldMap::Level*
void
WorldMap::draw(DrawingContext& context)
{
- for(int y = 0; y < height; ++y)
- for(int x = 0; x < width; ++x)
- {
- const Tile* tile = at(Vector(x, y));
- tile->draw(context, Vector(x*32, y*32), LAYER_TILES);
- }
-
+ for(GameObjects::iterator i = game_objects.begin();
+ i != game_objects.end(); ++i) {
+ GameObject* object = *i;
+ object->draw(context);
+ }
+
for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
{
if (i->solved)
Vector(i->pos.x*32, i->pos.y*32), LAYER_TILES+1);
}
- tux->draw(context);
draw_status(context);
}
{
context.push_transform();
context.set_translation(Vector(0, 0));
-
- char str[80];
- sprintf(str, " %d", total_stats.get_points(SCORE_STAT));
-
- context.draw_text(white_text, _("SCORE"), Vector(0, 0), LEFT_ALLIGN, LAYER_FOREGROUND1);
- context.draw_text(gold_text, str, Vector(96, 0), LEFT_ALLIGN, LAYER_FOREGROUND1);
-
- sprintf(str, "%d", player_status.coins);
- context.draw_text(white_text, _("COINS"), Vector(SCREEN_WIDTH/2 - 16*5, 0),
- LEFT_ALLIGN, LAYER_FOREGROUND1);
- context.draw_text(gold_text, str, Vector(SCREEN_WIDTH/2 + (16*5)/2, 0),
- LEFT_ALLIGN, LAYER_FOREGROUND1);
-
- if (player_status.lives >= 5)
- {
- sprintf(str, "%dx", player_status.lives);
- context.draw_text(gold_text, str,
- Vector(SCREEN_WIDTH - gold_text->get_text_width(str) - tux_life->w, 0),
- LEFT_ALLIGN, LAYER_FOREGROUND1);
- context.draw_surface(tux_life, Vector(SCREEN_WIDTH -
- gold_text->get_text_width("9"), 0), LAYER_FOREGROUND1);
- }
- else
- {
- for(int i= 0; i < player_status.lives; ++i)
- context.draw_surface(tux_life,
- Vector(SCREEN_WIDTH - tux_life->w*4 + (tux_life->w*i), 0),
- LAYER_FOREGROUND1);
- }
- context.draw_text(white_text, _("LIVES"),
- Vector(SCREEN_WIDTH - white_text->get_text_width(_("LIVES")) - white_text->get_text_width(" 99"), 0),
- LEFT_ALLIGN, LAYER_FOREGROUND1);
+
+ player_status.draw(context);
if (!tux->is_moving())
{
global_time += elapsed_time;
lastticks = ticks;
- // 40 fps minimum
+ // 40 fps minimum // TODO use same code as in GameSession here
if(elapsed_time > .025)
elapsed_time = .025;
Vector tux_pos = tux->get_pos();
-
- offset.x = -tux_pos.x + SCREEN_WIDTH/2;
- offset.y = -tux_pos.y + SCREEN_HEIGHT/2;
+ offset.x = tux_pos.x - SCREEN_WIDTH/2;
+ offset.y = tux_pos.y - SCREEN_HEIGHT/2;
- if (offset.x > 0) offset.x = 0;
- if (offset.y > 0) offset.y = 0;
+ if (offset.x < 0)
+ offset.x = 0;
+ if (offset.y < 0)
+ offset.y = 0;
+
+ if (offset.x > solids->get_width()*32 - SCREEN_WIDTH)
+ offset.x = solids->get_width()*32 - SCREEN_WIDTH;
+ if (offset.y > solids->get_height()*32 - SCREEN_HEIGHT)
+ offset.y = solids->get_height()*32 - SCREEN_HEIGHT;
- if (offset.x < SCREEN_WIDTH - width*32) offset.x = SCREEN_WIDTH - width*32;
- if (offset.y < SCREEN_HEIGHT - height*32) offset.y = SCREEN_HEIGHT - height*32;
-
context.push_transform();
- context.set_translation(-offset);
+ context.set_translation(offset);
draw(context);
context.pop_transform();
get_input();
if(Menu::current()) {
Menu::current()->draw(context);
- mouse_cursor->draw(context);
}
context.do_drawing();
}
} else {
std::cerr << "Unknown token '" << iter.item()
- << "' in levels block in worldmap.\n";
+ << "' in levels block in worldmap.\n";
}
}
}
} catch(std::exception& e) {
std::cerr << "Problem loading game '" << filename << "': " << e.what()
- << "\n";
+ << "\n";
load_map();
player_status.reset();
}
#include "statistics.h"
#include "timer.h"
#include "tile_manager.h"
+#include "game_object.h"
class Sprite;
class Menu;
+class SpawnPoint;
+class GameObject;
+class TileMap;
extern Menu* worldmap_menu;
namespace WorldMapNS {
class WorldMap;
-class Tux
+class Tux : public GameObject
{
public:
Direction back_direction;
std::string name;
std::string music;
- std::vector<int> tilemap;
- int width;
- int height;
+ typedef std::vector<GameObject*> GameObjects;
+ GameObjects game_objects;
+ TileMap* solids;
- int start_x;
- int start_y;
-
TileManager* tile_manager;
public:
typedef std::vector<SpecialTile> SpecialTiles;
SpecialTiles special_tiles;
-
typedef std::vector<Level> Levels;
Levels levels;
+ typedef std::vector<SpawnPoint*> SpawnPoints;
+ SpawnPoints spawn_points;
MusicRef song;
void get_input();
+ void add_object(GameObject* object);
+ void clear_objects();
+
/** Update Tux position */
void update(float delta);
void loadmap(const std::string& filename);
const std::string& get_world_title() const
- { return name; }
+ { return name; }
- const int& get_start_x() const
- { return start_x; }
-
- const int& get_start_y() const
- { return start_y; }
-
void set_map_filename(std::string filename)
- { map_filename = filename; }
+ { map_filename = filename; }
private:
void on_escape_press();