Loading levels

May 15, 2012 at 12:28pm
Hey i was wondering how i could make a menu for my game where i could pick my levels and things. It is made in c++ SDL/openGL.

I currently have a player class, which controls SDL input and player input, and a map class which reads co-ordinates form a txt file and draws the square to the screen. To load a map, i just call in main:
map.loadMap("level2.txt");
p1.collide("level2.txt");

Thankyou!
May 15, 2012 at 2:50pm
If you want to search through directories, you usually have to use OS calls. I think there if a boost lib that might wrap these calls into one universal interface if you prefer that.
One slightly simpler way you could remember what your levels are called would be to have a known file which lists all of the levels and saves that are available, and just run a check on all those files every time you start the game anew to make sure the files still exist.
In terms of letting the user decide which level to load, there are lots of ways to go about this. You could use the arguments passed to main, create your own little menu/button system, use cin>>...
May 16, 2012 at 8:11am
ohkay. thanks. I can load the map fine, so if i just call loadmap("level2.txt") in main, that works, but when i try to pass arguments or anyhting it freezes
May 16, 2012 at 10:02am
Pass arguments to what?
May 16, 2012 at 10:25am
oh okay, sorry i was in a rush. I didnt mean pass arguments. How can i make it so a user inputs something, like presses 0, and it loads map zero? because when i do:

1
2
if (press 1)
loadMap("level1.txt")

The app freeezes when i press one, and i have tried all diff ways, like setting a boll to true, and when the level's boolean is true, it loads. But that freezes too.
May 16, 2012 at 10:29am
Well... if your map freezes no matter what you do, what makes you think it has anything to do with user input? I have problems understanding exactly what your problem is.
May 17, 2012 at 2:14pm
oh okay. if i just go into main.cpp and put this in my main:
loadMap("level2.txt");

Then that will immediatley load level 2, and it will work fine and i can play the level perfectly.
But if i do something like:
In player class:
1
2
3
4
5
6
7
void levelPicker()
{
if (user presses 1) one =true;
else if (user presses 2) two =true;


}

Then if I I test whether they are true in my main then load the map:

1
2
 if (two) loadMap("level2.txt");
else if (one) loadMap ("level1.txt");


Then it will NOT work and it will freeze. So if i try to load a map by getting the user to enter the map number it will freeze.

Thankyou :) any help is appreciated.






May 17, 2012 at 2:31pm
Are one and two global variables? How exactly does the "levelPicker" function work?
May 17, 2012 at 2:44pm
There's nothing particularly wrong with your approach, so the problem is somewhere in the details (just like most other problems). So we probably can't help you any further unless you give us access to the source.
May 18, 2012 at 7:44am
okay, how cuold i get it to u, i could email u the whole thing?
May 18, 2012 at 10:32am
You can just post the relevant parts here, or if that gets too long on pastebin or something.
May 18, 2012 at 1:16pm
This is the function which i call in my main:
1
2
3
4
5
6
void Map::loadMap(string fileName_Spike, string fileName_Blocks, string fileName_Move) {

drawBlocks(fileName_Blocks);
drawSpike(fileName_Spike);
drawMove(fileName_Move);
}


And here is my function which draws blocks. The other fucntions which load different types of blocks (drawSpike and drawMove are the same as drawBlocks, only different things happen when you collide with them, so i wont bother posting them)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void Map::drawBlocks(string fileName_Blocks)
{
    float x, y, width, height;
      MapFile.open(fileName_Blocks.c_str());
    while (!MapFile.eof())
{
  MapFile >> xs;
   MapFile >> ys;
    MapFile >> ws;
     MapFile >> hs;


     glBegin(GL_QUADS); //GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_QUADS, GL_TRIANGLES, GL_POLIGON
     glColor4ub(255, 255, 50, 255);
glVertex2f(xs,ys);
glVertex2f(xs+ws, ys);
glVertex2f(xs+ws,ys+hs);
glVertex2f(xs, ys+hs);
glEnd(); //End drawing
}
MapFile.close();

}


And here is my main:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
bool run =true;

int main( int argc, char* args[] )
{

    //SDL Init and Set-up
  SDL_Init(SDL_INIT_EVERYTHING);
  SDL_Surface* screen;
  screen = SDL_SetVideoMode(800,600,32, SDL_OPENGL | SDL_SWSURFACE );
  glViewport(0,0,800,600);
  glLoadIdentity();
  glDisable(GL_DEPTH_TEST);
//disable depth checking
     Menu men;
     Player p1;
     Map level;
    while (p1.run)
    {
glClear(GL_COLOR_BUFFER_BIT);

glPushMatrix();//Start rendering phase
glOrtho( 0, 800,600, 0, -1, 1 );

//Player


    p1.draw();
 p1.move();
glClearColor(0,0,0,0);




level.loadMap("level4Spike.txt", "level4.txt", "level4Move.txt");
p1.collide("level4.txt");
p1.collideSpike("level4Spike.txt");
p1.collideMove("level4Move.txt");


 //Level obstacles

SDL_GL_SwapBuffers();
glPopMatrix(); //End rendering phase
    }

SDL_Quit();
 return 0;
}


Which is only loading level 4.

And in my player class is where the players movement and keyboard input loops are.

Thankyou for al this guys . I hope you read it or can help :)
May 18, 2012 at 1:39pm
That is... Well how should I put this... you aren't supposed to load the map every frame. Loading something from your HD is one of the (if not THE) slowest operations there is. What loading a map should do is to load it into some data structure (or object if you prefer OO, though it doesn't look like it) and then use that data structure as a representation of your map. This isn't just a recommendation, this is something you absolutely HAVE to do.

The same with all your other load stuff.

I'll still look into the rest of your code though.

Also, the OpenGL you use is very much deprecated. Instead of intermediate mode (with glBegin / glEnd) you usually load models into video memory (into a vertex buffer) and just tell it which buffers to draw. Again, this is because of speed considerations - pushing vertices to your GPU is also slow. Basically, anything that moves data somewhere else is slow, especially between different pieces of hardware.

You should look into http://en.wikibooks.org/wiki/OpenGL_Programming#Modern_OpenGL
for a more modern approach. I don't see your real error that causes the crash right now though.
Last edited on May 18, 2012 at 1:45pm
May 18, 2012 at 2:48pm
ohh wow .. Thankyou very much for telling me alll of this. I will definately read that tutorial link you gave me. But just now, could u just explain breifly what i need to change to make the code correct? Like, the classes and how to adjust it soo it's proper OOP? And also explain about the struct about the map you were talking about? thankyou very much though! i was wondering why it was lagging and my 2d game was running slowly. Thanks again :)
May 18, 2012 at 3:42pm
Writing proper OO code is pretty hard, it's a lot more work than I'm willing to invest (and I'm not that great at it myself).

About the data structure - just look at what data you need to draw / check for collisions etc, and instead of reading it from your file every frame store that data somewhere and tell your drawing/collision functions to get their data from there. Example (a real one should probably be a little bit more sophisticated, I'm trying to do this as simple as possible):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
struct Vertex {
   float x;
   float y;
};

struct Quad {
    Vertex bottomLeftCorner;
    Vertex bottomRightCorner;
};

struct Map {
   std::vector<Quad> quads;
   Map load(std::istream&);
};

Map Map::load(std::istream& in)
{
     Map result;
     std::stringstream ss;
     std::string line;
     // assumes two coordinate pairs per line
     while(std::getline(in,line)) {
            ss << line;
            Vertex v1;
            Vertex v2;
            in >> v1.x >> v1.y >> v2.x >> v2.y;
            Quad q = {v1,v2};
            result.quads,push_back(q);
     }
     return result;
}


Now you can load a map with Map map = Map::load(std::ifstream(filename)); and then it'd have the data you need to draw a bunch of quads (which you've been doing before). Again, I wouldn't recommend doing it exactly like this, it's just supposed to give you some general idea.
Topic archived. No new replies allowed.