From: Matthias Braun Date: Wed, 24 Nov 2004 23:10:09 +0000 (+0000) Subject: some cleanups in the sprite class, increased delta for collision response X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=4ada19ad88b175b612e8f09d6426eb940a7d947f;p=supertux.git some cleanups in the sprite class, increased delta for collision response SVN-Revision: 2177 --- diff --git a/TODO b/TODO index 21b90ac70..37ab3ba61 100644 --- a/TODO +++ b/TODO @@ -110,6 +110,7 @@ L: low priority themselfes. This could speed up rendering of tilemaps. [H] implement quadtree to speed up collision detection [?] remove badguyspecs and bitmask files +[M] Make the gamelogic run in a fixed logical framerate --Miscellaneous-- [?] think about how to implement scripting, and how to make a simple and easy to diff --git a/lib/app/setup.cpp b/lib/app/setup.cpp index fb41e0ffd..20de54224 100644 --- a/lib/app/setup.cpp +++ b/lib/app/setup.cpp @@ -262,6 +262,7 @@ void Setup::init(const std::string& _package_name, directories(); dictionary_manager.add_directory(datadir + "/locale"); + dictionary_manager.set_charset("iso8859-1"); } /* --- SETUP --- */ diff --git a/lib/app/tinygettext.cpp b/lib/app/tinygettext.cpp index abaa48a11..fb88278b7 100644 --- a/lib/app/tinygettext.cpp +++ b/lib/app/tinygettext.cpp @@ -237,6 +237,8 @@ DictionaryManager::get_dictionary(const std::string& spec) Dictionary& dict = dictionaries[lang]; dict.set_language(get_language_def(lang)); + if(charset != "") + dict.set_charset(charset); for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p) { @@ -309,6 +311,14 @@ DictionaryManager::set_language(const std::string& lang) } void +DictionaryManager::set_charset(const std::string& charset) +{ + dictionaries.clear(); // changing charset invalidates cache + this->charset = charset; + set_language(language); +} + +void DictionaryManager::set_language_alias(const std::string& alias, const std::string& language) { @@ -334,9 +344,8 @@ DictionaryManager::get_language_from_spec(const std::string& spec) void DictionaryManager::add_directory(const std::string& pathname) { + dictionaries.clear(); // adding directories invalidates cache search_path.push_back(pathname); - // cache is outdated now - dictionaries.clear(); set_language(language); } diff --git a/lib/app/tinygettext.h b/lib/app/tinygettext.h index 5d4306306..207ce28a6 100644 --- a/lib/app/tinygettext.h +++ b/lib/app/tinygettext.h @@ -104,13 +104,14 @@ private: SearchPath search_path; typedef std::map Aliases; Aliases language_aliases; + std::string charset; std::string language; Dictionary* current_dict; Dictionary empty_dict; public: DictionaryManager(); - + /** Return the currently active dictionary, if none is set, an empty dictionary is returned. */ Dictionary& get_dictionary() @@ -122,6 +123,9 @@ public: /** Set a language based on a four? letter country code */ void set_language(const std::string& langspec); + /** Set a charset that will be set on the returned dictionaries */ + void set_charset(const std::string& charset); + /** Define an alias for a language */ void set_language_alias(const std::string& alias, const std::string& lang); diff --git a/lib/special/collision_hit.h b/lib/special/collision_hit.h index 07974f629..6e098ea8c 100644 --- a/lib/special/collision_hit.h +++ b/lib/special/collision_hit.h @@ -30,10 +30,15 @@ namespace SuperTux */ enum HitResponse { - ABORT_MOVE, // don't move the object - FORCE_MOVE, // do the move ignoring the collision - CONTINUE // move object out of collision and check for collisions again - // if this happens to often then the move will just be aborted + // note: keep the elements in this order + + /// don't move the object + ABORT_MOVE = 0, + /// move object out of collision and check for collisions again + /// if this happens to often then the move will just be aborted + CONTINUE, + /// do the move ignoring the collision + FORCE_MOVE }; /** diff --git a/lib/special/sprite.cpp b/lib/special/sprite.cpp index c73dc3835..18c606777 100644 --- a/lib/special/sprite.cpp +++ b/lib/special/sprite.cpp @@ -32,17 +32,18 @@ namespace SuperTux { Sprite::Sprite(SpriteData& newdata) - : data(newdata) + : data(newdata), frame(0), animation_loops(-1) { action = data.actions.begin()->second; - reset(); + last_ticks = SDL_GetTicks(); } Sprite::Sprite(const Sprite& other) : data(other.data), frame(other.frame), - animation_loops(other.animation_loops), last_tick(other.last_tick), - action(other.action), next_action(other.next_action) + animation_loops(other.animation_loops), + action(other.action) { + last_ticks = SDL_GetTicks(); } Sprite::~Sprite() @@ -50,34 +51,22 @@ Sprite::~Sprite() } void -Sprite::set_action(std::string name) +Sprite::set_action(std::string name, int loops) { - if(!next_action.empty() && animation_loops > 0) { - next_action = name; + if(action && action->name == name) return; - } + SpriteData::Action* newaction = data.get_action(name); - if(!action) + if(!action) { +#ifdef DEBUG + std::cerr << "Action '" << name << "' not found.\n"; +#endif return; + } action = newaction; -} - -void -Sprite::start_animation(int loops) -{ - reset(); animation_loops = loops; -} - -void -Sprite::reset() -{ frame = 0; - last_tick = SDL_GetTicks(); - animation_reversed = false; - animation_loops = -1; - next_action.clear(); } bool @@ -87,71 +76,24 @@ Sprite::check_animation() } void -Sprite::reverse_animation(bool reverse) -{ - animation_reversed = reverse; - - if(animation_reversed) - frame = get_frames()-1; - else - frame = 0; -} - -void Sprite::update() { if(animation_loops == 0) - { - if(frame >= get_frames() || frame < 0) - frame = 0; return; - } - float frame_inc = (action->fps/1000.0) * (SDL_GetTicks() - last_tick); - last_tick = SDL_GetTicks(); + Uint32 ticks = SDL_GetTicks(); + float frame_inc = action->fps * float(ticks - last_ticks)/1000.0; + last_ticks = ticks; - if(animation_reversed) - frame -= frame_inc; - else - frame += frame_inc; - - if(animation_reversed) { - if(frame < 0 || frame >= (float)get_frames()) { - // last case can happen when not used reverse_animation() - float excedent = frame - 0; - frame = get_frames() - 1; - if(animation_loops > 0) - { - animation_loops--; - if(animation_loops == 0 && !next_action.empty()) - { - set_action(next_action); - start_animation(-1); - } - } - - if(fabsf(excedent) < get_frames()) - frame += excedent; - } - } - else - { - if(frame >= (float)get_frames()) - { - float excedent = frame - get_frames(); - frame = 0; - if(animation_loops > 0) - { - animation_loops--; - if(animation_loops == 0 && !next_action.empty()) - { - set_action(next_action); - start_animation(-1); - } - } - - if(excedent < get_frames()) - frame += excedent; + frame += frame_inc; + + float lastframe = frame; + frame = fmodf(frame+get_frames(), get_frames()); + if(frame != lastframe) { + if(animation_loops > 0) { + animation_loops--; + if(animation_loops == 0) + frame = 0; } } } diff --git a/lib/special/sprite.h b/lib/special/sprite.h index 655aba800..6d0ed7bac 100644 --- a/lib/special/sprite.h +++ b/lib/special/sprite.h @@ -22,6 +22,7 @@ #include #include +#include #include #include "utils/lispreader.h" @@ -47,20 +48,13 @@ namespace SuperTux Uint32 drawing_effect = NONE_EFFECT); /** Set action (or state) */ - void set_action(std::string act); + void set_action(std::string act, int loops = -1); - /* Start an animation - -1 - for infinite - 0 - stopped - 1,2,3 - one, two, three times... */ - void start_animation(int loops); /* Stop animation */ void stop_animation() - { start_animation(0); } + { animation_loops = 0; } /** Check if animation is stopped or not */ bool check_animation(); - /** Reverse the animation */ - void reverse_animation(bool reverse); float get_fps() const { return action->fps; } @@ -85,24 +79,20 @@ namespace SuperTux { if(frame_ > get_frames()) frame = 0; else frame = frame_; } Surface* get_frame(unsigned int frame) { - if(frame < action->surfaces.size()) - return action->surfaces[frame]; - else - return action->surfaces[0]; + assert(frame < action->surfaces.size()); + return action->surfaces[frame]; } + private: void update(); - void reset(); SpriteData& data; float frame; int animation_loops; - bool animation_reversed; - float last_tick; + Uint32 last_ticks; SpriteData::Action* action; - std::string next_action; }; } //namespace SuperTux diff --git a/src/badguy/badguy.cpp b/src/badguy/badguy.cpp index cfa3af262..b13c0d5ab 100644 --- a/src/badguy/badguy.cpp +++ b/src/badguy/badguy.cpp @@ -194,6 +194,9 @@ BadGuy::set_state(State state) } flags |= FLAG_NO_COLLDET; break; + case STATE_FALLING: + flags |= FLAG_NO_COLLDET; + break; default: break; } diff --git a/src/badguy/dispenser.cpp b/src/badguy/dispenser.cpp index d8ec81257..1f62e61fd 100644 --- a/src/badguy/dispenser.cpp +++ b/src/badguy/dispenser.cpp @@ -45,7 +45,7 @@ Dispenser::collision_squished(Player& player) } void -Dispenser::active_action(float elapsed_time) +Dispenser::active_action(float ) { if (dispense_timer.check()) { launch_badguy(); diff --git a/src/object/block.cpp b/src/object/block.cpp index c75c990fa..0dcc549fd 100644 --- a/src/object/block.cpp +++ b/src/object/block.cpp @@ -13,6 +13,8 @@ #include "flower.h" #include "oneup.h" #include "star.h" +#include "badguy/badguy.h" +#include "coin.h" static const float BOUNCY_BRICK_MAX_OFFSET=8; static const float BOUNCY_BRICK_SPEED=90; @@ -35,8 +37,6 @@ Block::~Block() HitResponse Block::collision(GameObject& other, const CollisionHit& hitdata) { - // TODO kill badguys when bumping them... - Player* player = dynamic_cast (&other); if(player) { // collided from below? @@ -45,6 +45,17 @@ Block::collision(GameObject& other, const CollisionHit& hitdata) } } + if(bouncing) { + BadGuy* badguy = dynamic_cast (&other); + if(badguy) { + badguy->kill_fall(); + } + Coin* coin = dynamic_cast (&other); + if(coin) { + coin->collect(); + } + } + return FORCE_MOVE; } diff --git a/src/object/coin.cpp b/src/object/coin.cpp index 7bdded489..0799ef02e 100644 --- a/src/object/coin.cpp +++ b/src/object/coin.cpp @@ -5,7 +5,9 @@ #include "video/drawing_context.h" #include "special/sprite_manager.h" #include "player.h" +#include "sector.h" #include "scene.h" +#include "gameobjs.h" Coin::Coin(const Vector& pos) { @@ -30,6 +32,14 @@ Coin::draw(DrawingContext& context) sprite->draw(context, get_pos(), LAYER_TILES); } +void +Coin::collect() +{ + Sector::current()->player->get_status().incCoins(); + Sector::current()->add_object(new BouncyCoin(get_pos())); + remove_me(); +} + HitResponse Coin::collision(GameObject& other, const CollisionHit& ) { @@ -37,8 +47,7 @@ Coin::collision(GameObject& other, const CollisionHit& ) if(player == 0) return ABORT_MOVE; - player->get_status().incCoins(); - remove_me(); + collect(); return ABORT_MOVE; } diff --git a/src/object/coin.h b/src/object/coin.h index a4157a4c4..051d1c045 100644 --- a/src/object/coin.h +++ b/src/object/coin.h @@ -19,6 +19,8 @@ public: virtual void action(float elapsed_time); virtual void draw(DrawingContext& context); + void collect(); + private: Sprite* sprite; }; diff --git a/src/player.cpp b/src/player.cpp index e50bdab2f..cba8829b3 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -91,29 +91,16 @@ void player_input_init(player_input_type* pplayer_input) } void -TuxBodyParts::set_action(std::string action) +TuxBodyParts::set_action(std::string action, int loops) { if(head != NULL) - head->set_action(action); + head->set_action(action, loops); if(body != NULL) - body->set_action(action); + body->set_action(action, loops); if(arms != NULL) - arms->set_action(action); + arms->set_action(action, loops); if(feet != NULL) - feet->set_action(action); -} - -void -TuxBodyParts::one_time_animation() -{ - if(head != NULL) - head->start_animation(1); - if(body != NULL) - body->start_animation(1); - if(arms != NULL) - arms->start_animation(1); - if(feet != NULL) - feet->start_animation(1); + feet->set_action(action, loops); } void @@ -789,11 +776,9 @@ Player::draw(DrawingContext& context) if(size == BIG) { if(dir == LEFT) - tux_body->head->set_action("idle-left"); + tux_body->head->set_action("idle-left", 1); else // dir == RIGHT - tux_body->head->set_action("idle-right"); - - tux_body->head->start_animation(1); + tux_body->head->set_action("idle-right", 1); } } diff --git a/src/player.h b/src/player.h index bc47b133b..ada9e96aa 100644 --- a/src/player.h +++ b/src/player.h @@ -111,7 +111,7 @@ public: delete feet; } - void set_action(std::string action); + void set_action(std::string action, int loops = -1); void one_time_animation(); void draw(DrawingContext& context, const Vector& pos, int layer, Uint32 drawing_effect = NONE_EFFECT); diff --git a/src/sector.cpp b/src/sector.cpp index c5b81a8f3..e5d76c9e3 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -600,6 +600,8 @@ Sector::draw(DrawingContext& context) context.pop_transform(); } +static const float DELTA = .001; + void Sector::collision_tilemap(MovingObject* object, int depth) { @@ -701,7 +703,7 @@ Sector::collision_tilemap(MovingObject* object, int depth) return; } // move out of collision and try again - object->movement += hit.normal * (hit.depth + .05); + object->movement += hit.normal * (hit.depth + DELTA); collision_tilemap(object, depth+1); } @@ -724,15 +726,15 @@ Sector::collision_object(MovingObject* object1, MovingObject* object2) if(response1 == ABORT_MOVE) object1->movement = Vector(0, 0); if(response2 == CONTINUE) - object2->movement += hit.normal * (hit.depth + .05); + object2->movement += hit.normal * (hit.depth + DELTA); } else if(response2 != CONTINUE) { if(response2 == ABORT_MOVE) object2->movement = Vector(0, 0); if(response1 == CONTINUE) - object1->movement += -hit.normal * (hit.depth + .05); + object1->movement += -hit.normal * (hit.depth + DELTA); } else { - object1->movement += -hit.normal * (hit.depth/2 + .05); - object2->movement += hit.normal * (hit.depth/2 + .05); + object1->movement += -hit.normal * (hit.depth/2 + DELTA); + object2->movement += hit.normal * (hit.depth/2 + DELTA); } } } @@ -743,12 +745,16 @@ Sector::collision_handler() for(std::vector::iterator i = gameobjects.begin(); i != gameobjects.end(); ++i) { GameObject* gameobject = *i; - if(!gameobject->is_valid() - || gameobject->get_flags() & GameObject::FLAG_NO_COLLDET) + if(!gameobject->is_valid()) continue; MovingObject* movingobject = dynamic_cast (gameobject); if(!movingobject) continue; + if(movingobject->get_flags() & GameObject::FLAG_NO_COLLDET) { + movingobject->bbox.move(movingobject->movement); + movingobject->movement = Vector(0, 0); + continue; + } // collision with tilemap if(! (movingobject->movement == Vector(0, 0))) diff --git a/src/trigger/door.cpp b/src/trigger/door.cpp index a832da9df..1d576aee3 100644 --- a/src/trigger/door.cpp +++ b/src/trigger/door.cpp @@ -90,8 +90,7 @@ void Door::event(Player& , EventType type) { if(type == EVENT_ACTIVATE) { - sprite->set_action("open"); - sprite->start_animation(1); + sprite->set_action("open", 1); } }