From: Ingo Ruhnke Date: Thu, 22 Apr 2004 19:15:22 +0000 (+0000) Subject: - changed way badguy removal is handled (ie. with a flag now) X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=ddd864d8f63de465349cfb7b249b335a6b325066;p=supertux.git - changed way badguy removal is handled (ie. with a flag now) - changed some pointers to const references in collision code SVN-Revision: 648 --- diff --git a/src/badguy.cpp b/src/badguy.cpp index c09678b85..5331046fa 100644 --- a/src/badguy.cpp +++ b/src/badguy.cpp @@ -145,8 +145,8 @@ std::string badguykind_to_string(BadGuyKind kind) } } -void -BadGuy::init(float x, float y, BadGuyKind kind_, bool stay_on_platform_) +BadGuy::BadGuy(float x, float y, BadGuyKind kind_, bool stay_on_platform_) + : removable(false) { base.x = x; base.y = y; @@ -207,9 +207,9 @@ BadGuy::init(float x, float y, BadGuyKind kind_, bool stay_on_platform_) } // if we're in a solid tile at start correct that now - if(kind != BAD_FLAME && kind != BAD_FISH && collision_object_map(&base)) { + if(kind != BAD_FLAME && kind != BAD_FISH && collision_object_map(base)) { printf("Warning: badguy started in wall!.\n"); - while(collision_object_map(&base)) + while(collision_object_map(base)) --base.y; } } @@ -276,7 +276,7 @@ BadGuy::action_laptop(float frame_ratio) base.x = tux.base.x - 16; base.y = tux.base.y + tux.base.height/1.5 - base.height; } - if(collision_object_map(&base)) + if(collision_object_map(base)) { base.x = tux.base.x; base.y = tux.base.y + tux.base.height/1.5 - base.height; @@ -408,7 +408,7 @@ BadGuy::fall() void BadGuy::remove_me() { - World::current()->remove_bad_guy(this); + removable = true; } void @@ -856,7 +856,7 @@ BadGuy::squish(Player* player) World::current()->add_score(base.x - scroll_x, base.y, 50 * player_status.score_multiplier); play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER); player_status.score_multiplier++; - remove_me(); + remove_me(); return; } else if(kind == BAD_BSOD) { @@ -960,6 +960,7 @@ BadGuy::collision(void *p_c_object, int c_object, CollisionType type) bump(); return; } + if(type == COLLISION_SQUISH) { Player* player = static_cast(p_c_object); squish(player); diff --git a/src/badguy.h b/src/badguy.h index 29d5a19f8..c7b03cce8 100644 --- a/src/badguy.h +++ b/src/badguy.h @@ -112,6 +112,7 @@ public: Direction dir; private: + bool removable; bool seen; base_type old_base; Timer timer; @@ -123,7 +124,7 @@ private: int animation_offset; public: - void init(float x, float y, BadGuyKind kind, bool stay_on_platform); + BadGuy(float x, float y, BadGuyKind kind, bool stay_on_platform); void action(float frame_ratio); void draw(); @@ -135,7 +136,14 @@ public: * screen. Some badguys like the flame might ignore this. */ void kill_me(); - + + /** remove ourself from the list of badguys. WARNING! This function will + * invalidate all members. So don't do anything else with member after calling + * this. + */ + void remove_me(); + bool is_removable() const { return removable; } + private: void action_bsod(float frame_ratio); void action_laptop(float frame_ratio); @@ -153,13 +161,10 @@ private: /** handles falling down. disables gravity calculation when we're back on * ground */ void fall(); - /** remove ourself from the list of badguys. WARNING! This function will - * invalidate all members. So don't do anything else with member after calling - * this. - */ - void remove_me(); + /** let the player jump a bit (used when you hit a badguy) */ void make_player_jump(Player* player); + /** check if we're running left or right in a wall and eventually change * direction */ diff --git a/src/collision.cpp b/src/collision.cpp index 15a8b8b7f..1c96d9178 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -26,53 +26,53 @@ #include "level.h" #include "tile.h" -bool rectcollision(base_type* one, base_type* two) +bool rectcollision(const base_type& one, const base_type& two) { - return (one->x >= two->x - one->width + 1 && - one->x <= two->x + two->width - 1 && - one->y >= two->y - one->height + 1 && - one->y <= two->y + two->height - 1); + return (one.x >= two.x - one.width + 1 && + one.x <= two.x + two.width - 1 && + one.y >= two.y - one.height + 1 && + one.y <= two.y + two.height - 1); } -bool rectcollision_offset(base_type* one, base_type* two, float off_x, float off_y) +bool rectcollision_offset(const base_type& one, const base_type& two, float off_x, float off_y) { - return (one->x >= two->x - one->width +off_x + 1 && - one->x <= two->x + two->width + off_x - 1 && - one->y >= two->y - one->height + off_y + 1 && - one->y <= two->y + two->height + off_y - 1); + return (one.x >= two.x - one.width + off_x + 1 && + one.x <= two.x + two.width + off_x - 1 && + one.y >= two.y - one.height + off_y + 1 && + one.y <= two.y + two.height + off_y - 1); } -bool collision_object_map(base_type* pbase) +bool collision_object_map(const base_type& pbase) { - int v = (int)pbase->height / 16; - int h = (int)pbase->width / 16; + int v = (int)pbase.height / 16; + int h = (int)pbase.width / 16; - if(issolid(pbase->x + 1, pbase->y + 1) || - issolid(pbase->x + pbase->width -1, pbase->y + 1) || - issolid(pbase->x +1, pbase->y + pbase->height -1) || - issolid(pbase->x + pbase->width -1, pbase->y + pbase->height - 1)) + if(issolid(pbase.x + 1, pbase.y + 1) || + issolid(pbase.x + pbase.width -1, pbase.y + 1) || + issolid(pbase.x +1, pbase.y + pbase.height -1) || + issolid(pbase.x + pbase.width -1, pbase.y + pbase.height - 1)) return true; for(int i = 1; i < h; ++i) { - if(issolid(pbase->x + i*16,pbase->y + 1)) + if(issolid(pbase.x + i*16,pbase.y + 1)) return true; } for(int i = 1; i < h; ++i) { - if( issolid(pbase->x + i*16,pbase->y + pbase->height - 1)) + if( issolid(pbase.x + i*16,pbase.y + pbase.height - 1)) return true; } for(int i = 1; i < v; ++i) { - if( issolid(pbase->x + 1, pbase->y + i*16)) + if( issolid(pbase.x + 1, pbase.y + i*16)) return true; } for(int i = 1; i < v; ++i) { - if( issolid(pbase->x + pbase->width - 1, pbase->y + i*16)) + if( issolid(pbase.x + pbase.width - 1, pbase.y + i*16)) return true; } @@ -155,18 +155,18 @@ void collision_swept_object_map(base_type* old, base_type* current) steps--; } - if(collision_object_map(old)) + if(collision_object_map(*old)) { switch(h) { case 1: current->y = old->y - yd; - while(collision_object_map(current)) + while(collision_object_map(*current)) current->y -= yd; break; case 2: current->x = old->x - xd; - while(collision_object_map(current)) + while(collision_object_map(*current)) current->x -= xd; break; case 3: @@ -174,7 +174,7 @@ void collision_swept_object_map(base_type* old, base_type* current) yt = current->y; current->x = old->x - xd; current->y = old->y - yd; - while(collision_object_map(current)) + while(collision_object_map(*current)) { current->x -= xd; current->y -= yd; @@ -182,20 +182,20 @@ void collision_swept_object_map(base_type* old, base_type* current) temp = current->x; current->x = xt; - if(!collision_object_map(current)) + if(!collision_object_map(*current)) break; current->x = temp; temp = current->y; current->y = yt; - if(!collision_object_map(current)) + if(!collision_object_map(*current)) { break; } else { current->y = temp; - while(!collision_object_map(current)) + while(!collision_object_map(*current)) current->y += yd; current->y -= yd; break; diff --git a/src/collision.h b/src/collision.h index 3f6db2553..4a009e576 100644 --- a/src/collision.h +++ b/src/collision.h @@ -40,11 +40,11 @@ enum CollisionType { COLLISION_SQUISH }; -bool rectcollision(base_type* one, base_type* two); -bool rectcollision_offset(base_type* one, base_type* two, float off_x, float off_y); +bool rectcollision(const base_type& one, const base_type& two); +bool rectcollision_offset(const base_type& one, const base_type& two, float off_x, float off_y); void collision_swept_object_map(base_type* old, base_type* current); -bool collision_object_map(base_type* object); +bool collision_object_map(const base_type& object); /** Return a pointer to the tile at the given x/y coordinates */ Tile* gettile(float x, float y); diff --git a/src/leveleditor.cpp b/src/leveleditor.cpp index 6933e39e1..298489147 100644 --- a/src/leveleditor.cpp +++ b/src/leveleditor.cpp @@ -92,10 +92,7 @@ struct LevelEditorWorld void add_bad_guy(float x, float y, BadGuyKind kind) { - bad_guys.push_back(BadGuy()); - BadGuy& new_bad_guy = bad_guys.back(); - - new_bad_guy.init(x,y,kind, false /* stay_on_platform */); + bad_guys.push_back(BadGuy(x,y,kind, false /* stay_on_platform */)); } void activate_bad_guys() diff --git a/src/player.cpp b/src/player.cpp index 0c1599b05..7a387a283 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -203,10 +203,11 @@ Player::action(double frame_ratio) // special exception for cases where we're stuck under tiles after // being ducked. In this case we drift out if(!duck && on_ground() && old_base.x == base.x && old_base.y == base.y - && collision_object_map(&base)) { - base.x += frame_ratio * WALK_SPEED * (dir ? 1 : -1); - previous_base = old_base = base; - } + && collision_object_map(base)) + { + base.x += frame_ratio * WALK_SPEED * (dir ? 1 : -1); + previous_base = old_base = base; + } keep_in_bounds(); // Land: diff --git a/src/special.cpp b/src/special.cpp index 0bb4a1ae9..33878cfff 100644 --- a/src/special.cpp +++ b/src/special.cpp @@ -295,7 +295,7 @@ Upgrade::collision(void* p_c_object, int c_object) pplayer->size = BIG; pplayer->base.height = 64; pplayer->base.y -= 32; - if(collision_object_map(&pplayer->base)) + if(collision_object_map(pplayer->base)) { pplayer->base.height = 32; pplayer->base.y += 32; diff --git a/src/world.cpp b/src/world.cpp index 27a06c249..655c60a81 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -20,6 +20,7 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. +#include #include #include #include @@ -72,11 +73,9 @@ World::World(const std::string& subset, int level_nr) World::~World() { - for (unsigned int i = 0; i < bad_guys.size(); ++i) - { - delete bad_guys[i]; - } - + for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i) + delete *i; + halt_music(); // just to be sure (because levelmusic is freed now) delete level; } @@ -172,8 +171,8 @@ World::draw() for (unsigned int i = 0; i < bouncy_bricks.size(); ++i) bouncy_bricks[i].draw(); - for (unsigned int i = 0; i < bad_guys.size(); ++i) - bad_guys[i]->draw(); + for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i) + (*i)->draw(); tux.draw(); @@ -244,8 +243,8 @@ World::action(double frame_ratio) for (unsigned int i = 0; i < upgrades.size(); i++) upgrades[i].action(frame_ratio); - for (unsigned int i = 0; i < bad_guys.size(); i++) - bad_guys[i]->action(frame_ratio); + for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i) + (*i)->action(frame_ratio); /* update particle systems */ std::vector::iterator p; @@ -256,26 +255,33 @@ World::action(double frame_ratio) /* Handle all possible collisions. */ collision_handler(); + + { // Cleanup marked badguys + for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i) + if ((*i)->is_removable()) + delete *i; + bad_guys.remove_if(std::mem_fun(&BadGuy::is_removable)); + } } - void World::collision_handler() { // CO_BULLET & CO_BADGUY check for(unsigned int i = 0; i < bullets.size(); ++i) { - for(unsigned int j = 0; j < bad_guys.size(); ++j) + for (BadGuys::iterator j = bad_guys.begin(); j != bad_guys.end(); ++j) { - if(bad_guys[j]->dying != DYING_NOT) + if((*j)->dying != DYING_NOT) continue; - if(rectcollision(&bullets[i].base, &bad_guys[j]->base)) + + if(rectcollision(bullets[i].base, (*j)->base)) { // We have detected a collision and now call the // collision functions of the collided objects. // collide with bad_guy first, since bullet_collision will // delete the bullet - bad_guys[j]->collision(0, CO_BULLET); + (*j)->collision(0, CO_BULLET); bullets[i].collision(CO_BADGUY); break; // bullet is invalid now, so break } @@ -283,22 +289,24 @@ World::collision_handler() } /* CO_BADGUY & CO_BADGUY check */ - for(unsigned int i = 0; i < bad_guys.size(); ++i) + for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i) { - if(bad_guys[i]->dying != DYING_NOT) + if((*i)->dying != DYING_NOT) continue; - for(unsigned int j = i+1; j < bad_guys.size(); ++j) + BadGuys::iterator j = i; + ++j; + for (; j != bad_guys.end(); ++j) { - if(j == i || bad_guys[j]->dying != DYING_NOT) + if(j == i || (*j)->dying != DYING_NOT) continue; - if(rectcollision(&bad_guys[i]->base, &bad_guys[j]->base)) + if(rectcollision((*i)->base, (*j)->base)) { // We have detected a collision and now call the // collision functions of the collided objects. - bad_guys[j]->collision(&bad_guys[i], CO_BADGUY); - bad_guys[i]->collision(&bad_guys[j], CO_BADGUY); + (*j)->collision(*i, CO_BADGUY); + (*i)->collision(*j, CO_BADGUY); } } } @@ -306,25 +314,25 @@ World::collision_handler() if(tux.dying != DYING_NOT) return; // CO_BADGUY & CO_PLAYER check - for(unsigned int i = 0; i < bad_guys.size(); ++i) + for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i) { - if(bad_guys[i]->dying != DYING_NOT) + if((*i)->dying != DYING_NOT) continue; - if(rectcollision_offset(&bad_guys[i]->base,&tux.base,0,0)) + if(rectcollision_offset((*i)->base, tux.base, 0, 0)) { // We have detected a collision and now call the collision // functions of the collided objects. if (tux.previous_base.y < tux.base.y && tux.previous_base.y + tux.previous_base.height - < bad_guys[i]->base.y + bad_guys[i]->base.height/2) + < (*i)->base.y + (*i)->base.height/2) { - bad_guys[i]->collision(&tux, CO_PLAYER, COLLISION_SQUISH); + (*i)->collision(&tux, CO_PLAYER, COLLISION_SQUISH); } else { - tux.collision(&bad_guys[i], CO_BADGUY); - bad_guys[i]->collision(&tux, CO_PLAYER, COLLISION_NORMAL); + tux.collision(*i, CO_BADGUY); + (*i)->collision(&tux, CO_PLAYER, COLLISION_NORMAL); } } } @@ -332,7 +340,7 @@ World::collision_handler() // CO_UPGRADE & CO_PLAYER check for(unsigned int i = 0; i < upgrades.size(); ++i) { - if(rectcollision(&upgrades[i].base, &tux.base)) + if(rectcollision(upgrades[i].base, tux.base)) { // We have detected a collision and now call the collision // functions of the collided objects. @@ -388,26 +396,9 @@ World::add_bouncy_brick(float x, float y) BadGuy* World::add_bad_guy(float x, float y, BadGuyKind kind, bool stay_on_platform) { - bad_guys.push_back(new BadGuy()); - BadGuy* new_bad_guy = bad_guys.back(); - - new_bad_guy->init(x,y,kind, stay_on_platform); - return new_bad_guy; -} - -void -World::remove_bad_guy(BadGuy* badguy) -{ - for(std::vector::iterator i = bad_guys.begin(); - i != bad_guys.end(); ++i) - { - if(*i == badguy) - { - World::current()->bad_guys.erase(i); - delete badguy; - return; - } - } + BadGuy* badguy = new BadGuy(x,y,kind, stay_on_platform); + bad_guys.push_back(badguy); + return badguy; } void @@ -576,12 +567,12 @@ void World::trybumpbadguy(float x, float y) { // Bad guys: - for (unsigned int i = 0; i < bad_guys.size(); i++) + for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i) { - if (bad_guys[i]->base.x >= x - 32 && bad_guys[i]->base.x <= x + 32 && - bad_guys[i]->base.y >= y - 16 && bad_guys[i]->base.y <= y + 16) + if ((*i)->base.x >= x - 32 && (*i)->base.x <= x + 32 && + (*i)->base.y >= y - 16 && (*i)->base.y <= y + 16) { - bad_guys[i]->collision(&tux, CO_PLAYER, COLLISION_BUMP); + (*i)->collision(&tux, CO_PLAYER, COLLISION_BUMP); } } diff --git a/src/world.h b/src/world.h index d7b8e9712..b87a257d6 100644 --- a/src/world.h +++ b/src/world.h @@ -38,7 +38,9 @@ class Level; class World { private: - std::vector bad_guys; + typedef std::list BadGuys; + BadGuys bad_guys; + BadGuys bad_guys_to_add; Level* level; Player tux; @@ -93,7 +95,6 @@ public: void add_bouncy_brick(float x, float y); BadGuy* add_bad_guy(float x, float y, BadGuyKind kind, bool stay_on_platform = false); - void remove_bad_guy(BadGuy* badguy); void add_upgrade(float x, float y, Direction dir, UpgradeKind kind); void add_bullet(float x, float y, float xm, Direction dir);