Original Post
Hi. I'm having a bit of a memory management problem in a game project of mine. The game is a 1942 clone, just a simple overhead shooter in which the player takes control of a plane flying over the sea, fighting other planes. My problem, as I said, lies in memory management (or so I presume). When at first I start the game, it runs perfectly - smooth as buttuh. But if I let it sit for, say, three minutes, the frame rate begins to steadily drop at an unacceptable rate. Now, I have stepped through the program with the debugger, and have seen with my own eyes that the game objects are indeed being deleted. Thus, here is my dillemma: even though the game objects are being deleted (or so I have been lead to believe by the debugger), it appears to me that the RAM is still being eaten up with time. Here are my questions: * I am using ClanLib 0.7.8 as a graphics API. Is there, perhaps, a problem with ClanLib's graphics system, such as to lead to my problem? * Or am I just simply overlooking something/doing something totally wrong? Here is the code for the main loop: The code which is supposed to delete dead entities from memory comes right after the nested 'for' loops checking for collisions. Am I doing this wrongly? I greatly appreciate any responses, helpful or not! And if you do not understand something, or need more information, then by all means ask, and I will gladly answer!
void GameController::update(float TimeStep)
{
CL_Display::clear();
scroll_backdrops(TimeStep);
water_backdrop1.surf->draw(0, water_backdrop1.y_pos);
water_backdrop2.surf->draw(0, water_backdrop2.y_pos);
for (GameEntityList::iterator i = game_entities->begin(); i != game_entities->end(); ++i) {
(*i)->update(TimeStep);
if ((*i)->get_type() == GAMEENTITY_EXPLOSION)
continue;
if ((*i)->get_type() == GAMEENTITY_HEALTHCONTAINER) {
if ((*i)->is_colliding((GameEntity*)player_plane) && player_plane->get_death_timer() > player_plane->get_death_rate()) {
InteractionInfo* info = new InteractionInfo((GameEntity*)player_plane, INTERACTION_GENERAL);
info->set_specific_entity_ID((*i)->get_unique_ID());
interaction_manager->post_interaction(info);
InteractionInfo_NonOffensive* info2 = new InteractionInfo_NonOffensive((*i));
info2->set_specific_entity_ID(player_plane->get_unique_ID());
info2->set_health_gained(((GameEntity_HealthContainer*)(*i))->get_health_gained());
interaction_manager->post_interaction(info2);
}
}
else if ((*i)->get_type() == GAMEENTITY_ENEMYPLANE_TYPE1) {
if ((*i)->is_colliding((GameEntity*)player_plane) && player_plane->get_death_timer() > player_plane->get_death_rate()) {
InteractionInfo_Offensive* info = new InteractionInfo_Offensive((GameEntity*)player_plane);
info->set_specific_entity_ID((*i)->get_unique_ID());
info->set_damage_dealt(100);
interaction_manager->post_interaction(info);
InteractionInfo_Offensive* info2 = new InteractionInfo_Offensive((*i));
info2->set_specific_entity_ID(player_plane->get_unique_ID());
info2->set_damage_dealt(((GameEntity_EnemyPlane_Type1*)(*i))->get_damage_dealt());
interaction_manager->post_interaction(info2);
}
}
for (GameEntityList::iterator j = game_entities->begin(); j != game_entities->end(); ++j) {
if (j == i || (*j)->get_type() == GAMEENTITY_EXPLOSION)
continue;
if ((*i)->is_colliding((*j))) {
switch ((*i)->get_type()) {
case GAMEENTITY_PROJECTILE_NORMALBULLET:
{
switch ((*j)->get_type()) {
case GAMEENTITY_PROJECTILE_NORMALBULLET:
{
InteractionInfo* info = new InteractionInfo((*j), INTERACTION_GENERAL);
info->set_specific_entity_ID((*i)->get_unique_ID());
interaction_manager->post_interaction(info);
InteractionInfo* info2 = new InteractionInfo((*i), INTERACTION_GENERAL);
info->set_specific_entity_ID((*j)->get_unique_ID());
interaction_manager->post_interaction(info2);
break;
}
case GAMEENTITY_ENEMYPLANE_TYPE1:
{
InteractionInfo* info = new InteractionInfo((*j), INTERACTION_GENERAL);
info->set_specific_entity_ID((*i)->get_unique_ID());
interaction_manager->post_interaction(info);
InteractionInfo_Offensive* info2 = new InteractionInfo_Offensive((*i));
info2->set_specific_entity_ID((*j)->get_unique_ID());
info2->set_damage_dealt(((GameEntity_EnemyPlane_Type1*)(*j))->get_damage_dealt());
interaction_manager->post_interaction((InteractionInfo*)info2);
break;
}
}
break;
}
}
}
}
}
GameEntityList::iterator end = game_entities->end();
GameEntityList::iterator new_end = std::remove_if(game_entities->begin(), game_entities->end(), remove_entity_if_dead);
if (new_end != end)
game_entities->erase(new_end, end);
if (rand() % 1000 < chance_for_cloud) {
GameEntity_Cloud* cloud = new GameEntity_Cloud(this);
cloud->set_position(new CL_Vector2(rand() % parent->get_screen_width() - cloud->get_sprite()->get_width(), -cloud->get_sprite()->get_height()));
post_entity((GameEntity*)cloud);
}
if (rand() % 1000 < chance_for_eplane_1) {
GameEntity_EnemyPlane_Type1* eplane = new GameEntity_EnemyPlane_Type1(this);
eplane->set_dir((rand() % 5) - 1);
switch (eplane->get_dir()) {
case DIR_DOWN:
eplane->set_position(new CL_Vector2(rand() % parent->get_screen_width() - eplane->get_sprite()->get_width(), -eplane->get_sprite()->get_height()));
break;
case DIR_UP:
eplane->set_position(new CL_Vector2(rand() % parent->get_screen_width() - eplane->get_sprite()->get_width(), parent->get_screen_height()));
eplane->get_sprite()->rotate(180.0f);
break;
case DIR_LEFT:
eplane->set_position(new CL_Vector2(parent->get_screen_width(), rand() % parent->get_screen_height() - eplane->get_sprite()->get_height()));
eplane->get_sprite()->rotate(90.0f);
break;
case DIR_RIGHT:
eplane->set_position(new CL_Vector2(-eplane->get_sprite()->get_width(), rand() % parent->get_screen_height() - eplane->get_sprite()->get_height()));
eplane->get_sprite()->rotate(-90.0f);
break;
}
post_entity((GameEntity*)eplane);
}
player_plane->update(TimeStep);
interaction_manager->update();
stats_bar->draw(0, parent->get_screen_height() - stats_bar->get_height());
CL_Rect health_rect;
health_rect.left = 420;
health_rect.top = parent->get_screen_height() - stats_bar->get_height() / 2 + 7;
health_rect.set_size(CL_Size(player_plane->get_health(), 25));
CL_Display::fill_rect(health_rect, CL_Color::blue);
CL_Rect fuel_rect;
fuel_rect.left = 620;
fuel_rect.top = parent->get_screen_height() - stats_bar->get_height() / 2 + 7;
fuel_rect.set_size(CL_Size((int)player_plane->get_fuel(), 25));
CL_Display::fill_rect(fuel_rect, CL_Color::red);
if (player_plane->get_fuel() < 45)
low_fuel_notifier->draw(parent->get_screen_width() / 2 - low_fuel_notifier->get_width() / 2, 50);
CL_Display::flip();
}