SDL question: how to dynamically create & draw objects?

Started by
7 comments, last by Kylotan 6 years, 10 months ago
Good morning,
I've been building a game in C++ using SDL and I've run into a problem I'm not sure how to fix (or maybe it's just a limitation of SDL)
So I've got a "GameObject" class with a "draw" method that draws the object's sprite on the screen (obviously), and then have objects that extend if (like the player, enemies, weapons etc.); these all work fine. Then I have a Game object that handles the main game loop. This is the object where the trouble is coming from. Specifically this code:
while(running)
{
    // Clear the previous frame
    SDL_RenderClear(window->get_renderer());  // Oh yeah, I had a Window class too; this works though

    // Draw all the objects in the "objects" vector
    if (!objects.empty())
        for (GameObject * o : objects)
            o->draw(window->get_surface());

    // Handle keyboard events etc.
}
This is the loop that handles keyboard events, draws the background on the screen, etc. But the code that handles drawing seems to be the problem here. In the for loop, "objects" is a vector of pointers to GameObject instances, and it works fine for objects created in main().
So for the player, the one enemy ship I have, and pretty much anything I know is going to be there at compile time, this works great. Anything I can create before calling Game.start (where the code above is executed) will be drawn on the screen. The problem is with objects added to the vector during the game.
For example, this game is a 2D scroller with a space ship that shoots lasers. In the loop above, if the user presses Space it creates a laser object and adds it to the "objects" vector. Those objects are created and added to the vector (tested with a bunch of cout calls) but mysteriously never get drawn.
So my questions are:
1. Has anyone here ever run into a similar issue trying to create instances dynamically like this?
2. If so, how did you solve it? Or is it one of those things that just can't be done? Maybe there's some requirement that all instances to be drawn have to be defined at compile time or something? After all, we're talking about a platform that can only handle drawing BMP images (unless you can miraculously get SDL_Image to work, but that's a whole other can of worms lol).
Thanks.

PS: Just out of curiosity, is there a better platform for 2D in C++ than SDL? I'm slowly learning UE4 for 3D, but I mostly play 2D so I figured I'd start with something "simpler" :D
Advertisement

Sounds like the problem is elsewhere in your code, since I can't think of any good reason why updating the contents of that vector shouldn't result in everything being drawn. Perhaps you're accidentally adding objects to the wrong vector (e.g. a temporary copy). I suggest posting your whole code.

SDL is a good platform for 2D games. And SDL_Image should be simple enough to use; if you have a problem with that, it's worth asking!

Well my whole code is like 6-7 files with hundreds of lines, which is why I didn't do that (lol). But I like your temporary copy idea - I'll go down that road for awhile and see where it leads. But if you can think of a way to share more code without copy/pasting a book's worth of code in here I'm open to suggestions. :)

Now as far as SDL_Image, I've always had trouble with compiler issues screaming about what appears to be SDL's internals. It was like a week ago when I gave up on that thing so I don't have any exact error messages or code, but I vaguely remember one compiler tantrum about "SDL_toupper", or something like that. I had linked to the library file, put the DLL in the same folder as the EXE and #included the header (there was only one), but it's like it was somehow still missing stuff, and apparently stuff that didn't come with the zip file. I'll fight with it some more and get more info before posting a question about that. :)

I wasn't suggesting that you use a temporary copy - I was suggesting that you may be accidentally duplicating the vector and adding your new objects into the wrong copy.

Generally, instead of looking to share large amounts of code, you should try cutting down the code to the bare minimum that demonstrates your problem. 9 times out of 10, the act of doing that will show you exactly where the problem is. The other 1 time out of 10, it becomes quite easy for other people to read the small code example and find the error.

At the very least, in this case we need to see (a) where this 'objects' vector is initialised, and (b) how you're adding objects to it.

One very minor and quite unrelated point:

if "objects.empty()" holds, iterating over objects is very cheap. In other words, the "if (!objects.empty())" test isn't doing much at all, since the loop will immediately bump into that same case.

More related, and one common cause in duplicating a vector is to pass it into a function by value rather than by reference, ie

"func(std::vector<GameObject *> objects)" instead of the correct "func(std::vector<GameObject *> &objects)" (note the additional "&"!)

I understood what you meant about the temporary copy thing - I've made that mistake before. :)

But this whole idea of cutting down the code until you have a really small example that still has the problem sounds like almost as big a project as starting over completely and slowly reintroducing old code to find out what specifically is causing the problem - so I guess that's what I'll do. Maybe I can figure out why SDL_Image was griefing me last week too. :lol:

PS: Thanks for the info on not having to check for empty() too - I just figured it was necessary to prevent accidentally dereferencing something wrong and crashing the program. :)

I understood what you meant about the temporary copy thing - I've made that mistake before. :)

But this whole idea of cutting down the code until you have a really small example that still has the problem sounds like almost as big a project as starting over completely and slowly reintroducing old code to find out what specifically is causing the problem - so I guess that's what I'll do. Maybe I can figure out why SDL_Image was griefing me last week too. :lol:

PS: Thanks for the info on not having to check for empty() too - I just figured it was necessary to prevent accidentally dereferencing something wrong and crashing the program. :)

Invest time into learning how your debugger works.

Set breakpoints and/or debug prints -- when you add to the vector, does the vector size increase where it's being used for drawing? If it does, what does the newly added instance actually look like, etc.

Hello to all my stalkers.

But this whole idea of cutting down the code until you have a really small example that still has the problem sounds like almost as big a project as starting over completely and slowly reintroducing old code to find out what specifically is causing the problem - so I guess that's what I'll do. Maybe I can figure out why SDL_Image was griefing me last week too. :lol:

Not really, because you can take your existing code and comment things out.

It's worth digging in and trying to simplify your program, firstly because there will come a point when the program is obviously far too large and complex to start from the beginning again, and secondly because if you write a second program and it works perfectly for some reason you don't understand, you can't easily transfer that knowledge to the original program. Work with what you have.

This topic is closed to new replies.

Advertisement