From aeec9baba33ec63d2d0fdd97d961a53ec5c1541d Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Thu, 12 May 2005 11:25:09 +0000 Subject: [PATCH] - Refactored worldmap a bit to reuse GameObject from the rest of the game - Moved status drawing to PlayerStatus class - Made Level timeout an own object, so that you can explicitely enable it in some levels. (So all these levels with 999 time will no have no time) - Fixed wrong encoding for level/worldmap translations - Added workaround to tinygettext to skip the UTF-8 BOM SVN-Revision: 2474 --- data/images/engine/editor/clock.png | Bin 0 -> 1991 bytes data/levels/bonus1/abednego-level4.stl | 4 +- data/levels/bonus1/worldmap.stwm | 7 +- data/levels/misc/menu.stl | 1 - data/levels/world1/de.po | 28 ++-- data/levels/world1/worldmap.stwm | 9 +- src/badguy/badguy.cpp | 2 +- src/control/joystickkeyboardcontroller.cpp | 15 +++ src/control/joystickkeyboardcontroller.h | 1 + src/flip_level_transformer.cpp | 2 +- src/flip_level_transformer.h | 1 - src/game_session.cpp | 82 ++---------- src/game_session.h | 6 +- src/gettext.h | 7 +- src/gui/menu.cpp | 11 +- src/gui/mousecursor.cpp | 2 +- src/level.cpp | 6 +- src/level.h | 1 - src/lisp/parser.cpp | 1 + src/main.cpp | 2 +- src/object/level_time.cpp | 70 ++++++++++ src/object/level_time.h | 22 ++++ src/object/player.h | 1 - src/object/tilemap.cpp | 23 ++-- src/object/tilemap.h | 2 +- src/player_status.cpp | 43 +++++++ src/player_status.h | 3 + src/sector.cpp | 8 +- src/sector.h | 8 +- src/tinygettext/tinygettext.cpp | 21 +++ src/tinygettext/tinygettext.h | 2 + src/title.cpp | 4 - src/trigger/scripttrigger.cpp | 5 +- src/video/surface.cpp | 18 +-- src/video/surface.h | 2 +- src/worldmap.cpp | 199 ++++++++++++++++------------- src/worldmap.h | 31 +++-- 37 files changed, 393 insertions(+), 257 deletions(-) create mode 100644 data/images/engine/editor/clock.png create mode 100644 src/object/level_time.cpp create mode 100644 src/object/level_time.h diff --git a/data/images/engine/editor/clock.png b/data/images/engine/editor/clock.png new file mode 100644 index 0000000000000000000000000000000000000000..ce4d5840823c6b63ff5f0603b3b5613118065712 GIT binary patch literal 1991 zcmV;&2RQhNP)7`_g~-Mdwp7xB&-F89>J_s<#%&A{d2``Z77}5vbh{~p&PT=NTOB~>9_GK3&}*Y znYoZ4z}wbcZC_S5LQZdAY7vc>rPwjJbC`3TGi%oy|-w1gyqD27l$Bn@QS zpmfUc$4_(AY@1)W_aK!ICEzFb%DdKYG!EQ&v$oF4DR4rFLxP${B27}Zj%jL086!kQ ztSJ&lAT*80wg?+GW1~)OdYs=r@R0SL%M!4EpL%@f^~To*uZ@ByN zd-|`E2DU)V*rZ*XDAuv<&NV?GXf)=@B&;e+Nq7dX({t3NQbBXUSd z#GH!?EljgRRIiut{R%>`Vk~C9d`NlD38g?PoAv#Js8WS6HEX%+<(&`gC%;0#zP;*) zBRA+)<8I@t;VNix9r_*)2}2mq)D4@gr{oiquAxs>^0w(T~=@m8wU8twL(56n1<6k}u0AjC!7 z2~B#sHzUe5+Uw_vQ7nI;18AE0VDCU=iC7Q`YstDG0N?Kj2!c+K_3L+Y;>2H2D!72; z^yxp4N{t|;v*L+Ze(t(?RMjJ>)lhbLs}7LOu|w$!(NIL8y>!F*h1Lm@X2XWtIC=8- zD*{hX|CL$|T=&{b)a+i%R7fO2NXy z>%9E(GYkxTkwya=4QRDiIyW_Sg2~C_NCl>uMpivyN9A<@%huA82<2-?3DeVOn4h1z zz`o_bH*LC;7hX8b)YLyYa^%~LjO?S;GV#1~%hql~vkCP&BuO8qPQ5`8KpY#$x{oqd z+62(R5mAKvpW5;9QIrx44}WPz6^G%uM+>^xHS#HjyY?{ovBycLx1Rq}U4craL>wE0 zVMl;yOFTVDnE+BGfeMp?3Pb93(Dkjpz zHjJ=w;|%~PB~dEEke06l2uVvy2oZ!K^!5(3bLUr1X%uCjhwp_8$=hH7u)t)%!G{ z*{mTg0|KL_1E?T5E?Xwb($V$iszJ_2q405XxvST7t&$DSmc|gSgXyKlbO6%|_lwz7 zAX64mT)%7qmxG0c_X$LdRxFTGCL%T3ML34VyM?!89x6^N`7am zH$QZ5xEzNb!7NRvZ?z)z$+j5`Nk?=kOJplaJCly>z{YM8ShYgvj&\n" "Language-Team: German \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" @@ -45,9 +45,9 @@ msgstr "" "\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" @@ -82,11 +82,11 @@ msgstr "Zu den Sternen" #: 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" @@ -94,7 +94,7 @@ msgstr "Unter dem Eis" #: 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?'" @@ -126,7 +126,7 @@ msgstr "Die Flucht" #: 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" @@ -146,7 +146,7 @@ msgstr "Die Reise Beginnt" #: basest/levels/world1/level3.stl:5 msgid "Via Nostalgica" -msgstr "Nostalgiestra�" +msgstr "Nostalgiestraße" #: basest/levels/world1/level4.stl:5 msgid "Tobgle Road" @@ -162,7 +162,7 @@ msgstr "Eisige Felder" #: 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" @@ -170,7 +170,7 @@ msgstr "Steinkalt" #: 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 "" @@ -228,17 +228,17 @@ msgstr "" "#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" diff --git a/data/levels/world1/worldmap.stwm b/data/levels/world1/worldmap.stwm index 67c2a9579..8934bc942 100644 --- a/data/levels/world1/worldmap.stwm +++ b/data/levels/world1/worldmap.stwm @@ -4,11 +4,16 @@ (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 diff --git a/src/badguy/badguy.cpp b/src/badguy/badguy.cpp index a312986bf..7dcb5c850 100644 --- a/src/badguy/badguy.cpp +++ b/src/badguy/badguy.cpp @@ -153,7 +153,7 @@ BadGuy::collision_player(Player& player, const CollisionHit& ) 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)) diff --git a/src/control/joystickkeyboardcontroller.cpp b/src/control/joystickkeyboardcontroller.cpp index 09220c99d..6bebf6b3d 100644 --- a/src/control/joystickkeyboardcontroller.cpp +++ b/src/control/joystickkeyboardcontroller.cpp @@ -116,6 +116,13 @@ JoystickKeyboardController::JoystickKeyboardController() 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() @@ -228,6 +235,14 @@ JoystickKeyboardController::write(lisp::Writer& writer) } 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) { diff --git a/src/control/joystickkeyboardcontroller.h b/src/control/joystickkeyboardcontroller.h index 150ddb3d1..6520a2b7e 100644 --- a/src/control/joystickkeyboardcontroller.h +++ b/src/control/joystickkeyboardcontroller.h @@ -43,6 +43,7 @@ public: 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(); diff --git a/src/flip_level_transformer.cpp b/src/flip_level_transformer.cpp index 6e2b2dbe0..22f10d4e2 100644 --- a/src/flip_level_transformer.cpp +++ b/src/flip_level_transformer.cpp @@ -17,7 +17,6 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. - #include #include "flip_level_transformer.h" @@ -25,6 +24,7 @@ #include "badguy/badguy.h" #include "sector.h" #include "tile_manager.h" +#include "spawn_point.h" void FlipLevelTransformer::transform_sector(Sector* sector) diff --git a/src/flip_level_transformer.h b/src/flip_level_transformer.h index 317629fe3..79b7b0297 100644 --- a/src/flip_level_transformer.h +++ b/src/flip_level_transformer.h @@ -17,7 +17,6 @@ // 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__ diff --git a/src/game_session.cpp b/src/game_session.cpp index 86b38e3d9..1402e6457 100644 --- a/src/game_session.cpp +++ b/src/game_session.cpp @@ -109,7 +109,7 @@ GameSession::restart_level() 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); @@ -129,7 +129,6 @@ GameSession::restart_level() if(mode == ST_GL_PLAY || mode == ST_GL_LOAD_LEVEL_FILE) levelintro(); - start_timers(); currentsector->play_music(LEVEL_MUSIC); if(capture_file != "") @@ -219,13 +218,6 @@ GameSession::levelintro() wait_for_event(1.0, 3.0); } -/* Reset Timers */ -void -GameSession::start_timers() -{ - time_left.start(level->timelimit); -} - void GameSession::on_escape_press() { @@ -315,6 +307,8 @@ GameSession::process_events() void GameSession::try_cheats() { + if(currentsector == 0) + return; Player& tux = *currentsector->player; // Cheating words (the goal of this is really for debugging, @@ -442,7 +436,6 @@ GameSession::draw() if(Menu::current()) { Menu::current()->draw(*context); - mouse_cursor->draw(*context); } context->do_drawing(); @@ -601,10 +594,6 @@ GameSession::run() //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) { @@ -631,14 +620,18 @@ GameSession::run() } // 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 @@ -696,10 +689,6 @@ GameSession::start_sequence(const std::string& sequencename) 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()); } @@ -714,58 +703,11 @@ GameSession::start_sequence(const std::string& sequencename) 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), diff --git a/src/game_session.h b/src/game_session.h index 5fc2f681c..eb31ed465 100644 --- a/src/game_session.h +++ b/src/game_session.h @@ -59,7 +59,6 @@ public: public: DrawingContext* context; - Timer time_left; GameSession(const std::string& levelfile, GameSessionMode mode, Statistics* statistics=0); @@ -77,8 +76,8 @@ public: { 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, @@ -95,7 +94,6 @@ private: void restart_level(); void check_end_conditions(); - void start_timers(); void process_events(); void capture_demo_step(); diff --git a/src/gettext.h b/src/gettext.h index 8ecae1a84..b12cdd2f7 100644 --- a/src/gettext.h +++ b/src/gettext.h @@ -22,7 +22,12 @@ extern TinyGetText::DictionaryManager dictionary_manager; 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) diff --git a/src/gui/menu.cpp b/src/gui/menu.cpp index 87d083d08..d70472d68 100644 --- a/src/gui/menu.cpp +++ b/src/gui/menu.cpp @@ -76,11 +76,10 @@ bool confirm_dialog(Surface *background, std::string text) 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); } @@ -691,6 +690,10 @@ int Menu::get_height() const void Menu::draw(DrawingContext& context) { + if(MouseCursor::current()) { + MouseCursor::current()->draw(context); + } + int menu_height = get_height(); int menu_width = get_width(); diff --git a/src/gui/mousecursor.cpp b/src/gui/mousecursor.cpp index 5a935635c..8b774f7a0 100644 --- a/src/gui/mousecursor.cpp +++ b/src/gui/mousecursor.cpp @@ -80,6 +80,6 @@ void MouseCursor::draw(DrawingContext& context) 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); } diff --git a/src/level.cpp b/src/level.cpp index b097cc422..e9f8ccd53 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -51,7 +51,7 @@ using namespace std; Level::Level() - : name("noname"), author("Mr. X"), timelimit(500) + : name("noname"), author("Mr. X") { } @@ -92,8 +92,6 @@ Level::load(const std::string& filepath) 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())); @@ -116,7 +114,6 @@ Level::load_old_format(const lisp::Lisp& reader) { reader.get("name", name); reader.get("author", author); - reader.get("time", timelimit); Sector* sector = new Sector; sector->parse_old_format(reader); @@ -142,7 +139,6 @@ Level::save(const std::string& filename) 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; diff --git a/src/level.h b/src/level.h index 555138ae1..18d180312 100644 --- a/src/level.h +++ b/src/level.h @@ -35,7 +35,6 @@ class Level public: std::string name; std::string author; - int timelimit; typedef std::vector Sectors; Sectors sectors; diff --git a/src/lisp/parser.cpp b/src/lisp/parser.cpp index 65f163ad4..cd74886e2 100644 --- a/src/lisp/parser.cpp +++ b/src/lisp/parser.cpp @@ -38,6 +38,7 @@ Parser::Parser(bool translate) { if(translate) { dictionary_manager = new TinyGetText::DictionaryManager(); + dictionary_manager->set_charset("ISO8859-1"); } } diff --git a/src/main.cpp b/src/main.cpp index 494209f7f..a48b3f4f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -133,7 +133,7 @@ static void find_directories() 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) diff --git a/src/object/level_time.cpp b/src/object/level_time.cpp new file mode 100644 index 000000000..fc0ae13e7 --- /dev/null +++ b/src/object/level_time.cpp @@ -0,0 +1,70 @@ +#include + +#include "level_time.h" + +#include +#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"); diff --git a/src/object/level_time.h b/src/object/level_time.h new file mode 100644 index 000000000..3c7e67e2f --- /dev/null +++ b/src/object/level_time.h @@ -0,0 +1,22 @@ +#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 + diff --git a/src/object/player.h b/src/object/player.h index 731b44363..22fb0f295 100644 --- a/src/object/player.h +++ b/src/object/player.h @@ -39,7 +39,6 @@ static const float TUX_SAFE_TIME = 1.250; 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; diff --git a/src/object/tilemap.cpp b/src/object/tilemap.cpp index a8ca571c1..15c61256b 100644 --- a/src/object/tilemap.cpp +++ b/src/object/tilemap.cpp @@ -45,11 +45,13 @@ TileMap::TileMap() 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)) { @@ -72,10 +74,11 @@ TileMap::TileMap(const lisp::Lisp& reader) } 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."); @@ -149,9 +152,11 @@ TileMap::draw(DrawingContext& context) /** 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; diff --git a/src/object/tilemap.h b/src/object/tilemap.h index 2aaf3ce42..d647a5ef2 100644 --- a/src/object/tilemap.h +++ b/src/object/tilemap.h @@ -41,7 +41,7 @@ class TileMap : public GameObject, public Serializable { 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(); diff --git a/src/player_status.cpp b/src/player_status.cpp index 6fcf66c0f..304a076b7 100644 --- a/src/player_status.cpp +++ b/src/player_status.cpp @@ -22,6 +22,9 @@ #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; @@ -117,3 +120,43 @@ PlayerStatus::read(const lisp::Lisp& lisp) 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(); +} diff --git a/src/player_status.h b/src/player_status.h index e4fb3359f..c1bdc25e9 100644 --- a/src/player_status.h +++ b/src/player_status.h @@ -26,6 +26,7 @@ enum BonusType { NO_BONUS, GROWUP_BONUS, FIRE_BONUS, ICE_BONUS }; +class DrawingContext; /** * This class memorizes player status between different game sessions (for @@ -42,6 +43,8 @@ public: void write(lisp::Writer& writer); void read(const lisp::Lisp& lisp); + void draw(DrawingContext& context); + int coins; int lives; BonusType bonus; diff --git a/src/sector.cpp b/src/sector.cpp index cc1689b0d..11957a4b9 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -46,6 +46,7 @@ #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" @@ -145,12 +146,7 @@ Sector::parse(const lisp::Lisp& sector) 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); diff --git a/src/sector.h b/src/sector.h index 547722120..51a135b99 100644 --- a/src/sector.h +++ b/src/sector.h @@ -41,13 +41,7 @@ class TileMap; class Bullet; class CollisionGrid; class ScriptInterpreter; - -class SpawnPoint -{ -public: - std::string name; - Vector pos; -}; +class SpawnPoint; enum MusicType { LEVEL_MUSIC, diff --git a/src/tinygettext/tinygettext.cpp b/src/tinygettext/tinygettext.cpp index dd73e8028..9ffd17ca6 100644 --- a/src/tinygettext/tinygettext.cpp +++ b/src/tinygettext/tinygettext.cpp @@ -433,6 +433,20 @@ Dictionary::translate(const std::string& msgid) 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& , @@ -477,6 +491,13 @@ public: { 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); } diff --git a/src/tinygettext/tinygettext.h b/src/tinygettext/tinygettext.h index 207ce28a6..a8a584680 100644 --- a/src/tinygettext/tinygettext.h +++ b/src/tinygettext/tinygettext.h @@ -78,6 +78,8 @@ public: /** 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 diff --git a/src/title.cpp b/src/title.cpp index 255b38d98..9afb6675b 100644 --- a/src/title.cpp +++ b/src/title.cpp @@ -185,14 +185,12 @@ void check_levels_contrib_menu() // 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 = ⊂ @@ -433,8 +431,6 @@ void title() Menu::set_current(main_menu); } - mouse_cursor->draw(context); - context.do_drawing(); //frame_rate.update(); diff --git a/src/trigger/scripttrigger.cpp b/src/trigger/scripttrigger.cpp index e5bc84863..7a7c27a53 100644 --- a/src/trigger/scripttrigger.cpp +++ b/src/trigger/scripttrigger.cpp @@ -18,8 +18,8 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. // - #include + #include #include "scripttrigger.h" @@ -103,4 +103,5 @@ ScriptTrigger::event(Player& , EventType type) } } -IMPLEMENT_FACTORY(ScriptTrigger, "scripttrigger") +IMPLEMENT_FACTORY(ScriptTrigger, "scripttrigger"); + diff --git a/src/video/surface.cpp b/src/video/surface.cpp index 998748232..ec846e796 100644 --- a/src/video/surface.cpp +++ b/src/video/surface.cpp @@ -137,7 +137,7 @@ static int power_of_two(int input) } 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) @@ -149,7 +149,7 @@ Surface::Surface(SDL_Surface* surf, bool use_alpha) } 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) @@ -161,7 +161,7 @@ Surface::Surface(const std::string& file, bool use_alpha) } 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) @@ -173,7 +173,7 @@ Surface::Surface(const std::string& file, int x, int y, int w_, int h_, bool use } 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) @@ -296,8 +296,7 @@ sdl_surface_part_from_file(const std::string& file, int x, int y, int w, int h, 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()); @@ -346,8 +345,7 @@ sdl_surface_from_file(const std::string& file, bool use_alpha) 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()); @@ -454,11 +452,13 @@ sdl_surface_from_gradient(Color top, Color bottom, int w, int h) //--------------------------------------------------------------------------- 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 diff --git a/src/video/surface.h b/src/video/surface.h index 55f6ed051..b7adb5f7e 100644 --- a/src/video/surface.h +++ b/src/video/surface.h @@ -95,8 +95,8 @@ public: class Surface { public: - SurfaceData data; SurfaceImpl* impl; + SurfaceData data; int w; int h; diff --git a/src/worldmap.cpp b/src/worldmap.cpp index d90afe776..e193b0f81 100644 --- a/src/worldmap.cpp +++ b/src/worldmap.cpp @@ -44,10 +44,13 @@ #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; @@ -116,8 +119,6 @@ Tux::Tux(WorldMap* worldmap_) 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; } @@ -176,7 +177,7 @@ Tux::get_pos() break; } - return Vector((int)x, (int)y); + return Vector(x, y); } void @@ -343,21 +344,21 @@ Tux::update(float delta) //--------------------------------------------------------------------------- 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 = ""; music = "salcon.mod"; @@ -368,7 +369,12 @@ WorldMap::WorldMap() 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; @@ -377,6 +383,29 @@ WorldMap::~WorldMap() delete teleporterdot; } +void +WorldMap::add_object(GameObject* object) +{ + TileMap* tilemap = dynamic_cast (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() @@ -392,23 +421,21 @@ 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") { @@ -417,9 +444,20 @@ WorldMap::load_map() 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 << "': " << @@ -588,8 +626,8 @@ WorldMap::path_ok(Direction direction, Vector old_pos, Vector* new_pos) { *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; } @@ -644,6 +682,24 @@ WorldMap::update(float delta) 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) @@ -725,7 +781,6 @@ WorldMap::update(float delta) if (dir != D_NONE) { tux->set_direction(dir); - //tux->update(delta); } } } @@ -802,7 +857,6 @@ WorldMap::update(float delta) } else { - tux->update(delta); // tux->set_direction(input_direction); } } @@ -810,14 +864,7 @@ WorldMap::update(float delta) 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* @@ -847,13 +894,12 @@ WorldMap::at_special_tile() 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) @@ -878,7 +924,6 @@ WorldMap::draw(DrawingContext& context) Vector(i->pos.x*32, i->pos.y*32), LAYER_TILES+1); } - tux->draw(context); draw_status(context); } @@ -887,38 +932,8 @@ WorldMap::draw_status(DrawingContext& 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()) { @@ -985,23 +1000,26 @@ WorldMap::display() 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(); @@ -1009,7 +1027,6 @@ WorldMap::display() if(Menu::current()) { Menu::current()->draw(context); - mouse_cursor->draw(context); } context.do_drawing(); @@ -1140,13 +1157,13 @@ WorldMap::loadgame(const std::string& filename) } } 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(); } diff --git a/src/worldmap.h b/src/worldmap.h index dd5d03a99..0894d28d2 100644 --- a/src/worldmap.h +++ b/src/worldmap.h @@ -30,9 +30,13 @@ #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 { @@ -59,7 +63,7 @@ Direction reverse_dir(Direction d); class WorldMap; -class Tux +class Tux : public GameObject { public: Direction back_direction; @@ -108,13 +112,10 @@ private: std::string name; std::string music; - std::vector tilemap; - int width; - int height; + typedef std::vector GameObjects; + GameObjects game_objects; + TileMap* solids; - int start_x; - int start_y; - TileManager* tile_manager; public: @@ -187,9 +188,10 @@ private: typedef std::vector SpecialTiles; SpecialTiles special_tiles; - typedef std::vector Levels; Levels levels; + typedef std::vector SpawnPoints; + SpawnPoints spawn_points; MusicRef song; @@ -219,6 +221,9 @@ public: void get_input(); + void add_object(GameObject* object); + void clear_objects(); + /** Update Tux position */ void update(float delta); @@ -244,16 +249,10 @@ public: 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(); -- 2.11.0