}
}
-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;
}
// 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;
}
}
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;
void
BadGuy::remove_me()
{
- World::current()->remove_bad_guy(this);
+ removable = true;
}
void
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) {
bump();
return;
}
+
if(type == COLLISION_SQUISH) {
Player* player = static_cast<Player*>(p_c_object);
squish(player);
Direction dir;
private:
+ bool removable;
bool seen;
base_type old_base;
Timer timer;
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();
* 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);
/** 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
*/
#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;
}
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:
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;
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;
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);
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()
// 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:
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;
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
+#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <string.h>
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;
}
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();
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<ParticleSystem*>::iterator p;
/* 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
}
}
/* 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);
}
}
}
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);
}
}
}
// 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.
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<BadGuy*>::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
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);
}
}
class World
{
private:
- std::vector<BadGuy*> bad_guys;
+ typedef std::list<BadGuy*> BadGuys;
+ BadGuys bad_guys;
+ BadGuys bad_guys_to_add;
Level* level;
Player tux;
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);