<MatzeB> -fixes 3 potential crashs (deleting Sprite classes, using member function in
<MatzeB> BadGuy class after removing it)
<MatzeB> -cleans up sound init code and hopes that calling Mix_AllocateChannel will make
<MatzeB> SDL_mixer happy...
<MatzeB> -fix paths that missed a / after DATADIR
<MatzeB> at least valgrind doesn't report any errors anymore when you apply that patch
<MatzeB> (memory errors though, not memory leaks)
SVN-Revision: 737
img_snowball_right = sprite_manager->load("snowball-right");
img_snowball_squished_left = sprite_manager->load("snowball-squished-left");
img_snowball_squished_right = sprite_manager->load("snowball-squished-right");
-#if 0
- /* (BSOD) */
- img_bsod_left[0] = new Surface(datadir + "/images/shared/bsod-left-0.png", USE_ALPHA);
-
- img_bsod_left[1] = new Surface(datadir +
- "/images/shared/bsod-left-1.png",
- USE_ALPHA);
-
- img_bsod_left[2] = new Surface(datadir +
- "/images/shared/bsod-left-2.png",
- USE_ALPHA);
-
- img_bsod_left[3] = new Surface(datadir +
- "/images/shared/bsod-left-3.png",
- USE_ALPHA);
-
- img_bsod_right[0] = new Surface(datadir +
- "/images/shared/bsod-right-0.png",
- USE_ALPHA);
-
- img_bsod_right[1] = new Surface(datadir +
- "/images/shared/bsod-right-1.png",
- USE_ALPHA);
-
- img_bsod_right[2] = new Surface(datadir +
- "/images/shared/bsod-right-2.png",
- USE_ALPHA);
-
- img_bsod_right[3] = new Surface(datadir +
- "/images/shared/bsod-right-3.png",
- USE_ALPHA);
-
- img_bsod_squished_left[0] = new Surface(datadir +
- "/images/shared/bsod-squished-left.png",
- USE_ALPHA);
-
- img_bsod_squished_right[0] = new Surface(datadir +
- "/images/shared/bsod-squished-right.png",
- USE_ALPHA);
-
- img_bsod_falling_left[0] = new Surface(datadir +
- "/images/shared/bsod-falling-left.png",
- USE_ALPHA);
-
- img_bsod_falling_right[0] = new Surface(datadir +
- "/images/shared/bsod-falling-right.png",
- USE_ALPHA);
-
-
- /* (Laptop) */
-
- img_laptop_left[0] = new Surface(datadir + "/images/shared/mriceblock-left-0.png", USE_ALPHA);
- img_laptop_left[1] = new Surface(datadir + "/images/shared/mriceblock-left-1.png", USE_ALPHA);
- img_laptop_left[2] = new Surface(datadir + "/images/shared/mriceblock-left-2.png", USE_ALPHA);
- img_laptop_left[3] = new Surface(datadir + "/images/shared/mriceblock-left-1.png", USE_ALPHA);
-
- img_laptop_right[0] = new Surface(datadir + "/images/shared/mriceblock-right-0.png", USE_ALPHA);
- img_laptop_right[1] = new Surface(datadir + "/images/shared/mriceblock-right-1.png", USE_ALPHA);
- img_laptop_right[2] = new Surface(datadir + "/images/shared/mriceblock-right-2.png", USE_ALPHA);
- img_laptop_right[3] = new Surface(datadir + "/images/shared/mriceblock-right-1.png", USE_ALPHA);
-
- img_laptop_flat_left[0] = new Surface(
- datadir + "/images/shared/laptop-flat-left.png",
- USE_ALPHA);
-
- img_laptop_flat_right[0] = new Surface(datadir +
- "/images/shared/laptop-flat-right.png",
- USE_ALPHA);
-
- img_laptop_falling_left[0] = new Surface(datadir +
- "/images/shared/laptop-falling-left.png",
- USE_ALPHA);
-
- img_laptop_falling_right[0] = new Surface(datadir +
- "/images/shared/laptop-falling-right.png",
- USE_ALPHA);
-
-
- /* (Money) */
- img_jumpy_left_up = new Surface(datadir +
- "/images/shared/jumpy-left-up-0.png",
- USE_ALPHA);
- img_jumpy_left_down = new Surface(datadir +
- "/images/shared/jumpy-left-down-0.png",
- USE_ALPHA);
- img_jumpy_left_middle = new Surface(datadir +
- "/images/shared/jumpy-left-middle-0.png",
- USE_ALPHA);
-
- /* Mr. Bomb */
- for(int i=0; i<4; ++i) {
- char num[4];
- snprintf(num, 4, "%d", i);
- img_mrbomb_left[i] = new Surface(
- datadir + "/images/shared/mrbomb-left-" + num + ".png", USE_ALPHA);
- img_mrbomb_right[i] = new Surface(
- datadir + "/images/shared/mrbomb-right-" + num + ".png", USE_ALPHA);
- }
- img_mrbomb_ticking_left[0] = new Surface(
- datadir + "/images/shared/mrbombx-left-0.png", USE_ALPHA);
- img_mrbomb_ticking_right[0] = new Surface(
- datadir + "/images/shared/mrbombx-right-0.png", USE_ALPHA);
- img_mrbomb_explosion[0] = new Surface(
- datadir + "/images/shared/mrbomb-explosion.png", USE_ALPHA);
-
- /* stalactite */
- img_stalactite[0] = new Surface(
- datadir + "/images/shared/stalactite.png", USE_ALPHA);
- img_stalactite_broken[0] = new Surface(
- datadir + "/images/shared/stalactite-broken.png", USE_ALPHA);
-
- /* flame */
- img_flame[0] = new Surface(
- datadir + "/images/shared/flame-0.png", USE_ALPHA);
- img_flame[1] = new Surface(
- datadir + "/images/shared/flame-1.png", USE_ALPHA);
-
- /* fish */
- img_fish[0] = new Surface(
- datadir + "/images/shared/fish-left-0.png", USE_ALPHA);
- img_fish[1] = new Surface(
- datadir + "/images/shared/fish-left-1.png", USE_ALPHA);
- img_fish_down[0] = new Surface(
- datadir + "/images/shared/fish-down-0.png", USE_ALPHA);
-
- /* bouncing snowball */
- for(int i=0; i<6; ++i) {
- char num[4];
- snprintf(num, 4, "%d", i);
- img_bouncingsnowball_left[i] = new Surface(
- datadir + "/images/shared/bouncingsnowball-left-" + num + ".png",
- USE_ALPHA);
- img_bouncingsnowball_right[i] = new Surface(
- datadir + "/images/shared/bouncingsnowball-right-" + num + ".png",
- USE_ALPHA);
- }
- img_bouncingsnowball_squished[0] = new Surface(
- datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA);
-
- /* flying snowball */
- img_flyingsnowball[0] = new Surface(
- datadir + "/images/shared/flyingsnowball-left-0.png", USE_ALPHA);
- img_flyingsnowball[1] = new Surface(
- datadir + "/images/shared/flyingsnowball-left-1.png", USE_ALPHA);
- img_flyingsnowball_squished[0] = new Surface(
- datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA);
-
- /* spiky */
- for(int i = 0; i < 3; ++i) {
- char num[4];
- snprintf(num, 4, "%d", i);
- img_spiky_left[i] = new Surface(
- datadir + "/images/shared/spiky-left-" + num + ".png",
- USE_ALPHA);
- img_spiky_right[i] = new Surface(
- datadir + "/images/shared/spiky-right-" + num + ".png",
- USE_ALPHA);
- }
-
- /** snowball */
- img_snowball_left[0] = new Surface(datadir + "/images/shared/snowball-left-0.png", USE_ALPHA);
- img_snowball_left[1] = new Surface(datadir + "/images/shared/snowball-left-1.png", USE_ALPHA);
- img_snowball_left[2] = new Surface(datadir + "/images/shared/snowball-left-2.png", USE_ALPHA);
- img_snowball_left[3] = new Surface(datadir + "/images/shared/snowball-left-1.png", USE_ALPHA);
-
- img_snowball_right[0] = new Surface(datadir + "/images/shared/snowball-right-0.png", USE_ALPHA);
- img_snowball_right[1] = new Surface(datadir + "/images/shared/snowball-right-1.png", USE_ALPHA);
- img_snowball_right[2] = new Surface(datadir + "/images/shared/snowball-right-2.png", USE_ALPHA);
- img_snowball_right[3] = new Surface(datadir + "/images/shared/snowball-right-1.png", USE_ALPHA);
-
- img_snowball_squished_left[0] = new Surface(
- datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA);
- img_snowball_squished_right[0] = new Surface(
- datadir + "/images/shared/bsod-squished-right.png", USE_ALPHA);
-#endif
}
void free_badguy_gfx()
Level::Level(const std::string& subset, int level)
: img_bkgd(0)
{
- load(subset, level);
+ if(load(subset, level) < 0)
+ st_abort("Couldn't load level from subset", subset.c_str());
}
Level::Level(const std::string& filename)
: img_bkgd(0)
{
- load(filename);
+ if(load(filename) < 0)
+ st_abort("Couldn't load level " , filename.c_str());
}
Level::~Level()
if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-level") == 0)
{
LispReader reader(lisp_cdr(root_obj));
+ version = 0;
reader.read_int("version", &version);
+ use_endsequence = false;
reader.read_bool("use-endsequence", &use_endsequence);
- reader.read_int("width", &width);
+ if(!reader.read_int("width", &width))
+ st_abort("No width specified for level.", "");
if (!reader.read_int("start_pos_x", &start_pos_x)) start_pos_x = 100;
if (!reader.read_int("start_pos_y", &start_pos_y)) start_pos_y = 170;
- reader.read_int("time", &time_left);
+ time_left = 500;
+ if(!reader.read_int("time", &time_left)) {
+ printf("Warning no time specified for level.\n");
+ }
+ bkgd_top.red = bkgd_top.green = bkgd_top.blue = 0;
reader.read_int("bkgd_red_top", &bkgd_top.red);
reader.read_int("bkgd_green_top", &bkgd_top.green);
reader.read_int("bkgd_blue_top", &bkgd_top.blue);
+ bkgd_bottom.red = bkgd_bottom.green = bkgd_bottom.blue = 0;
reader.read_int("bkgd_red_bottom", &bkgd_bottom.red);
reader.read_int("bkgd_green_bottom", &bkgd_bottom.green);
reader.read_int("bkgd_blue_bottom", &bkgd_bottom.blue);
+ gravity = 10;
reader.read_float("gravity", &gravity);
+ name = "Noname";
reader.read_string("name", &name);
+ author = "unknown author";
reader.read_string("author", &author);
- reader.read_string("theme", &theme);
+ if(!reader.read_string("theme", &theme))
+ st_abort("No theme specified in level file", "");
+ song_title = "";
reader.read_string("music", &song_title);
+ bkgd_image = "";
reader.read_string("background", &bkgd_image);
+ particle_system = "";
reader.read_string("particle_system", &particle_system);
+
reader.read_int_vector("background-tm", &bg_tm);
if (!reader.read_int_vector("interactive-tm", &ia_tm))
obj = lisp_read(&stream);
fclose(in);
}
- else
+ else {
std::cerr << "LispReader: File not found: " << filename << endl;
+ st_abort("aborting", "");
+ }
+
return obj;
free_special_gfx();
free_badguy_gfx();
- delete smalltux_gameover;
-
delete img_water;
for (i = 0; i < 3; i++)
delete img_waves[i];
{
std::string exedir = std::string(dirname(exe_file)) + "/";
- datadir = exedir + "../data/"; // SuperTux run from source dir
+ datadir = exedir + "../data"; // SuperTux run from source dir
if (access(datadir.c_str(), F_OK) != 0)
{
- datadir = exedir + "../share/supertux/"; // SuperTux run from PATH
+ datadir = exedir + "../share/supertux"; // SuperTux run from PATH
if (access(datadir.c_str(), F_OK) != 0)
{ // If all fails, fall back to compiled path
datadir = DATA_PREFIX;
abort();
}
-
/* Set Icon (private) */
void seticon(void)
int open_audio (int frequency, Uint16 format, int channels, int chunksize)
{
- /* if success we reserved some channels and register panning effects */
- if (Mix_OpenAudio( frequency, format, channels, chunksize ) == 0)
- {
- if (Mix_ReserveChannels( SOUND_RESERVED_CHANNELS )
- != SOUND_RESERVED_CHANNELS )
- {
- DEBUG_MSG( "Warning: open_audio could'nt reserve channels" );
- }
-
- /* prepare the spanning effects, no error checking */
- Mix_SetPanning( SOUND_LEFT_SPEAKER, 230, 24 );
- Mix_SetPanning( SOUND_RIGHT_SPEAKER, 24, 230 );
- return 0;
- }
- else
- {
- return -1;
- }
+ if (Mix_OpenAudio( frequency, format, channels, chunksize ) < 0)
+ return -1;
+
+ // allocate 16 channels for mixing
+ if (Mix_AllocateChannels(8) != 8)
+ return -2;
+
+ /* reserve some channels and register panning effects */
+ if (Mix_ReserveChannels(SOUND_RESERVED_CHANNELS) != SOUND_RESERVED_CHANNELS)
+ return -3;
+
+ /* prepare the spanning effects */
+ Mix_SetPanning( SOUND_LEFT_SPEAKER, 230, 24 );
+ Mix_SetPanning( SOUND_RIGHT_SPEAKER, 24, 230 );
+ return 0;
}
/* --- LOAD A SOUND --- */
-Mix_Chunk * load_sound(const std::string& file)
+Mix_Chunk* load_sound(const std::string& file)
{
- Mix_Chunk * snd;
-
- snd = Mix_LoadWAV(file.c_str());
+ if(!audio_device)
+ return 0;
+
+ Mix_Chunk* snd = Mix_LoadWAV(file.c_str());
- if ((snd == NULL) && audio_device)
+ if (snd == 0)
st_abort("Can't load", file);
return(snd);
}
-
-/* --- LOAD A SONG --- */
-
-Mix_Music * load_song(const std::string& file)
-{
- if(!audio_device)
- return (Mix_Music*) ~0;
-
- Mix_Music* song = Mix_LoadMUS(file.c_str());
- return song;
-}
-
-
/* --- PLAY A SOUND ON LEFT OR RIGHT OR CENTER SPEAKER --- */
void play_sound(Mix_Chunk * snd, enum Sound_Speaker whichSpeaker)
/* this won't call the function if the user has disabled sound
* either via menu or via command-line option
*/
- if (use_sound && audio_device)
- {
- Mix_PlayChannel( whichSpeaker, snd, 0);
-
- /* prepare for panning effects for next call */
- /* warning: currently, I do not check for errors here */
- switch (whichSpeaker) {
- case SOUND_LEFT_SPEAKER:
- Mix_SetPanning( SOUND_LEFT_SPEAKER, 230, 24 );
- break;
- case SOUND_RIGHT_SPEAKER:
- Mix_SetPanning( SOUND_RIGHT_SPEAKER, 24, 230 );
- break;
- default: // keep the compiler happy
- break;
- }
- }
-}
+ if(!audio_device || !use_sound)
+ return;
+ Mix_PlayChannel( whichSpeaker, snd, 0);
+
+ /* prepare for panning effects for next call */
+ switch (whichSpeaker) {
+ case SOUND_LEFT_SPEAKER:
+ Mix_SetPanning( SOUND_LEFT_SPEAKER, 230, 24 );
+ break;
+ case SOUND_RIGHT_SPEAKER:
+ Mix_SetPanning( SOUND_RIGHT_SPEAKER, 24, 230 );
+ break;
+ default: // keep the compiler happy
+ break;
+ }
+}
void free_chunk(Mix_Chunk *chunk)
{
- if (chunk != NULL)
- {
- Mix_FreeChunk( chunk );
- chunk = NULL;
- }
+ Mix_FreeChunk( chunk );
}
#include "defines.h" /* get YES/NO defines */
-/* used to reserve some channels for panning effects */
-#define SOUND_RESERVED_CHANNELS 2
-
/*global variable*/
extern bool use_sound; /* handle sound on/off menu and command-line option */
extern bool use_music; /* handle music on/off menu and command-line */
HERRING_MUSIC
};
-
/* panning effects: terrible :-) ! */
enum Sound_Speaker {
SOUND_LEFT_SPEAKER = 0,
SOUND_RIGHT_SPEAKER = 1,
+ SOUND_RESERVED_CHANNELS = 2, // 2 channels reserved for left/right speaker
SOUND_CENTER_SPEAKER = -1
};
void free_special_gfx()
{
- delete img_bullet;
}
#include <math.h>
#include "globals.h"
#include "sprite.h"
+#include "setup.h"
Sprite::Sprite(lisp_object_t* cur)
{
LispReader reader(cur);
- reader.read_string("name", &name);
+ if(!reader.read_string("name", &name))
+ st_abort("Sprite wihtout name", "");
reader.read_int("x-hotspot", &x_hotspot);
reader.read_int("y-hotspot", &y_hotspot);
reader.read_float("fps", &fps);
+
std::vector<std::string> images;
- reader.read_string_vector("images", &images);
- surfaces.resize(images.size());
+ if(!reader.read_string_vector("images", &images))
+ st_abort("Sprite contains no images: ", name.c_str());
for(std::vector<std::string>::size_type i = 0; i < images.size(); ++i)
{
- surfaces[i] = new Surface(datadir + "/images/" + images[i], USE_ALPHA);
+ surfaces.push_back(
+ new Surface(datadir + "/images/" + images[i], USE_ALPHA));
}
frame_delay = 1000.0f/fps;
}
+Sprite::~Sprite()
+{
+ for(std::vector<Surface*>::iterator i = surfaces.begin(); i != surfaces.end();
+ ++i)
+ delete *i;
+}
+
void
Sprite::init_defaults()
{
/** cur has to be a pointer to data in the form of ((x-hotspot 5)
(y-hotspot 10) ...) */
Sprite(lisp_object_t* cur);
+ ~Sprite();
void reset();
load_resfile(filename);
}
+SpriteManager::~SpriteManager()
+{
+ for(std::map<std::string, Sprite*>::iterator i = sprites.begin();
+ i != sprites.end(); ++i) {
+ delete i->second;
+ }
+}
+
void
SpriteManager::load_resfile(const std::string& filename)
{
Sprites sprites;
public:
SpriteManager(const std::string& filename);
+ ~SpriteManager();
void load_resfile(const std::string& filename);
+ /** loads a sprite.
+ * WARNING: You must not delete the returned object.
+ */
Sprite* load(const std::string& name);
};
#include "screen.h"
#include "worldmap.h"
#include "resources.h"
+#include "texture.h"
+#include "tile.h"
int main(int argc, char * argv[])
{
updatescreen();
unloadshared();
+ TileManager::destroy_instance();
+#ifdef DEBUG
+ Surface::debug_check();
+#endif
st_shutdown();
return 0;
}
void
+Surface::debug_check()
+{
+ for(Surfaces::iterator i = surfaces.begin(); i != surfaces.end(); ++i)
+ {
+ printf("Surface not freed: T:%d F:%s.\n", (*i)->data.type,
+ (*i)->data.file.c_str());
+ }
+}
+
+void
Surface::draw(float x, float y, Uint8 alpha, bool update)
{
if (impl)
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
- /* Avoid compiler warnings */
- if(update)
- {}
+ (void) update; // avoid warnings
return 0;
}
#endif
static Surfaces surfaces;
public:
static void reload_all();
+ static void debug_check();
Surface(SDL_Surface* surf, int use_alpha);
Surface(const std::string& file, int use_alpha);
TileManager::TileManager()
{
- std::string filename = datadir + "images/tilesets/supertux.stgt";
+ std::string filename = datadir + "/images/tilesets/supertux.stgt";
load_tileset(filename);
}
+TileManager::~TileManager()
+{
+ for(std::vector<Tile*>::iterator i = tiles.begin(); i != tiles.end(); ++i) {
+ delete *i;
+ }
+}
+
void TileManager::load_tileset(std::string filename)
{
+ if(filename == current_tileset)
+ return;
+
// free old tiles
for(std::vector<Tile*>::iterator i = tiles.begin(); i != tiles.end(); ++i) {
delete *i;
Surface* cur_image;
tile->images.push_back(cur_image);
tile->images[tile->images.size()-1] = new Surface(
- datadir + "images/tilesets/" + (*it),
+ datadir + "/images/tilesets/" + (*it),
USE_ALPHA);
}
for(std::vector<std::string>::iterator it = editor_filenames.begin();
Surface* cur_image;
tile->editor_images.push_back(cur_image);
tile->editor_images[tile->editor_images.size()-1] = new Surface(
- datadir + "images/tilesets/" + (*it),
+ datadir + "/images/tilesets/" + (*it),
USE_ALPHA);
}
LispReader reader(lisp_cdr(element));
std::string filename;
reader.read_string("file", &filename);
- filename = datadir + "images/tilesets/" + filename;
+ filename = datadir + "/images/tilesets/" + filename;
load_tileset(filename);
}
else if (strcmp(lisp_symbol(lisp_car(element)), "tilegroup") == 0)
}
lisp_free(root_obj);
+ current_tileset = filename;
}
void
{
private:
TileManager();
+ ~TileManager();
+
std::vector<Tile*> tiles;
static TileManager* instance_ ;
static std::vector<TileGroup>* tilegroups_;
void load_tileset(std::string filename);
+
+ std::string current_tileset;
public:
static TileManager* instance() { return instance_ ? instance_ : instance_ = new TileManager(); }
+ static void destroy_instance() { delete instance_; instance_ = 0; }
+
static std::vector<TileGroup>* tilegroups() { return tilegroups_ ? tilegroups_ : tilegroups_ = new std::vector<TileGroup>; }
Tile* get(unsigned int id) {
if(id < tiles.size())
/* 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));
+ // Cleanup marked badguys
+ for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end();
+ /* ++i handled at end of the loop */) {
+ if ((*i)->is_removable()) {
+ delete *i;
+ i = bad_guys.erase(i);
+ } else {
+ ++i;
+ }
}
}
TileManager::TileManager()
{
- std::string stwt_filename = datadir + "images/worldmap/antarctica.stwt";
+ std::string stwt_filename = datadir + "/images/worldmap/antarctica.stwt";
lisp_object_t* root_obj = lisp_read_from_file(stwt_filename);
if (!root_obj)
void
WorldMap::load_map()
{
- std::string filename = datadir + "levels/default/worldmap.stwm";
+ std::string filename = datadir + "/levels/default/worldmap.stwm";
lisp_object_t* root_obj = lisp_read_from_file(filename);
if (!root_obj)
FILE * fi;
lisp_object_t* root_obj = 0;
- fi = fopen((datadir + "levels/" + level->name).c_str(), "r");
+ fi = fopen((datadir + "/levels/" + level->name).c_str(), "r");
if (fi == NULL)
{
- perror((datadir + "levels/" + level->name).c_str());
+ perror((datadir + "/levels/" + level->name).c_str());
return;
}
level->y == tux->get_tile_pos().y)
{
std::cout << "Enter the current level: " << level->name << std::endl;;
- GameSession session(datadir + "levels/" + level->name,
+ GameSession session(datadir + "/levels/" + level->name,
1, ST_GL_LOAD_LEVEL_FILE);
switch (session.run())