help with loop (SDL Images)

Started by
4 comments, last by Lord_Spatulator 19 years ago
Hey, I'm making a SDL game at the moment, and for each image I want in the game I've got:

    //load menu image
    img_menu = SDL_LoadBMP("data/menu.bmp");
    if(img_menu == NULL)
        fprintf(stderr,
                "Unable to load image %s\n",
                SDL_GetError());
                
    //load cursor image
    img_cursor = SDL_LoadBMP("data/cursor.bmp");
    if(img_cursor == NULL)
        fprintf(stderr,
                "Unable to load image %s\n",
                SDL_GetError());
    
    //load background image
    img_arena = SDL_LoadBMP("data/arena.bmp");
    if(img_arena == NULL)
        fprintf(stderr,
                "Unable to load image %s\n",
                SDL_GetError());
etc, is there a way I can put "menu", "cursor", "arena" etc into a vector and just iterate through that vector throwing the data into that little chunk of code each time? The main problem I see is getting it within the ""'s for the image file directory. Thanks in advance.
Advertisement
Sure there is:

#include <vector>std::vector<SDL_Surface*> images;bool LoadImage(std::string filename){   SDL_Surface* temp = SDL_LoadBMP(filename.c_str());   if(temp){       images.push_back(temp);       return true;   }   return false;}void DrawImages(){   for(std::vector<SDL_Surface*>::iterator pos = images.begin(); pos != images.end(); pos++){       // Draw Image - DrawIMG(*pos);   }}


Is that similar to what you're looking for? I haven't compiled any of that so be warned.
Rob Loach [Website] [Projects] [Contact]
no I don't think so sorry... either it's not quite what I'm after, or I just don't understand what you've written....

taking into note that in my first post is how it looks now, what I'm after would be something like this:

    string image[] = {"menu",                      "cursor",                      "background",                      "health",                      "title",                      "badguy",                      "END"};        //load all images    for (int i = 0; image != "END"; i++)    {        string varName = "img_" + image;        string location = "data/images/" + image + ".bmp");                varName = SDL_LoadBMP(location);        if(varName == NULL)            fprintf(stderr,                    "Unable to load image %s\n",                    SDL_GetError());            }


of course the string varName is pretty much.. nonsensicle, and doesn't work... but that's what I'm after... being able to use a string variable in the name of another variable..


If anyone can gimme a hand I'll be greatly appreciative!
Thanks in advance!
I think you are close with your last post. However there is one little problem:
varName = SDL_LoadBMP(location);        if(varName == NULL)            fprintf(stderr,                    "Unable to load image %s\n",                    SDL_GetError());


Since varName is defined as a string, that will not compile (incorrect data types). Consider this:
  vector<string> image;  image.push_back("menu");  image.push_back("cursor");  image.push_back("background");  image.push_back("health");  image.push_back("title");  image.push_back("badguy");    vector <SDL_Surface*> DataImages;    //load all images    for (int i = 0; i < image.size(); i++)    {        string varName = "img_" + image;        string location = "data/images/" + image + ".bmp");                DataImages.push_back( SDL_LoadBMP(location) ); // Rob's idea [wink]        if(DataImages[ DataImages.size() - 1 ] == NULL)            fprintf(stderr, "Unable to load image[%s]: %s\n", location .c_str(), SDL_GetError());    }


Give that a try out. Basically it will add all the images to a vector as Rob has suggested in previous posts. You will definitly need to track all of the images so you can SDL_FreeSurface them at the end [smile].
First, @Rob: storing things in a non-keyed container like a vector and rejecting nulls is a bad idea. You saddle the rest of the code with the task of figuring out the index into the vector for each successfully loaded image, given the successes/failures. Needlessly complex. Better to leave the nulls in, or better yet (probably), replace them with pointers to a Null Object.

Anyway. I think you two are misunderstanding; the OP seems to want to create new identifier names at runtime.

@OP: Sorry, it can't be made to work exactly as you seem to want it. The variable names don't exist at run-time. The calculation of the variable name that you want - i.e. appending whatever to the "img_" - can't happen until the program is already compiled and running, and at that point it is too late for the compiler to say "oh wait, we need a variable with this name, too".

You need to have some structure that will hold all the images instead, such as an array, a std::vector (as illustrated), or what I will suggest, a std::map. The map is a data structure which lets you insert and look up its contents by "key" - which is of a type of your choosing - rather than by a numerical index; the information about key values is preserved at runtime, as part of the map data. What this means is that you can use the "friendly" names when looking things up:

#include <map>#include <string>using namespace std;map<string, SDL_Surface*> img;const string imageNames[] = {   "menu", "cursor", "background", "health", "title", "badguy"};// Create Null ObjectSDL_Surface * nullSurface = SDL_CreateRGBSurface(0, 0, 0, 8, 0, 0, 0, 0);//load all imagesconst int imageCount = sizeof(imageNames) / sizeof(string);for (int i = 0; i < imageCount; i++) {  string location = "data/images/" + imageNames + ".bmp");  // the std::map overloads operator[] to do what you'd expect - you supply the  // key where you would normally put an array index, and you get a reference to  // that "slot".  // if the load fails, we'll point at the null object instead.  img[imageNames] = SDL_LoadBMP(filename.c_str()) || nullSurface;  // May as well log an error in that case  if (img[imageNames] == nullSurface) {    cerr << "Unable to load image[" << location << "]: "          << SDL_GetError() << endl;  }}// Now you access an image like this:do_something_with(img["cursor"]); // rather than img_cursor// If you specify a bad name, you'll get a null pointer, rather than a pointer// to our null object, unfortunately. To fix that we'd need to make a // wrapper class to encapsulate our SDL_Surface* (and in the default ctor, make// the SDL_Surface* data member point at the null object). Basically, the map// returns a default-constructed element of the value type in this case; // "default-constructed" primitives are zero, i.e. NULL for pointers.
Quote:The variable names don't exist at run-time.

Ah. of course. :) I knew my particular chunk of code wasn't going to work, I just put that there to demonstrate exactly what I was trying to acomplish, but thinking about it logically, it could never have worked for that exact reason. I don't know why I thought it would work... I think I used a similar idea in Flash ActionScript once... :p

ok, so I suppose I'll use the map idea, unless I can't figure it out, in which case i'll just use a good ol'e vector like the others suggested, all in all, thanks a lot guys!

EDIT: Looking back over it, Rob's first reply will work quite nicely indeed! sorry for not just running with that one the first time. on another note; rob, it was your SDL tuts I used to get me started, so thanks for that too!!

EDIT2: Looking through it another time, each suggestion was really a kinda.. better version of the prev one, so I'm gonna go w/ the last one there, but I'm a little confused with this line:

Quote:img[imageNames] = SDL_LoadBMP(filename.c_str()) || nullSurface;


should: filename.c_str()
in there just be: location

or even : location.c_str()

on that note, what is .c_str() ?

Thanks again!

[Edited by - Lord_Spatulator on March 22, 2005 4:40:50 AM]

This topic is closed to new replies.

Advertisement